Commit fdad165
authored
feat: 编译器是能力,不是配置 —— payload 版本权威 + specs 污染 + xlings pin (2026.8.8.2) (#378)
一个 payload 交付两样可分离的东西:编译的**能力**,以及关于如何链接的**主张**。mcpp 要前者,后者自己给 —— 链接行才是构建决策该待的地方,因为它是逐次构建而变的那一个。四个看起来无关的缺陷收敛到这一条上。
设计:`.agents/docs/2026-08-08-payload-version-and-contract-drift-design.md`(含 §9 实施回写)。替代已关闭的 #377。
## 1. 产物加载哪个 glibc,由权威决定,不再靠目录顺序
旧规则向目录问「那个 glibc」并取 `readdir` 的第一项。只装一个时它永远正确,所以从没有东西逼它正确 —— 而一条带 `xim:glibc@>=2.38` 的依赖就足以装进第二个。mcpp-index 上真实发生过:编译侧取 2.44,产物 interpreter(冻结在 gcc specs 里)仍是 2.39,二进制引用 `GLIBC_2.42` 却跑在没有它的运行时上,**报错落在与那条依赖无关的包上**。
解析顺序:`[xlings] subos` 自述 → 活动 subos 自述 → 兼容记录(specs / cfg / **PT_INTERP**)→ 单例 payload。计入工具链指纹(11 字段)。
两条判据是落地时被 CI 逼出来的,已写回设计:
- **没得选就不算猜。** 恰好一个 glibc payload 时没有选择可言,拒答等于拒答一个只有一个答案的问题。两个及以上才沉默 —— 那才是事故的形状。
- **化石不算权威。** `specs`/`.cfg`/`PT_INTERP` 都是过去某刻的记录,payload 被换掉时没人回头改。一条记录只有在它指的东西还在,才算数。subos 自己的声明同样适用。
把「查不到」也当成「有歧义」的代价是产物掉到宿主 loader —— 比猜错版本更糟,因为它连沙箱都出去了。
## 2. 不再改写 GCC 的 `specs`
旧重写用单路径 needle 配双路径 replacement,每个跑过它的 home 都漏下一条:一台开发机产出的**每个** gcc 产物里都带 **68 条**陈旧 `RUNPATH`,全指向已删除的 `mktemp` 目录。没有东西发现它们,因为一条死 RUNPATH 只多花一点搜索时间。
改为 `-specs=` 一份逐构建生成的干净文件(`-dumpspecs` 取**内建** `*link:`,去掉 loader/rpath)。不带 `+` 的 `-specs=` 是**替换**,payload 分毫未动。逐构建、不需写权限,继承来的只读 payload 也能用。
删掉 `*link:` 也删掉了它提供的东西,因此 loader 与每条 rpath 由 mcpp 显式写在链接行上 —— 包括**编译器自己的 `lib64`**(`libgcc_s.so.1` 在那)。
## 3. 落后于 pin 的 vendored xlings 会被替换 —— 但只在替换品确实更新时
一个 home 会永远留着第一次获取的 xlings(实测 2026.8.2.1 对 pin 2026.8.6.3)。`subos_info` 是 2026.8.5.1 才有的,所以那台机器上 subos 的自述一直被太旧的客户端丢弃,#352 的修复无论 mcpp 多新都无法生效。
修复的第一版直接删了重取,把 2026.8.2.1 换成系统的 **0.4.51** —— 更旧、且同样缺那个特性。现在先给替换品定价再动手。
## 4. `--sysroot` 的判据从「存在」改为「归属」
gcc 把 `--sysroot=<...>/.xlings/subos/default` 当字符串烙进去,而一台机器上有很多同名目录 —— 烙入的路径经常**存在、却属于另一个 checkout**。实测:本仓库的构建解析到了无关仓库下的 sysroot。归属先于可用性。
---
## 验证
| | |
|---|---|
| 单测 | **67/67**(新增 5 个文件、28 条断言) |
| 本地全量 e2e | **186 passed / 6 failed / 8 skipped**,6 个失败全在已记录基线内(03/09/20/33/59/98),其中 03/09/20/155/184 逐一用**已发布的 2026.8.6.3** 复现确认;`178` 反而转绿 |
| CI | **18/18 全绿** |
| 版本 | 2026.8.8.2;xlings pin → 2026.8.7.1(索引最新;上游 2026.8.8.1 未收录,pin 过去会让 CI 装不到) |
runtime binding 四条来源逐条实测:新建自述 subos、注入 `glibc@2.99`(不存在)、挪开 `specs` **且**把 gcc 自身 `PT_INTERP` 改指宿主、三条来源全打掉只剩单例。
## 这一轮真正的教训
**十轮 CI 抓出 11 个缺陷,其中 8 个在本地定向子集全绿时不可见。** 形状高度一致:修补落在控制流或本机状态到不了的地方。
- 兼容回落读的是**本 PR 让 mcpp 不再写**的文件 —— 每台老机器都还留着它,所以本机永远绿
- 归属谓词加在 `probe_sysroot` **第一步就 return 掉**的函数里
- `--no-cache` 删 `target/`,带走了我放进去的 spec;e2e 201 只跑暖构建,**那个专为此机制存在的测试看不见它**
- 我给 201 加的 PayloadFirst 分支,**把修复拿掉后照样通过** —— 本机 gcc 的 baked sysroot 指向另一个仓库且存在,把它拉回了 Sysroot 模式。守卫因此改成**指名模式**的单测,并逐一验证过红→绿
- 判据本身也错过:**「跑不跑得起来」在任何有宿主工具链的机器上都是 yes**,哪怕产物正在偷用宿主的库。换成「是否从 `/lib`、`/usr/lib` 加载任何库」
- 最后一条是**误报**:`ldd` 用宿主 loader 内省,总把 payload 解释器报成解析到宿主 —— 一个会拦下正确工作的检查,代价一样大
以及一个低级错误:`mcpp.toml` 的 `[toolchain] default` 被本地试验写成 llvm,`git add -A` 一起提交,五个 job 连带失败。**多个 job 同时开始失败,几乎总是指向一处共同输入被改动。**1 parent 463dedf commit fdad165
43 files changed
Lines changed: 2691 additions & 190 deletions
File tree
- .agents/docs
- .github
- actions
- bootstrap-mcpp
- setup-macos-llvm
- workflows
- docs
- zh
- src
- build
- fallback
- toolchain
- xlings
- tests
- e2e
- unit
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 148 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
0 commit comments