-
Notifications
You must be signed in to change notification settings - Fork 0
189 lines (178 loc) · 8.67 KB
/
Copy pathci.yml
File metadata and controls
189 lines (178 loc) · 8.67 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
name: CI
on:
push:
branches: [main]
pull_request:
workflow_dispatch:
jobs:
build:
name: boots under real OpenSBI
runs-on: ubuntu-24.04
timeout-minutes: 40
env:
MCPP_VERSION: 2026.8.20.2
XLINGS_VERSION: v2026.8.17.2
XLINGS_NON_INTERACTIVE: '1'
steps:
- uses: actions/checkout@v4
- name: Install xlings
run: |
curl -fsSL 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: |
# ⚠️ A LOOP, BECAUSE ONE `xlings update` CAN RETURN A STALE INDEX
# WITHOUT SAYING SO.
#
# The index is published as an artifact behind a pointer, and that
# pointer propagates asynchronously after a version bump is merged.
# Measured on release day: an update run four minutes after the merge
# printed `index updated`, and the install then failed with
#
# package 'mcpp@<ver>' not found in the synced index
# (xim@artifact:<an older sha>, ...), synced 0 seconds ago
#
# Nothing had gone wrong. The update fetched the PREVIOUS artifact,
# and "synced 0 seconds ago" describes when it was fetched rather than
# what it contains — which is why the message reads as freshness.
#
# So this is not a retry around flakiness; it is the wait that a
# single update does not perform. A pin naming a version that was
# never published still fails, after the last attempt, and says which
# of the two situations it is.
for attempt in 1 2 3 4 5 6; do
xlings update > /dev/null 2>&1 || true
if xlings install "mcpp@$MCPP_VERSION" -y -g; then break; fi
if [ "$attempt" = 6 ]; then
echo "::error::mcpp@$MCPP_VERSION never appeared in the index (6 attempts over 5 minutes). If it was just released, the pointer has not propagated; if the pin names a version that was never published, it never will."
exit 1
fi
echo "the index has not caught up yet (attempt $attempt of 6); waiting 60s"
sleep 60
done
mcpp --version
mcpp self config --mirror GLOBAL
- name: Install the emulator
run: |
# Both homes: the shim on PATH dispatches against whichever home owns
# it, while mcpp starts the runner through its own.
xlings install xim:qemu-riscv -y
XLINGS_HOME="$HOME/.mcpp/registry" xlings install xim:qemu-riscv -y
# ⚠️ The assertion is on the OUTPUT, not on the exit status. A firmware
# that never reaches the payload exits zero, and so does a payload whose
# console writes go nowhere — which is precisely the failure this backend
# exists to avoid on a second machine.
- name: The example prints under `-bios default`
run: |
set -euo pipefail
cd examples/hello
Q=$(ls -d "$HOME"/.mcpp/registry/data/xpkgs/xim-x-qemu-riscv/*/bin/qemu-system-riscv64 | head -1)
sed -i "s|\"qemu-system-riscv64\"|\"$Q\"|" mcpp.toml
mcpp run 2>&1 | tee run.log
grep -q "hello from openkal over SBI" run.log
grep -q "heap ok" run.log
# ⚠️ `clock ok` is the line that distinguishes a counter that reads
# from a counter that MOVES. The example takes two readings with a
# sleep between them; a stuck clock reads fine and prints
# `clock stuck`. Verified to print it, by returning a constant from
# `kal_time_monotonic` and rerunning.
grep -q "clock ok" run.log
grep -q "env empty" run.log
# ---------------------------------------------------------------------------
# The cross-compilation is performed FROM three systems, not only from Linux.
#
# Every target in this repository is a cross target, which makes the host a
# separate axis from the target: the compiler, the target C library and the
# emulator are payloads mcpp resolves for whichever system it is running on.
# A package that has only ever been built from Linux is a package whose
# consumers must use Linux, and nothing in these sources says so.
#
# ⚠️ A TOOLCHAIN AXIS IS ABSENT HERE, AND THAT IS MEASURED RATHER THAN
# ASSUMED. The row for a bare-metal triple names its compiler, and the
# command-line override does not displace it: `--toolchain gcc@16.1.0` on a
# `riscv64-none-elf` build resolves llvm@22.1.8 regardless. A matrix over
# compiler families would therefore run the same compiler on every row and
# report coverage it does not have. The toolchain axis belongs where the
# choice is real — openkal, whose declarations are compiled by three families
# on three systems.
#
# ⚠️ BUILD ONLY, AND DELIBERATELY. Behaviour is asserted once, above, under an
# emulator. Booting the same image from three systems would be a statement
# about the emulator rather than about this package, and "the image does what
# the README says" does not become more true for having been observed from
# macOS.
portability:
name: cross-builds from ${{ matrix.os }}
runs-on: ${{ matrix.os }}
timeout-minutes: 45
strategy:
fail-fast: false
matrix:
os: [macos-14, windows-2022]
defaults:
run:
shell: bash
env:
MCPP_VERSION: 2026.8.20.2
XLINGS_VERSION: v2026.8.17.2
XLINGS_NON_INTERACTIVE: '1'
steps:
- uses: actions/checkout@v4
- name: Install xlings (Unix)
if: runner.os != 'Windows'
run: |
curl -fsSL 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 xlings (Windows)
if: runner.os == 'Windows'
shell: pwsh
run: |
irm https://d2learn.org/xlings-install.ps1.txt | iex
# The installer amends the user's environment; no later step in this
# job reads it back, so the directory is named here.
"$env:USERPROFILE\.xlings\subos\current\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
- name: Install mcpp
run: |
# ⚠️ A LOOP, BECAUSE ONE `xlings update` CAN RETURN A STALE INDEX
# WITHOUT SAYING SO.
#
# The index is published as an artifact behind a pointer, and that
# pointer propagates asynchronously after a version bump is merged.
# Measured on release day: an update run four minutes after the merge
# printed `index updated`, and the install then failed with
#
# package 'mcpp@<ver>' not found in the synced index
# (xim@artifact:<an older sha>, ...), synced 0 seconds ago
#
# Nothing had gone wrong. The update fetched the PREVIOUS artifact,
# and "synced 0 seconds ago" describes when it was fetched rather than
# what it contains — which is why the message reads as freshness.
#
# So this is not a retry around flakiness; it is the wait that a
# single update does not perform. A pin naming a version that was
# never published still fails, after the last attempt, and says which
# of the two situations it is.
for attempt in 1 2 3 4 5 6; do
xlings update > /dev/null 2>&1 || true
if xlings install "mcpp@$MCPP_VERSION" -y -g; then break; fi
if [ "$attempt" = 6 ]; then
echo "::error::mcpp@$MCPP_VERSION never appeared in the index (6 attempts over 5 minutes). If it was just released, the pointer has not propagated; if the pin names a version that was never published, it never will."
exit 1
fi
echo "the index has not caught up yet (attempt $attempt of 6); waiting 60s"
sleep 60
done
mcpp --version
mcpp self config --mirror GLOBAL
- name: The backend cross-builds
run: |
# ⚠️ TWICE, AND THE FIRST IS ALLOWED TO FAIL — every row of this
# matrix is a machine that has never targeted this triple, which is
# precisely where mcpp's lazy install of the target C library shows.
# The first build compiles sources needing its headers before they
# exist; the second has them. A single build here reported a
# portability failure that was really a cold-machine one.
mcpp build --target riscv64-none-elf || true
mcpp build --target riscv64-none-elf