Skip to content

Native musl path: dependency-package C++ module units miss the target C++-ABI include set; global build cache reuses BMIs across targets #514

Description

@yspbwx2010

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 -I set
    (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:

  1. musl build reuses a host-flavored nlohmann.json BMI → the ambiguity
    above, even with the config-file workaround in place (the poisoned BMI
    is simply reused, never recompiled).
  2. After a musl build populated the cache, a plain host mcpp build
    reused the musl/openkal-flavored BMI → same ambiguity mirrored on host.
  3. 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::FindExternalVisibleDeclsByName during 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

  1. yspbwx2010 commented on Aug 28, 2026

    @yspbwx2010
    MemberAuthor

    升到 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 可以顺带更新入口,或者在提示里带一句。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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