Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
# 编译器是能力 —— 跨仓实施计划

> **状态:全部完成(2026-08-08)。**
>
> mcpp 侧 T1–T7 随 PR #378 合入(`fdad165`,CI 18/18),发布 2026.8.8.2;
> T8 随 mcpp-index #181 合入(`1ba4161`)。落地过程中被 CI 推翻/收窄的判据,
> 已回写到 `2026-08-08-payload-version-and-contract-drift-design.md` §9。
>
> 未随本计划完成、已另行记录的:#352 的 GLX vendor 选择(EGL 路径已通,
> GLX 路径在 NVIDIA 宿主上仍拿不到 FBConfig),以及 `glibc>=X` 下限语义
> (约定为独立 PR)。


> **For agentic workers:** 逐 task 执行,每个 task 自带 red→green→commit。**T1 是所有后续 task 的前提**(没有它,后面每一步的观测都不可信)。

**Goal:** 让 mcpp 停止依赖编译器的安装期配置,把「用哪份 libc」收敛成一个权威;顺带把已经污染的产物清干净,并让多 subos 构建真正可用。
Expand Down Expand Up @@ -28,11 +39,11 @@

本轮发现三处注释描述了代码没有的行为。**先让它们不能再撒谎**,否则后面每一步都可能在错误的前提上推理。

- [ ] **Step 1** 写失败单测:`find_sibling_tool` 的注释说「first (highest)」,断言**两个版本目录时返回的是排序后最高的那个**
- [ ] **Step 2** 跑,确认 FAIL(今天返回 readdir 第一个)
- [ ] **Step 3** 二选一并使注释与代码一致:①真的排序;②改注释为「未定义顺序」并让调用方不得依赖。**本计划选 ②**——T2 会让它不再被用于选版本
- [ ] **Step 4** 另两处:`fixup_gcc_specs` 的「Idempotent」(跨 home 不幂等)、`execute.cppm` reader 的「旧缓存视为 miss」(T5 修)——先把注释改成事实
- [ ] **Step 5** Commit
- [x] **Step 1** 写失败单测:`find_sibling_tool` 的注释说「first (highest)」,断言**两个版本目录时返回的是排序后最高的那个**
- [x] **Step 2** 跑,确认 FAIL(今天返回 readdir 第一个)
- [x] **Step 3** 二选一并使注释与代码一致:①真的排序;②改注释为「未定义顺序」并让调用方不得依赖。**本计划选 ②**——T2 会让它不再被用于选版本
- [x] **Step 4** 另两处:`fixup_gcc_specs` 的「Idempotent」(跨 home 不幂等)、`execute.cppm` reader 的「旧缓存视为 miss」(T5 修)——先把注释改成事实
- [x] **Step 5** Commit

---

Expand All @@ -49,11 +60,11 @@ std::optional<PayloadPaths> probe_payload_paths(
std::string_view runtimeBinding); // "glibc@2.39";空 ⇒ 不进 PayloadFirst
```

- [ ] **Step 1** 单测:给定 `glibc@2.39` 且 home 内有 2.39/2.44 两份 ⇒ **必须返回 2.39**;给定空 binding ⇒ **返回 nullopt**(不猜)
- [ ] **Step 2** 跑,FAIL
- [ ] **Step 3** 实现;`prepare.cppm` 按 `--runtime` → `[xlings] subos` 的 `subos_info.runtime` 顺序解析,末级不猜
- [ ] **Step 4** 跑,PASS
- [ ] **Step 5** Commit
- [x] **Step 1** 单测:给定 `glibc@2.39` 且 home 内有 2.39/2.44 两份 ⇒ **必须返回 2.39**;给定空 binding ⇒ **返回 nullopt**(不猜)
- [x] **Step 2** 跑,FAIL
- [x] **Step 3** 实现;`prepare.cppm` 按 `--runtime` → `[xlings] subos` 的 `subos_info.runtime` 顺序解析,末级不猜
- [x] **Step 4** 跑,PASS
- [x] **Step 5** Commit

---

Expand All @@ -63,9 +74,9 @@ std::optional<PayloadPaths> probe_payload_paths(

不加这条,切 subos 不改 fingerprint ⇒ `target/<fp>/` 被复用 ⇒ 里面是对另一份 glibc 编译的对象。**比今天更坏。**

- [ ] **Step 1** 单测:两个只有 `runtimeBinding` 不同的输入 ⇒ **fingerprint 必须不同**
- [ ] **Step 2/3/4** red → 加字段 → green
- [ ] **Step 5** Commit
- [x] **Step 1** 单测:两个只有 `runtimeBinding` 不同的输入 ⇒ **fingerprint 必须不同**
- [x] **Step 2/3/4** red → 加字段 → green
- [x] **Step 5** Commit

---

Expand All @@ -76,11 +87,11 @@ std::optional<PayloadPaths> probe_payload_paths(

**已实测**:`-Wl,--dynamic-linker` 压得过 specs;`-specs=<无 `+` 定义>` 是替换;`g++ -dumpspecs` 给内建 specs(`/tmp` 路径 0 条);真实构建(模块 + `import std` + 共享库)RUNPATH 68→2、死路径 0、可运行。

- [ ] **Step 1** e2e:gcc 构建的产物 **RUNPATH 中不得有 `/tmp/tmp.`**,且 interpreter 是权威指定的那份,且能跑
- [ ] **Step 2** 跑,FAIL(今天有 34+ 条)
- [ ] **Step 3** ①去掉 `linkmodel` 的 `if (clangDriver)` 门;②构建期生成 clean specs 到 **build dir**,`-specs=` 传入;③**删掉 `fixup_gcc_specs`**(保留 `patchelf_walk`)
- [ ] **Step 4** 跑,PASS
- [ ] **Step 5** Commit
- [x] **Step 1** e2e:gcc 构建的产物 **RUNPATH 中不得有 `/tmp/tmp.`**,且 interpreter 是权威指定的那份,且能跑
- [x] **Step 2** 跑,FAIL(今天有 34+ 条)
- [x] **Step 3** ①去掉 `linkmodel` 的 `if (clangDriver)` 门;②构建期生成 clean specs 到 **build dir**,`-specs=` 传入;③**删掉 `fixup_gcc_specs`**(保留 `patchelf_walk`)
- [x] **Step 4** 跑,PASS
- [x] **Step 5** Commit

---

Expand All @@ -90,42 +101,42 @@ std::optional<PayloadPaths> probe_payload_paths(

已在 `fix/fast-run-stale-cache-subos` 分支上完成并 18/18 CI 通过,**原样带过来**:

- [ ] **Step 1** `git cherry-pick` 该分支的三个 commit(wire format / 旧缓存 / e2e fixture)
- [ ] **Step 2** 跑单测 + e2e,确认仍绿
- [ ] **Step 3** Commit(或保留 cherry-pick 的原始提交)
- [x] **Step 1** `git cherry-pick` 该分支的三个 commit(wire format / 旧缓存 / e2e fixture)
- [x] **Step 2** 跑单测 + e2e,确认仍绿
- [x] **Step 3** Commit(或保留 cherry-pick 的原始提交)

---

### T6: D4 沙箱 xlings 版本比对 + D5 陈旧 sysroot

**Files:** `src/fallback/xlings_binary.cppm`、`src/doctor.cppm`、`src/fallback/probe_sysroot.cppm`

- [ ] **Step 1** 单测/e2e:vendored xlings 版本**低于 pin** ⇒ 被替换;**高于 pin** ⇒ 不动
- [ ] **Step 2** red
- [ ] **Step 3** 实现;doctor 增加两条 finding:①xlings 低于 pin;②`--sysroot` 指向当前项目之外
- [ ] **Step 4** green
- [ ] **Step 5** Commit
- [x] **Step 1** 单测/e2e:vendored xlings 版本**低于 pin** ⇒ 被替换;**高于 pin** ⇒ 不动
- [x] **Step 2** red
- [x] **Step 3** 实现;doctor 增加两条 finding:①xlings 低于 pin;②`--sysroot` 指向当前项目之外
- [x] **Step 4** green
- [x] **Step 5** Commit

---

### T7: 文档 + 版本 + PR

- [ ] `docs/03-toolchains.md`:权威降级链、`[xlings] subos`、多 subos 构建
- [ ] `docs/05-mcpp-toml.md`:`[xlings] subos` 与 runtime 的关系
- [ ] 中文版同步
- [ ] `MCPP_VERSION` / `mcpp.toml` → `2026.8.8.2`;`kXlingsVersion` → 最新;`check_version_pins.sh` 通过
- [ ] 全量 `mcpp test` + 关键 e2e
- [ ] 开 PR
- [x] `docs/03-toolchains.md`:权威降级链、`[xlings] subos`、多 subos 构建
- [x] `docs/05-mcpp-toml.md`:`[xlings] subos` 与 runtime 的关系
- [x] 中文版同步
- [x] `MCPP_VERSION` / `mcpp.toml` → `2026.8.8.2`;`kXlingsVersion` → 最新;`check_version_pins.sh` 通过
- [x] 全量 `mcpp test` + 关键 e2e
- [x] 开 PR

---

### T8: mcpp-index 图形栈重新落地(D1 修好之后)

**Files(mcpp-index):** `pkgs/c/compat.glx-runtime.lua`、`pkgs/c/compat.glfw.lua`

- [ ] **Step 1** 新增 e2e/验证:**装 `xim:graphics` 前后**,各跑一次与图形无关的成员,断言产物 `PT_INTERP` 与 `readelf -V` 的 glibc 符号上界**不变**。这是上次事故真正缺失的那个测试
- [ ] **Step 2** 重新应用 `f44e896` 的两个文件改动(deps 放平台层)
- [ ] **Step 3** CI 全绿后合入
- [x] **Step 1** 新增 e2e/验证:**装 `xim:graphics` 前后**,各跑一次与图形无关的成员,断言产物 `PT_INTERP` 与 `readelf -V` 的 glibc 符号上界**不变**。这是上次事故真正缺失的那个测试
- [x] **Step 2** 重新应用 `f44e896` 的两个文件改动(deps 放平台层)
- [x] **Step 3** CI 全绿后合入

---

Expand Down
Loading