@@ -1453,8 +1453,7 @@ std::string emit_ninja_string(const BuildPlan& plan, std::string* placements,
14531453 plan.toolchain .binaryPath , plan.toolchain .targetTriple );
14541454
14551455 if (!fsObjcopy.empty ()) {
1456- append (" objcopy = " + mcpp::platform::linux_::build_clean_ld_library_path_prefix (
1457- plan.toolchain .compilerRuntimeDirs ) + escape_ninja_path (fsObjcopy) + " \n\n " );
1456+ append (" objcopy = " + escape_ninja_path (fsObjcopy) + " \n\n " );
14581457 // ── The raw image a flasher takes ──────────────────────────────────
14591458 //
14601459 // A SEPARATE EDGE with the ELF as its input, not a second output of
@@ -1484,20 +1483,26 @@ std::string emit_ninja_string(const BuildPlan& plan, std::string* placements,
14841483 const std::string launch = flags.launcher .empty () ? std::string{}
14851484 : escape_ninja_path (std::filesystem::path (flags.launcher )) + " " ;
14861485 // D29: THE TOOLCHAIN'S PRIVATE LIBRARIES ARE THE TOOLCHAIN'S. A managed
1487- // LLVM's `clang`, `llvm-ar` and `clang-scan-deps` find their own libc++ and
1488- // libLLVM through LD_LIBRARY_PATH, and that path used to be in ninja's
1489- // environment -- so every `/bin/sh -c` ninja starts had it too. A shell
1490- // that links libc++ (Android's bionic `sh`) then loaded the LLVM's,
1486+ // LLVM's library directories used to be put in ninja's environment as
1487+ // LD_LIBRARY_PATH, so every `/bin/sh -c` ninja starts inherited them. A
1488+ // shell that links libc++ (Android's bionic `sh`) then loaded the LLVM's,
14911489 // built for glibc, and died before running anything:
14921490 // CANNOT LINK EXECUTABLE "/bin/sh": .../xim-x-llvm/23.1.3/lib/
14931491 // aarch64-unknown-linux-gnu/libc++.so is too small
1494- // (termux-docker, design 2026-10-10 §13). The path now prefixes the tools
1495- // that need it and reaches nothing else; macOS keeps no such path at all
1492+ // (termux-docker, design 2026-10-10 §13). A managed payload's programs
1493+ // carry their own search path (the RPATH xlings writes at install), so on
1494+ // Linux the variable reaches no process ninja starts. A compiler without
1495+ // one -- a toolchain named by path -- gets it on the tools alone, as an
1496+ // `env` prefix. macOS keeps no such path at all
14961497 // (`runtime_library_path_key`), Windows keeps its PATH.
1497- const std::string toolEnv = mcpp::platform::is_linux
1498- ? mcpp::platform::linux_::build_clean_ld_library_path_prefix (
1499- plan.toolchain .compilerRuntimeDirs )
1500- : std::string{};
1498+ const std::string toolEnv = [&]() -> std::string {
1499+ if (!mcpp::platform::is_linux || plan.toolchain .compilerRuntimeDirs .empty ()) return {};
1500+ if (auto facts = mcpp::platform::elf::inspect_elf_runtime (flags.cxxBinary );
1501+ facts && facts->searchPathTag != mcpp::platform::elf::SearchPathTag::None)
1502+ return {};
1503+ return mcpp::platform::linux_::build_clean_ld_library_path_prefix (
1504+ plan.toolchain .compilerRuntimeDirs );
1505+ }();
15011506 append (std::format (" cxx = {}{}{}\n " , toolEnv, launch, escape_ninja_path (flags.cxxBinary )));
15021507 // The driver alone, for the dependency scan: `clang-scan-deps` reads its
15031508 // argv[0] as the compiler (and the resource directory beside it), and a
0 commit comments