Skip to content

Commit 908d912

Browse files
committed
fix: scope bound glibc to compiler commands
1 parent a143909 commit 908d912

5 files changed

Lines changed: 42 additions & 12 deletions

File tree

src/build/ninja_backend.cppm

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -589,10 +589,17 @@ std::string emit_ninja_string(const BuildPlan& plan) {
589589
// The macOS initializer-ordering shim (#336) is a C translation unit, so
590590
// it needs the C driver bindings even in a project with no .c sources.
591591
const bool need_ios_init_shim = flags.needsStreamInitShim;
592-
append(std::format("cxx = {}\n", escape_ninja_path(flags.cxxBinary)));
592+
auto compiler_command = [&](const std::filesystem::path& binary) {
593+
const auto& dirs = plan.toolchain.compilerInvocationRuntimeDirs.empty()
594+
? plan.toolchain.compilerRuntimeDirs
595+
: plan.toolchain.compilerInvocationRuntimeDirs;
596+
return mcpp::platform::linux_::build_clean_ld_library_path_prefix(dirs)
597+
+ escape_ninja_path(binary);
598+
};
599+
append(std::format("cxx = {}\n", compiler_command(flags.cxxBinary)));
593600
append(std::format("cxxflags = {}\n", flags.cxx));
594601
if (need_c_rule || need_asm_rule || need_ios_init_shim) { // asm_object drives the C compiler too
595-
append(std::format("cc = {}\n", escape_ninja_path(flags.ccBinary)));
602+
append(std::format("cc = {}\n", compiler_command(flags.ccBinary)));
596603
}
597604
if (need_c_rule || need_ios_init_shim) {
598605
append(std::format("cflags = {}\n", flags.cc));

src/toolchain/detect.cppm

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,9 @@ detect(const std::filesystem::path& explicit_compiler,
5858
return tc;
5959
}
6060

61-
tc.compilerRuntimeDirs = discover_compiler_runtime_dirs(tc.binaryPath, runtimeBinding);
61+
tc.compilerRuntimeDirs = discover_compiler_runtime_dirs(tc.binaryPath);
62+
tc.compilerInvocationRuntimeDirs =
63+
discover_compiler_invocation_runtime_dirs(tc.binaryPath, runtimeBinding);
6264
auto envPrefix = compiler_env_prefix(tc);
6365

6466
auto ver_r = run_capture(std::format("{}{} --version 2>&1",

src/toolchain/model.cppm

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,13 @@ struct Toolchain {
100100
// zero-libc tier and on hosted targets.
101101
std::string targetSysrootPkg;
102102
std::filesystem::path targetSysrootLib;
103-
std::vector<std::filesystem::path> compilerRuntimeDirs; // LD_LIBRARY_PATH for private tools
103+
// Runtime directories inherited by Ninja and its whole process tree. Keep
104+
// private libc out of this list: Ninja launches each edge through /bin/sh.
105+
std::vector<std::filesystem::path> compilerRuntimeDirs;
106+
// Directories required when starting a compiler driver. On Linux this may
107+
// include the bound glibc payload, but it is applied inside each compiler
108+
// command after Ninja's shell has already started.
109+
std::vector<std::filesystem::path> compilerInvocationRuntimeDirs;
104110
std::vector<std::filesystem::path> linkRuntimeDirs; // -L/-rpath dirs for produced binaries
105111
// Environment the toolchain's tools need when invoked (set on the ninja
106112
// process, inherited by compiler/linker children). Empty for GCC/Clang

src/toolchain/probe.cppm

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,11 @@ std::string trim_line(std::string s);
3131
std::string normalize_driver_output(std::string_view s);
3232

3333
std::vector<std::filesystem::path>
34-
discover_compiler_runtime_dirs(const std::filesystem::path& compilerBin,
35-
std::string_view runtimeBinding = {});
34+
discover_compiler_runtime_dirs(const std::filesystem::path& compilerBin);
35+
36+
std::vector<std::filesystem::path>
37+
discover_compiler_invocation_runtime_dirs(const std::filesystem::path& compilerBin,
38+
std::string_view runtimeBinding);
3639

3740
std::vector<std::filesystem::path>
3841
discover_link_runtime_dirs(const std::filesystem::path& compilerBin,
@@ -190,8 +193,7 @@ std::string normalize_driver_output(std::string_view s) {
190193
}
191194

192195
std::vector<std::filesystem::path>
193-
discover_compiler_runtime_dirs(const std::filesystem::path& compilerBin,
194-
std::string_view runtimeBinding) {
196+
discover_compiler_runtime_dirs(const std::filesystem::path& compilerBin) {
195197
std::vector<std::filesystem::path> dirs;
196198
auto root = compilerBin.parent_path().parent_path();
197199

@@ -212,6 +214,14 @@ discover_compiler_runtime_dirs(const std::filesystem::path& compilerBin,
212214
append_existing_unique(dirs, *rt / "lib");
213215
}
214216

217+
return dirs;
218+
}
219+
220+
std::vector<std::filesystem::path>
221+
discover_compiler_invocation_runtime_dirs(const std::filesystem::path& compilerBin,
222+
std::string_view runtimeBinding) {
223+
auto dirs = discover_compiler_runtime_dirs(compilerBin);
224+
215225
// A managed compiler's DT_RUNPATH reaches its bound private libc for its
216226
// own direct dependencies only. A host /etc/ld.so.preload library can
217227
// require libdl.so.2 itself, where that non-transitive RUNPATH cannot help.
@@ -251,7 +261,8 @@ discover_link_runtime_dirs(const std::filesystem::path& compilerBin,
251261
}
252262

253263
std::string compiler_env_prefix(const Toolchain& tc) {
254-
return env_prefix_for_dirs(tc.compilerRuntimeDirs);
264+
return env_prefix_for_dirs(tc.compilerInvocationRuntimeDirs.empty()
265+
? tc.compilerRuntimeDirs : tc.compilerInvocationRuntimeDirs);
255266
}
256267

257268
std::expected<std::filesystem::path, DetectError>

tests/unit/test_toolchain_detect.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -127,9 +127,13 @@ esac
127127

128128
auto tc = detect(compiler, "glibc@2.44");
129129
ASSERT_TRUE(tc.has_value()) << tc.error().message;
130-
EXPECT_NE(std::find(tc->compilerRuntimeDirs.begin(), tc->compilerRuntimeDirs.end(), wanted),
131-
tc->compilerRuntimeDirs.end());
132-
EXPECT_EQ(std::find(tc->compilerRuntimeDirs.begin(), tc->compilerRuntimeDirs.end(), other),
130+
EXPECT_NE(std::find(tc->compilerInvocationRuntimeDirs.begin(),
131+
tc->compilerInvocationRuntimeDirs.end(), wanted),
132+
tc->compilerInvocationRuntimeDirs.end());
133+
EXPECT_EQ(std::find(tc->compilerInvocationRuntimeDirs.begin(),
134+
tc->compilerInvocationRuntimeDirs.end(), other),
135+
tc->compilerInvocationRuntimeDirs.end());
136+
EXPECT_EQ(std::find(tc->compilerRuntimeDirs.begin(), tc->compilerRuntimeDirs.end(), wanted),
133137
tc->compilerRuntimeDirs.end());
134138
}
135139
#endif // defined(__linux__)

0 commit comments

Comments
 (0)