about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2023-06-04 19:41:14 +0200
committerGitHub <noreply@github.com>2023-06-04 19:41:14 +0200
commitef2c64ba6c49417907502128e3d4672855ee16a9 (patch)
tree3319af45540bd4984a8c56382d7a35241c8824e8
parente04e19d2229a48f5b4cb68e832121f9cadbb2fa3 (diff)
parent4117b5e65bdcace7df94fe28a621f252d4a9412d (diff)
Rollup merge of #112247 - lqd:lld-rpath, r=Mark-Simulacrum
rust-lld: add rpath entry to the correct `lib` folder

An explanation, for our linux rustup toolchain:
- `lld` / `rust-lld` is built as a regular LLVM tool, but is not distributed via the `llvm-tools` component. It's distributed by default, like a regular rust binary, like cargo and rustc. The general expected setup is: binaries in `bin` and libraries in `lib`, so the rpath we use for a `bin/$executable` is `$ORIGIN/../lib`.
- However, `rust-lld` is _not_ in the same location as our other executables (`$root/bin`), it's in `$root/lib/rustlib/$host/bin/`. The current rpath thus expects the LLVM's shared library to be in `$root/lib/rustlib/$host/lib/`.
- That .so is only present in `$root/lib`, causing #80703. (LLVM's shared library is also copied to `$root/lib/rustlib/$host/lib/` with the `llvm-tools` component, so it also was [a workaround for the issue](https://github.com/rust-lang/rust/issues/80703#issuecomment-1574788504))

rustup's `LD_LIBRARY_PATH` overrides made this discrepancy invisible when we switched to `llvm.link-shared = true`, and this only showed up when running `rustc` or `rust-lld`'s executables directly.

To fix this we could:
- copy the .so to this expected location all the time, but that seems wasteful.
- or, add an rpath entry when building LLD, which seems preferable to me (but I don't know if it could cause issues).

This PR does the latter, tweaking how bootstrap builds LLD to point to the expected directory, and fixes #80703.

(Since this is related to P-high issues about switching to lld by default, I'll cc `@petrochenkov` to keep them updated.)
-rw-r--r--src/bootstrap/llvm.rs25
1 files changed, 25 insertions, 0 deletions
diff --git a/src/bootstrap/llvm.rs b/src/bootstrap/llvm.rs
index 3fd0cca40e5..19e595650cf 100644
--- a/src/bootstrap/llvm.rs
+++ b/src/bootstrap/llvm.rs
@@ -834,6 +834,31 @@ impl Step for Lld {
             }
         }
 
+        // LLD is built as an LLVM tool, but is distributed outside of the `llvm-tools` component,
+        // which impacts where it expects to find LLVM's shared library. This causes #80703.
+        //
+        // LLD is distributed at "$root/lib/rustlib/$host/bin/rust-lld", but the `libLLVM-*.so` it
+        // needs is distributed at "$root/lib". The default rpath of "$ORIGIN/../lib" points at the
+        // lib path for LLVM tools, not the one for rust binaries.
+        //
+        // (The `llvm-tools` component copies the .so there for the other tools, and with that
+        // component installed, one can successfully invoke `rust-lld` directly without rustup's
+        // `LD_LIBRARY_PATH` overrides)
+        //
+        if builder.config.rpath_enabled(target)
+            && util::use_host_linker(target)
+            && builder.config.llvm_link_shared()
+            && target.contains("linux")
+        {
+            // So we inform LLD where it can find LLVM's libraries by adding an rpath entry to the
+            // expected parent `lib` directory.
+            //
+            // Be careful when changing this path, we need to ensure it's quoted or escaped:
+            // `$ORIGIN` would otherwise be expanded when the `LdFlags` are passed verbatim to
+            // cmake.
+            ldflags.push_all("-Wl,-rpath,'$ORIGIN/../../../'");
+        }
+
         configure_cmake(builder, target, &mut cfg, true, ldflags, &[]);
         configure_llvm(builder, target, &mut cfg);