Skip to content

Commit 6f1f65e

Browse files
committed
fix: keep clang link flags out of compile commands
1 parent 67655e8 commit 6f1f65e

3 files changed

Lines changed: 33 additions & 41 deletions

File tree

src/build/flags.cppm

Lines changed: 28 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,8 @@ CompileFlags compute_flags(const BuildPlan& plan) {
9696
// potentially-stale paths, then provide all flags explicitly.
9797
//
9898
// Fallback: if no PayloadPaths, use --sysroot from probe_sysroot().
99-
std::string sysroot_flag;
99+
std::string compile_toolchain_flags;
100+
std::string link_toolchain_flags;
100101
bool isClangWithCfg = false;
101102
std::filesystem::path cfgPath;
102103
if (mcpp::toolchain::is_clang(plan.toolchain)) {
@@ -109,51 +110,54 @@ CompileFlags compute_flags(const BuildPlan& plan) {
109110
// Clang with cfg: bypass cfg and provide all paths explicitly.
110111
auto llvmRoot = plan.toolchain.binaryPath.parent_path().parent_path();
111112
auto libcxxInclude = llvmRoot / "include" / "c++" / "v1";
112-
sysroot_flag = " --no-default-config -nostdinc++";
113+
compile_toolchain_flags = " --no-default-config -nostdinc++";
113114
// libc++ headers
114-
sysroot_flag += " -stdlib=libc++";
115-
sysroot_flag += " -isystem" + escape_path(libcxxInclude);
115+
compile_toolchain_flags += " -isystem" + escape_path(libcxxInclude);
116116
if (!plan.toolchain.targetTriple.empty()) {
117117
auto targetInclude = llvmRoot / "include"
118118
/ plan.toolchain.targetTriple / "c++" / "v1";
119119
if (std::filesystem::exists(targetInclude))
120-
sysroot_flag += " -isystem" + escape_path(targetInclude);
120+
compile_toolchain_flags += " -isystem" + escape_path(targetInclude);
121121
}
122122
// C library + kernel headers from payload
123123
if (plan.toolchain.payloadPaths) {
124124
auto& pp = *plan.toolchain.payloadPaths;
125-
sysroot_flag += " -isystem" + escape_path(pp.glibcInclude);
125+
compile_toolchain_flags += " -isystem" + escape_path(pp.glibcInclude);
126126
if (!pp.linuxInclude.empty())
127-
sysroot_flag += " -isystem" + escape_path(pp.linuxInclude);
127+
compile_toolchain_flags += " -isystem" + escape_path(pp.linuxInclude);
128128
} else if (auto sdk = mcpp::platform::macos::sdk_path()) {
129-
sysroot_flag += " --sysroot=" + escape_path(*sdk);
129+
auto sysroot_flag = " --sysroot=" + escape_path(*sdk);
130+
compile_toolchain_flags += sysroot_flag;
131+
link_toolchain_flags += sysroot_flag;
130132
} else if (!plan.toolchain.sysroot.empty()) {
131-
sysroot_flag += " --sysroot=" + escape_path(plan.toolchain.sysroot);
133+
auto sysroot_flag = " --sysroot=" + escape_path(plan.toolchain.sysroot);
134+
compile_toolchain_flags += sysroot_flag;
135+
link_toolchain_flags += sysroot_flag;
132136
}
133137
// Linker flags that cfg normally provides
134-
sysroot_flag += " -fuse-ld=lld --rtlib=compiler-rt --unwindlib=libunwind";
135-
f.sysroot = sysroot_flag;
138+
link_toolchain_flags = " --no-default-config" + link_toolchain_flags
139+
+ " -stdlib=libc++ -fuse-ld=lld --rtlib=compiler-rt --unwindlib=libunwind";
140+
f.sysroot = link_toolchain_flags;
136141
} else if (!plan.toolchain.sysroot.empty()) {
137142
// GCC (or Clang without cfg): use --sysroot from probe.
138143
// GCC requires --sysroot for include-fixed headers (stdlib.h wrapper).
139144
// Supplement with -isystem for linux kernel headers from payload
140145
// if the probed sysroot is missing them.
141-
sysroot_flag = " --sysroot=" + escape_path(plan.toolchain.sysroot);
146+
auto sysroot_flag = " --sysroot=" + escape_path(plan.toolchain.sysroot);
147+
compile_toolchain_flags = sysroot_flag;
148+
link_toolchain_flags = sysroot_flag;
142149
if (plan.toolchain.payloadPaths && !plan.toolchain.payloadPaths->linuxInclude.empty()) {
143150
auto sysrootLinux = plan.toolchain.sysroot / "usr" / "include" / "linux" / "limits.h";
144151
if (!std::filesystem::exists(sysrootLinux))
145-
sysroot_flag += " -isystem" + escape_path(plan.toolchain.payloadPaths->linuxInclude);
152+
compile_toolchain_flags += " -isystem" + escape_path(plan.toolchain.payloadPaths->linuxInclude);
146153
}
147-
f.sysroot = sysroot_flag;
154+
f.sysroot = link_toolchain_flags;
148155
} else if (plan.toolchain.payloadPaths) {
149156
// No sysroot but have payload paths: use -isystem.
150157
auto& pp = *plan.toolchain.payloadPaths;
151-
sysroot_flag += " -isystem" + escape_path(pp.glibcInclude);
158+
compile_toolchain_flags += " -isystem" + escape_path(pp.glibcInclude);
152159
if (!pp.linuxInclude.empty())
153-
sysroot_flag += " -isystem" + escape_path(pp.linuxInclude);
154-
f.sysroot = sysroot_flag;
155-
sysroot_flag = " --sysroot=" + escape_path(plan.toolchain.sysroot);
156-
f.sysroot = sysroot_flag;
160+
compile_toolchain_flags += " -isystem" + escape_path(pp.linuxInclude);
157161
}
158162

159163
// Binutils -B flag
@@ -224,9 +228,9 @@ CompileFlags compute_flags(const BuildPlan& plan) {
224228
}
225229
f.cxx = std::format("-std=c++23{}{}{}{}{}{}{}{}{}{}", module_flag, std_module_flag,
226230
std_compat_module_flag, prebuilt_module_flag,
227-
opt_flag, pic_flag, sysroot_flag, b_flag, include_flags, user_cxxflags);
228-
f.cc = std::format("-std={}{}{}{}{}{}{}", c_std, opt_flag, pic_flag, sysroot_flag, b_flag,
229-
include_flags, user_cflags);
231+
opt_flag, pic_flag, compile_toolchain_flags, b_flag, include_flags, user_cxxflags);
232+
f.cc = std::format("-std={}{}{}{}{}{}{}", c_std, opt_flag, pic_flag, compile_toolchain_flags,
233+
b_flag, include_flags, user_cflags);
230234

231235
// Link flags
232236
f.staticStdlib = plan.manifest.buildConfig.staticStdlib;
@@ -257,7 +261,8 @@ CompileFlags compute_flags(const BuildPlan& plan) {
257261
} else if constexpr (mcpp::platform::needs_explicit_libcxx) {
258262
f.ld = std::format("{}{}{} -lc++", full_static, static_stdlib, b_flag);
259263
} else {
260-
f.ld = std::format("{}{}{}{}{}{}", full_static, static_stdlib, sysroot_flag, b_flag, runtime_dirs, payload_ld);
264+
f.ld = std::format("{}{}{}{}{}{}", full_static, static_stdlib, link_toolchain_flags, b_flag,
265+
runtime_dirs, payload_ld);
261266
}
262267

263268
return f;

src/build/ninja_backend.cppm

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -179,23 +179,6 @@ bool is_command_line(std::string_view trimmed,
179179
return false;
180180
}
181181

182-
bool is_toolchain_unused_argument_warning(std::string_view line) {
183-
if (line.find("argument unused during compilation") == std::string_view::npos)
184-
return false;
185-
186-
constexpr std::array<std::string_view, 4> toolchainFlags = {
187-
"'-stdlib=libc++'",
188-
"'-fuse-ld=lld'",
189-
"'--rtlib=compiler-rt'",
190-
"'--unwindlib=libunwind'",
191-
};
192-
for (auto flag : toolchainFlags) {
193-
if (line.find(flag) != std::string_view::npos)
194-
return true;
195-
}
196-
return false;
197-
}
198-
199182
std::optional<std::pair<std::string, std::string>>
200183
runtime_env_for_dirs(const std::vector<std::filesystem::path>& dirs) {
201184
auto key = mcpp::platform::env::runtime_library_path_key();
@@ -219,7 +202,6 @@ std::string filter_ninja_output(std::string_view output,
219202
|| trimmed.starts_with("ninja: build stopped")
220203
|| trimmed.starts_with("FAILED:")
221204
|| is_ninja_progress_line(trimmed)
222-
|| is_toolchain_unused_argument_warning(trimmed)
223205
|| is_command_line(trimmed, commandPrefixes)) {
224206
continue;
225207
}

tests/e2e/48_build_error_output.sh

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,11 @@ if grep -q 'LD_LIBRARY_PATH\|toolenv' "$build_ninja"; then
9292
sed -n '1,80p' "$build_ninja"
9393
exit 1
9494
fi
95+
if grep '^cxxflags\|^cflags' "$build_ninja" | grep -Eq -- '-stdlib=libc\+\+|-fuse-ld=lld|--rtlib=compiler-rt|--unwindlib=libunwind'; then
96+
echo "compile flags should not contain clang link/runtime-only flags"
97+
grep '^cxxflags\|^cflags' "$build_ninja"
98+
exit 1
99+
fi
95100

96101
rc=0
97102
verbose_out=$("$MCPP" build --verbose 2>&1) || rc=$?

0 commit comments

Comments
 (0)