Skip to content

Commit 265cde6

Browse files
committed
fix: restrict --no-default-config to macOS only
On Linux, clang++.cfg contains essential linker flags (-fuse-ld=lld, --rtlib=compiler-rt, --unwindlib=libunwind). Using --no-default-config strips these, causing "cannot find crtbeginS.o" link failures because clang falls back to system GNU ld looking for GCC runtime objects. On Linux, let the cfg apply normally. The cfg's --sysroot points to the xlings subos which is valid and complete. Pass --sysroot explicitly only when needed (to override a stale cfg value), leveraging the fact that command-line --sysroot takes precedence over the cfg's value. Keep --no-default-config for macOS only, where the cfg-baked paths genuinely become stale (pointing to CommandLineTools SDK when Xcode SDK is active).
1 parent b3d3e88 commit 265cde6

2 files changed

Lines changed: 32 additions & 23 deletions

File tree

src/build/flags.cppm

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -88,32 +88,36 @@ CompileFlags compute_flags(const BuildPlan& plan) {
8888
include_flags += " -I" + escape_path(abs);
8989
}
9090

91-
// Sysroot + config override for Clang with a driver config file.
92-
// xlings LLVM ships a clang++.cfg with hardcoded --sysroot and -isystem
93-
// paths from the original install location. After mcpp copies the package
94-
// to its sandbox, these paths may become stale. Detect the cfg and bypass
95-
// it with --no-default-config, providing correct flags from the payload.
91+
// Sysroot + config override.
92+
//
93+
// On macOS, xlings LLVM's clang++.cfg has hardcoded paths that become
94+
// stale after copying. Use --no-default-config + explicit flags.
95+
//
96+
// On Linux, the cfg contains essential linker flags (-fuse-ld=lld,
97+
// --rtlib=compiler-rt). Let the cfg apply normally; pass --sysroot
98+
// explicitly to override any stale sysroot value in the cfg.
9699
std::string sysroot_flag;
97-
if (mcpp::toolchain::is_clang(plan.toolchain)) {
100+
bool is_macos_clang = mcpp::toolchain::is_clang(plan.toolchain)
101+
&& (plan.toolchain.targetTriple.find("apple") != std::string::npos
102+
|| plan.toolchain.targetTriple.find("darwin") != std::string::npos);
103+
if (is_macos_clang) {
98104
auto cfgPath = plan.toolchain.binaryPath.parent_path()
99105
/ (plan.toolchain.binaryPath.stem().string() + ".cfg");
100106
if (std::filesystem::exists(cfgPath)) {
101107
auto llvmRoot = plan.toolchain.binaryPath.parent_path().parent_path();
102108
auto libcxxInclude = llvmRoot / "include" / "c++" / "v1";
103109
sysroot_flag = " --no-default-config";
104110
sysroot_flag += " -isystem" + escape_path(libcxxInclude);
105-
// Target-specific libc++ headers (e.g. __config_site) live under
106-
// include/<triple>/c++/v1/. Add if present.
107111
if (!plan.toolchain.targetTriple.empty()) {
108112
auto targetInclude = llvmRoot / "include"
109113
/ plan.toolchain.targetTriple / "c++" / "v1";
110114
if (std::filesystem::exists(targetInclude))
111115
sysroot_flag += " -isystem" + escape_path(targetInclude);
112116
}
113-
if (!plan.toolchain.sysroot.empty())
114-
sysroot_flag += " --sysroot=" + escape_path(plan.toolchain.sysroot);
115-
else if (auto sdk = mcpp::platform::macos::sdk_path())
117+
if (auto sdk = mcpp::platform::macos::sdk_path())
116118
sysroot_flag += " --sysroot=" + escape_path(*sdk);
119+
else if (!plan.toolchain.sysroot.empty())
120+
sysroot_flag += " --sysroot=" + escape_path(plan.toolchain.sysroot);
117121
f.sysroot = sysroot_flag;
118122
} else if (!plan.toolchain.sysroot.empty()) {
119123
sysroot_flag = " --sysroot=" + escape_path(plan.toolchain.sysroot);

src/toolchain/stdmod.cppm

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -94,33 +94,38 @@ std::expected<StdModule, StdModError> ensure_built(
9494

9595
// Build sysroot + include flags for std module precompilation.
9696
//
97-
// xlings LLVM ships a clang++.cfg with hardcoded --sysroot and -isystem
98-
// paths from the original install location. After mcpp copies the package
99-
// to its sandbox, these cfg paths may become stale. We detect a cfg file
100-
// and bypass it with --no-default-config, providing correct flags derived
101-
// from the payload's actual binary location and the probed sysroot.
97+
// On macOS, xlings LLVM's clang++.cfg contains hardcoded --sysroot and
98+
// -isystem paths that become stale when the package is copied to mcpp's
99+
// sandbox. We use --no-default-config to bypass the cfg and provide
100+
// correct flags derived from the payload's actual location + xcrun SDK.
101+
//
102+
// On Linux, the cfg also contains linker flags (-fuse-ld=lld,
103+
// --rtlib=compiler-rt, --unwindlib=libunwind) that are essential. Using
104+
// --no-default-config would strip these, causing link failures. Instead,
105+
// we let the cfg apply normally and only pass --sysroot to override the
106+
// sysroot if needed (command-line --sysroot takes precedence over cfg).
102107
std::string sysroot_flag;
103-
if (is_clang(tc)) {
108+
bool is_macos = tc.targetTriple.find("apple") != std::string::npos
109+
|| tc.targetTriple.find("darwin") != std::string::npos;
110+
if (is_macos && is_clang(tc)) {
104111
auto cfgPath = tc.binaryPath.parent_path()
105112
/ (tc.binaryPath.stem().string() + ".cfg");
106113
if (std::filesystem::exists(cfgPath)) {
107-
// Bypass potentially-stale cfg; provide correct flags directly.
114+
// Bypass stale macOS cfg; provide correct flags directly.
108115
auto llvmRoot = tc.binaryPath.parent_path().parent_path();
109116
auto libcxxInclude = llvmRoot / "include" / "c++" / "v1";
110117
sysroot_flag = " --no-default-config";
111118
sysroot_flag += std::format(" -isystem'{}'", libcxxInclude.string());
112-
// Target-specific libc++ headers (e.g. __config_site) live under
113-
// include/<triple>/c++/v1/. Add if present.
114119
if (!tc.targetTriple.empty()) {
115120
auto targetInclude = llvmRoot / "include"
116121
/ tc.targetTriple / "c++" / "v1";
117122
if (std::filesystem::exists(targetInclude))
118123
sysroot_flag += std::format(" -isystem'{}'", targetInclude.string());
119124
}
120-
if (!tc.sysroot.empty())
121-
sysroot_flag += std::format(" --sysroot='{}'", tc.sysroot.string());
122-
else if (auto sdk = mcpp::platform::macos::sdk_path())
125+
if (auto sdk = mcpp::platform::macos::sdk_path())
123126
sysroot_flag += std::format(" --sysroot='{}'", sdk->string());
127+
else if (!tc.sysroot.empty())
128+
sysroot_flag += std::format(" --sysroot='{}'", tc.sysroot.string());
124129
} else if (!tc.sysroot.empty()) {
125130
sysroot_flag = std::format(" --sysroot='{}'", tc.sysroot.string());
126131
}

0 commit comments

Comments
 (0)