Skip to content

[Linux] mcpp run 无法启动:私有 glibc 2.39 与系统库 GLIBC 版本冲突,以及切换 glibc 2.44 过程中的排查与发现 #392

Description

@FarnaHerry

环境

  • OS:Linux 6.6.87.2-microsoft-standard-WSL2(WSL2,系统 Mesa)
  • mcpp 2026.8.8.2,xlings 2026.8.8.1
  • subos:default,runtime glibc@2.39
  • toolchain:llvm@22.1.8(xim-x-llvm)
  • 系统 glibc 2.43(run.sh 注释记录);系统 /lib64/libtinfo.so.6 需要 GLIBC_2.42,系统 Mesa 需要 GLIBC_2.43

现象

mcpp run 静默退出,exit 1:
sh: /home/farna/.mcpp/registry/data/xpkgs/xim-x-glibc/2.39/lib64/libc.so.6: version `GLIBC_2.42' not found (required by /lib64/libtinfo.so.6)
用 ./run.sh(显式用系统 /lib64/ld-linux-x86-64.so.2 启动)可正常运行 → 问题定位在 mcpp 私有 glibc 与系统库不兼容,而非应用代码。

根因

  1. llvm@22.1.8/bin/clang.cfg(以及 clang++.cfg / clang-22.cfg)把链接参数全部硬编码到私有 glibc 2.39:
    -B…/xim-x-glibc/2.39/lib64
    -L…/xim-x-glibc/2.39/lib64
    -Wl,--dynamic-linker=…/2.39/lib64/ld-linux-x86-64.so.2
    -Wl,-rpath,…/2.39/lib64
    -isystem …/2.39/include
  2. 因此产物 PT_INTERP 指向 2.39/ld-linux-x86-64.so.2,RUNPATH 也带 2.39 lib64。
  3. 系统库版本高于 2.39:libtinfo.so.6 要 GLIBC_2.42,系统 Mesa 要 GLIBC_2.43。
  4. 2.39 进程加载系统库 → 动态链接器报版本不够 → 进程静默退出。
  5. 这是 xim/xlings 的有意设计:glibc 包的 la 确说明 moving to 2.44 是"deliberatedecision",2.44 为 opt-in)。所以这不是简单升级能解决的默认行为。

修复:切到 glibc 2.44

2.44 > 2.43 > 2.42,私有 libc 自身满足全部系统库要求 → mcpp run 原生可启动。

改动(都在 ~/.mcpp / ~/.xlings,仓库代码零改动):

  1. ~/.xlings/subos/default/.xlings.json:"runtime": "glibc@2.39" →
    "glibc@2.44"。解析层据此更新(.xlings-resolu4,subos lib 软链 crt1.o/ld-linux/libc.so.6等全部指向 2.44)。
  2. xim-x-llvm/22.1.8/.xpkg.lua:"xim:glibc@>=2.39" → ">=2.44"(依赖约束同步)。
  3. 删除 xim-x-glibc/2.39/(决定性步骤,见机
  4. mcpp clean --bmi-cache + 全量重建:清掉焊(不清的话编译仍报 cannot open…/2.39/include/…),并让所有产物重新链接到 2.44。

机制发现(重点,建议 mcpp/xlings 侧跟进)

metic fixup 的 glibc 选择不读取 resolver 记录,而是扫描 xim-x-glibc/ 目录取"字典序第一个"版本目录,用它重新生成 clang.cfg 与 .mcpp-fixup.json。

实证链:

  • 把 runtime 改成 2.44、解析层已到 2.44 后,每次 mcpp clean 构建仍把 clang.cfg 重写成 2.39(fixup 重新生成)。
  • 手改 clang.cfg / .mcpp-fixup.json 都会被下一次 clean build 覆盖回 2.39。
  • 把 2.39 改名 2.39.off:fixup 仍选中它(2.39.off 字典序仍小于 2.44),产物路径直接变成 …/2.39.off/…。
  • 只有把 2.39 移出 xim-x-glibc/ 目录、让扫描只剩 2.44,fixup 才落到 2.44。

后果:只要 registry 里存在 2.39,无论 subos runtime 怎么配,clean build 后 toolchain 都会悄悄回到 2.39。建议 fixup 优先采用 resolver 的版本选择,或至少按语义化版本(而非字典序)排序。

切换后的状态与副作用

  • ✅ 二进制 PT_INTERP / RUNPATH 均指向 2.44;mcpp run 正常启动(tinynext 为 mcpp 直接子进程,3/3
    次测试稳定存活);aria2 引擎走 posix_spawn, 。
  • ⚠️ 新问题 A(2.44 载荷兼容性):2.44 的 libc.so.6 将 __pointer_chk_guard 作为 UND 引用、不导出 GLIBC_PRIVATE 全局符号,而系统 bash 需要它。mcpp run 会把 toolchain 库路径(含 2.44 lib64)放进 LD_LIBRARY_PATH 传给子进程 → 应用内所有 bash 调用失败(symbol lookup error: __pointer_chk_guard, version GLIBC_PRIVATE),影响 xdg-open(打开文件/文件夹/URL)、notify-send(通知)、gio trash(回收站)、深色模式 popen 探测。tinynext 自身不引用该符号,故主进程不受影响。
  • ⚠️ 新问题 B(run.sh 回归):2.44 链接的二进制在系统 ld.so (2.43) 下静默退出——2.43 供不起 2.44 引入的符号。此前唯一能跑的 run.sh 路径失效。
  • ⚠️ 脆弱点:索引中 glibc 的 latest 仍是 2.39;若某次解析/重装把 2.39 拉回 registry,fixup 扫描会让 toolchain 悄悄回退 2.39,需人工再删。

建议

  1. mcpp/xlings:fixup 的 glibc 定位改为读 re 避免字典序扫描带来的静默回退。
  2. 2.44 载荷:核查 __pointer_chk_guard 的 GLIBC_PRIVATE 导出,保证与系统 bash 等常见二进制的兼容性。
  3. 用户侧:若需要完整 bash 功能,可在应用 shell-out(system/popen)前 unsetenv("LD_LIBRARY_PATH")(应用自身的 RUNPATH 已足够)。

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