Support feeding rust-lld into gcc (and clang) · Issue #71519 · rust-lang/rust (original) (raw)

This is a subtask of #71515

summary of discussion

On linux/unix platforms, you aren't supposed to directly invoke ld/lld. You're supposed to invoke the linker through your system c compiler (i.e. gcc), whose responsibility it is to discover system symbols like crt1.o and provide them to ld. This means we can't "just" use rust-lld; we must feed it into gcc/clang/whatever. (We really don't want to implement this system symbol logic ourselves.)

In general, you can't provide the linker as a path, you must inject it into the C compiler's search path as "ld". ("ld.lld" with -fuse-ld=lld would also be possible, but requires newer versions of GCC, so plain "ld" is preferable if possible.)

Solution: add a new -C linker-flavor mode, gcc-lld, that would place rust-lld on the PATH as "ld" and invoke it through the system cc.

Note that distros do not build rust's private rust-lld binary. They make their rust packages depend on lld and symlink it in. So if you have installed rustc via your package manager, using rust-lld is using your system lld. This is all to say that it's generally unnecessary to "check" for a system lld, as rust-lld will already be pointing at it for the folks who care about using system toolchains.

Should this mode become the default on linux, anyone slipping through the cracks can similarly replace rust-lld with a symlink, or explicitly pass a linker-flavor.

Note: the private rust-lld binary can be found at:

$(rustc --print sysroot)/lib/rustlib/$HOST_TARGET_TRIPLE/bin/rust-lld

which for desktop linux would be:

$(rustc --print sysroot)/lib/rustlib/x86_64-unknown-linux-gnu/rust-lld

original comment:

On linux/unix platforms, you aren't supposed to directly invoke ld/lld. You're supposed to invoke the linker through your system c compiler (i.e. gcc), whose responsibility it is to discover system symbols like crt1.o and provide them to ld. This means we can't "just" use rust-lld; we must feed it into gcc/clang/whatever. (We really don't want to implement this system symbol logic ourselves.)

In general, you can't provide the linker as a path, you must inject it into the C compiler's search path as "ld". Alternatively, you can do the same thing but inject it as "ld.lld", and pass "-fuse-ld=lld" to gcc, which may be important as apparently lld does clang-style binary name detection to select different behaviour based on whether it's "ld" or "ld.lld". (needs investigation)

Unfortunately -fuse-ld=lld is only part of GCC 9, so we may require feature/version detection to use it (clang has had it for a long time). Doing this detection may be fairly expensive (execing gcc, possibly multiple times), so we may not want to do this in rustc itself. Ideally something higher up like cargo or maybe even rustup or something would do this analysis and cache the result. (needs design discussion)

It's also not clear to me how one would manually opt into this compilation mode, and/or force it on. Should it be controlled by -C linker-flavor? (needs design discussion)