现象
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、
运行期加载了另一份。
直接后果:
建议
只做轻档 (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 做任何过滤或例外。
背景
现象
resolution.json记录的运行期搜索闭包少一项:产物自己的目录($ORIGIN)不在里面。实测(2026.8.11.3,一个消费依赖共享库的工程):
为什么这不只是"记录不全"
src/platform/runtime_search.cppm自称是唯一的排序:src/build/plan.cppm:660进一步写着「search::orderedis what enforces it」。但
$ORIGIN由另一个函数(plan.cppm的shared_library_link_flags)在另一条通道(per-unit flags)上发出,从不进入闭包 —— 所以这个排序模型对最关键的那个目录
是装饰性的。#414 修的正是这条:farm 曾经排在
$ORIGIN前面,产物链接了一份 libX11、运行期加载了另一份。
直接后果:
resolution.json与 DT_RPATH 天生不可逐项比对。e2e 219 想做"记录 vs 产物"的比对时因此有个结构性缺口 —— 这也是它当初把断言放宽成「最后一个绝对路径条目」
的由来之一(见 fix: 产物必须加载它链接的那一份库 —— 链接行顺序成为声明,共享库不再劫持运行时 (2026.8.11.3) #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:667runtime_search_closure():加入产物输出目录src/build/prepare.cppm:6417写记录、src/doctor.cppm:703打标签不涉及
pack(已核):is_machine_local全仓只有那一个生产消费方;src/pack/pack.cppm不 importmcpp.platform.runtime_search,它自己用 patchelf 把所有 RPATH 重写成
$ORIGIN/../lib。重档 (ii) 不建议现在做:让闭包成为唯一的 rpath 生产者(把
$ORIGIN的发出也从
shared_library_link_flags挪进来)才真正消灭"两个生产者",但$ORIGIN本质是per-unit 的(只有消费共享库的单元才需要),挪进全局闭包意味着要给闭包引入 per-unit
概念,改动量与风险都明显更大。
判据
e2e 219 能把「记录的闭包」与「产物的 DT_RPATH」逐项比对并通过,而不必对
$ORIGIN做任何过滤或例外。背景
.agents/docs/2026-08-11-runtime-search-origin-precedence-analysis.md§4 A+