Skip to content

Commit 40907fd

Browse files
committed
A verified Web run that asked the host for node (2026.9.12.1)
The sandbox verification of the published 2026.9.11.4 held on 26 of 27 checks. The one that did not was the Web run: `mcpp build --target wasm32-emscripten` succeeded, and `mcpp run` stopped at /usr/bin/env: 'node': No such file or directory An Emscripten link produces a JavaScript launcher whose first line is `#!/usr/bin/env node`. With nothing declared, mcpp executes the artefact, so the interpreter came from the PATH mcpp inherited, while the node `xim:emsdk` declares, and writes into its own `.emscripten`, sat in the store. The development host has node on PATH, which is why no earlier measurement, including the dry run of the verification script, could see it. THE PAYLOAD NAMES THE PROGRAM THAT RUNS WHAT IT PRODUCES. `.mcpp-toolchain.json` gains a fourth key, `runner`: - one program, no arguments; the artefact path is appended, so the key cannot carry flags - relative to the payload under the rules `frontend` obeys, or absolute and honoured only inside the package store that holds the payload, compared on canonical paths; a runner outside the store is ignored, so a payload cannot choose a host interpreter - structurally malformed values are refused by name at read time; the path rules are now one helper shared by `frontend` and `runner`, with the `frontend` messages unchanged - last in precedence and in the run slot only: a project's `[target.<triple>] runner` and a dependency's `mcpp::runner(...)` outrank it, and `--no-runner` still executes the artefact directly `xim:emsdk` writes the key (openxlings/xim-pkgindex#823). An engine that predates it ignores it, and a payload installed before the recipe change has no descriptor and runs as before. Measured: - unit: five new descriptor tests; with the store rule removed, ARunnerOutsideTheStoreIsNotHonoured fails - sandbox, no node on PATH, a musl-static build of this tree: with a descriptor in the sandbox's emsdk payload the run prints 1-2-3; with it removed the run fails at `/usr/bin/env: 'node'` again. The first attempt used the glibc development binary, whose loader lives in the host's ~/.mcpp, and measured nothing - CI: `scan (linux-x86_64)` runs a Web program with a fresh MCPP_HOME and a decoy `node` first on PATH that exits 97 with a marker Docs: docs/20-toolchains.md and its Chinese copy state where the interpreter comes from; both READMEs and examples/13 no longer imply a node from PATH. The design record is .agents/docs/2026-09-12-a-verified-web-run-that-asked-the-host-for-node.md.
1 parent c58d61e commit 40907fd

14 files changed

Lines changed: 520 additions & 32 deletions

File tree

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
---
2+
subject: targets
3+
status: landed
4+
---
5+
6+
# A verified Web run that asked the host for node
7+
8+
**Status:** implemented in mcpp 2026.9.12.1 and openxlings/xim-pkgindex#823.
9+
10+
## What was measured
11+
12+
The sandbox verification of the published mcpp 2026.9.11.4 ran 27 checks in an
13+
`xlings subos use <name> --sandbox` environment: a fresh `$HOME`, a fresh
14+
`/tmp`, and no `mcpp` or `node` on PATH. Twenty-six held. The one that did not
15+
was the Web run:
16+
17+
```
18+
mcpp run --target wasm32-emscripten
19+
Compiling w v0.1.0 (.)
20+
Finished dev [unoptimized + debuginfo] in 0.84s
21+
Running `target/wasm32-emscripten/.../bin/w`
22+
/usr/bin/env: 'node': No such file or directory
23+
```
24+
25+
The build was correct. The run depended on the host.
26+
27+
## Why the development host could not see it
28+
29+
An Emscripten link produces a JavaScript launcher whose first line is
30+
`#!/usr/bin/env node`. When neither the project nor its dependency graph
31+
declares a runner, `mcpp run` executes the artefact, and the kernel resolves the
32+
interpreter from the PATH mcpp inherited. `choose_device_action` consults the
33+
manifest and the graph and nothing else, and the spawned artefact receives no
34+
toolchain directory on its PATH.
35+
36+
The ecosystem had already installed the right program. `xim:emsdk` declares
37+
`xim:node` as a runtime dependency and writes that payload's `bin/node` into its
38+
own `.emscripten`, deliberately so that linking does not depend on PATH. Running
39+
the result was the one step that still did.
40+
41+
The row's `verified` record states how it was measured: `node bin/<name>`, with
42+
a `node` the measuring machine had. The development host has one on PATH through
43+
its default xlings environment. So every measurement on that host, including the
44+
dry run of the verification script itself, read the host's `node` and passed.
45+
Only an environment without one could distinguish "the ecosystem runs this" from
46+
"this machine runs this".
47+
48+
## Where the answer belongs
49+
50+
Three placements were considered and rejected.
51+
52+
- **The engine reads `NODE_JS` from emsdk's `.emscripten`.** This would put an
53+
emsdk layout fact into the engine, which is the coupling the payload
54+
descriptor was introduced to remove (2026-09-11 record, item C).
55+
- **The recipe places a `node` link inside the emsdk payload's `bin/`.** Recipe
56+
hooks in this ecosystem have no reliable symlink or permission primitive, and
57+
a link would restate a fact the recipe already records as a path.
58+
- **Projects declare `[target.wasm32-emscripten] runner` and `xim:node`.** A
59+
`verified` row that needs two lines of vocabulary to run is not the row the
60+
2026.9.11.3 release described, where changing a flag was the whole cost.
61+
62+
The payload knows which program runs what its compiler produces, so the payload
63+
states it. `.mcpp-toolchain.json` gains a fourth key.
64+
65+
## The contract
66+
67+
```json
68+
{
69+
"schema": 1,
70+
"frontend": "emscripten/em++",
71+
"runner": "<store>/xim-x-node/26.7.0/bin/node"
72+
}
73+
```
74+
75+
- **One program, no arguments.** The artefact path is appended. The key cannot
76+
carry flags, which keeps the descriptor what it was: a set of answers to
77+
questions the engine already asks, and not a flag channel.
78+
- **Relative or absolute.** A relative runner obeys the rules `frontend` obeys
79+
and resolves against the directory the descriptor was read from. An absolute
80+
runner exists because the program is usually a dependency's, and it is
81+
honoured only inside the package store that holds the payload
82+
(`<store>/<package>/<version>`), compared on canonical paths so that a store
83+
reached through a symbolic link is still that store.
84+
- **Outside the store is ignored, malformed is refused.** Where a store lives is
85+
a property of the machine, so a runner outside it is not honoured and the run
86+
proceeds as it did before the key existed. A structurally wrong value (not a
87+
string, empty, a backslash, a `.` or `..` component) is refused by name at
88+
read time, like every other key.
89+
- **Last in precedence, run slot only.** A project's `[target.<triple>] runner`
90+
and a dependency's `mcpp::runner(...)` are statements about this program and
91+
outrank a statement about everything a compiler produces. `--no-runner` still
92+
executes the artefact directly. `flash`, `monitor` and `debug` name actions a
93+
board package owns, and a compiler has no opinion about them.
94+
95+
## Compatibility
96+
97+
Both directions hold without coordination. An mcpp that predates the key ignores
98+
it, so the recipe ships first. A payload installed before the recipe wrote the
99+
descriptor has none, and its artefact runs through its own shebang exactly as
100+
before; reinstalling the payload adds the descriptor.
101+
102+
## Criteria
103+
104+
| claim | criterion | measured |
105+
|---|---|---|
106+
| a runner in the payload's store is the default for its compiler | unit test with the emsdk shape: compiler at `emscripten/em++`, runner a sibling payload's `bin/node` | yes |
107+
| a runner outside the store is not honoured | unit test with `/usr/bin/node`; and the same test with the store rule removed | yes, and the probe turned it red |
108+
| malformed runners are refused by name and by key | seven shapes, each refusal naming the file and `"runner"` | yes |
109+
| the wiring reaches `mcpp run` | in the sandbox, no `node` on PATH, with a descriptor in the sandbox's own emsdk payload | `1-2-3` |
110+
| the runner came from the descriptor and not from somewhere else | the same run with the descriptor removed | fails at `/usr/bin/env: 'node'` again |
111+
| CI holds the claim against the published recipe | `scan (linux-x86_64)` runs a Web program with a fresh `MCPP_HOME`, so the emsdk payload is the one the index publishes rather than one restored from cache, and with a decoy `node` first on PATH that exits 97 with a marker; the step fails if the payload has no descriptor, if the decoy ran, or if `1-2-3` is not a line of the output | on this PR, after openxlings/xim-pkgindex#823 was published |
112+
113+
The first attempt at the sandbox reading measured nothing. The development binary
114+
was dynamically linked, and its loader lives in the host's `~/.mcpp`, which the
115+
sandbox replaces with its own; both readings were "cannot execute: required file
116+
not found" and said nothing about runners. The reading above used a
117+
`x86_64-linux-musl` static build, the form a release ships.
118+
119+
## What remains
120+
121+
An emsdk payload already installed on a machine keeps running through PATH until
122+
it is reinstalled. The published-artefact check is the sandbox verification
123+
script's Web section, run again after this release.

.agents/docs/README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ superseded_by: 2026-09-07-....md # when status is superseded
1818
---
1919
```
2020

21-
278 records.
21+
279 records.
2222

2323
## By subject
2424

@@ -46,6 +46,7 @@ Records that declare one. Everything else is listed by date below.
4646

4747
### targets
4848

49+
- [A verified Web run that asked the host for node](2026-09-12-a-verified-web-run-that-asked-the-host-for-node.md) — landed
4950
- [SDK toolchains, the payload/engine seam, and openkal across iOS, Android and Web](2026-09-11-sdk-toolchains-and-ios-local-verification.md) — landed
5051
- [Where a platform's knowledge belongs: iOS, Android and Web across the engine, the index and the plugins](2026-09-11-platform-targets-design-review.md) — active
5152

@@ -57,6 +58,7 @@ Records that declare one. Everything else is listed by date below.
5758

5859
### 2026-09
5960

61+
- [A verified Web run that asked the host for node](2026-09-12-a-verified-web-run-that-asked-the-host-for-node.md) — landed
6062
- [Six open issues: what each one actually is, and what would answer it](2026-09-11-six-open-issues-analysis.md) — active
6163
- [SDK toolchains, the payload/engine seam, and openkal across iOS, Android and Web](2026-09-11-sdk-toolchains-and-ios-local-verification.md) — landed
6264
- [Where a platform's knowledge belongs: iOS, Android and Web across the engine, the index and the plugins](2026-09-11-platform-targets-design-review.md) — active

.github/workflows/ci-target-matrix.yml

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,64 @@ jobs:
348348
tests/matrix/expected.tsv ${{ matrix.host }} graph || fail=1
349349
[ "$fail" = 0 ] || exit 1
350350
351+
# A WEB ARTEFACT RUNS THROUGH THE INTERPRETER ITS PAYLOAD NAMES, NOT
352+
# THROUGH PATH. That is what `wasm32-emscripten`'s `verified` tier
353+
# claims, and no step measured it until a sandbox with no `node` on PATH
354+
# showed that the run depended on the host:
355+
#
356+
# /usr/bin/env: 'node': No such file or directory
357+
#
358+
# A FRESH MCPP_HOME, BECAUSE THE CACHE IS NOT THE PUBLISHED FORM.
359+
# `~/.mcpp` is restored by key prefix, so the emsdk payload in it may
360+
# predate the recipe that writes `.mcpp-toolchain.json`, and that older
361+
# payload would be the object measured. A fresh home installs what the
362+
# index publishes today.
363+
#
364+
# AND A DECOY `node` FIRST ON PATH, rather than `node` removed from PATH.
365+
# Removing it would also remove whatever else those directories hold,
366+
# and an image that ships a real `node` would pass for the wrong reason.
367+
# A decoy that exits 97 with a marker separates the two outcomes on any
368+
# image: the payload's runner never reaches it.
369+
- name: "wasm32-emscripten runs through its payload's runner, not PATH"
370+
if: ${{ !cancelled() && matrix.host == 'linux-x86_64' }}
371+
run: |
372+
set -uo pipefail
373+
home=$(mktemp -d); work=$(mktemp -d); decoy=$(mktemp -d)
374+
printf '#!/bin/sh\necho "DECOY-NODE-WAS-RUN" >&2\nexit 97\n' > "$decoy/node"
375+
chmod +x "$decoy/node"
376+
export MCPP_HOME="$home" MCPP_VENDORED_XLINGS="$XLINGS_BIN"
377+
"$MCPP_UNDER_TEST" self config --mirror GLOBAL >/dev/null 2>&1 || true
378+
mkdir -p "$work/src"
379+
printf '[package]\nname = "w"\nversion = "0.1.0"\n' > "$work/mcpp.toml"
380+
cat > "$work/src/main.cpp" <<'CPP'
381+
import std;
382+
int main() {
383+
std::vector<int> v{3, 1, 2};
384+
std::ranges::sort(v);
385+
std::print("{}-{}-{}\n", v[0], v[1], v[2]);
386+
}
387+
CPP
388+
out=$(cd "$work" && PATH="$decoy:$PATH" "$MCPP_UNDER_TEST" run --target wasm32-emscripten 2>&1) && rc=0 || rc=$?
389+
printf '%s\n' "$out" | tail -12
390+
desc="$home/registry/data/xpkgs/xim-x-emsdk/6.0.9/.mcpp-toolchain.json"
391+
if [ ! -f "$desc" ]; then
392+
echo "::error::the freshly installed emsdk payload has no .mcpp-toolchain.json; the published recipe does not name its runner"
393+
exit 1
394+
fi
395+
if grep -q 'DECOY-NODE-WAS-RUN' <<<"$out"; then
396+
echo "::error::the artefact ran through the node on PATH, not through the payload's runner"
397+
exit 1
398+
fi
399+
if [ "$rc" -ne 0 ]; then
400+
echo "::error::mcpp run --target wasm32-emscripten exited $rc"
401+
exit 1
402+
fi
403+
if ! grep -qx '1-2-3' <<<"$out"; then
404+
echo "::error::the program's output line 1-2-3 is absent"
405+
exit 1
406+
fi
407+
echo "ok: wasm32-emscripten ran through the payload's runner; the decoy node was never run"
408+
351409
coverage:
352410
# THE DENOMINATOR. Every check above is per host, and no per-host check
353411
# can notice a host that never ran.

CHANGELOG.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,35 @@
55
66
## [Unreleased]
77

8+
## [2026.9.12.1] - 2026-09-12
9+
10+
### Web 产物的运行不再依赖宿主的 `node`
11+
12+
2026.9.11.4 发布后在 xlings 沙箱里核验发布物:`mcpp build --target wasm32-emscripten`
13+
成功,而 `mcpp run` 停在
14+
15+
```
16+
/usr/bin/env: 'node': No such file or directory
17+
```
18+
19+
Emscripten 链接产出的是首行为 `#!/usr/bin/env node` 的 JavaScript 启动器。项目什么都不
20+
声明时 mcpp 直接执行它,于是解释器取自机器的 PATH。而生态早已装好了它:`xim:emsdk` 声明
21+
依赖 `xim:node`,并把那份载荷的 `bin/node` 写进自己的 `.emscripten`。开发机的 PATH 上恰好
22+
`node`,所以此前那次 `verified` 测量看不出这条宿主依赖;沙箱没有,于是看出来了。
23+
24+
- 载荷描述文件 `.mcpp-toolchain.json` 增加第四个键 `runner`:运行这个工具链产物的程序,
25+
一个程序、不带参数,产物路径追加在后,因此不构成 flag 通道。它可以是载荷内的相对路径
26+
(与 `frontend` 同一套规则),也可以是绝对路径;绝对路径只在持有该载荷的包存储
27+
(`<store>/<package>/<version>`)之内才被采用,按规范化路径比较,存储之外的一律忽略
28+
—— 载荷不能选择宿主解释器。
29+
- 优先级:项目的 `[target.<triple>] runner` 与依赖图提供的 runner 在前,载荷的 runner
30+
在后;`--no-runner` 仍然直接执行产物。只作用于 run 槽位,即 `mcpp run``mcpp test`
31+
- 结构错误的 `runner`(非字符串、为空、含反斜杠、含 `.``..` 分量)按描述文件的既有
32+
规则拒绝,并点名该文件。
33+
- `xim:emsdk` 的配方写出 `runner`(openxlings/xim-pkgindex#823)。早于这个键的 mcpp
34+
忽略它,所以配方可以先发;在此之前安装的 emsdk 载荷没有描述文件,行为与之前相同,重新
35+
安装后获得。
36+
837
## [2026.9.11.4] - 2026-09-11
938

1039
### iOS 三行:生态编译器与定位到的 SDK

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -419,7 +419,7 @@ list` reports for this machine):
419419
| `aarch64-none-elf` · `x86_64-none-elf` | llvm 22 — bare metal, no C library by default ² | preview |
420420
| `thumbv7em-none-eabi` · `thumbv8m.base-none-eabi` · `thumbv8m.main-none-eabihf` | llvm 22 — Cortex-M4/M7 soft float, M23, M33F/M55F ² | preview |
421421
| `riscv64-linux-musl` · `aarch64-linux-gnu` · `x86_64-macos` || planned |
422-
| `wasm32-emscripten` | `emsdk@6.0.9` — Emscripten ships its own sysroot and its own libc++ module surface; `mcpp run` executes the module with `node` | verified |
422+
| `wasm32-emscripten` | `emsdk@6.0.9` — Emscripten ships its own sysroot and its own libc++ module surface; `mcpp run` executes the module with the `node` the payload declares (`xim:node`), not one found on PATH | verified |
423423
| `x86_64-linux-android` | `android-ndk@30.0.16248370` — bionic from the NDK, one payload for both ABIs; ran on an API 24 x86_64 emulator image | verified |
424424
| `aarch64-linux-android` | the same payload and the same build; ran under qemu-user over the system image's own bionic, which the platform emulator cannot do from an x86_64 host | verified |
425425
| `aarch64-ios-sim` | llvm 22 plus the machine's iPhoneSimulator SDK, which mcpp locates rather than installs; ran on a simulator through `simctl-run` ³ | verified |

README.zh-CN.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -406,7 +406,7 @@ mcpp 的身份模型是两条正交轴:**工具链** = `family@version`(family
406406
| `aarch64-none-elf` · `x86_64-none-elf` | llvm 22——裸机,默认不带 C 库 ² | preview |
407407
| `thumbv7em-none-eabi` · `thumbv8m.base-none-eabi` · `thumbv8m.main-none-eabihf` | llvm 22——Cortex-M4/M7 软浮点、M23、M33F/M55F ² | preview |
408408
| `riscv64-linux-musl` · `aarch64-linux-gnu` · `x86_64-macos` || planned |
409-
| `wasm32-emscripten` | `emsdk@6.0.9` —— Emscripten 自带 sysroot 和它自己的 libc++ 模块面;`mcpp run` `node` 把模块跑起来 | verified |
409+
| `wasm32-emscripten` | `emsdk@6.0.9` —— Emscripten 自带 sysroot 和它自己的 libc++ 模块面;`mcpp run` 用载荷声明的 `node`(`xim:node`)把模块跑起来,不取 PATH 上的 | verified |
410410
| `x86_64-linux-android` | `android-ndk@30.0.16248370` —— bionic 来自 NDK,一个载荷服务两个 ABI;在 API 24 的 x86_64 模拟器镜像上跑过 | verified |
411411
| `aarch64-linux-android` | 同一个载荷、同样的构建;在 qemu-user 上、配系统镜像自带的 bionic 跑过 —— 这是平台模拟器从 x86_64 宿主做不到的 | verified |
412412
| `aarch64-ios-sim` | llvm 22 加上机器自己的 iPhoneSimulator SDK,mcpp 定位而不安装它;经 `simctl-run` 在模拟器上跑过 ³ | verified |

docs/20-toolchains.md

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -587,10 +587,19 @@ the NDK itself declares in `meta/platforms.json`.
587587

588588
### Running what they produce
589589

590-
Neither the emulator nor a device is part of the toolchain axis. `mcpp run`
591-
executes a wasm module directly, because Emscripten's output is a program
592-
`node` can run. For a target whose artifact runs elsewhere, the `runner` key is
593-
an argv prefix and the session belongs to a package rather than to the engine:
590+
Neither the emulator nor a device is part of the toolchain axis. A wasm module
591+
needs an interpreter rather than an emulator, and the payload names it:
592+
`xim:emsdk` writes `.mcpp-toolchain.json` beside itself, and its `runner` key is
593+
the `node` of the `xim:node` payload it depends on. `mcpp run` and `mcpp test`
594+
use that program when neither the project nor a dependency declares a runner,
595+
so no `node` on PATH is involved. A payload's runner is one program with the
596+
artefact path appended; it is either relative to the payload or absolute inside
597+
the package store that holds the payload, and a path outside that store is
598+
ignored. A payload installed before its recipe wrote the key has no descriptor,
599+
and its artefact runs through its own `#!/usr/bin/env node` line as before.
600+
601+
For a target whose artifact runs elsewhere, the `runner` key is an argv prefix
602+
and the session belongs to a package rather than to the engine:
594603

595604
```toml
596605
[target.x86_64-linux-android]

docs/zh/20-toolchains.md

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -535,9 +535,15 @@ macos_deployment_target = "14.0" # Apple
535535

536536
### 产物的运行方式
537537

538-
模拟器和真机都不属于工具链这根轴。`mcpp run` 直接执行一个 wasm 模块,因为
539-
Emscripten 的产物就是一个 `node` 能跑的程序。对于产物在别处运行的目标,`runner`
540-
键是一个 argv 前缀,而那个会话属于一个****而不属于引擎:
538+
模拟器和真机都不属于工具链这根轴。wasm 模块需要的是解释器而不是模拟器,由载荷说出它:
539+
`xim:emsdk` 在自身旁边写出 `.mcpp-toolchain.json`,其中的 `runner` 键就是它所依赖的
540+
`xim:node` 载荷里的 `node`。项目与依赖都没有声明 runner 时,`mcpp run``mcpp test`
541+
使用这个程序,因此不涉及 PATH 上的 `node`。载荷的 runner 是一个程序,产物路径追加在后;
542+
它或是载荷内的相对路径,或是持有该载荷的包存储之内的绝对路径,存储之外的路径一律忽略。
543+
在配方写出这个键之前安装的载荷没有描述文件,其产物仍按自身的 `#!/usr/bin/env node`
544+
一行运行,与之前相同。
545+
546+
对于产物在别处运行的目标,`runner` 键是一个 argv 前缀,而那个会话属于一个****而不属于引擎:
541547

542548
```toml
543549
[target.x86_64-linux-android]

examples/13-platform-targets/README.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@ bin/platform-targets.wasm 447183 bytes the module
2323
node bin/platform-targets -> 1-2-3
2424
```
2525

26+
运行用的 `node` 取自 `xim:emsdk` 声明的依赖 `xim:node`,而不是 PATH 上的某一个。载荷在
27+
`.mcpp-toolchain.json` 里用 `runner` 写出它,项目与依赖图都没有声明 runner 时 mcpp 使用
28+
它。这需要 mcpp 2026.9.12.1,以及在配方更新之后安装的 emsdk 载荷;更早安装的载荷没有
29+
描述文件,仍按产物首行的 `#!/usr/bin/env node` 取 PATH 上的 `node`
30+
2631
`mcpp run` 会用 `node` 跑它,所以不需要额外的一步。工程侧**一个新词汇都不需要**
2732
`wasm32-emscripten` 这一行自己命名了它的载荷(`emsdk@6.0.9`),载荷自带 sysroot,
2833
而 Emscripten 自己就发布一份 libc++ 的模块面。
@@ -175,7 +180,7 @@ error: target aarch64-ios needs the iphoneos SDK, which this machine does not pr
175180

176181
| target | tier | pin | 运行过? |
177182
|---|---|---|---|
178-
| `wasm32-emscripten` | verified | `emsdk@6.0.9` | 是,`node` |
183+
| `wasm32-emscripten` | verified | `emsdk@6.0.9` | 是,载荷声明的 `node` |
179184
| `x86_64-linux-android` | verified | `android-ndk@30.0.16248370` | 是,平台模拟器 |
180185
| `aarch64-linux-android` | verified | `android-ndk@30.0.16248370` | 是,`qemu-aarch64-static` + 从镜像取出的 bionic |
181186
| `aarch64-ios` | preview | `llvm@22.1.8` | 否 —— 真机需要开发者自己的签名 |

mcpp.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "mcpp"
3-
version = "2026.9.11.4"
3+
version = "2026.9.12.1"
44
description = "Modern C++ build & package management tool"
55
license = "Apache-2.0"
66
authors = ["mcpp-community"]

0 commit comments

Comments
 (0)