Linker path not passed in with `-B` when linker is auto-selected by Bazel
- Dominant language
- Java
- Stars
- 25.8k
- Forks
- 4.6k
- Avg merge
- 2d 20h
- Merged PRs (30d)
- 72
Description
### Description of the bug:
On my Gentoo system, it is possible to have multiple versions of LLVM installed at the same time, and the "preferred" LLVM version is selected by adding a path like `/usr/lib/llvm//bin` to my PATH. From my understanding, Bazel notices that `ld.lld` is available in PATH and decides to pass in `-fuse-ld=lld` because it is available. However, it doesn't seem to pass in the actual path the linker exists at, instead always passing `-B/usr/bin`. This results in GCC giving up because it can't find the linker:
```
ERROR: /home/agni/.cache/bazel/_bazel_agni/3fb7a3e5b9cd29a38413274391ba0a4a/external/rules_rust+/util/process_wrapper/BUILD.bazel:31:36: Compiling Rust (without process_wrapper) bin process_wrapper (6 files) [for tool] failed: (Exit 1): bootstrap_process_wrapper.sh failed: error executing Rustc command (from target @@rules_rust+//util/process_wrapper:process_wrapper) bazel-out/k8-opt-exec-ST-d57f47055a04/bin/external/rules_rust+/util/process_wrapper/bootstrap_process_wrapper.sh -- ... (remaining 35 arguments skipped)
Use --sandbox_debug to see verbose messages from the sandbox and retain the sandbox build root for debugging
error: linking with `/usr/bin/gcc` failed: exit status: 1
|
= note: "/usr/bin/gcc" "-m64" "/tmp/rustcUyoGUa/symbols.o" "<17 object files omitted>" "-Wl,--as-needed" "-Wl,-Bstatic" "/home/agni/.cache/bazel/_bazel_agni/3fb7a3e5b9cd29a38413274391ba0a4a/execroot/_main/bazel-out/k8-opt-exec-ST-d57f47055a04/bin/external/rules_rust++i+rules_rust_tinyjson/{libtinyjson-1317710085.rlib}.rlib" "/home/agni/.cache/bazel/_bazel_agni/3fb7a3e5b9cd29a38413274391ba0a4a/external/rules_rust++rust+rust_linux_x86_64__x86_64-unknown-linux-gnu__stable_tools/lib/rustlib/x86_64-unknown-linux-gnu/lib/{libstd-f6265b21db1f990f.rlib,libpanic_unwind-8ce3a70abd6a88e8.rlib,libobject-07d1981fc698c677.rlib,libmemchr-54c112ba14290bf7.rlib,libaddr2line-c494935c56a6518a.rlib,libgimli-feaffba60805f631.rlib,librustc_demangle-2a593b8e7756da8d.rlib,libstd_detect-de1086e0b879d219.rlib,libhashbrown-48621906ff1bdb6b.rlib,librustc_std_workspace_alloc-2003c47ed5dd7b8d.rlib,libminiz_oxide-19b210802dff98c6.rlib,libadler2-14ce453623f8f9b8.rlib,libunwind-366453c7550071f8.rlib,libcfg_if-e9b6dd26c5efa091.rlib,liblibc-cce3d7e1d2dfef14.rlib,liballoc-f51c91a777c2aaf5.rlib,librustc_std_workspace_core-bfa26ceed9d2a637.rlib,libcore-a88b4ab71963f9fd.rlib,libcompiler_builtins-18a70055b0fa6d09.rlib}.rlib" "-Wl,-Bdynamic" "-lgcc_s" "-lutil" "-lrt" "-lpthread" "-lm" "-ldl" "-lc" "-Wl,--eh-frame-hdr" "-Wl,-z,noexecstack" "-L" "/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-L" "/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-o" "bazel-out/k8-opt-exec-ST-d57f47055a04/bin/external/rules_rust+/util/process_wrapper/process_wrapper" "-Wl,--gc-sections" "-pie" "-Wl,-z,relro,-z,now" "-Wl,-O1" "-Wl,--strip-debug" "-nodefaultlibs" "-fuse-ld=lld" "-B/usr/bin" "-Wl,-no-as-needed" "-Wl,-z,relro,-z,now" "-pass-exit-codes" "-Wl,--gc-sections" "-Wl,--push-state,-as-needed" "-lstdc++" "-Wl,--pop-state" "-Wl,--push-state,-as-needed" "-lm" "-Wl,--pop-state"
= note: some arguments are omitted. use `--verbose` to show all linker arguments
= note: collect2: fatal error: cannot find 'ld'
```
### Which category does this issue belong to?
C++ Rules
### What's the simplest, easiest way to reproduce this bug? Please provide a minimal example if possible.
1. Start a `gentoo/stage3` Docker image: https://hub.docker.com/r/gentoo/stage3
2. Install an LLD version, like LLD 20, using binpkgs:
```
emerge --sync
getuto
emerge --ask --getbinpkg lld:20 dev-vcs/git bazelisk
source /etc/profile # Update PATH
```
3. Build any Bazel project that issues some link command.
I created a reproducer here: https://github.com/sin-ack/bazel-link-reproducer
On my system, running `bazel build //:test` fails with the above error.
### Which operating system are you running Bazel on?
Gentoo Linux amd64
### What is the output of `bazel info release`?
release 8.3.1
### If `bazel info release` returns `development version` or `(@non-git)`, tell us how you built Bazel.
_No response_
### What's the output of `git remote get-url origin; git rev-parse HEAD` ?
```text
```
### If this is a regression, please try to identify the Bazel commit where the bug was introduced with bazelisk --bisect.
_No response_
### Have you found anything relevant by searching the web?
Another occurrence of this from a while back: `GoLink` fails for Gazelle because of this. https://github.com/bazel-contrib/rules_go/issues/3937
### Any other information, logs, or outputs that you want to share?
Ugly workaround: `ln -s /usr/lib/llvm/20/bin/ld.lld /usr/bin/ld.lld` and update it with every LLVM update.
Slightly less ugly workaround: Add this to `$HOME/.bazelrc` and update it with every LLVM update:
```ini
build --linkopt="-B/usr/lib/llvm/20/bin"
```
Contributor guide
Research direction
Start with the linked bazel-link-reproducer and run `bazel build //:test` in the Gentoo stage3 environment. Inspect the verbose link command and Bazel's linker auto-selection; done means the selected `ld.lld` path is passed without the `/usr/bin` or `.bazelrc` workarounds and the build succeeds.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- linux
- Domain
- build-system, compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100