11# 编译器是能力 —— 跨仓实施计划
22
3+ > ** 状态:全部完成(2026-08-08)。**
4+ >
5+ > mcpp 侧 T1–T7 随 PR #378 合入(` fdad165 ` ,CI 18/18),发布 2026.8.8.2;
6+ > T8 随 mcpp-index #181 合入(` 1ba4161 ` )。落地过程中被 CI 推翻/收窄的判据,
7+ > 已回写到 ` 2026-08-08-payload-version-and-contract-drift-design.md ` §9。
8+ >
9+ > 未随本计划完成、已另行记录的:#352 的 GLX vendor 选择(EGL 路径已通,
10+ > GLX 路径在 NVIDIA 宿主上仍拿不到 FBConfig),以及 ` glibc>=X ` 下限语义
11+ > (约定为独立 PR)。
12+
13+
314> ** For agentic workers:** 逐 task 执行,每个 task 自带 red→green→commit。** T1 是所有后续 task 的前提** (没有它,后面每一步的观测都不可信)。
415
516** Goal:** 让 mcpp 停止依赖编译器的安装期配置,把「用哪份 libc」收敛成一个权威;顺带把已经污染的产物清干净,并让多 subos 构建真正可用。
2839
2940本轮发现三处注释描述了代码没有的行为。** 先让它们不能再撒谎** ,否则后面每一步都可能在错误的前提上推理。
3041
31- - [ ] ** Step 1** 写失败单测:` find_sibling_tool ` 的注释说「first (highest)」,断言** 两个版本目录时返回的是排序后最高的那个**
32- - [ ] ** Step 2** 跑,确认 FAIL(今天返回 readdir 第一个)
33- - [ ] ** Step 3** 二选一并使注释与代码一致:①真的排序;②改注释为「未定义顺序」并让调用方不得依赖。** 本计划选 ②** ——T2 会让它不再被用于选版本
34- - [ ] ** Step 4** 另两处:` fixup_gcc_specs ` 的「Idempotent」(跨 home 不幂等)、` execute.cppm ` reader 的「旧缓存视为 miss」(T5 修)——先把注释改成事实
35- - [ ] ** Step 5** Commit
42+ - [x ] ** Step 1** 写失败单测:` find_sibling_tool ` 的注释说「first (highest)」,断言** 两个版本目录时返回的是排序后最高的那个**
43+ - [x ] ** Step 2** 跑,确认 FAIL(今天返回 readdir 第一个)
44+ - [x ] ** Step 3** 二选一并使注释与代码一致:①真的排序;②改注释为「未定义顺序」并让调用方不得依赖。** 本计划选 ②** ——T2 会让它不再被用于选版本
45+ - [x ] ** Step 4** 另两处:` fixup_gcc_specs ` 的「Idempotent」(跨 home 不幂等)、` execute.cppm ` reader 的「旧缓存视为 miss」(T5 修)——先把注释改成事实
46+ - [x ] ** Step 5** Commit
3647
3748---
3849
@@ -49,11 +60,11 @@ std::optional<PayloadPaths> probe_payload_paths(
4960 std::string_view runtimeBinding); // "glibc@2.39";空 ⇒ 不进 PayloadFirst
5061```
5162
52- - [ ] **Step 1** 单测:给定 `glibc@2.39` 且 home 内有 2.39/2.44 两份 ⇒ **必须返回 2.39**;给定空 binding ⇒ **返回 nullopt**(不猜)
53- - [ ] **Step 2** 跑,FAIL
54- - [ ] **Step 3** 实现;`prepare.cppm` 按 `--runtime` → `[xlings] subos` 的 `subos_info.runtime` 顺序解析,末级不猜
55- - [ ] **Step 4** 跑,PASS
56- - [ ] **Step 5** Commit
63+ - [x ] **Step 1** 单测:给定 `glibc@2.39` 且 home 内有 2.39/2.44 两份 ⇒ **必须返回 2.39**;给定空 binding ⇒ **返回 nullopt**(不猜)
64+ - [x ] **Step 2** 跑,FAIL
65+ - [x ] **Step 3** 实现;`prepare.cppm` 按 `--runtime` → `[xlings] subos` 的 `subos_info.runtime` 顺序解析,末级不猜
66+ - [x ] **Step 4** 跑,PASS
67+ - [x ] **Step 5** Commit
5768
5869---
5970
@@ -63,9 +74,9 @@ std::optional<PayloadPaths> probe_payload_paths(
6374
6475不加这条,切 subos 不改 fingerprint ⇒ `target/<fp>/` 被复用 ⇒ 里面是对另一份 glibc 编译的对象。**比今天更坏。**
6576
66- - [ ] **Step 1** 单测:两个只有 `runtimeBinding` 不同的输入 ⇒ **fingerprint 必须不同**
67- - [ ] **Step 2/3/4** red → 加字段 → green
68- - [ ] **Step 5** Commit
77+ - [x ] **Step 1** 单测:两个只有 `runtimeBinding` 不同的输入 ⇒ **fingerprint 必须不同**
78+ - [x ] **Step 2/3/4** red → 加字段 → green
79+ - [x ] **Step 5** Commit
6980
7081---
7182
@@ -76,11 +87,11 @@ std::optional<PayloadPaths> probe_payload_paths(
7687
7788**已实测**:`-Wl,--dynamic-linker` 压得过 specs;`-specs=<无 `+` 定义>` 是替换;`g++ -dumpspecs` 给内建 specs(`/tmp` 路径 0 条);真实构建(模块 + `import std` + 共享库)RUNPATH 68→2、死路径 0、可运行。
7889
79- - [ ] **Step 1** e2e:gcc 构建的产物 **RUNPATH 中不得有 `/tmp/tmp.`**,且 interpreter 是权威指定的那份,且能跑
80- - [ ] **Step 2** 跑,FAIL(今天有 34+ 条)
81- - [ ] **Step 3** ①去掉 `linkmodel` 的 `if (clangDriver)` 门;②构建期生成 clean specs 到 **build dir**,`-specs=` 传入;③**删掉 `fixup_gcc_specs`**(保留 `patchelf_walk`)
82- - [ ] **Step 4** 跑,PASS
83- - [ ] **Step 5** Commit
90+ - [x ] **Step 1** e2e:gcc 构建的产物 **RUNPATH 中不得有 `/tmp/tmp.`**,且 interpreter 是权威指定的那份,且能跑
91+ - [x ] **Step 2** 跑,FAIL(今天有 34+ 条)
92+ - [x ] **Step 3** ①去掉 `linkmodel` 的 `if (clangDriver)` 门;②构建期生成 clean specs 到 **build dir**,`-specs=` 传入;③**删掉 `fixup_gcc_specs`**(保留 `patchelf_walk`)
93+ - [x ] **Step 4** 跑,PASS
94+ - [x ] **Step 5** Commit
8495
8596---
8697
@@ -90,42 +101,42 @@ std::optional<PayloadPaths> probe_payload_paths(
90101
91102已在 `fix/fast-run-stale-cache-subos` 分支上完成并 18/18 CI 通过,**原样带过来**:
92103
93- - [ ] **Step 1** `git cherry-pick` 该分支的三个 commit(wire format / 旧缓存 / e2e fixture)
94- - [ ] **Step 2** 跑单测 + e2e,确认仍绿
95- - [ ] **Step 3** Commit(或保留 cherry-pick 的原始提交)
104+ - [x ] **Step 1** `git cherry-pick` 该分支的三个 commit(wire format / 旧缓存 / e2e fixture)
105+ - [x ] **Step 2** 跑单测 + e2e,确认仍绿
106+ - [x ] **Step 3** Commit(或保留 cherry-pick 的原始提交)
96107
97108---
98109
99110### T6: D4 沙箱 xlings 版本比对 + D5 陈旧 sysroot
100111
101112**Files:** `src/fallback/xlings_binary.cppm`、`src/doctor.cppm`、`src/fallback/probe_sysroot.cppm`
102113
103- - [ ] **Step 1** 单测/e2e:vendored xlings 版本**低于 pin** ⇒ 被替换;**高于 pin** ⇒ 不动
104- - [ ] **Step 2** red
105- - [ ] **Step 3** 实现;doctor 增加两条 finding:①xlings 低于 pin;②`--sysroot` 指向当前项目之外
106- - [ ] **Step 4** green
107- - [ ] **Step 5** Commit
114+ - [x ] **Step 1** 单测/e2e:vendored xlings 版本**低于 pin** ⇒ 被替换;**高于 pin** ⇒ 不动
115+ - [x ] **Step 2** red
116+ - [x ] **Step 3** 实现;doctor 增加两条 finding:①xlings 低于 pin;②`--sysroot` 指向当前项目之外
117+ - [x ] **Step 4** green
118+ - [x ] **Step 5** Commit
108119
109120---
110121
111122### T7: 文档 + 版本 + PR
112123
113- - [ ] `docs/03-toolchains.md`:权威降级链、`[xlings] subos`、多 subos 构建
114- - [ ] `docs/05-mcpp-toml.md`:`[xlings] subos` 与 runtime 的关系
115- - [ ] 中文版同步
116- - [ ] `MCPP_VERSION` / `mcpp.toml` → `2026.8.8.2`;`kXlingsVersion` → 最新;`check_version_pins.sh` 通过
117- - [ ] 全量 `mcpp test` + 关键 e2e
118- - [ ] 开 PR
124+ - [x ] `docs/03-toolchains.md`:权威降级链、`[xlings] subos`、多 subos 构建
125+ - [x ] `docs/05-mcpp-toml.md`:`[xlings] subos` 与 runtime 的关系
126+ - [x ] 中文版同步
127+ - [x ] `MCPP_VERSION` / `mcpp.toml` → `2026.8.8.2`;`kXlingsVersion` → 最新;`check_version_pins.sh` 通过
128+ - [x ] 全量 `mcpp test` + 关键 e2e
129+ - [x ] 开 PR
119130
120131---
121132
122133### T8: mcpp-index 图形栈重新落地(D1 修好之后)
123134
124135**Files(mcpp-index):** `pkgs/c/compat.glx-runtime.lua`、`pkgs/c/compat.glfw.lua`
125136
126- - [ ] **Step 1** 新增 e2e/验证:**装 `xim:graphics` 前后**,各跑一次与图形无关的成员,断言产物 `PT_INTERP` 与 `readelf -V` 的 glibc 符号上界**不变**。这是上次事故真正缺失的那个测试
127- - [ ] **Step 2** 重新应用 `f44e896` 的两个文件改动(deps 放平台层)
128- - [ ] **Step 3** CI 全绿后合入
137+ - [x ] **Step 1** 新增 e2e/验证:**装 `xim:graphics` 前后**,各跑一次与图形无关的成员,断言产物 `PT_INTERP` 与 `readelf -V` 的 glibc 符号上界**不变**。这是上次事故真正缺失的那个测试
138+ - [x ] **Step 2** 重新应用 `f44e896` 的两个文件改动(deps 放平台层)
139+ - [x ] **Step 3** CI 全绿后合入
129140
130141---
131142
0 commit comments