Skip to content

Commit 0856e8a

Browse files
committed
fix(build): the managed tools run on their own RPATH; the library path is given only to a compiler without one
1 parent c28e2ee commit 0856e8a

3 files changed

Lines changed: 25 additions & 15 deletions

File tree

‎.agents/docs/2026-10-10-one-source-one-meaning-design.md‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ status: landed
3131
- D28:以 argv 启动的 shell 由 `posix_shell()` 解析;`popen` 与 `std::system` 仍用 C 库的 `/bin/sh`,
3232
因此 Android 的基线是 10 及以上。
3333
- D23:mcpp 把 xlings 的 `extract`、`hook` 事件显示为 `Installing …` 行,并写入日志;不另加 30 s 心跳。
34+
- D29:受管载荷的程序带有 xlings 安装时写入的 RPATH,不依赖 `LD_LIBRARY_PATH`(实测 clang、clang-scan-deps、
35+
llvm-ar、lld 去掉该变量都能运行)。因此在 Linux 上该变量不再进入 ninja 的环境,也不加在工具上;只有编译器
36+
本身没有 RPATH/RUNPATH 时(以路径指定的工具链),才以 `env LD_LIBRARY_PATH=… <tool>` 前缀加在工具上。
37+
这样 `build.ninja` 中 `cxx =` 的写法对受管工具链不变(tests/e2e/188 读取它)。
3438
- D26 以 `degraded`(`build-program/provides`)实现。
3539
- 工作空间层的解析:`[workspace.*]` 下的文档由同一个 `parse_document` 读取,保留原值的行号。
3640
- 测试:e2e 893–901(在 2026.10.8.1 上全部失败);Windows 探测由单元测试覆盖;D27 的两个 job 在

‎CHANGELOG.md‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,10 @@
4444
- Write nothing at an action's outputs before the action runs. A generated
4545
translation unit enters the plan from its action's declaration; a generated
4646
module interface without `.provides(...)` is reported as degraded.
47-
- Pass the managed toolchain's library path on Linux to the tools that need
48-
it (`$cxx`, `$cc`, `$ar`, `clang-scan-deps`) instead of ninja's environment,
49-
so no shell ninja starts loads the toolchain's libc++.
47+
- Keep the managed toolchain's library path out of ninja's environment on
48+
Linux, so no shell ninja starts loads the toolchain's libc++. The managed
49+
tools find their libraries through their own RPATH; a compiler without one
50+
gets the path on the tools alone.
5051
- Pin xlings 2026.10.10.2 and bootstrap from mcpp 2026.10.8.1.
5152

5253
### Added

‎src/build/ninja_backend.cppm‎

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)