You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 8de3847
Browse filesBrowse the repository at this point in the historyBrowse files
runner beyond bare metal: honour [target.<triple>].runner on hosted targets, typed launch failures, not-run reporting, [xlings] values per host (#544) (#545)
* platform: carry the spawn errno up instead of re-spawning; run_exec is never silent (#544)
* manifest: [xlings] values per host platform; the target sweep reports array typos and lists runner (#544)
* build: runner lookup through declared payloads then PATH, with typed messages (#544)
* run/test: honour the declared runner on every target; --no-runner; not-run reporting with exit 2; e2e 330 (#544)
* docs: runner on hosted targets, not-run reporting, [xlings] values per host platform (#544)
* release: 2026.9.2.1
* tests: the ENOEXEC unit test is Linux-only — macOS posix_spawnp runs an unloadable file through /bin/sh (measured on CI)
* run/test: look the runner up by the canonical triple — the driver's spelling matched on Linux and never on macOS (measured on CI)
* run/test: diagnostics name the canonical triple, which is the key the reader wrote
`choose_runner` resolves `[target.<triple>].runner` against the canonical
spelling — the output directory's name, and the key every other
`[target.<triple>]` reader uses. The four diagnostics it feeds printed
`tc.targetTriple`, the spelling the driver reported, which on a Linux host is
the same string and on macOS is `arm64-apple-darwin24.6.0`.
Two consequences, both user-facing. The not-found message named a triple the
author never wrote. The unrunnable message printed a `[target.…]` block to
paste whose key no lookup would ever match, so following the advice would have
left the artifact running bare a second time.
`RunnerChoice` now carries `tripleKey`, derived once beside the lookup that
uses it, so the two cannot disagree. The triple is parsed once rather than
three times.
Measured: e2e 330 §3 asserts the message names the triple the manifest key
uses and failed only on macOS ARM64 (run 33609434208).
* run/test: the two notes and the freestanding error name the key as well
Six message sites remained on `tc.targetTriple` after the previous commit, and
three of them print a `[target.<triple>]` key the reader is meant to act on:
the override note, its `mcpp test` twin, and `no_runner_message`, which shows a
complete key-and-value block to paste. On macOS each named
`arm64-apple-darwin24.6.0`, a spelling no `[target.…]` lookup resolves, so
following the advice would have produced a key that is never read.
The remaining two, the `--no-runner` notes, name the target a runner was
declared for, and the declaration is under the canonical key.
Every diagnostic on both paths now reads `RunnerChoice::tripleKey`. On Linux
the two spellings coincide, which is why e2e 130, 131 and 132 pass unchanged.
* CHANGELOG: 2026.9.2.1
* design: state where the payload-bin rule is actually covered
---------
Co-authored-by: speak-agent <248744407+speak-agent@users.noreply.github.com>
|**exact triple**| one specific target (also carries `toolchain` / `linkage`) |`[target.x86_64-linux-musl]`|
1089
+
|**exact triple**| one specific target (also carries `toolchain` / `linkage` / `sysroot` / `runner`; see §2.7.3) |`[target.x86_64-linux-musl]`|
1090
1090
1091
1091
A selector may carry platform-conditional **dependencies** and **build flags**:
1092
1092
@@ -1284,6 +1284,75 @@ different argv (`-bios default` for an OpenSBI boot, `-bios none -semihosting`
1284
1284
for a picolibc image) — and an engine that guesses one is an engine the other
1285
1285
board has to fight. A board-support package normally supplies it.
1286
1286
1287
+
### 2.7.3 `runner` on a hosted target (2026.9.2.1+)
1288
+
1289
+
`[target.<triple>].runner` applies to every exact triple, not only to bare
1290
+
metal. A hosted cross artifact — `aarch64-linux-musl` built on an x86_64
1291
+
machine — is executable by some hosts (binfmt_misc with qemu-user registered)
1292
+
and refused by others with `Exec format error`, and which of the two applies is
1293
+
a property of the machine, not of the triple. mcpp does not predict it. It
1294
+
either executes the artifact through the runner the project declared, or it
1295
+
attempts direct execution and reports what the kernel answered.
1296
+
1297
+
```toml
1298
+
[target.aarch64-linux-musl]
1299
+
runner = ["qemu-aarch64-static"]
1300
+
```
1301
+
1302
+
The rules, for `mcpp run` and `mcpp test` alike:
1303
+
1304
+
-**A declared runner is used.** Its first element is located by mcpp: first in
1305
+
the `bin/` directory of each payload declared under `[xlings] deps` (§2.13),
1306
+
then on `PATH`. A bare name on `PATH` resolves to an xvm shim, which answers
1307
+
for the current SubOS rather than for the package; the payload lookup is what
1308
+
lets a runner name a program the project declared.
1309
+
-**A declared runner that cannot be found or started is an error**, with the
1310
+
program, the directories searched and the errno. There is no fallback to
1311
+
direct execution: running the artifact under a different interpreter with
1312
+
different arguments is the failure the key exists to prevent.
1313
+
-**No runner, and the kernel refuses the artifact:**`mcpp run` reports the
1314
+
refusal and the key to write, and exits 2. `mcpp test` reports every test as
1315
+
not run, with the reason once, and exits 2 (§2.7.3.1).
1316
+
-**`--no-runner`** executes the artifact directly and ignores a declared
1317
+
runner. It states a fact about this host — the triple is native here — that
1318
+
the manifest has no axis to carry; a project whose runner was written for
1319
+
x86_64 developers is still readable on an aarch64 machine.
1320
+
1321
+
Provisioning the emulator through `[xlings] deps` is the form for a CI job or
1322
+
a project built on one host class. `qemu-user-aarch64` in the index is built
1323
+
for x86_64 Linux only, and `[xlings] deps` provisions on every host that builds
1324
+
the project, so the entry is written per platform (§2.13):
1325
+
1326
+
```toml
1327
+
[xlings]
1328
+
deps = [{ linux = "qemu-user-aarch64" }]
1329
+
1330
+
[target.aarch64-linux-musl]
1331
+
runner = ["qemu-aarch64-static"]
1332
+
```
1333
+
1334
+
A package the host cannot install is a hard build error, so an entry without
1335
+
the platform form would make the project unbuildable on macOS and Windows. The
1336
+
Linux/aarch64 host, where the package does not exist either, passes
1337
+
`--no-runner`.
1338
+
1339
+
#### 2.7.3.1 `mcpp test` and tests that were not run
1340
+
1341
+
A test whose artifact this host cannot execute has neither passed nor failed.
1342
+
`mcpp test` reports it as **not run**, prints the reason once when it is
1343
+
established, repeats the first line of the reason in the summary, and exits 2:
1344
+
1345
+
```
1346
+
warning: this host cannot execute aarch64-linux-musl artifacts: Exec format error (error 8); declare [target.aarch64-linux-musl].runner, or pass --no-runner on a host that can
1347
+
smoke ... not run
1348
+
error: test result: NOT RUN. 0 passed; 0 failed; 1 not run (this host cannot execute aarch64-linux-musl artifacts: Exec format error (error 8); ...); finished in 0.41s (build 0.39s + run 0.00s)
1349
+
```
1350
+
1351
+
Exit code 1 keeps its meaning — a test ran and failed — and 0 means every test
1352
+
ran and passed. `--message-format json` carries `"status":"not_run"` and a
1353
+
`reason` on each record, and `not_run` / `not_run_reason` on the summary
1354
+
record (see [11 — Machine-Readable Output](11-machine-output.md)).
1355
+
1287
1356
### 2.8 `[features]` — Features (Cargo-style, additive)
1288
1357
1289
1358
```toml
@@ -1820,6 +1889,27 @@ build needs (`make`/`cmake`/`protoc`/…), pin tool versions per project, or set
1820
1889
build-time env vars — without hand-editing `.xlings.json`. `[toolchain]` (§2.7) remains
1821
1890
the ergonomic shorthand for the compiler; `[xlings.workspace]` is the general form.
1822
1891
1892
+
**Values per host platform (2026.9.2.1+).** A `deps` entry and a
1893
+
`[xlings.workspace]` value may be a table keyed by platform, the form xlings'
1894
+
own `.xlings.json` accepts for `workspace`:
1895
+
1896
+
```toml
1897
+
[xlings]
1898
+
deps = ["xim:ninja", { linux = "qemu-user-aarch64" }, { windows = "nasm", default = "yasm" }]
1899
+
1900
+
[xlings.workspace]
1901
+
gcc = { linux = "15.1.0" }
1902
+
llvm = { macos = "20", default = "22" }
1903
+
```
1904
+
1905
+
The keys are `linux`, `macos`, `windows` and `default`; `macosx` is accepted as
1906
+
xlings' spelling of `macos`. mcpp resolves the table against the host it runs
1907
+
on when the manifest is loaded: the host's key wins, `default` is the fallback,
1908
+
and a table with neither declares nothing on that host — the entry is absent,
1909
+
not empty. An unknown key is an error rather than a dropped entry. The axis is
1910
+
the host operating system only; a package that exists for the OS but not for
1911
+
the architecture is still a provisioning error on that host.
1912
+
1823
1913
`subos` selects the root project's **local build/run OS environment**. If the
1824
1914
key is absent, mcpp uses its initialized, release-verified `McppDefault` SubOS;
1825
1915
`subos = "default"` is an explicit `NamedSubos("default")` selection. There is
0 commit comments