摘要
E2b(binutils 载荷里的 ld 包装器)一次追加三样东西:
exec <real-ld> "$@" -rpath "$XLINGS_SUBOS_LIB" -rpath-link "$XLINGS_SUBOS_LIB" --disable-new-dtags
标签那一样 mcpp 需要且已自己实现;路径那一样 mcpp 必须能不要。
这条要在 E2b 落地之前谈妥,否则它落地当天就会给 mcpp 造出一个新缺陷。
mcpp 侧的实现已发布(2026.8.10.2,PR mcpp-community/mcpp#408):
可执行文件 DT_RPATH、共享库保持 DT_RUNPATH,链接期与 mcpp pack 的 patchelf 期
读同一条契约,并在 resolution.json 留 loader_tags 记录(warn-first)。
为什么 mcpp 自己做标签那一半
不是不信任 E2b,是覆盖面不同。mcpp 有大量不经过那个 ld 的链路:
交叉 musl / mingw、-fuse-ld=lld、gcc@system / msvc@system、host 工具子构建。
而且 mcpp 要能在自己的 e2e 里断言它。两者同向(都是 --disable-new-dtags),
后出现者胜出,不冲突。
反过来,E2b 仍然是必要的 —— mcpp 覆盖不到的恰恰是 xlings 的定位承诺:
用户手敲 gcc -lGL(E2 自己的验收判据就是「用户零 flag」)、从源码构建的 xim recipe、
subos 里的 cmake / meson / xmake / cargo 工程。
为什么 mcpp 必须能拒绝路径那一半(实测)
① mcpp 确实链过 xlings 的 ld —— 所以包装器会作用到 mcpp:
$ <xim-x-gcc>/bin/g++ -print-prog-name=ld
ld # 载荷里没有自带 ld,从 PATH 解析 ⇒ 就是 xim binutils 那个
② <subos>/lib 是一个带 libc 的目录(199 个条目里):
ld-linux-x86-64.so.2 libc.so.6 libm.so.6 libpthread.so.0 crt1.o crti.o crtn.o
mcpp 的 Rule A/B 闭包校验(mcpp#396 / #400)要求解释器 + 直接/传递 libc 与
同一个 RuntimeBinding 一致。一条未经审查的、带 libc 的目录进 RPATH,
要么触发 mcpp 自己的守卫、要么在运行期静默选错 libc。
mcpp pack 更是必须把它剥掉 —— 产物不得残留构建机绝对路径。
请求
-
E2b 给出一条声明式的退出,让消费方能只要标签、不要路径。
E1c 已经立过规矩:退出必须是声明出来的,不能靠推断,
也不能靠「某个工具重写 spec 去对抗另一个工具的默认值」。
若 E2b 无退出即落地,mcpp 的 pack 产物会被烙进一条 store 绝对路径。
-
E2a(XLINGS_SUBOS_LIB 契约声明)对 mcpp 有独立价值:
有它 mcpp 读声明,没有它 mcpp 只能硬编码 <subos>/lib —— 那又是一处
「同一决策两处推导」。
顺带:一条独立佐证 §3.1 的现场证据
这台机器上共享 gcc 载荷的 specs 已被历次安装累积污染:
--dynamic-linker → <store>/xim-x-glibc/2.44/lib64/ld-linux-x86-64.so.2 ← 该目录已被改名走
rpath → 约 40 条 /tmp/tmp.XXXXXX/mcpphome/…(全部来自已删除的沙箱)
libraries(-print-search-dirs) → 指向**另一个工程**的 subos
后果:每个 build.mcpp helper 的 PT_INTERP 指向不存在的加载器,
posix_spawnp 返回 ENOENT。这与 mcpp 版本无关(已发布的 2026.8.8.2 同样复现),
但它正是「specs 是共享可变状态,不能承载契约」的实物。
摘要
E2b(binutils 载荷里的
ld包装器)一次追加三样东西:标签那一样 mcpp 需要且已自己实现;路径那一样 mcpp 必须能不要。
这条要在 E2b 落地之前谈妥,否则它落地当天就会给 mcpp 造出一个新缺陷。
mcpp 侧的实现已发布(
2026.8.10.2,PR mcpp-community/mcpp#408):可执行文件 DT_RPATH、共享库保持 DT_RUNPATH,链接期与
mcpp pack的 patchelf 期读同一条契约,并在
resolution.json留loader_tags记录(warn-first)。为什么 mcpp 自己做标签那一半
不是不信任 E2b,是覆盖面不同。mcpp 有大量不经过那个
ld的链路:交叉 musl / mingw、
-fuse-ld=lld、gcc@system/msvc@system、host 工具子构建。而且 mcpp 要能在自己的 e2e 里断言它。两者同向(都是
--disable-new-dtags),后出现者胜出,不冲突。
反过来,E2b 仍然是必要的 —— mcpp 覆盖不到的恰恰是 xlings 的定位承诺:
用户手敲
gcc -lGL(E2 自己的验收判据就是「用户零 flag」)、从源码构建的 xim recipe、subos 里的 cmake / meson / xmake / cargo 工程。
为什么 mcpp 必须能拒绝路径那一半(实测)
① mcpp 确实链过 xlings 的
ld—— 所以包装器会作用到 mcpp:②
<subos>/lib是一个带 libc 的目录(199 个条目里):mcpp 的 Rule A/B 闭包校验(mcpp#396 / #400)要求解释器 + 直接/传递 libc 与
同一个 RuntimeBinding 一致。一条未经审查的、带 libc 的目录进 RPATH,
要么触发 mcpp 自己的守卫、要么在运行期静默选错 libc。
mcpp pack更是必须把它剥掉 —— 产物不得残留构建机绝对路径。请求
E2b 给出一条声明式的退出,让消费方能只要标签、不要路径。
E1c 已经立过规矩:退出必须是声明出来的,不能靠推断,
也不能靠「某个工具重写 spec 去对抗另一个工具的默认值」。
若 E2b 无退出即落地,mcpp 的 pack 产物会被烙进一条 store 绝对路径。
E2a(
XLINGS_SUBOS_LIB契约声明)对 mcpp 有独立价值:有它 mcpp 读声明,没有它 mcpp 只能硬编码
<subos>/lib—— 那又是一处「同一决策两处推导」。
顺带:一条独立佐证 §3.1 的现场证据
这台机器上共享 gcc 载荷的 specs 已被历次安装累积污染:
后果:每个
build.mcpphelper 的 PT_INTERP 指向不存在的加载器,posix_spawnp返回 ENOENT。这与 mcpp 版本无关(已发布的2026.8.8.2同样复现),但它正是「specs 是共享可变状态,不能承载契约」的实物。