GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — mcpp/.github/workflows/ci-aarch64-fresh-install.yml at main · mcpp-community/mcpp

Expand file tree

/

ci-aarch64-fresh-install.yml

Copy path
View runs
More file actions
More file actions

Latest commit

 

History

History
History
407 lines (392 loc) · 20.7 KB
/

ci-aarch64-fresh-install.yml

Copy path

File metadata and controls

407 lines (392 loc) · 20.7 KB
Raw
Copy raw file
Download raw file
Open symbols panel
Edit and raw actions
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
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
name: ci-aarch64-fresh-install
# End-to-end "fresh install" of the whole ecosystem on a NATIVE aarch64 host,
# exactly as a new aarch64-Linux / Termux(-proot) user would:
#
# curl quick_install.sh | bash -> installs aarch64 xlings (static musl)
# xlings install mcpp -> installs aarch64 mcpp (static musl)
# mcpp new / build / run -> NATIVE aarch64 build (pulls the native
# musl-gcc toolchain from the ecosystem)
#
# Validates that every published aarch64 asset (xlings, mcpp, musl-gcc) lines
# up and that mcpp can build & run a real `import std` program natively on
# aarch64 — no cross, no qemu. Runs on GitHub's native ARM64 runner.
on:
workflow_dispatch:
inputs:
xim_pkgindex_ref:
description: 'Candidate xim-pkgindex SHA or branch; empty runs ordinary released fresh-install'
type: string
required: false
default: ''
mcpp_run_id:
description: 'CI run with a successful native build of exactly this dispatched mcpp head'
type: string
required: false
default: ''
schedule:
- cron: '0 6 * * 1' # weekly Mon 06:00 UTC
pull_request:
branches: [ main ]
paths:
- 'src/build/build_program.cppm'
- 'src/run/run.cpp'
- 'tests/e2e/168_build_mcpp_musl_host_static.sh'
- '.github/workflows/ci-aarch64-fresh-install.yml'
push:
branches: [ main ]
paths:
- '.github/workflows/ci-aarch64-fresh-install.yml'
permissions:
contents: read
actions: read
concurrency:
group: ci-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
fresh-install:
if: github.event_name != 'workflow_dispatch' || inputs.xim_pkgindex_ref == ''
name: fresh install + native build (aarch64 / glibc)
runs-on: ubuntu-24.04-arm
timeout-minutes: 60
env:
# Verbose every mcpp invocation — cold bootstrap path (src/cli.cppm).
MCPP_VERBOSE: "1"
steps:
# NB: the checkout deliberately comes LAST, after every fresh-install
# step below — see the comment above it.
- name: System info
run: |
uname -a
echo "arch: $(uname -m)" # aarch64 on this runner
- name: Fresh-install xlings (curl | bash)
env:
XLINGS_NON_INTERACTIVE: '1'
run: |
curl -fsSL https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.sh | bash
echo "$HOME/.xlings/subos/current/bin" >> "$GITHUB_PATH"
echo "$HOME/.xlings/bin" >> "$GITHUB_PATH"
- name: Verify xlings + GLOBAL mirror
run: |
xlings --version
xlings config --mirror GLOBAL 2>/dev/null || true
xlings update -y 2>/dev/null || xlings update 2>/dev/null || true
- name: Fresh-install mcpp via xlings
run: |
xlings install mcpp -y
mcpp --version
mcpp self config --mirror GLOBAL 2>/dev/null || true
- name: Refresh mcpp package index (force latest xim-pkgindex)
run: |
# mcpp seeds a baseline index with a freshness TTL marker, so a plain
# `index update` can no-op within the window. Force the latest index
# so this run validates the native build against current packages.
mcpp index update || true
idx="$HOME/.mcpp/registry/data/xim-pkgindex"
rm -rf "$idx"
# A bare `git clone` here fails the whole job on a runner DNS
# hiccup. The policy lives in .github/tools/git_clone_retry.sh —
# but this job checks the repository out LAST ON PURPOSE (a
# `.xlings.json` in the workspace re-points where `xlings install`
# writes, so an early checkout silently changes what the
# fresh-install steps above are testing). The helper therefore does
# not exist on disk yet, and the retry is spelled inline. Same
# policy: retry every failure, bounded, git's own message survives.
clone_retry() {
local rc dest="${@: -1}"
for i in 1 2 3 4; do
rc=0; git clone "$@" || rc=$?
[ "$rc" = 0 ] && return 0
[ "$i" = 4 ] && return "$rc"
[ -e "$dest" ] && rm -rf -- "$dest"
echo "clone_retry: attempt $i failed (exit $rc); retrying" >&2
sleep $((i * 5))
done
}
clone_retry --depth 1 https://github.com/openxlings/xim-pkgindex "$idx"
grep -n "skipping relocation\|os.isfile(path.join(bindir" "$idx/pkgs/m/musl-gcc.lua" | head -2 || true
- name: Native build + run an `import std` program
run: |
work=$(mktemp -d); cd "$work"
mcpp new hello
cd hello
# default src uses import std (C++23)
mcpp build
out=$(mcpp run 2>/dev/null || true)
echo "program output: $out"
bin=$(find target -type f -path '*/bin/hello' | head -1)
file "$bin"
file "$bin" | grep -q "ARM aarch64" || { echo "expected aarch64 ELF"; exit 1; }
- name: Self-host — build mcpp + xlings from source natively
run: |
# mcpp/xlings manifests pin a glibc default toolchain; on aarch64 the
# musl-static target is the published path, so build with --target.
#
# On a pull_request, self-host the code UNDER REVIEW rather than
# upstream main. Cloning main meant this gate never saw the PR at
# all: a change that breaks the from-source build passed here and
# only failed after merge, and — the way this surfaced — a fix to
# the repo's own bootstrap pin was untestable, because the fix was
# on the branch while the clone was of main. Outside a PR there is
# no head ref and main is exactly right.
ref='${{ github.event.pull_request.head.sha }}'
repo='${{ github.event.pull_request.head.repo.clone_url }}'
[ -n "$ref" ] || ref='${{ github.sha }}'
[ -n "$repo" ] || repo='https://github.com/mcpp-community/mcpp'
# fetch-by-sha rather than `clone --depth 1`, which cannot take one.
git init -q /tmp/mcpp-src
cd /tmp/mcpp-src
git remote add origin "$repo"
git fetch -q --depth 1 origin "$ref"
git checkout -q FETCH_HEAD
echo "self-hosting $repo @ $ref"
# The clone's .xlings.json declares `workspace.mcpp` — the BOOTSTRAP
# pin, hand-maintained and deliberately lagging the newest release.
# It is scoped to the working directory and beats anything installed,
# so every `mcpp` below resolved the bootstrap version, which the
# fresh-install steps above never installed:
#
# [error] xlings: version '2026.8.6.2' not found for 'mcpp'
# [error] available: 2026.8.8.2
#
# "newest release != bootstrap pin" is the NORMAL state, so this step
# failed on every run from the moment the two diverged — and it is
# weekly, so nothing pointed at it. This step tests the freshly
# installed RELEASED binary against a source tree; the bootstrap pin
# has no standing in that question. install_released_mcpp.sh removes
# it for exactly this reason on the x86_64 legs (its point 1); this
# leg was written separately and never got it.
rm -f .xlings.json
mcpp self config --mirror GLOBAL 2>/dev/null || true
# Two compiles at a time: the runner (4 vCPU, 16 GB) received a
# shutdown signal twice at 656/689, with four of the engine's largest
# module units compiling at once with debug information
# (2026-10-28). The build is the same; only its width is not.
MCPP_JOBS=2 mcpp build --target aarch64-linux-musl
# Absolute: it is used again after `cd /tmp/xlings-src` below.
m=$(find "$PWD/target/aarch64-linux-musl" -type f -path '*/bin/mcpp' | head -1)
file "$m" | grep -q "ARM aarch64" || { echo "expected aarch64 mcpp"; exit 1; }
"$m" --version
# MCPP_HOME must be carried over explicitly: mcpp derives it from the
# BINARY's location, so a binary sitting in /tmp/mcpp-src/target would
# otherwise adopt an empty home and re-bootstrap the whole ecosystem
# instead of reusing what the fresh-install steps above provisioned.
#
# Resolved HERE, before the cd below, and that placement is load-
# bearing: `mcpp` is the shim, so it obeys whatever workspace pin the
# CURRENT DIRECTORY carries — and the xlings checkout declares one too
# (`workspace.mcpp = 2026.8.6.1`, its own bootstrap). Run from there,
# this resolves a version nothing installed, MCPP_HOME comes back
# empty, and the step dies on the guard below instead of on the real
# cause. /tmp/mcpp-src has had its pin removed above, so ask from here.
export MCPP_HOME=$(mcpp self env | awk -F'= *' '/^MCPP_HOME/{print $2; exit}')
echo "reusing MCPP_HOME=$MCPP_HOME"
test -d "$MCPP_HOME" || { echo "could not determine MCPP_HOME"; exit 1; }
# Same inline retry as the index clone above, and for the same
# reason — the checkout that would provide the shared helper is
# deliberately the last step in this job.
clone_retry() {
local rc dest="${@: -1}"
for i in 1 2 3 4; do
rc=0; git clone "$@" || rc=$?
[ "$rc" = 0 ] && return 0
[ "$i" = 4 ] && return "$rc"
[ -e "$dest" ] && rm -rf -- "$dest"
echo "clone_retry: attempt $i failed (exit $rc); retrying" >&2
sleep $((i * 5))
done
}
clone_retry --depth 1 https://github.com/openxlings/xlings /tmp/xlings-src
cd /tmp/xlings-src
# "$m", not `mcpp`: the just-built binary is the code under review,
# and building xlings with the INSTALLED one meant this half of the
# gate never saw the PR — the same defect the clone-ref comment above
# records, one line further down. It surfaced the same way: a fix for
# an aarch64-only failure in exactly this build could not be
# validated here, because the binary running it predated the fix.
"$m" build --target aarch64-linux-musl
x=$(find target/aarch64-linux-musl -type f -path '*/bin/xlings' | head -1)
file "$x" | grep -q "ARM aarch64" || { echo "expected aarch64 xlings"; exit 1; }
"$x" --version
# ── PR regression gate ────────────────────────────────────────────────
# Everything above is the fresh-install charter: it must run exactly as a
# new user's machine does. Check out only NOW — this repo's .xlings.json
# declares an `mcpp` WORKSPACE pin, so with the checkout present in
# $GITHUB_WORKSPACE `xlings install mcpp` installs workspace-scoped
# instead of globally: the steps above would silently validate the pinned
# version rather than the freshly published one, and bare `mcpp` stops
# resolving anywhere outside the workspace.
- uses: actions/checkout@v4
with:
persist-credentials: false
# The PR's own source, then the musl host-helper regression against it.
# This is the only runner where a musl toolchain is the NATIVE one, so it
# is the only place #295 can actually be reproduced.
- name: Build current mcpp source for native regression tests
run: |
# Third site of the same pin, and the reason to remove it here too:
# this job installs `xlings install mcpp` (bare = latest) and NOTHING
# else, so the bootstrap version the checkout pins is never on this
# runner. Obeying the pin here does not select an older builder — it
# selects one that does not exist. Same removal as the self-host step
# above, same reason as install_released_mcpp.sh point 1.
rm -f .xlings.json
# Two compiles at a time, for the reason of the self-host step above.
MCPP_JOBS=2 mcpp build --target aarch64-linux-musl
self=$(find target/aarch64-linux-musl -type f -path '*/bin/mcpp' | head -1)
test -x "$self"
self=$(realpath "$self")
"$self" --version
echo "MCPP_SELF=$self" >> "$GITHUB_ENV"
- name: "Regression: build.mcpp host helper is self-contained (#295)"
run: MCPP="$MCPP_SELF" bash tests/e2e/168_build_mcpp_musl_host_static.sh
candidate-admission:
name: candidate index + current mcpp native admission
if: github.event_name == 'workflow_dispatch' && inputs.xim_pkgindex_ref != ''
runs-on: ubuntu-24.04-arm
timeout-minutes: 90
defaults:
run:
shell: bash
env:
XLINGS_NON_INTERACTIVE: '1'
MCPP_E2E_MIRROR: GLOBAL
MCPP_NATIVE_XIM_INDEX: ${{ github.workspace }}/_candidate-xim
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v4
with:
repository: openxlings/xim-pkgindex
ref: ${{ inputs.xim_pkgindex_ref }}
path: _candidate-xim
- name: Candidate admission contracts
run: |
echo "MCPP_NATIVE_REPORT_DIR=$RUNNER_TEMP/native-llvm-arm64" >> "$GITHUB_ENV"
python3 tests/scripts/test_native_candidate_admission.py
- name: Verify and download this head's successful native mcpp build
env:
GH_TOKEN: ${{ github.token }}
MCPP_SOURCE_RUN: ${{ inputs.mcpp_run_id }}
run: python3 .github/tools/download_native_admission_mcpp.py "$MCPP_SOURCE_RUN" "$RUNNER_TEMP/mcpp-built"
- uses: ./.github/actions/bootstrap-mcpp
- name: Seed the candidate index before installing the native runtime
run: |
set -euo pipefail
mkdir -p "$MCPP_NATIVE_REPORT_DIR"
git -C "$MCPP_NATIVE_XIM_INDEX" rev-parse HEAD | tee "$MCPP_NATIVE_REPORT_DIR/xim-commit.txt"
printf '%s\n' "$GITHUB_SHA" > "$MCPP_NATIVE_REPORT_DIR/mcpp-commit.txt"
python3 .github/tools/seed_native_xim_index.py "$HOME/.mcpp" "$MCPP_NATIVE_XIM_INDEX"
echo "MCPP_HOME=$HOME/.mcpp" >> "$GITHUB_ENV"
"$XLINGS_BIN" --version
- name: Use this head's mcpp against the candidate runtime
run: bash .github/actions/use-built-mcpp/use.sh linux-aarch64 GLOBAL
- name: Install, build, run and pack the native GNU default with candidate recipes
env:
MCPP: ${{ env.MCPP_FRESH }}
run: |
set -euo pipefail
bash .github/tools/check_aarch64_llvm_payload.sh 2>&1 | tee "$RUNNER_TEMP/native-llvm-arm64/admission.log"
grep -qF 'PASS: native ARM64 LLVM installs, builds and runs' "$RUNNER_TEMP/native-llvm-arm64/admission.log"
- name: GNU self-host with LLVM 23.1.3 on native ARM64
run: |
set -euo pipefail
python3 .github/tools/seed_native_xim_index.py --verify "$MCPP_HOME" "$MCPP_NATIVE_XIM_INDEX"
marker="$MCPP_NATIVE_REPORT_DIR/gnu-build-start"
touch "$marker"
"$MCPP_FRESH" build --toolchain [email protected] --target aarch64-linux-gnu 2>&1 | tee "$MCPP_NATIVE_REPORT_DIR/gnu-selfhost.log"
mapfile -t binaries < <(find "$GITHUB_WORKSPACE/target/aarch64-linux-gnu" -type f -path '*/bin/mcpp' -newer "$marker")
[ "${#binaries[@]}" = 1 ] || { echo "expected one newly built GNU mcpp, found ${#binaries[@]}"; exit 1; }
gnu=$(realpath "${binaries[0]}")
readelf -hW "$gnu" | tee "$MCPP_NATIVE_REPORT_DIR/gnu-mcpp-header.txt"
grep -q 'Machine:.*AArch64' "$MCPP_NATIVE_REPORT_DIR/gnu-mcpp-header.txt"
readelf -lW "$gnu" | tee "$MCPP_NATIVE_REPORT_DIR/gnu-mcpp-program-headers.txt"
python3 - "$MCPP_HOME" "$MCPP_NATIVE_REPORT_DIR/gnu-mcpp-program-headers.txt" <<'PY'
import pathlib, re, sys
home = pathlib.Path(sys.argv[1]).resolve()
text = pathlib.Path(sys.argv[2]).read_text()
match = re.search(r'Requesting program interpreter: ([^\]]+)', text)
assert match, text
loader = pathlib.Path(match.group(1)).resolve()
loader.relative_to(home / 'registry/data/xpkgs/xim-x-glibc')
assert loader.name == 'ld-linux-aarch64.so.1', loader
PY
"$gnu" --version | tee "$MCPP_NATIVE_REPORT_DIR/gnu-mcpp-version.txt"
printf '%s\n' "$gnu" > "$MCPP_NATIVE_REPORT_DIR/gnu-mcpp-binary.txt"
echo "MCPP_NATIVE_GNU=$gnu" >> "$GITHUB_ENV"
- name: The GNU self-host runs the complete native unit and integration suite
run: |
set -euo pipefail
"$MCPP_NATIVE_GNU" test --toolchain [email protected] --target aarch64-linux-gnu 2>&1 | tee "$MCPP_NATIVE_REPORT_DIR/gnu-tests.log"
- name: Preserve native ELF and link evidence when the suite fails
if: failure()
run: |
set -euo pipefail
evidence="$MCPP_NATIVE_REPORT_DIR/native-link-evidence"
mkdir -p "$evidence"
while IFS= read -r -d '' binary; do
relative="${binary#target/}"
mkdir -p "$evidence/$(dirname "$relative")"
cp "$binary" "$evidence/$relative"
readelf -aW "$binary" > "$evidence/$relative.readelf.txt"
done < <(find target/aarch64-linux-gnu -type f -path '*/bin/unit' -print0)
while IFS= read -r -d '' plan; do
relative="${plan#target/}"
mkdir -p "$evidence/$(dirname "$relative")"
cp "$plan" "$evidence/$relative"
done < <(find target/aarch64-linux-gnu -type f -name build.ninja -print0)
- name: GNU mcpp builds the LLVM path host helper (804 LLVM case only)
env:
MCPP: ${{ env.MCPP_NATIVE_GNU }}
MCPP_E2E_804_LLVM_HOST_ONLY: '1'
run: |
set -euo pipefail
bash tests/e2e/804_a_path_host_tool_builds_with_its_chosen_toolchain.sh 2>&1 | tee "$MCPP_NATIVE_REPORT_DIR/gnu-llvm-host-helper.log"
grep -qF 'PASS: 804 native LLVM path host helper (LLVM case only)' "$MCPP_NATIVE_REPORT_DIR/gnu-llvm-host-helper.log"
- uses: actions/checkout@v4
with:
repository: mcpp-community/mcpp-index
ref: main
path: _native-mcpp-index
- name: Four real index members consume the native LLVM GNU ecosystem
run: |
set -euo pipefail
git -C _native-mcpp-index rev-parse HEAD | tee "$MCPP_NATIVE_REPORT_DIR/mcpp-index-commit.txt"
python3 .github/tools/seed_native_xim_index.py --verify "$MCPP_HOME" "$MCPP_NATIVE_XIM_INDEX"
adapter="$RUNNER_TEMP/mcpp-llvm-gnu-consumer"
cat > "$adapter" <<'SH'
#!/usr/bin/env bash
set -euo pipefail
case "${1:-}" in
build|test|run) set -- "$@" --toolchain [email protected] --target aarch64-linux-gnu ;;
esac
{ printf 'GNU consumer argv:'; printf ' %q' "$@"; printf '\n'; } >> "$MCPP_NATIVE_REPORT_DIR/index-consumer-argv.log"
exec "$MCPP_NATIVE_GNU" "$@"
SH
chmod +x "$adapter"
cd _native-mcpp-index
MCPP="$adapter" MCPP_VERBOSE=1 MCPP_TIMINGS="$MCPP_NATIVE_REPORT_DIR/index-members.tsv" \
bash tests/run_members.sh cjson sqlite3 fmtlib.fmt nlohmann.json 2>&1 | tee "$MCPP_NATIVE_REPORT_DIR/index-members.log"
python3 - "$MCPP_NATIVE_REPORT_DIR/index-members.tsv" <<'PY'
import pathlib, sys
rows = [line.split('\t') for line in pathlib.Path(sys.argv[1]).read_text().splitlines()]
assert len(rows) == 4, rows
assert {row[1] for row in rows} == {'cjson', 'sqlite3', 'fmtlib.fmt', 'nlohmann.json'}, rows
assert all(row[2] == 'ok' for row in rows), rows
PY
- name: The real openkal stack runs as native ARM64 without skipping
env:
MCPP: ${{ env.MCPP_NATIVE_GNU }}
MCPP_E2E_EXPECT_ARCH: aarch64
run: |
set -euo pipefail
export MCPP_OPENKAL_INDEX="$GITHUB_WORKSPACE/_native-mcpp-index"
bash tests/e2e/286_the_openkal_stack_still_builds.sh 2>&1 | tee "$RUNNER_TEMP/native-llvm-arm64/openkal.log"
! grep -q '^SKIP:' "$RUNNER_TEMP/native-llvm-arm64/openkal.log"
grep -qF 'OK: the openkal stack builds, links statically and runs' "$RUNNER_TEMP/native-llvm-arm64/openkal.log"
grep -qxF 'openkal hosted threads: isolation, destructors and concurrent unwind ok' "$RUNNER_TEMP/native-llvm-arm64/openkal.log"
grep -qxF 'openkal indexed JSON: dump, parse, literals and ordered_json ok' "$RUNNER_TEMP/native-llvm-arm64/openkal.log"
- uses: actions/upload-artifact@v4
if: always()
with:
name: candidate-native-ecosystem-admission
path: ${{ runner.temp }}/native-llvm-arm64
if-no-files-found: warn
You are visitor 01402520 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.