Skip to content

fix: resolve LLVM toolchain install failure on Linux#61

Open
Sunrisepeak wants to merge 12 commits into
mainfrom
fix/llvm-toolchain-install
Open

fix: resolve LLVM toolchain install failure on Linux#61
Sunrisepeak wants to merge 12 commits into
mainfrom
fix/llvm-toolchain-install

Conversation

@Sunrisepeak
Copy link
Copy Markdown
Member

Summary

  • Use direct xlings install -y on all platforms (not just Windows) for reliable large package installation
  • Extend global xlings directory fallback from Windows-only to all platforms
  • Add CI smoke test for mcpp toolchain install llvm + build

Problem

mcpp toolchain install llvm fails with "xpkg payload missing" on Linux. Dependencies (libxml2, zlib) install fine but LLVM (~800MB) doesn't. Root cause: </dev/null stdin closure and NDJSON interface mode break xlings subprocess coordination for large packages.

Test plan

  • CI passes on all three platforms
  • New "Toolchain install smoke test" step passes on Linux
  • Existing tests unaffected

Three fixes for `mcpp toolchain install llvm` failing with
"xpkg payload missing":

1. install_with_progress(): use direct `xlings install -y` command
   on ALL platforms (not just Windows). The direct command avoids
   stdin closure (</dev/null) that breaks xlings subprocess
   coordination for large packages like LLVM (~800MB). Falls back
   to NDJSON interface path if direct install fails.

2. package_fetcher.cppm: extend the global xlings directory fallback
   from Windows-only to all platforms. If xlings installs a package
   to ~/.xlings/ instead of the mcpp sandbox, detect and copy it.

3. ci.yml: add "Toolchain install smoke test" step that exercises
   `mcpp toolchain install llvm` + build with it. This core user
   flow was previously untested in CI.
Also replace raw WIFEXITED/WEXITSTATUS with
platform::process::extract_exit_code() in xlings.cppm.
The added import changed the module dependency graph fingerprint,
invalidating BMI cache on macOS CI and exposing a pre-existing
Xcode 16.4 SDK incompatibility during std module precompilation.

Use #if defined(_WIN32) instead of if constexpr for the USERPROFILE
check to avoid changing the module import set.
macOS CI was missing the MCPP_HOME job-level env var that Linux CI
has. The freshly-built mcpp resolved to a fresh ~/.mcpp/ sandbox,
triggering a clean std module precompile that exposed a pre-existing
Xcode 16.4 + LLVM 20.1.7 sysroot incompatibility.

Fix: set MCPP_HOME=/Users/runner/.mcpp (consistent with Linux CI)
and export MCPP_VENDORED_XLINGS in the test step so the sandbox
reuses the pre-installed xlings binary.
Root cause: probe_sysroot() falls back to xcrun --show-sdk-path on
macOS when the compiler doesn't report a sysroot via -print-sysroot.
For xlings-installed LLVM 20.1.7, this sets --sysroot to the Xcode
SDK path. Combined with -nostdinc++ from clang++.cfg, this breaks
C runtime header resolution — macOS SDK headers reference internal
macros (_CTYPE_A, etc.) that are only defined via default include
paths which --sysroot overrides.

Fix: remove the xcrun SDK fallback in probe_sysroot(). If the
compiler itself doesn't report a sysroot, none should be used.
The xcrun fallback was designed for Apple's system clang, not for
standalone xlings LLVM which provides its own libc++ headers.

Also revert the ci-macos.yml MCPP_HOME workaround — the real bug
is fixed, no workaround needed.
probe_sysroot() called -print-sysroot first, which on macOS with
xlings LLVM just echoed back the --sysroot from clang++.cfg. That
cfg-baked path points to CommandLineTools SDK, which may differ from
the active Xcode SDK. When the two SDKs have different header
versions, std module precompilation fails with undeclared _CTYPE_A
and related C runtime macro errors.

Fix: on macOS, probe xcrun --show-sdk-path FIRST (always returns the
active SDK), then fall back to -print-sysroot for non-macOS. The
xcrun sysroot passed on the command line overrides the cfg-baked one.
Root cause: on macOS, xlings LLVM's clang++.cfg already contains a
--sysroot for the macOS SDK. When mcpp additionally passes --sysroot
on the command line during std module precompilation, it changes the
C header include ordering. The macOS SDK's ___wctype.h references
_CTYPE_A (defined in _ctype.h), but the duplicate --sysroot flag
prevents _ctype.h from being included transitively during module
purview compilation, causing "undeclared identifier '_CTYPE_A'" errors.

Fix: detect apple/darwin target triple in stdmod.cppm and skip the
--sysroot flag for std module precompile. The cfg's own --sysroot
handles macOS SDK discovery correctly for this compilation mode.
Regular compilation (flags.cppm) and linking still use the probed
sysroot as before.

Also restore probe_sysroot() to its original logic (xcrun fallback)
since the issue was in stdmod.cppm passing sysroot, not in probing it.
The previous fix skipped --sysroot entirely on macOS, but xlings
LLVM's clang++.cfg still applies its own --sysroot pointing to
CommandLineTools SDK. When the active SDK is Xcode (different path),
the cfg's stale sysroot causes _CTYPE_A undeclared errors.

Fix: on macOS, always probe xcrun and pass the active SDK as
--sysroot to OVERRIDE the cfg-baked stale path. This ensures the
std module precompile uses the correct SDK regardless of what was
baked into clang++.cfg at LLVM install time.
CI step 9 proves that clang++ WITHOUT explicit --sysroot precompiles
std.cppm correctly on macOS — the clang++.cfg's built-in --sysroot
and -isystem flags handle SDK header resolution properly.

When mcpp passes an explicit --sysroot (even the identical value),
it changes Clang's internal header search order, breaking the
transitive inclusion of _ctype.h before ___wctype.h. The macOS SDK's
___wctype.h references _CTYPE_A which is only defined via the
default cfg-driven include chain.

Fix: detect apple/darwin target and skip --sysroot for std module
precompile, letting clang++.cfg handle it. Non-macOS platforms
(Linux, Windows) continue to use the probed sysroot as before.
When xlings copies LLVM to mcpp's sandbox, clang++.cfg retains
hardcoded absolute paths from the original install (--sysroot and
-isystem pointing to ~/.xlings/... instead of ~/.mcpp/...). These
stale paths cause _CTYPE_A undeclared errors during std module
precompilation.

Fix: on macOS Clang, pass --no-default-config to ignore the stale
cfg, then explicitly provide the correct -isystem (libc++ headers
from the sandbox LLVM root) and --sysroot (active SDK from xcrun).
This produces the same header search behavior as a fresh clang++
invocation with the correct paths.
The stale clang++.cfg issue affects not just std module precompile
but also regular compilation via ninja. flags.cppm now applies the
same --no-default-config + correct -isystem + xcrun --sysroot fix
for all macOS Clang compilation, bypassing the cfg's stale paths.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant