-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
Support feeding rust-lld into gcc (and clang) #71519
Comments
CMake (or autotools, etc) do that in C++ world. It would be nice to have this for other things, like detection of (Then it can be fed to |
FWIW, firefox's build system does exactly this analysis in its configure step. If we're lucky we'll be able to copy the logic they use for detecting linkers. (Except we would be injecting our own ld and just validating that it worked, and presumably we won't bother with checking for the presence of Gold) |
Ok did a bit of analysis on the binary name stuff, and it's pretty clearly laid out in the main entry point for the binary. lld is basically 4 independent implementations of the targets it supports, which it calls Drivers: gnu (ELF), darwin (Mach-O), winlink (COFF), wasm. Binary name is used to select the Driver, and it can be overloaded with the The file name "ld" is special in that it's behaviour depends on the host: on macos it will pick the darwin driver, while on all other platforms it will pick the gnu driver. So for non-cross builds it will "do the right thing" on unix-like platforms (where you would expect a thing called "ld" to exist) (but also using lld for targetting macos is currently Always Wrong regardless). So this is all to say that the most portable option -- putting rust-lld on the PATH with the name "ld" during our linking -- should work perfectly fine. At least for the common case of targetting your host platform. For now I'll be ignoring the distro-friendly usecase of detecting installed lld's and selecting that version, for the purpose of getting an MVP working so we can ask people to test out how well this configuration works on their projects. TODO: figure out whether the "rule" that you must invoke TODO: figure out what distro maintainers currently do about the rustc-private rust-lld binary (in rustup installs it's not on the PATH, and can be found at TODO: is PATH the right mechanism for this? Should/can we use something else to make rust-lld shadow the system ld? Should we keep that shadowing enabled for the whole build (so e.g. build.rs scripts which go off and build some C/C++ code will also use lld?) PROPOSAL: add two new modes to -C linker-flavor:
BIKESHED: gcc-lld deviates from the lld-link naming scheme, but I believe in that case we do actually directly invoke lld with the link driver. Whereas the configuration we are concerned with is invoke (g)cc and tell it to use lld (with the gnu driver). Automatically enabling these modes is out of scope for this bug, for now they will never be selected without manual intervention, although the ultimate goal is to automatically use these modes in some cases. |
@cuviper does the proposed distinction and mechanism for "use rust-lld" and "use the system lld" make sense to you? Would love any insights you have here, so that I can be confident in this approach. |
At least Alpine, Arch, Fedora, OpenSUSE and Solus don't build it. |
Oh!! Is that just a symlink to a system install of ld.lld, implying package managers consider lld a dependency of rustc? And therefore if you're using a version of cargo/rust installed via your package manager, "using" rust-lld is using the system lld? If so, we may not need to care about making a distinction between the system and bundled lld, since the way you installed rust basically defines your preference..? |
Indeed
As long as system LLD is recent enough it doesn't differ much from |
I think this |
I feel if anything the neutral option should mean the system lld, and rust-lld should be a more specific choice. But if we're willing to probe around a little, I'd also be happy with a single option that uses rust-lld when present, or else uses the system lld. When we head further toward using lld by default, that order would go rust-lld, system lld, or just default ld. |
GCC (and clang) support a We used to use that for cross-mac Firefox builds:
This is a much harder problem to solve and I think it's fine to declare it out of scope at first. Linking Rust code is a much more tightly scoped problem since we control the linker invocation from rustc. Also if your build requires a C compiler so a build script can compile something odds are you already have a linker that works for your target anyway. Making pure-Rust builds less dependent on external toolchains is a very good and useful goal without solving arbitrary C compilation. |
I'd like to push this issue forward, is it waiting on something specific? |
I took a look at it a while ago (April) and I don't see any technical blockers. I think we just need to agree on the exact method of selecting lld, and what happens in conflicting cases. As I said earlier, it's not at all clear to me that the correct behavior when both lld and gold are specified (for example) is to silently use lld instead. |
I'm really interested in seeing this happen as well. The proposed |
This is the last known blocker for using lld on linux, so I've updated the first comment with a summary of the discussion for anyone who would like to take a crack at implementing it. |
I'm starting work on this. Besides adding a linker flavor and relevant documentation, I am customizing bootstrap/dist.rs to prepare a directory ending in |
About target specs: |
@g2p do you have any thoughts on which would be the better approach? If not then we can ask for guidance from the compiler team. |
Is this issue being worked on? I'm new to the "guts" of Rust, and this seems like something useful to work on, but I'll need someone who can answer my questions about this stuff. |
@1000teslas I would ask the compiler team directly in one of the following Zulip channels: |
@bstrie I've already done so and I'm blocked on this https://rust-lang.zulipchat.com/#narrow/stream/182449-t-compiler.2Fhelp/topic/building.20lld.20fails |
@bstrie I made a PR. Is there anyone in particular you think should review my PR? |
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)The text was updated successfully, but these errors were encountered: