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.

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