Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

clang -fuse-ld=lld --target= prefers target-prefixed lld binaries over non-prefixed lld in its own directory #133709

Open
zmodem opened this issue Mar 31, 2025 · 7 comments
Labels
clang:driver 'clang' and 'clang++' user-facing binaries. Not 'clang-cl'

Comments

@zmodem
Copy link
Collaborator

zmodem commented Mar 31, 2025

clang's --target flag affects which lld binary it chooses. That seems reasonable, but it can lead to surprising behaviour if there are multiple toolchains available.

Let's pretend we have some old crosscompiling toolchain in our PATH:

$ mkdir -p /tmp/somepath/bin
$ touch /tmp/somepath/bin/x86_64-linux-ld.lld
$ chmod +x /tmp/somepath/bin/x86_64-linux-ld.lld
$ export PATH=$PATH:/tmp/somepath/bin

clang will normally prefer the lld installed right next to itself:

$ touch a.o
$ build/bin/clang -### -fuse-ld=lld a.o
[...]
build/bin/ld.lld [...]

However, if we pass a --target flag, it prefers the lld version that has that target prefix even if this is not in the clang directory:

$ build/bin/clang -### --target=x86_64-linux -fuse-ld=lld a.o
[...]
/tmp/somepath/bin/x86_64-linux-ld.lld [...]

That seems potentially surprising!

It seems there are two criteria at play here:

  1. clang will prefer an lld binary in its own directory over binaries on PATH
  2. clang will prefer an lld binary with the target prefix over one without

It seems that 2) currently takes precedence. Maybe it should be the other way around?

@zmodem zmodem added clang:driver 'clang' and 'clang++' user-facing binaries. Not 'clang-cl' lld labels Mar 31, 2025
@llvmbot
Copy link
Member

llvmbot commented Mar 31, 2025

@llvm/issue-subscribers-clang-driver

Author: Hans Wennborg (zmodem)

clang's `--target` flag affects which `lld` binary it chooses. That seems reasonable, but it can lead to surprising behaviour if there are multiple toolchains available.

Let's pretend we have some old crosscompiling toolchain in our PATH:

$ mkdir -p /tmp/somepath/bin
$ touch /tmp/somepath/bin/x86_64-linux-ld.lld
$ chmod +x /tmp/somepath/bin/x86_64-linux-ld.lld
$ export PATH=$PATH:/tmp/somepath/bin

clang will normally prefer the lld installed right next to itself:

$ touch a.o
$ build/bin/clang -### -fuse-ld=lld a.o
[...]
build/bin/ld.lld [...]

However, if we pass a --target flag, it prefers the lld version that has that target prefix even if this is not in the clang directory:

$ build/bin/clang -### --target=x86_64-linux -fuse-ld=lld a.o
[...]
/tmp/somepath/bin/x86_64-linux-ld.lld [...]

That seems potentially surprising!

It seems there are two criteria at play here:

  1. clang will prefer an lld binary in its own directory over binaries on PATH
  2. clang will prefer an lld binary with the target prefix over one without

It seems that 2) currently takes precedence. Maybe it should be the other way around?

@zmodem
Copy link
Collaborator Author

zmodem commented Mar 31, 2025

+cc @nico @inglorion

@nico
Copy link
Contributor

nico commented Mar 31, 2025

Maybe d6efc98 changed things to the current state? @DavidSpickett

The relevant code is ToolChain::GetLinkerPath which calls Driver::GetProgramPath.

@nico
Copy link
Contributor

nico commented Mar 31, 2025

That revision is a reland of 028571d which points at https://llvm.org/PR45693 / #45038 as motivation for the current behavior.

@zmodem
Copy link
Collaborator Author

zmodem commented Mar 31, 2025

Aha, and that points to an RFC about exactly this: https://discourse.llvm.org/t/rfc-changing-tool-search-path-priority/55341

@EugeneZelenko EugeneZelenko removed the lld label Mar 31, 2025
@DavidSpickett
Copy link
Collaborator

It seems there are two criteria at play here:

  1. clang will prefer an lld binary in its own directory over binaries on PATH
  2. clang will prefer an lld binary with the target prefix over one without

It seems that 2) currently takes precedence.

Yes, Clang currently starts with the most specific name and looks for that in its install directory and then on PATH. If that fails, it looks for the next name in both places and so on.

Maybe it should be the other way around?

At the time, my opinion was that for the use case in the bug report, 2) then 1) made the most sense. Though I could see how you would disagree if file system "distance" is the first criteria in your mental model of this.

(and to be honest, I can't remember what I thought it would be, prior to seeing that bug report)

In the situation where you need a cross compiler gcc, it was finding gcc first. Which was never going to work. If gcc was a cross compiler by default like clang, then 1) 2) order would have also worked. Which may apply for lld too, but probably we would want to keep the search logic the same for all tools.

Not sure how to proceed here.

One way might be to look at the workaround that the original bug report would have to have done (a couple were suggested at the time), vs. what your use case(s) would have to do.

As I am clearly too biased to be saying which strategy makes more sense intuitively.

@zmodem
Copy link
Collaborator Author

zmodem commented Apr 2, 2025

Not sure how to proceed here.

Yeah, I'm not sure either. We worked around this on our end, but it was definitely a surprise, so I figured it made sense to raise it.

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
clang:driver 'clang' and 'clang++' user-facing binaries. Not 'clang-cl'
Projects
None yet
Development

No branches or pull requests

5 participants