Repository navigation
Native musl path: dependency-package C++ module units miss the target C++-ABI include set; global build cache reuses BMIs across targets #514
Description
Follow-up to the native-path guidance in #492 — thanks for v2026.8.26.2 and
openkal-llvm-runtime; the single-package flow works as documented (static
ELF, no PT_INTERP, qemu-verified). Scaling it to a 7-member C++23 modules
workspace surfaced two engine-side gaps. Verified on mcpp v2026.8.26.2,
llvm@22.1.8, x86_64-linux-musl, openkal-llvm-runtime@0.1.3.
A. Dependency-package module units don't get the openkal include set
With --target x86_64-linux-musl and openkal in the graph:
- Workspace-member units correctly receive the full openkal
-Iset
(libcxx/libcxxabi/libunwind includes, musl arch/generated dirs, port
includes — 18 dirs). - Dependency-package module units (e.g.
nlohmann.json's generated
module unit) receive none of it. They fall back to the clang driver's
default C++ headers — the toolchain's own libc++, configured for glibc.
Result: the std module BMI is openkal-flavored (correct — mcpp builds it
from openkal's llvm-generated/std.cppm), while dependency BMIs are
xim/glibc-flavored. Any TU importing both flavors fails on the first
template instantiation that touches declarations present in both header
sets:
.../include/c++/v1/istream:1245:26: error: reference to 'space' is ambiguous
note: candidate ... xim-x-llvm/22.1.8/include/c++/v1/__locale:321
note: candidate ... openkal-llvm-runtime-0.1.3/llvm/libcxx/include/__locale:302
Reproduces with: member A import std; + import nlohmann.json; +
stream >> token;.
Things that do not change this (tried): [target.<triple>].cxxflags
(doesn't propagate to dependency units), mcpp toolchain default llvm@22.1.8,
--cache local.
A second wrinkle: when other mcpp homes exist on the machine (~/.mcpp, a
project-local legacy home), dependency-unit configuration picks up their
host toolchain include set (xim libc++ + glibc + linux-headers -isystem
rows appear verbatim in compile_commands.json) even though MCPP_HOME
points elsewhere and the build is --target musl. With those homes removed
the units fall back to driver defaults as described above. The chosen
flavor also sticks in target/<triple>/*/resolution.json across runs.
Workaround we ship with (works, full workspace compiles + links
statically): a per-triple clang config file
$MCPP_HOME/registry/data/xpkgs/xim-x-llvm/22.1.8/bin/x86_64-unknown-linux-musl-clang++.cfg
containing the same 18 -I lines members get. Members re-receiving them is
a harmless dedup. Note it must be the -clang++.cfg name only — a bare
<triple>.cfg also applies to C compiles and breaks them (musl's internal
src/include headers use the hidden macro and must not be visible to
plain C dependency builds like mbedtls).
Suggested fix: pass the same target C++-ABI include set to dependency
package units that member units already get (and scope home discovery to
MCPP_HOME).
B. Global build-cache key omits the target axis
build-cache/v1/pkg/<ns>/<pkg>@<ver>/<hash> hits the same entry for host
and musl builds of the same dependency. Both directions observed:
- musl build reuses a host-flavored
nlohmann.jsonBMI → the ambiguity
above, even with the config-file workaround in place (the poisoned BMI
is simply reused, never recompiled). - After a musl build populated the cache, a plain host
mcpp build
reused the musl/openkal-flavored BMI → same ambiguity mirrored on host. - Worst form: two host builds with a changed configuration axis
(dependency graph edited; glibc headers resolved from a different home,
2.39 vs 2.44) still hit the same cache entry — the mixed BMIs then
crash the clang frontend outright (SIGSEGV in
ASTReader::FindExternalVisibleDeclsByNameduring deserialization)
instead of producing a readable diagnostic.
Workaround: purge the C++ dependency entries under build-cache/v1/pkg/
(and build-cache/v1/std) when switching targets or editing the
dependency graph. Suggested fix: include the target/C++-ABI/header-set
axis in the cache key.
Happy to provide full logs / compile_commands diffs.
Activity
2026.8.27.1 —— 目标侧被解析出来了,只发给了一个编译单元
fix: 头集轴把这台机器的 home 写进了键(自我 review 实测)
Sunrisepeak commentedon Aug 27, 2026
@yspbwx2010
xlings update mcpp -y更新mcpp到最新版本, 然后使用 llvm runtime 0.3.0 版本,重新尝试hiddenvisibility macro into consumer include paths mcpplibs/openkal-musl#13yspbwx2010 commentedon Aug 28, 2026
升到 mcpp 2026.8.28.1 + openkal-llvm-runtime 0.3.0 跑了一遍(openkal-musl 解析到 0.5.0),F1 没复现。
mcpp build --target x86_64-linux-musl七个成员全过,零 error 零 warning,341s,其中 openkal-llvm-runtime 244 units。之前必踩的reference to 'space' is ambiguous(istream:1245)一次都没出现,nlohmann.json、tinyhttps、ftxui、mbedtls、zlib、tomlplusplus 这些 compat 包的模块单元都正常拿到头集了。产物静态链接,
readelf -l零 INTERP,ldd 说不是动态可执行文件。F2 也没观察到,两个目标各自 fingerprint,切目标时如实报
fingerprint changed → full rebuild。顺带说一下环境:这次是干净的。前两次的结论有问题——克隆沙箱之后 payload 里的 .cfg 还写着原来 home 的绝对路径,试验项目又放在了有 .mcpp 祖先的目录下,环境串了。这次新建了一个独立的 mcpp 家,旧的原样留着没动。
还有个小地方,
xlings update mcpp -y在我这个家里只更新了索引,然后提示xim:mcpp is not installed — run: xlings install mcpp。装完之后二进制在registry/data/xpkgs/xim-x-mcpp/2026.8.28.1/bin/mcpp,但<home>/bin/mcpp还是旧文件,得手动换过去才生效。不知道这个家的形态是不是预期内的,如果是,也许 install 可以顺带更新入口,或者在提示里带一句。Resolve the target side once, and let every translation unit read it (m…