## 现象 `resolution.json` 记录的运行期搜索闭包**少一项**:产物自己的目录(`$ORIGIN`)不在里面。 实测(2026.8.11.3,一个消费依赖共享库的工程): ``` 记录的闭包(resolution.json → runtime.search.closure): payload <store>/xim-x-glibc/2.44/lib64 payload <store>/xim-x-gcc/16.1.0/lib64 subos_farm <home>/registry/subos/default/lib 产物真实的 DT_RPATH: …/xim-x-glibc/2.44/lib64 : …/xim-x-gcc/16.1.0/lib64 : $ORIGIN : …/subos/default/lib ^^^^^^^ 记录里没有 ``` ## 为什么这不只是"记录不全" `src/platform/runtime_search.cppm` 自称是**唯一的排序**: > Search order = decreasing immutability. This is the one invariant in this > module, and it is not stylistic. `src/build/plan.cppm:660` 进一步写着「`search::ordered` is what enforces it」。 但 `$ORIGIN` 由另一个函数(`plan.cppm` 的 `shared_library_link_flags`)在另一条通道 (per-unit flags)上发出,**从不进入闭包** —— 所以这个排序模型对**最关键的那个目录** 是装饰性的。#414 修的正是这条:farm 曾经排在 `$ORIGIN` 前面,产物链接了一份 libX11、 运行期加载了另一份。 直接后果: - `resolution.json` 与 DT_RPATH **天生不可逐项比对**。e2e 219 想做"记录 vs 产物"的 比对时因此有个结构性缺口 —— 这也是它当初把断言放宽成「最后一个**绝对路径**条目」 的由来之一(见 #414 的分析)。 - `mcpp why runtime` / `mcpp doctor` 展示的闭包不是产物真正会走的那条。 ## 建议 **只做轻档 (i)**:把产物输出目录以新的 `Origin::Artifact` 纳入闭包**记录**, `rank()` 置于 `Package` 与 `SubosFarm` 之间。 - `src/platform/runtime_search.cppm`:`Origin` 加一档 + `rank()` + `to_string()` + `is_machine_local()`(`$ORIGIN` 随产物走 ⇒ **非** machine-local) - `src/build/plan.cppm:667` `runtime_search_closure()`:加入产物输出目录 - 显示侧:`src/build/prepare.cppm:6417` 写记录、`src/doctor.cppm:703` 打标签 **不涉及 `pack`(已核)**:`is_machine_local` 全仓只有那一个生产消费方; `src/pack/pack.cppm` 不 import `mcpp.platform.runtime_search`,它自己用 patchelf 把 所有 RPATH 重写成 `$ORIGIN/../lib`。 **重档 (ii) 不建议现在做**:让闭包成为**唯一**的 rpath 生产者(把 `$ORIGIN` 的发出 也从 `shared_library_link_flags` 挪进来)才真正消灭"两个生产者",但 `$ORIGIN` 本质是 per-unit 的(只有消费共享库的单元才需要),挪进全局闭包意味着要给闭包引入 per-unit 概念,改动量与风险都明显更大。 ## 判据 e2e 219 能把「记录的闭包」与「产物的 DT_RPATH」**逐项**比对并通过,而不必对 `$ORIGIN` 做任何过滤或例外。 ## 背景 - 修复 PR: #414 - 分析: `.agents/docs/2026-08-11-runtime-search-origin-precedence-analysis.md` §4 A+
Activity
docs: 七个 issue(#412 #415 #416 #417 #418 #421 #422)的逐条核实与修复方案
fix(runtime): #415 — $ORIGIN enters the search closure, so the record…
feat(bench): cross-platform benchmark suite, and the defects it expos…
speak-agent commentedon Aug 31, 2026
已修复,随 2026.8.15.1(commit
c459cf2)发布 —— 关闭得晚了,补记在此。按 issue 建议的轻档 (i) 实施,重档 (ii) 未做,理由与 issue 写的一致:
$ORIGIN本质是 per-unit 的,把它的发出也搬进全局闭包需要给闭包引入 per-unit 概念。落地:
modules/platform/src/runtime_search.cppm——Origin增加Artifact一档,rank()为 2(落在Package与SubosFarm之间),is_machine_local()返回 false($ORIGIN随产物走),to_string()为"artifact"。runtime_search_closure()纳入产物输出目录;记录侧与mcpp why runtime/doctor的展示侧同步。tests/unit/test_runtime_search.cpp钉住 rank 的两侧不等式与is_machine_local,因为这两条是这一档存在的全部理由,而它们不会由任何构建失败报出来。判据用的是 issue 自己写的那一条,不是别的:
tests/e2e/219_runtime_search_farm_is_last.sh现在就是逐项比对,通过时打印失败信息里保留了两个方向的解释,并点名本 issue:记录里少
$ORIGIN说明Origin::Artifact不再进闭包;记录里有而产物里没有,说明它被记给了一个根本不发 rpath 的工程。pack不受影响这一点也按 issue 的核查结论确认过:src/pack/不 importmcpp.platform.runtime_search,它自己用 patchelf 把 RPATH 重写成$ORIGIN/../lib。