Skip to content

Commit 1838fb2

Browse files
committed
fix: skip --sysroot for std module precompile on macOS
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.
1 parent e345067 commit 1838fb2

2 files changed

Lines changed: 18 additions & 10 deletions

File tree

src/toolchain/probe.cppm

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -254,15 +254,6 @@ probe_target_triple(const std::filesystem::path& compilerBin,
254254
std::filesystem::path
255255
probe_sysroot(const std::filesystem::path& compilerBin,
256256
const std::string& envPrefix) {
257-
// macOS: prefer xcrun's SDK path over -print-sysroot.
258-
// xlings LLVM bakes --sysroot into clang++.cfg at install time, and
259-
// -print-sysroot echoes that back. If the CLT/Xcode SDK was updated
260-
// after the LLVM package was cached, the cfg-baked path may be stale
261-
// or point to an incompatible SDK. xcrun always returns the currently
262-
// active SDK, so mcpp passes it on the command line to override the cfg.
263-
if (auto sdk = mcpp::platform::macos::sdk_path())
264-
return *sdk;
265-
266257
auto r = run_capture(std::format("{}{} -print-sysroot {}",
267258
envPrefix,
268259
mcpp::xlings::shq(compilerBin.string()),
@@ -271,6 +262,12 @@ probe_sysroot(const std::filesystem::path& compilerBin,
271262
auto s = trim_line(*r);
272263
if (!s.empty() && std::filesystem::exists(s)) return s;
273264
}
265+
// macOS fallback: use xcrun to discover the SDK path.
266+
// The sysroot is used for regular compilation flags (flags.cppm) but
267+
// skipped for std module precompilation on macOS (stdmod.cppm) to
268+
// avoid breaking SDK internal header dependencies.
269+
if (auto sdk = mcpp::platform::macos::sdk_path())
270+
return *sdk;
274271
return {};
275272
}
276273

src/toolchain/stdmod.cppm

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,18 @@ std::expected<StdModule, StdModError> ensure_built(
9494

9595
std::string sysroot_flag;
9696
if (!tc.sysroot.empty()) {
97-
sysroot_flag = std::format(" --sysroot='{}'", tc.sysroot.string());
97+
// On macOS, skip --sysroot for std module precompilation.
98+
// xlings LLVM ships a clang++.cfg with a --sysroot that is tuned to
99+
// work for normal compilation. Adding a second --sysroot (even the
100+
// identical value) changes header include ordering and breaks macOS
101+
// SDK internal dependencies — ___wctype.h references _CTYPE_A which
102+
// is defined in _ctype.h, but the duplicate --sysroot flag causes
103+
// the C runtime header to not be included transitively during module
104+
// purview compilation. Let the cfg's own --sysroot handle it.
105+
bool skip_sysroot = tc.targetTriple.find("apple") != std::string::npos
106+
|| tc.targetTriple.find("darwin") != std::string::npos;
107+
if (!skip_sysroot)
108+
sysroot_flag = std::format(" --sysroot='{}'", tc.sysroot.string());
98109
}
99110

100111
bool std_cached = std::filesystem::exists(sm.bmiPath) && std::filesystem::exists(sm.objectPath);

0 commit comments

Comments
 (0)