-
Notifications
You must be signed in to change notification settings - Fork 13.5k
Clang does not resolve path to linker executable using PATH env variable #79771
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
|
@llvm/issue-subscribers-clang-driver Author: Artem Labazov (artem)
For example, if you create a symbolic link from /usr/bin/lld-18 to /usr/local/bin/ld, GCC successfully hooks it up. However, Clang does not, and running `clang -v` reveals that it unconditionally calls `/usr/bin/ld`.
I'm not sure whether such behavior is intended, but at least it is very confusing and frustrating to discover. |
@MaskRay has done quite a bit of work around this area. I am weakly against looking up the linker from the PATH, I don't think it fixes any real-world problems. But it might be worth it for the compatibility with GCC. |
Quoting LLD website:
However, such thing is infeasible in environments without superuser access. Instead, doing |
Clang does consult ln -s path/to/lld bin/ld
clang -### -Bbin a.o % PATH=/tmp/c/bin:$PATH fclang a.o -fuse-ld=lld '-###'
clang version 19.0.0git
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /tmp/Rel/bin
"/tmp/c/bin/ld.lld" ... |
Unfortunately, it does not make LLD the "default system linker", every project here and there has its own way to pass extra flags to compiler (or none at all without patching its build recipes).
Thanks! I have confirmed that creating an extra clang symlink kinda works, but is there any strong reason behind such behavior? This workaround requires an extra counterintuitive step and is misaligned with what GCC driver does. |
I think this is a Ubuntu packaging problem. Debian's is good:) Clang basically calls string GetProgramPath(name) {
for (b : OPT_B) {
cand = is_directory(b) ? join(b, name) : b + name;
if (is_executable(cand))
return cand;
}
for (TargetSpecificExecutable : TargetSpecificExecutables) { // e.g. aarch64-linux-gnu-$name, $name
for (auto dir : TC.getProgramPaths()) { // -ccc-install-dir, /usr/lib/gcc-cross/aarch64-linux-gnu/13/../../../../aarch64-linux-gnu/bin
cand = join(b, name);
if (is_executable(cand))
return cand;
}
for (auto dir : split(getenv("PATH"))) {
cand = join(b, name);
if (is_executable(cand))
return cand;
}
}
return name;
}
Note that In your case,
|
Debian is affected as well: there're two symlinks:
If you do not add As you suggested, adding Put another way, it's weird that clang considers cmdline basedir a part of toolchain, no matter where the actual binary is located on the filesystem. From user's perspective, Calling
GCC does not exhibit this problem since there are COMPILER_PATH and PATH, the former has higher precedence and does not include /usr/bin/: After all, if the current situation is not to change, it would be great to at least document it (please forgive me if it already is) to warn users about this pitfall in the future. |
Agree. Debian has the problem as well. I've created #80527 , which should update
I agree that some documentation will be nice. Perhaps |
Seems to work in Clang 19 |
For example, if you create a symbolic link from /usr/bin/lld-18 to /usr/local/bin/ld, GCC successfully hooks it up. However, Clang does not, and running
clang -v
reveals that it unconditionally calls/usr/bin/ld
.I'm not sure whether such behavior is intended, but at least it is very confusing and frustrating to discover.
The text was updated successfully, but these errors were encountered: