fix(run): --target X wrote X's build into the host's cache slot - #498
Merged
Conversation
`mcpp run --target X` 正确地为 X 交叉构建,然后把结果**记在了宿主的槽里**。
损害不在这条命令,而在下一条:
$ mcpp run --target riscv64-none-elf # 正确,经 qemu 跑起来
$ mcpp run
Running `target/riscv64-none-elf/…/bin/openkal-same-source`
exit=1
缓存文件里逐字可见 —— 一次 riscv 交叉构建写下的是:
[target=]
空键的含义是「为这台机器构建」,而这正是 `try_fast_run` 允许自己
**直接 exec 缓存产物**的唯一依据。于是裸的 `mcpp run` 命中它,
跳过整个 prepare_build(所以既没有构建宿主目标,也没有解析 runner),
把另一个目标的二进制在本机执行了。
真因是一个丢掉的实参。`build_run_target` 收到了 `target_triple`、
用它建好 `ov` 并正确交叉构建,唯独在这里没有传下去:
- run_build_plan(*ctx, false, no_cache);
+ run_build_plan(*ctx, false, no_cache, target_triple);
而最后那个形参就是缓存条目的 `[target=]` 键。`cmd_build` 的两个调用点
都传了,只有 run 这条路径没传。
⚠️ **`try_fast_run` 的注释里记着同一个缺陷的另一条到达路径**(目标写在
清单的 `[build] target` 里),并且只守了那一扇门:
if (!want->defaultTarget.empty()) return std::nullopt;
这是另一扇门:flag。同一个缺陷有两个入口,修好一个不会暴露另一个 ——
只有走到那条路径上才会。
── 回归测试的判据是路径,不是退出码 ────────────────────────
⭐ 异架构产物 exec 会失败,所以只看退出码的测试**在那里因错误的理由通过,
而在同架构上完全测不到** —— 后者恰恰更危险:用户不会看到崩溃,
只会拿到一个 musl 产物冒充宿主产物,静默地跑下去。
`283_run_target_flag_owns_its_cache_slot.sh` 因此用
`x86_64-linux-musl`(同架构、本机能跑),断言 `Running \`…\`` 那行里的
**路径**不含交叉目标的目录。在修复前的二进制上实测为红:
FAIL: a bare `mcpp run` exec'd the x86_64-linux-musl artifact
target/x86_64-linux-musl/50af2973556be3d7/bin/runslot
修复后转绿。单元测试 93 通过 / 0 失败。
发现路径:openkal-llvm-runtime 的 CI 有一步名为「on bare metal」却跑裸的
`mcpp run`(即宿主)。把它改成真的 `--target riscv64-none-elf` 之后,
**下一步**炸了 —— 缺陷一直都在,只是没有任何东西走到那条顺序上。
版本号两处同步(mcpp.toml + src/version.cppm),CHANGELOG 记下缺陷、 两条到达路径,以及回归测试为何断言路径而非退出码。 bootstrap pin 不动:它是自举起点,指向一个已发布且能构建当前树的版本。
Sunrisepeak
added a commit
to mcpplibs/openkal-llvm-runtime
that referenced
this pull request
Aug 24, 2026
…l step 把 pin 移到 24.3 让裸机那一步第一次真正到达 OpenSBI,而**它之后的那一步** 随即失败:`mcpp run --target X` 一直把 X 的构建记在宿主的缓存槽里, 于是下一条裸的 `mcpp run` 直接 exec 了交叉产物。 那个缺陷早于本包,只因为一个自称测裸机的步骤开始真的测裸机才现形。 mcpp-community/mcpp#498 修复,随 2026.8.24.4 发布。
Sunrisepeak
added a commit
to mcpplibs/openkal-llvm-runtime
that referenced
this pull request
Aug 24, 2026
…s package (#4) * declare the compiler runtime, which was always the larger half of this package 本包 729 个对象里,**498 个是 compiler-rt 的 builtins、21 个是 libunwind 的**。 那些是一个 **C 程序**需要的东西 —— `__udivti3` 和它的亲戚与 C++ 无关 —— 而清单此前只声明 `mcpp:c++-abi=libc++`,于是它说自己供给了不供给的东西, 同时隐瞒了真正供给的那一半。 provides = [ "hosted-standard-library", "mcpp:c++-abi=libc++", "mcpp:compiler-runtime=compiler-rt", ← 新增 ] 实测(本机,mcpp 2026.8.24.3): compiler llvm (22.1.8, payload) compiler-runtime compiler-rt (openkal-llvm-runtime@0.1.2, graph) ← 原为 payload kernel-abi openkal (openkal-linux@0.5.3, graph) c-abi musl (openkal-musl@0.3.3, graph) c++-abi libc++ (openkal-llvm-runtime@0.1.2, graph) 五层里四层来自图,只剩编译器本身来自载荷。 ──⚠️ 同一改动里必须上移 MCPP_VERSION,原因不是兼容性 ──────── 一个键有三种结局,而其中两种都是 exit 0: provides = ["mcpp:compiler-runtime=…"] 2026.8.19.4 exit 0 **没有被校验** 2026.8.24.1 exit 2 拒绝 2026.8.24.3 exit 0 解析成功 ⭐ 19.4 那个零和 24.3 那个零**不是同一种成功**。前者早于层词表, 整个数组被当作不认识的键忽略 —— 它既不拒绝这条声明,也不读它。 CI 停在那里会在一份**中心主张从未被检查过**的清单上报绿。 因此 `MCPP_VERSION` 2026.8.19.4 → 2026.8.24.3 与本行同时改。 拒绝窗口只有 2026.8.24.1 一个版本(开始校验 `mcpp:` 前缀之后、 学会这一层之前)。索引已于今日到达 2026.8.24.3,且这些包尚无存量用户。 * ci: drop the branch-built tool, and make the bare-metal step reach bare metal 删掉的那个步骤自己写着退出条件:「⇒ When #486 ships, delete this step and raise MCPP_VERSION」。#486 已于 2026-08-23 合入并随 2026.8.24.1 起发布, 而这个步骤还在从 `feat/import-std-capability` 分支构建 mcpp 并盖掉刚装好的那个。 后果不是「多跑一次构建」。日志里两行并排: Install mcpp mcpp 2026.8.24.3 The build tool, from the branch… mcpp 2026.8.21.3 ← 实际跑的是它 于是 `MCPP_VERSION` 这个变量对**被测的行为**不起作用,本 PR 把它移到 24.3 之后 CI 仍然用 21.3 跑,报出三层版的错误信息。两个 job 各一处,一并删除。 ──⚠️ 并且那一步在测宿主,而它的名字说的是裸机 ────────────── `The same source on bare metal, with exceptions` 跑的是裸的 `mcpp run`。 这个清单**刻意没有 `[build] target`**(注释就写在第 5 行),所以裸的 `mcpp run` 构建的是**宿主**。四行断言两种跑法都会打印 —— 那是清单自己的 主张,不是巧合 —— 于是这一步在宿主构建上报绿,**一次都没有到过 OpenSBI**。 实测 2026-08-24:产物是 `target/x86_64-linux-gnu/…`。 改法两处: · `mcpp run --target riscv64-none-elf` · 加一条 `grep -q 'Boot HART'`,即固件自己的横幅 —— 这样一次没离开宿主 的运行**无法**靠打印那四行应用输出来满足本步骤 本机实测改后:OpenSBI 横幅出现,四行输出与宿主一致。 * ci: pin 2026.8.24.4, which is the release that survives the bare-metal step 把 pin 移到 24.3 让裸机那一步第一次真正到达 OpenSBI,而**它之后的那一步** 随即失败:`mcpp run --target X` 一直把 X 的构建记在宿主的缓存槽里, 于是下一条裸的 `mcpp run` 直接 exec 了交叉产物。 那个缺陷早于本包,只因为一个自称测裸机的步骤开始真的测裸机才现形。 mcpp-community/mcpp#498 修复,随 2026.8.24.4 发布。 * ci: the emulated serial console ends lines with CRLF 裸机那一步的四行与宿主的四行**内容完全一致**,而 `diff` 报四行全不同: 1,4c1,4 < sorted: 2 4 7 --- > sorted: 2 4 7 不可见字符。裸机运行经由模拟的 16550 UART 到达控制台,而串口控制台 以 CRLF 结束一行;宿主运行不是。 ⭐ 这种失败读起来像是**被测的主张不成立**,而不像承载它的传输层不同 —— 两侧各加一个 `tr -d '\r'`。断言的是程序打印了什么,不是字节怎么到达的。 同样是把那一步从裸的 `mcpp run`(宿主)改成真的 `--target riscv64-none-elf` 之后才暴露的。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
mcpp run --target X正确地为 X 交叉构建,然后把结果记在了宿主的槽里。损害不在这条命令,而在下一条:缓存文件里逐字可见:一次 riscv 交叉构建写下的是
[target=]。空键的含义是「为这台机器构建」,而这正是try_fast_run允许自己直接 exec 缓存产物的唯一依据。裸的mcpp run命中它,跳过整个 prepare_build(既没构建宿主目标,也没解析 runner),在本机执行了另一个目标的二进制。真因是一个丢掉的实参:
最后那个形参就是缓存条目的
[target=]键。cmd_build两个调用点都传了,只有 run 这条没传。try_fast_run的注释里记着同一个缺陷的另一条到达路径(目标写在清单的[build] target里),并且只守了那一扇门。这是另一扇门:flag。回归测试的判据是路径,不是退出码
⭐ 异架构产物 exec 会失败,所以只看退出码的测试在那里因错误的理由通过,而在同架构上完全测不到——后者更危险:用户不会看到崩溃,只会拿到一个 musl 产物冒充宿主产物。测试因此用
x86_64-linux-musl(同架构、本机能跑),断言Running那行的路径。修复前实测为红:
修复后转绿;单元测试 93 通过 / 0 失败。
发现路径:openkal-llvm-runtime 的 CI 有一步名为「on bare metal」却跑裸的
mcpp run(即宿主)。改成真的--target riscv64-none-elf之后,下一步炸了——缺陷一直都在,只是没有任何东西走到那条顺序上。