Skip to content
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

How to find LLD with old versions of gcc? #97402

Closed
petrochenkov opened this issue May 25, 2022 · 15 comments
Closed

How to find LLD with old versions of gcc? #97402

petrochenkov opened this issue May 25, 2022 · 15 comments
Labels
A-linkage Area: linking into static, shared libraries and binaries T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@petrochenkov
Copy link
Contributor

This issue is related to stabilizing use of LLD from rustc and/or making it default - rust-lang/compiler-team#510, #39915.

GCC and Clang have several ways to specify linker.

  • -B directory, you specify a search directory, then the compiler finds a file named ld in it an uses it as a linker.
    This is the old way working on all versions of GCC and Clang that we want to support (?).
  • -fuse-ld=bfd|gold|lld|mold limited to 4 well-known linker names, you specify the name, then the compiler finds a file named ld.name in its search directories.
    This is a somewhat new way, the well-known name -fuse-ld=lld works in Clang, and in GCC since 2018 (which GCC version?).
  • -fuse-ld=/absolute/path/to/lld, where you specify the full linker path.
    This doesn't work with GCC, and worked with Clang since 2016, but is now deprecated in favor of --ld-path.
  • --ld-path=/absolute/path/to/lld, where you specify the full linker path.
    This doesn't work with GCC, and works with Clang since 2021.

rustc needs to tell C compiler to use LLD in two modes

  • "Self-contained" mode when we need to find the LLD shipped with rustc.
    This mode always uses -B directory right now (after Simplify implementation of -Z gcc-ld #97375) just because it's simple to do, but it also means that old compilers are supported.
  • Mode in which we should find system-provided LLD.
    QUESTIONS:
    • How should we do it?
    • Do we care about older GCC versions that don't support -fuse-ld=lld?
@petrochenkov petrochenkov added A-linkage Area: linking into static, shared libraries and binaries T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels May 25, 2022
@petrochenkov
Copy link
Contributor Author

cc @lqd @bjorn3 @nagisa @hkratz @cuviper

@bjorn3
Copy link
Member

bjorn3 commented May 25, 2022

Do we care about older GCC versions that don't support -fuse-ld=lld?

A system where GCC is old enough that it doesn't support -fuse-ld=lld probably doesn't have lld at all, right? So for the non-self-contained mode that would just be an error. I think -fuse-ld=lld for a system lld and -B for the self-contained mode would be the easiest.

@tschuett
Copy link

There is no autoconf step in cargo resp. rustc?

@bjorn3
Copy link
Member

bjorn3 commented May 25, 2022

No, there isn't.

@petrochenkov
Copy link
Contributor Author

There is no autoconf step in cargo resp. rustc?

No idea, even if cargo caches some info about the environment, it does it implicitly, and the cache doesn't survive cargo clean.

@bjorn3
Copy link
Member

bjorn3 commented May 25, 2022

Everything cargo caches afaik is the output of rustc -vV and rustc - --crate-name ___ --print=file-names --crate-type bin --crate-type rlib --crate-type dylib --crate-type cdylib --crate-type staticlib --crate-type proc-macro --print=sysroot --print=cfg. The former is to get the rustc version and the later is to get what different file kinds are called on the selected target (hard coded per target in rustc) and the list of cfg's to use for conditional dependencies (partially hard coded, extendable through --cfg in RUSTFLAGS) Neither reads anything from the environment it runs on.

@mati865
Copy link
Contributor

mati865 commented May 25, 2022

Do we care about older GCC versions that don't support -fuse-ld=lld?

A system where GCC is old enough that it doesn't support -fuse-ld=lld probably doesn't have lld at all, right? So for the non-self-contained mode that would just be an error. I think -fuse-ld=lld for a system lld and -B for the self-contained mode would be the easiest.

LLD was usable earlier than that but I agree we shouldn't bother with them because they likely won't be able to correctly link Rust libraries.

@est31
Copy link
Member

est31 commented May 27, 2022

This is a somewhat new way, the well-known name -fuse-ld=lld works in Clang, and in GCC since 2018 (which GCC version?).

I've tried different gcc versions on gcc.godbolt.org using the dropdown and the oldest that supported -fuse-ld=bfd was 4.8.1 (released May 31, 2013), while the oldest that supported -fuse-ld=lld was 9.1 (released May 3, 2019). I couldn't find any mention of the option or of lld in the changelog, but there are public docs for the command line options (way better than what rustc has btw), for all the versions that gcc has, and if you change the version number, you see the lld entry appearing in 9.1.0 while not existing in 8.5.0.

@petrochenkov
Copy link
Contributor Author

If we don't need to support old versions then the main alternative to -B directory (#97375) is always using -fuse-ld=lld.
In that case we'd keep multiple "symlinks" named ld.lld, ld64.lld etc in our directory, and C compiler will find them.

This would be nice in cases where we ship both classic LD and LLD, like with windows-gnu targets.
-Clink-self-contained then would just setup search directories, and -Cwhatever-option-to-enable-lld would control which file (ld or ld.lld) to find there by name, so the options would be orthogonal.

Then we get the question (which is even more relevant to finding system-provided LLD).
How to make C compiler find anything besides ld.lld?

  • Looks like GCC can only find something named ld.lld when using -fuse-ld=lld.
    It can never find wasm-ld or ld64.lld.
    A specific instance of GCC is built to compile code for a single target, so it doesn't even have something like clang's --target to give details like this.
  • Clang chooses the linker name based on passed --target, so clang --target=x86_64-apple-something would make it use ld64.lld.
    • Rustc's target spec for wasm (compiler\rustc_target\src\spec\wasm32_unknown_unknown.rs) actually passes --target=wasm32-unknown-unknown to C compiler right now, to choose the right linker flavor!
  • QUESTION: Is GCC even used for Apple and Wasm targets?
    • If no then we have a recipe of setting the right flavor with -fuse-ld (for both system-provided and shipped linkers) - pass the --target for Apple and Wasm targets, and do nothing otherwise.

@bjorn3
Copy link
Member

bjorn3 commented Jun 6, 2022

If we don't need to support old versions then the main alternative to -B directory (#97375) is always using -fuse-ld=lld.
In that case we'd keep multiple "symlinks" named ld.lld, ld64.lld etc in our directory, and C compiler will find them.

That only works if you add the directory to the search path for toolchain tools using -B, right? ld.lld is not added to the PATH as it ends up in $(rustc --print sysroot)/lib/rustlib/$HOST_TRIPLE/bin and not $(rustc --print sysroot)/bin. Putting it in the later location would conflict with a system lld installation when globally installing rustc.

QUESTION: Is GCC even used for Apple and Wasm targets?

Gcc can only be used for whichever target you compile it with. If you want to use gcc with an apple target you have to set it as target when compiling gcc. In that case I think it would look for ld64.lld. Same with wasm. For wasm32-unknown-none we directly call lld as there are no system libraries. For wasm32-wasi there is the wasi-sdk which I believe ships with clang and not gcc.

@petrochenkov
Copy link
Contributor Author

That only works if you add the directory to the search path for toolchain tools using -B, right?

Yes, I mean -B will still be used in addition to -fuse-ld if we are in self-contained mode.

In that case I think it would look for ld64.lld. Same with wasm.

I couldn't find such logic in GCC's source code.

@petrochenkov
Copy link
Contributor Author

Update: turns out we cannot pass -rustc-lld-flavor=<flavor> through clang reliably because it can pack linker command line into @files.
So we'll have to partially revert #97375 and use something based on file names like #97402 (comment).

@tschuett
Copy link

tschuett commented Jun 7, 2022

Note that:

> brew search gcc

offers a wide range of gccs: from v4.9 to v12 on my Mac. I never bothered to try them. My Apple clang is fine.

@petrochenkov
Copy link
Contributor Author

Update: #100200 uses the strategy described in #97402 (comment) to fix #97755.

matthiaskrgr added a commit to matthiaskrgr/rust that referenced this issue Sep 1, 2022
…imulacrum

Change implementation of `-Z gcc-ld` and `lld-wrapper` again

This PR partially reverts rust-lang#97375 and uses the strategy described in rust-lang#97402 (comment) instead, thus fixes rust-lang#97755.
Dylan-DPC added a commit to Dylan-DPC/rust that referenced this issue Sep 1, 2022
…imulacrum

Change implementation of `-Z gcc-ld` and `lld-wrapper` again

This PR partially reverts rust-lang#97375 and uses the strategy described in rust-lang#97402 (comment) instead, thus fixes rust-lang#97755.
Dylan-DPC added a commit to Dylan-DPC/rust that referenced this issue Sep 1, 2022
…imulacrum

Change implementation of `-Z gcc-ld` and `lld-wrapper` again

This PR partially reverts rust-lang#97375 and uses the strategy described in rust-lang#97402 (comment) instead, thus fixes rust-lang#97755.
Dylan-DPC added a commit to Dylan-DPC/rust that referenced this issue Sep 1, 2022
…imulacrum

Change implementation of `-Z gcc-ld` and `lld-wrapper` again

This PR partially reverts rust-lang#97375 and uses the strategy described in rust-lang#97402 (comment) instead, thus fixes rust-lang#97755.
Dylan-DPC added a commit to Dylan-DPC/rust that referenced this issue Sep 2, 2022
…imulacrum

Change implementation of `-Z gcc-ld` and `lld-wrapper` again

This PR partially reverts rust-lang#97375 and uses the strategy described in rust-lang#97402 (comment) instead, thus fixes rust-lang#97755.
Dylan-DPC added a commit to Dylan-DPC/rust that referenced this issue Sep 2, 2022
…imulacrum

Change implementation of `-Z gcc-ld` and `lld-wrapper` again

This PR partially reverts rust-lang#97375 and uses the strategy described in rust-lang#97402 (comment) instead, thus fixes rust-lang#97755.
Dylan-DPC added a commit to Dylan-DPC/rust that referenced this issue Sep 2, 2022
…imulacrum

Change implementation of `-Z gcc-ld` and `lld-wrapper` again

This PR partially reverts rust-lang#97375 and uses the strategy described in rust-lang#97402 (comment) instead, thus fixes rust-lang#97755.
Dylan-DPC added a commit to Dylan-DPC/rust that referenced this issue Sep 2, 2022
…imulacrum

Change implementation of `-Z gcc-ld` and `lld-wrapper` again

This PR partially reverts rust-lang#97375 and uses the strategy described in rust-lang#97402 (comment) instead, thus fixes rust-lang#97755.
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this issue Sep 2, 2022
…imulacrum

Change implementation of `-Z gcc-ld` and `lld-wrapper` again

This PR partially reverts rust-lang#97375 and uses the strategy described in rust-lang#97402 (comment) instead, thus fixes rust-lang#97755.
Dylan-DPC added a commit to Dylan-DPC/rust that referenced this issue Sep 2, 2022
…imulacrum

Change implementation of `-Z gcc-ld` and `lld-wrapper` again

This PR partially reverts rust-lang#97375 and uses the strategy described in rust-lang#97402 (comment) instead, thus fixes rust-lang#97755.
Dylan-DPC added a commit to Dylan-DPC/rust that referenced this issue Sep 2, 2022
…imulacrum

Change implementation of `-Z gcc-ld` and `lld-wrapper` again

This PR partially reverts rust-lang#97375 and uses the strategy described in rust-lang#97402 (comment) instead, thus fixes rust-lang#97755.
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this issue Sep 2, 2022
…imulacrum

Change implementation of `-Z gcc-ld` and `lld-wrapper` again

This PR partially reverts rust-lang#97375 and uses the strategy described in rust-lang#97402 (comment) instead, thus fixes rust-lang#97755.
bors added a commit to rust-lang-ci/rust that referenced this issue Jan 3, 2023
Only specify `--target` by default for `-Zgcc-ld=lld` on wasm

On macOS, it's not yet clear which cases of clang/OS/target/SDK version impact how to find ld/lld/rust-lld. The `--target` argument is not needed on our current targets with a vanilla config to do so, but may be in some cases ?

That is, things look to be different and more subtle than suggested in rust-lang#97402 (comment).

Specifying this argument unconditionally currently breaks `-Zgcc-ld=lld` on the 10.7+ targets on x64 macOS. Vanilla configs on x64 and aarch64 don't seem to need it to be able to find `rust-lld`.

This fixes rust-lang#101653 on macOS (I've tried on x64 and aarch64: vanilla installs with the most recent command line tools available for each of the OS versions I have access to, `run-make/issue-71519` passes).

I didn't expect the previous PRs to fail because of the existing tests, but CI does not actually run those tests yet, which explains the regressions. I was hoping to fix those in this PR but it's more involved (building lld is required for the tests to run, llvm/lld is not built on the test builders but on the dist builders, the dist builders don't run tests). This PR is just to unblock current users on macOS who have reported issues, but a regression could happen in the future by mistake until then.

r? `@petrochenkov`
RalfJung pushed a commit to RalfJung/miri that referenced this issue Jan 9, 2023
Only specify `--target` by default for `-Zgcc-ld=lld` on wasm

On macOS, it's not yet clear which cases of clang/OS/target/SDK version impact how to find ld/lld/rust-lld. The `--target` argument is not needed on our current targets with a vanilla config to do so, but may be in some cases ?

That is, things look to be different and more subtle than suggested in rust-lang/rust#97402 (comment).

Specifying this argument unconditionally currently breaks `-Zgcc-ld=lld` on the 10.7+ targets on x64 macOS. Vanilla configs on x64 and aarch64 don't seem to need it to be able to find `rust-lld`.

This fixes #101653 on macOS (I've tried on x64 and aarch64: vanilla installs with the most recent command line tools available for each of the OS versions I have access to, `run-make/issue-71519` passes).

I didn't expect the previous PRs to fail because of the existing tests, but CI does not actually run those tests yet, which explains the regressions. I was hoping to fix those in this PR but it's more involved (building lld is required for the tests to run, llvm/lld is not built on the test builders but on the dist builders, the dist builders don't run tests). This PR is just to unblock current users on macOS who have reported issues, but a regression could happen in the future by mistake until then.

r? `@petrochenkov`
@petrochenkov
Copy link
Contributor Author

The current strategy was implemented in #100200, closing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-linkage Area: linking into static, shared libraries and binaries T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

5 participants