-
Notifications
You must be signed in to change notification settings - Fork 0
277 lines (260 loc) · 12.3 KB
/
Copy pathci.yml
File metadata and controls
277 lines (260 loc) · 12.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
name: CI
# What this workflow asserts.
#
# A C++ standard library is configured for one C library and compiled against
# that library's headers. The claim here is that a program above this package
# imports `std`, reaches the two inline paths that failed at link on the iOS
# rows under the payload's headers over the SDK's libc++, links with no
# reference to another libc++, and runs where the runner can run it. Every row
# `[package] platforms` claims is a gate: Linux over glibc (the combination the
# engine change was first measured on, a prebuilt C library under a graph C++
# runtime), macOS natively, and the three iOS rows. Windows is not claimed and
# is measured by a probe job on request, so that a row this package does not
# serve cannot read as green beside the gates.
#
# Two further claims hold from mcpp 2026.9.15.2: the same program at c++20
# builds and runs, because the package's own sources compile at the level it
# states while the std module takes the program's; and a program over a C++
# shared library dependency builds and runs when it states a private copy of
# the runtime for shared libraries, with the shared library carrying no
# reference to another libc++.
on:
push:
branches: [main]
pull_request:
workflow_dispatch:
inputs:
mcpp_ref:
description: "Branch of mcpp-community/mcpp to build and test against (empty = the released pin)"
required: false
default: ""
env:
MCPP_SOURCE_REF: ${{ github.event.inputs.mcpp_ref || vars.MCPP_SOURCE_REF }}
MCPP_VERSION: 2026.9.15.2
XLINGS_VERSION: v2026.9.5.1
XLINGS_NON_INTERACTIVE: '1'
jobs:
linux:
name: a program imports std over this package (linux, glibc, ${{ matrix.toolchain }})
runs-on: ubuntu-24.04
timeout-minutes: 60
strategy:
fail-fast: false
matrix:
toolchain: ['llvm@22.1.8']
defaults:
run:
shell: bash
steps:
- uses: actions/checkout@v4
- name: Install xlings and mcpp
run: |
curl -fsSL --retry 3 --retry-all-errors --retry-delay 2 \
https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.sh \
| bash -s "$XLINGS_VERSION"
echo "$HOME/.xlings/subos/current/bin" >> "$GITHUB_PATH"
- name: Install mcpp
run: bash tools/install-mcpp.sh
- name: Select the toolchain
run: |
spec='${{ matrix.toolchain }}'
mcpp toolchain install "${spec%@*}" "${spec#*@}"
mcpp toolchain default "$spec"
# The report names the C++ layer as this package's, and the C library
# as the payload's: the combination this package exists for.
- name: The program builds, the report names both layers, the link is self-contained
run: |
set -euo pipefail
cd examples/import-std
mcpp build 2>&1 | tee build.log
grep -E 'c\+\+-abi +libc\+\+ +\(libcxx@22\.1\.8\.3, graph\)' build.log \
|| { echo "::error::the report does not name llvm.libcxx as the C++ layer"; exit 1; }
# The report prints a layer only when a package answers for it; the
# C library is the payload's here and is read from the target line.
grep -q 'Target x86_64-unknown-linux-gnu' build.log \
|| { echo "::error::the target line is not the glibc row"; exit 1; }
bin=$(ls -td target/*/*/bin/libcxx-import-std | head -1)
if ldd "$bin" | grep -q 'libc++'; then
echo "::error::the artefact still links a libc++ shared object"; ldd "$bin"; exit 1
fi
echo "ok: no libc++ shared object in the closure"
- name: The program runs and prints what the two paths compute
run: |
set -euo pipefail
cd examples/import-std
out=$(mcpp run 2>&1) || { echo "$out"; exit 1; }
echo "$out" | tail -3
grep -qx '1-2-3' <<<"$out" || { echo "::error::expected the line 1-2-3"; exit 1; }
- name: The program at c++20 builds and runs
run: |
set -euo pipefail
cd examples/import-std-cxx20
mcpp build 2>&1 | tee build.log
out=$(mcpp run 2>&1) || { echo "$out"; exit 1; }
echo "$out" | tail -3
grep -qx '1-2-3' <<<"$out" || { echo "::error::expected the line 1-2-3 at c++20"; exit 1; }
- name: A shared library dependency with a stated private copy builds and runs
run: |
set -euo pipefail
cd examples/shared-dependency
mcpp build 2>&1 | tee build.log
so=$(find target -name 'libgreeter.so' -type f | head -1)
[ -n "$so" ] || { echo "::error::no libgreeter.so was built"; exit 1; }
needed=$(readelf -d "$so" | grep NEEDED || true)
echo "$needed"
if grep -q 'libc++' <<<"$needed"; then
echo "::error::the shared library needs a libc++ shared object"; exit 1
fi
symbols=$(nm -D --undefined-only "$so")
n=$(grep -c '__1' <<<"$symbols" || true)
[ "$n" -eq 0 ] || { echo "::error::the shared library has $n undefined libc++ references"; exit 1; }
out=$(mcpp run 2>&1) || { echo "$out"; exit 1; }
echo "$out" | tail -3
grep -qx 'greeter-3' <<<"$out" || { echo "::error::expected the line greeter-3"; exit 1; }
echo "reading: $(grep runtime_error <<<"$out")"
apple:
name: a program imports std over this package (${{ matrix.row }})
runs-on: macos-15
timeout-minutes: 60
strategy:
fail-fast: false
matrix:
include:
# The native row: the payload has macOS archives of its own, and
# this package replaces them the same way it replaces the SDK's
# libc++ on iOS. `run` is the host's.
- { row: aarch64-macos, platform: "", runs: host }
# The simulator that runs on this runner's architecture, through
# `simctl-run` from `xim:apple-simulator-tools`.
- { row: aarch64-ios-sim, platform: "7", runs: simulator }
# The simulator for the other architecture: the artefact is the
# claim, since a simulator runs the host's architecture only.
- { row: x86_64-ios-sim, platform: "7", runs: none }
# The device row: the artefact is the claim, since running it
# needs a signature the developer owns.
- { row: aarch64-ios, platform: "2", runs: none }
defaults:
run:
shell: bash
steps:
- uses: actions/checkout@v4
- name: Install xlings and mcpp
run: |
curl -fsSL --retry 3 --retry-all-errors --retry-delay 2 \
https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.sh \
| bash -s "$XLINGS_VERSION"
echo "$HOME/.xlings/subos/current/bin" >> "$GITHUB_PATH"
- name: Install mcpp
run: bash tools/install-mcpp.sh
- name: The program builds and both the report and the load commands name no other libc++
run: |
set -euo pipefail
cd examples/import-std
target='${{ matrix.row }}'
if [ "$target" = "aarch64-macos" ]; then
mcpp build 2>&1 | tee build.log
else
mcpp build --target "$target" 2>&1 | tee build.log
fi
grep -E 'c\+\+-abi +libc\+\+ +\(libcxx@22\.1\.8\.3, graph\)' build.log \
|| { echo "::error::the report does not name llvm.libcxx as the C++ layer"; exit 1; }
bin=$(ls -td target/*/*/bin/libcxx-import-std | head -1)
file "$bin"
otool -L "$bin"
if otool -L "$bin" | grep -q 'libc++'; then
echo "::error::the artefact links a libc++ dylib"; exit 1
fi
echo "ok: no libc++ dylib in the load commands"
if [ -n '${{ matrix.platform }}' ]; then
# The platform in LC_BUILD_VERSION is what tells an iOS artefact
# from a macOS one; a build that succeeds cannot.
got=$(otool -l "$bin" | awk '/cmd LC_BUILD_VERSION/{f=1} f && $1=="platform"{print $2; exit}')
[ "$got" = '${{ matrix.platform }}' ] \
|| { echo "::error::LC_BUILD_VERSION platform is '$got', expected ${{ matrix.platform }}"; exit 1; }
echo "ok: LC_BUILD_VERSION platform ${{ matrix.platform }}"
fi
- name: The program runs and prints what the two paths compute
if: matrix.runs != 'none'
run: |
set -euo pipefail
cd examples/import-std
if [ '${{ matrix.runs }}' = host ]; then
out=$(mcpp run 2>&1) || { echo "$out"; exit 1; }
else
out=$(mcpp run --target '${{ matrix.row }}' 2>&1) || { echo "$out"; exit 1; }
fi
echo "$out" | tail -3
grep -qx '1-2-3' <<<"$out" || { echo "::error::expected the line 1-2-3"; exit 1; }
- name: The program at c++20 builds, and runs where the runner can
run: |
set -euo pipefail
cd examples/import-std-cxx20
target='${{ matrix.row }}'
if [ "$target" = "aarch64-macos" ]; then
mcpp build 2>&1 | tee build.log
else
mcpp build --target "$target" 2>&1 | tee build.log
fi
case '${{ matrix.runs }}' in
host) out=$(mcpp run 2>&1) || { echo "$out"; exit 1; } ;;
simulator) out=$(mcpp run --target "$target" 2>&1) || { echo "$out"; exit 1; } ;;
*) echo "ok: built at c++20; this row is not run here"; exit 0 ;;
esac
echo "$out" | tail -3
grep -qx '1-2-3' <<<"$out" || { echo "::error::expected the line 1-2-3 at c++20"; exit 1; }
- name: A shared library dependency with a stated private copy builds and runs
if: matrix.row == 'aarch64-macos'
run: |
set -euo pipefail
cd examples/shared-dependency
mcpp build 2>&1 | tee build.log
dylib=$(find target -name 'libgreeter.dylib' -type f | head -1)
[ -n "$dylib" ] || { echo "::error::no libgreeter.dylib was built"; exit 1; }
loads=$(otool -L "$dylib")
echo "$loads"
if grep -q 'libc++' <<<"$loads"; then
echo "::error::the shared library links a libc++ dylib"; exit 1
fi
out=$(mcpp run 2>&1) || { echo "$out"; exit 1; }
echo "$out" | tail -3
grep -qx 'greeter-3' <<<"$out" || { echo "::error::expected the line greeter-3"; exit 1; }
echo "reading: $(grep runtime_error <<<"$out")"
# THE ROW THIS PACKAGE DOES NOT CLAIM, MEASURED ON REQUEST. libc++ over the
# MSVC runtime takes a configuration this package does not carry; this job
# records what actually happens there, every step continuing on error, and
# it does not run on push so that it cannot read as a gate.
windows-probe:
name: "probe, not a gate: what happens on windows x86_64"
if: github.event_name == 'workflow_dispatch'
runs-on: windows-2022
timeout-minutes: 60
defaults:
run:
shell: bash
steps:
- uses: actions/checkout@v4
# The released Windows archive, the way mcpp-plugins' own Windows job
# takes it: the quick installer is a POSIX script and the runner's bash
# cannot put its shim on PATH.
- name: Fetch the released mcpp
continue-on-error: true
run: |
set -e
curl -L -fsS --retry 3 --retry-all-errors -o mcpp.zip \
"https://github.com/mcpp-community/mcpp/releases/download/v${MCPP_VERSION}/mcpp-${MCPP_VERSION}-windows-x86_64.zip"
unzip -q mcpp.zip
# A released archive is self-contained: its home is the extracted
# directory and its xlings sits at registry/bin/xlings, which the
# engine finds only when told (the first probe stopped on `xlings
# binary not found`). Host spelling for both, as the plugins CI does.
D="$PWD/mcpp-${MCPP_VERSION}-windows-x86_64"; command -v cygpath >/dev/null && D=$(cygpath -m "$D")
echo "MCPP=$D/bin/mcpp.exe" >> "$GITHUB_ENV"
echo "MCPP_HOME=$D" >> "$GITHUB_ENV"
echo "MCPP_VENDORED_XLINGS=$D/registry/bin/xlings.exe" >> "$GITHUB_ENV"
ls "$D/registry/bin" | head
- name: The program over this package, on the host's default toolchain
continue-on-error: true
run: |
cd examples/import-std
"$MCPP" --version
"$MCPP" build 2>&1 | tail -40