Repository navigation
355 lines (328 loc) · 15.4 KB
/
Copy pathtests.yml
File metadata and controls
355 lines (328 loc) · 15.4 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
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
# Boost 1.92.0 as C++23 named modules (mcpplibs.mwrap.boost) — build/test matrix.
#
# Ported from the pre-mwrap wrapper's CI (boost-module b1.92.0wdev tests.yml).
# The five host configurations and their pinned toolchains are the ones that
# wrapper validated; keep the set if a leg is added or dropped:
#
# windows-latest x86_64 llvm@22.1.8 (clang-cl / clang-msvc)
# ubuntu-24.04 x86_64 gcc@16.1.0
# ubuntu-24.04-arm arm64 gcc@16.1.0
# ubuntu-24.04 x86_64 llvm@22.1.8
# macos-latest arm64 llvm@22.1.8
#
# Every host is built twice, once per feature group, because a single clang
# aggregate closure of the whole package can exhaust the source-location space:
#
# A — the 105 library features of the original group A: 103 module-bearing
# libraries plus the two compiled include-only features (`log`,
# `unit-test-framework`);
# B — the twelve heavy libraries (asio, beast, geometry, ...) plus the two
# wrapper-only modules the mwrap migration added (`version`, `macros`),
# so group A's aggregate closure stays at the module count whose limit was
# validated.
#
# `mcpp build` compiles only the sources of the active features; `mcpp test`
# compiles the base `[build].sources` union, so each leg runs every test program
# and both groups together still re-export every library through the umbrella
# module exactly once. `tools/gen_features.py` regenerates `mcpp.toml`; the
# "Validate feature-group coverage" step refuses a run whose two groups do not
# partition every library feature, so a new library cannot silently go untested.
#
# The examples, the template smoke test and the release-page check run in the
# `examples` job, which `needs: [test]`: they start only after both groups have
# passed on all five hosts.
#
# mcpp comes from the repository's own pin: xlings installs `mcpp 2026.10.26.1`
# from `.xlings.json`, and the job asserts that CI's MCPP_VERSION and the
# manifest pin are the same build. Toolchains are then installed by mcpp into its
# sandbox (`~/.mcpp`), which actions/cache keeps warm per host and toolchain.
name: Build and Tests
on:
push:
branches: [main]
paths:
- ".github/workflows/tests.yml"
- "examples/**"
- "generated/**"
- "port/**"
- "src/**"
- "templates/**"
- "tests/**"
- "tools/**"
- "upstream/boost/**"
- ".xlings.json"
- "build.mcpp"
- "mcpp.toml"
pull_request:
branches: [main]
paths:
- ".github/workflows/tests.yml"
- "examples/**"
- "generated/**"
- "port/**"
- "src/**"
- "templates/**"
- "tests/**"
- "tools/**"
- "upstream/boost"
- ".xlings.json"
- "build.mcpp"
- "mcpp.toml"
permissions:
contents: read
concurrency:
group: ci-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
# Latest xlings release; the installer reads this for both the sh and ps1
# quick-install scripts, and xlings then installs the mcpp pin below.
XLINGS_VERSION: v2026.10.26.1
XLINGS_NON_INTERACTIVE: '1'
# Must match [workspace].mcpp in .xlings.json — checked on every leg.
MCPP_VERSION: "2026.10.26.1"
# Leave the runners room: the vendored tree is large and every leg compiles
# Boost from the same checkout.
MCPP_JOBS: '4'
# M12 grouping: group A is the original wrapper's 105-feature set; group B is
# its twelve heavy libraries plus the two wrapper-only modules added by the
# mwrap migration. Both are kebab-case features declared in mcpp.toml.
BOOST_GROUP_A: "optional,variant,variant2,any,core,container-hash,mp11,static-string,scope,type-traits,algorithm,iterator,range,io,rational,endian,tuple,system,filesystem,regex,thread,chrono,program-options,stacktrace,json,url,align,array,assert,assign,bimap,bind,bloom,callable-traits,circular-buffer,compat,concept-check,config,convert,crc,decimal,dll,dynamic-bitset,flyweight,format,function,functional,hash2,heap,histogram,hof,icl,integer,intrusive,lambda,lambda2,leaf,lexical-cast,lockfree,logic,move,multi-array,multi-index,outcome,parser,pfr,poly-collection,pool,property-map,property-tree,ptr-container,ratio,safe-numerics,signals2,smart-ptr,sort,statechart,stl-interfaces,throw-exception,tokenizer,type-index,units,unordered,utility,uuid,winapi,yap,atomic,charconv,cobalt,container,contract,date-time,graph,iostreams,log,math,nowide,process,random,serialization,unit-test-framework,timer,type-erasure,wave"
BOOST_GROUP_B: "accumulators,asio,beast,geometry,gil,hana,interprocess,mqtt5,multiprecision,numeric,polygon,qvm,version,macros"
jobs:
# One matrix entry per host; `group` doubles each host into the two aggregate
# closures. Tests run in both groups, so the compile surface is identical and
# only the umbrella's re-export set differs.
test:
name: ${{ matrix.target.name }}-${{ matrix.target.arch }} (group ${{ matrix.group }})
runs-on: ${{ matrix.target.os }}
timeout-minutes: 240
strategy:
fail-fast: false
matrix:
target:
- { name: windows-llvm-msvc, os: windows-latest, arch: x86_64, toolchain: "llvm@22.1.8", install: "llvm 22.1.8" }
- { name: linux-gcc, os: ubuntu-24.04, arch: x86_64, toolchain: "gcc@16.1.0", install: "gcc 16.1.0" }
- { name: linux-gcc, os: ubuntu-24.04-arm, arch: arm64, toolchain: "gcc@16.1.0", install: "gcc 16.1.0" }
- { name: linux-llvm, os: ubuntu-24.04, arch: x86_64, toolchain: "llvm@22.1.8", install: "llvm 22.1.8" }
- { name: macos-llvm, os: macos-latest, arch: arm64, toolchain: "llvm@22.1.8", install: "llvm 22.1.8" }
group: [A, B]
steps:
- uses: actions/checkout@v7
# Warm the mcpp sandbox (engine, registry, toolchain payloads and the
# global BMI cache). Keyed per toolchain so the gcc and llvm legs on one
# OS cannot restore each other's default (config.toml); A and B share the
# key and only race on the initial save.
- name: Cache mcpp sandbox
uses: actions/cache@v6
with:
path: ~/.mcpp
key: mcpp-${{ matrix.target.os }}-${{ matrix.target.name }}-${{ matrix.target.arch }}-${{ matrix.target.toolchain }}-v${{ env.MCPP_VERSION }}
restore-keys: |
mcpp-${{ matrix.target.os }}-${{ matrix.target.name }}-${{ matrix.target.arch }}-${{ matrix.target.toolchain }}-
- name: Install xlings
if: runner.os != 'Windows'
shell: bash
run: |
set -euo pipefail
curl -fsSL --retry 3 --retry-all-errors \
https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.sh \
| bash -s "$XLINGS_VERSION"
echo "$HOME/.xlings/subos/current/bin" >> "$GITHUB_PATH"
# The installer's parameter defaults to $env:XLINGS_VERSION, which is set
# by the job environment; `iex` therefore installs the pinned release.
- name: Install xlings
if: runner.os == 'Windows'
shell: pwsh
run: |
irm https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.ps1 | iex
"$env:USERPROFILE\.xlings\subos\current\bin" |
Out-File -Append -FilePath $env:GITHUB_PATH -Encoding utf8
- name: Install project tools (.xlings.json → mcpp)
shell: bash
run: |
set -euo pipefail
xlings update
xlings install -y
mcpp --version
# The CI pin and the repository pin must name the same tool build.
grep -Fq "\"mcpp\": \"$MCPP_VERSION\"" .xlings.json
mcpp --version | grep -Fq "$MCPP_VERSION"
- name: Install toolchain (${{ matrix.target.toolchain }})
shell: bash
run: |
set -euo pipefail
mcpp toolchain install ${{ matrix.target.install }}
mcpp toolchain default ${{ matrix.target.toolchain }}
mcpp toolchain list
# Guard the grouping invariant: every library feature in mcpp.toml is in
# exactly one group, and the backend profiles (not libraries) are in
# neither. A new library regenerated into the manifest fails here until it
# is assigned to a group.
- name: Validate feature-group coverage
shell: bash
run: |
set -euo pipefail
PY="$(command -v python3 || command -v python)"
"$PY" - <<'PY'
import os
import tomllib
manifest = tomllib.load(open("mcpp.toml", "rb"))
features = manifest["features"]
# Aggregates and the CPU-gated log backend profiles are not libraries:
# `default`/`all-modules` are selections, and the profiles are only
# valid on x86_64 and are exercised by examples/profiles.
aggregates = {"default", "all-modules"}
profiles = {name for name in features if name.startswith("backend-")}
libraries = set(features) - aggregates - profiles
group_a = set(os.environ["BOOST_GROUP_A"].split(","))
group_b = set(os.environ["BOOST_GROUP_B"].split(","))
if group_a & group_b:
raise SystemExit("group A and B overlap: " + ", ".join(sorted(group_a & group_b)))
missing = libraries - group_a - group_b
unknown = (group_a | group_b) - set(features)
if missing or unknown:
raise SystemExit(
"feature groups are stale; missing: {}; unknown: {}".format(
", ".join(sorted(missing)) or "-",
", ".join(sorted(unknown)) or "-"))
print("feature groups cover {} libraries (A: {}, B: {})".format(
len(libraries), len(group_a), len(group_b)))
PY
- name: Build libraries (group ${{ matrix.group }})
shell: bash
run: |
mcpp build --toolchain "${{ matrix.target.toolchain }}" \
--features "${{ (matrix.group == 'A' && env.BOOST_GROUP_A) || env.BOOST_GROUP_B }}"
- name: Test libraries (group ${{ matrix.group }})
shell: bash
run: |
mcpp test --toolchain "${{ matrix.target.toolchain }}" \
--features "${{ (matrix.group == 'A' && env.BOOST_GROUP_A) || env.BOOST_GROUP_B }}"
# Runs only after every A/B leg passed. The examples consume the wrapper the
# way a user does (umbrella import, explicit features, profile backend), then
# the template is rendered through a real `mcpp new` and built and run, and
# the release coordinate and bilingual entry pages are checked once.
examples:
name: ${{ matrix.name }}-${{ matrix.arch }} (examples + template)
needs: [test]
runs-on: ${{ matrix.os }}
timeout-minutes: 120
strategy:
fail-fast: false
matrix:
include:
- name: windows-llvm-msvc
os: windows-latest
arch: x86_64
toolchain: llvm@22.1.8
install: "llvm 22.1.8"
- name: linux-gcc
os: ubuntu-24.04
arch: x86_64
toolchain: gcc@16.1.0
install: "gcc 16.1.0"
- name: linux-gcc
os: ubuntu-24.04-arm
arch: arm64
toolchain: gcc@16.1.0
install: "gcc 16.1.0"
- name: linux-llvm
os: ubuntu-24.04
arch: x86_64
toolchain: llvm@22.1.8
install: "llvm 22.1.8"
- name: macos-llvm
os: macos-latest
arch: arm64
toolchain: llvm@22.1.8
install: "llvm 22.1.8"
steps:
- uses: actions/checkout@v7
- name: Cache mcpp sandbox
uses: actions/cache@v6
with:
path: ~/.mcpp
key: mcpp-${{ matrix.os }}-${{ matrix.name }}-${{ matrix.arch }}-${{ matrix.toolchain }}-v${{ env.MCPP_VERSION }}
restore-keys: |
mcpp-${{ matrix.os }}-${{ matrix.name }}-${{ matrix.arch }}-${{ matrix.toolchain }}-
- name: Install xlings
if: runner.os != 'Windows'
shell: bash
run: |
set -euo pipefail
curl -fsSL --retry 3 --retry-all-errors \
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
if: runner.os == 'Windows'
shell: pwsh
run: |
irm https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.ps1 | iex
"$env:USERPROFILE\.xlings\subos\current\bin" |
Out-File -Append -FilePath $env:GITHUB_PATH -Encoding utf8
- name: Install project tools (.xlings.json → mcpp)
shell: bash
run: |
set -euo pipefail
xlings update
xlings install -y
mcpp --version
grep -Fq "\"mcpp\": \"$MCPP_VERSION\"" .xlings.json
mcpp --version | grep -Fq "$MCPP_VERSION"
- name: Install toolchain (${{ matrix.toolchain }})
shell: bash
run: |
set -euo pipefail
mcpp toolchain install ${{ matrix.install }}
mcpp toolchain default ${{ matrix.toolchain }}
mcpp toolchain list
# examples/basic consumes the root package as a path dependency with the
# default feature closure (umbrella import plus compiled libraries).
- name: Build & run example (basic)
shell: bash
working-directory: examples
run: mcpp run -p basic --toolchain "${{ matrix.toolchain }}"
# examples/profiles selects backend-log-avx2, whose TUs carry -mavx2:
# x86_64 only, refused by build.mcpp on arm64.
- name: Build & run example (profiles, x86_64 only)
if: matrix.arch == 'x86_64'
shell: bash
working-directory: examples
run: mcpp run -p profiles --toolchain "${{ matrix.toolchain }}"
# examples/git-dep consumes the published `mwrap-<version>` tag, which
# exists only after the first release. Until then the step reports a skip
# instead of failing every run; once the tag is published it is exercised
# with no workflow change.
- name: Build & run example (git-dep, when the release tag exists)
shell: bash
working-directory: examples
run: |
set -euo pipefail
tag="$(sed -n 's/.*tag = "\([^"]*\)".*/\1/p' git-dep/mcpp.toml | head -n1)"
test -n "$tag"
set +e
git ls-remote --exit-code --tags \
https://github.com/mcpplibs/boost-m.git "refs/tags/$tag" >/dev/null 2>&1
status=$?
set -e
case "$status" in
0) mcpp run -p git-dep --toolchain "${{ matrix.toolchain }}" ;;
2) echo "::notice title=git-dep example skipped::tag $tag is not published yet" ;;
*) echo "::error::cannot resolve tag $tag (git ls-remote exit $status)"; exit "$status" ;;
esac
# A real `mcpp new` render, then build and run: the template is only
# evidence once mcpp itself produced the project and it compiled.
- name: Render, build and run the template
shell: bash
run: |
set -euo pipefail
PY="$(command -v python3 || command -v python)"
"$PY" tools/test_template.py --toolchain "${{ matrix.toolchain }}"
- name: Check release coordinate and bilingual entry pages
if: matrix.name == 'linux-gcc' && matrix.arch == 'x86_64'
shell: bash
run: |
set -euo pipefail
PY="$(command -v python3 || command -v python)"
"$PY" tools/check_mwrap_release.py