Skip to content

host tool 链接 shared 依赖后无法运行:.so 未被 stage 到工具旁边(且会被 subos 同名库悄悄顶上) #535

Description

@Sunrisepeak

概述

kind = "bin"host tool 如果依赖一个 kind = "shared" 的包,构建出的可执行文件带着一条没人满足的 DT_NEEDED:mcpp 不会把那个 .so 放到工具旁边,子构建的 bin/ 里只有可执行文件本身。工具随后被 build.mcpp 调用时直接起不来。

实测环境:mcpp 2026.8.27.2


复现

一个 host tool 包(freedesktop.wayland-scanner,mcpplibs/mcpp-index#290):

[targets.wayland-scanner]
kind = "bin"
main = "../../upstream/src/scanner.c"

[dependencies]
compat.expat = "2.7.1"     # kind = "shared", soname = libexpat.so.1

另一个包用 tools = ["wayland-scanner"] 请求它,并在自己的 build.mcpp 里执行。

结果

    Building host tool wayland-scanner:wayland-scanner from wayland-scanner v1.26.0
error: dependency 'wayland': build.mcpp exited with 1 (build aborted):
/home/runner/.mcpp/build-cache/v1/tool/freedesktop/wayland-scanner@1.26.0/…/bin/wayland-scanner:
  error while loading shared libraries: libexpat.so.1: cannot open shared object file: No such file or directory

子构建的产物

$ ls <build-cache>/v1/tool/freedesktop/wayland-scanner@1.26.0/<hash>/bin/
wayland-scanner            # 只有它

$ find <build-cache>/v1/tool/freedesktop/wayland-scanner@1.26.0/<hash> -name 'libexpat*'
(无)

工具确实链了它:

$ readelf -d wayland-scanner | grep -E 'NEEDED|RPATH'
 (NEEDED)   Shared library: [libexpat.so.1]
 (NEEDED)   Shared library: [libc.so.6]
 (RPATH)    Library rpath: [<store>/xim-x-glibc/2.44/lib64:<store>/xim-x-gcc/16.1.0/lib64:$ORIGIN:<registry>/subos/default/lib]

RPATH 里有 $ORIGIN,但那个目录里没有 .so;依赖包建出来的 libexpat.so.1 没有被搬过去。


更糟的一面:在开发机上它「成功」

RPATH 的最后一项是 <registry>/subos/default/lib装了图形栈的机器上那里正好有一个 libexpat.so.1 —— 是 xim:expat(Mesa 的传递依赖)的那一份。于是工具照常启动,只不过链的是另一个库的另一个版本:

$ ld.so --list wayland-scanner | grep expat
libexpat.so.1 => <registry>/subos/default/lib/libexpat.so.1   # xim:expat 2.6.2,不是 compat.expat 2.7.1

所以:开发机绿、干净 runner 红,而且开发机上那次"成功"用的根本不是声明的那个依赖。这比直接失败更难发现。


影响

任何"自己构建、在 build.mcpp 里运行"的代码生成器都会踩到 —— 而这正是 host tool 存在的意义。目前只能靠让被依赖的包用 kind = "lib" 绕开(mcpplibs/mcpp-index#291 就是这么做的),但那把一个本该由消费场景决定的形态,变成了包作者必须提前替所有消费者做的决定:同一个包既要能被 host tool 静态链、又可能需要作为进程里唯一的 .so 被别人共享。

[build] dependency_linkage / per-dependency linkage(#519)看起来正是这一根轴,但它在 2026.8.27.2 之后才有,而索引的 floor 就是 2026.8.27.2。

建议

host tool 子构建把它的 shared 依赖产物 stage 到工具旁边($ORIGIN 已经在 RPATH 里,所以放过去就够),或者在 tool 的 RPATH 里指向那些 .so 的实际产出目录。

另外值得考虑:让 <registry>/subos/default/lib 不要出现在 host tool 的 RPATH 里,否则一个缺失的依赖会被 subos 里同名的库悄悄顶上 —— 上面那个「开发机成功」就是这么来的。


相关

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions