Properly pass linker arguments that contain commas
When linking with the system C compiler, we sometimes want to forward certain arguments unchanged to the linker. This can be done with `-Wl,arg1,arg2` or `-Xlinker arg1 -Xlinker arg2`. `-Wl` is used when possible, since it is more compact, but it does not support commas in the argument itself - in those cases, we need to use `-Xlinker`, and that is what this PR implements.
This also fixes using sanitizers on macOS with `-Clinker-flavor=ld`, as those were previously manually using `-Wl`/`-Xlinker` (probably since the support wasn't present in the `link_args` function).
Note that there has been [a previous PR for this](https://github.com/rust-lang/rust/pull/38798), but it only implemented this in certain cases when passing `-rpath`.
r? compiler
Using `cc_args` panics when using `-Clinker-flavor=ld`, because the
arguments are in a form tailored for `-Clinker-flavor=gcc`.
So instead, we use `link_args` and let that wrap the arguments with the
appropriate `-Wl` or `-Xlinker` when needed.
[AIX] Add option -X32_64 to the "strip" command
The AIX `strip` utility requires option `-X` to specify the object mode. This patch adds the `-X32_64` option to the `strip` command so that it can handle both 32-bit and 64-bit objects. The parameter `option` of function `strip_symbols_with_external_utility`, previously a single string, has been changed to `options`, an array of string slices, to accommodate multiple `strip` options.
Over in Zed we've noticed that loading crates for a large-ish workspace can take almost 200ms. We've pinned it down to how rustc searches for paths, as it performs a linear search over the list of candidate paths. In our case the candidate list had about 20k entries which we had to iterate over for each dependency being loaded.
This commit introduces a simple FilesIndex that's just a sorted Vec under the hood. Since crates are looked up by both prefix and suffix, we perform a range search on said Vec (which constraints the search space based on prefix) and follow up with a linear scan of entries with matching suffixes.
FilesIndex is also pre-filtered before any queries are performed using available target information; query prefixes/sufixes are based on the target we are compiling for, so we can remove entries that can never match up front.
Overall, this commit brings down build time for us in dev scenarios by about 6%.
100ms might not seem like much, but this is a constant cost that each of our workspace crates has to pay, even when said crate is miniscule.
Add a default implementation for CodegenBackend::link
As a side effect this should add raw-dylib support to cg_gcc as the default ArchiveBuilderBuilder that is used implements create_dll_import_lib. I haven't tested if the raw-dylib support actually works however.
After link_binary the temporary files referenced by CodegenResults are
deleted, so calling link_binary again with the same CodegenResults
should not be allowed.
On arm64, Cranelift used to produce object files that don't work with
lld. This has since been fixed. The GCC backend should always produce
object files that work with lld unless lld for whatever reason drops GCC
support. Most of the other more niche backends don't use cg_ssa's linker
code at all. If they do and don't work with lld, they can always disable
lld usage using a cli argument.
Without this commit using cg_clif is by default in a non-trivial amount
of cases a perf regression on Linux due to ld.bfd being a fair bit
slower than lld. It is possible to explicitly enable it without this
commit, but most users are unlikely to do this.
Set "symbol name" in raw-dylib import libraries to the decorated name
`windows-rs` received a bug report that mixing raw-dylib generated and the Windows SDK import libraries was causing linker failures: <https://github.com/microsoft/windows-rs/issues/3285>
The root cause turned out to be #124958, that is we are not including the decorated name in the import library and so the import name type is also not being correctly set.
This change modifies the generation of import libraries to set the "symbol name" to the fully decorated name and correctly marks the import as being data vs function.
Note that this also required some changes to how the symbol is named within Rust: for MSVC we now need to use the decorated name but for MinGW we still need to use partially decorated (or undecorated) name.
Fixes#124958
Passing i686 MSVC and MinGW build: <https://github.com/rust-lang/rust/actions/runs/11000433888?pr=130586>
r? `@ChrisDenton`
The target name can be anything with custom target specs. Matching on
fields inside the target spec is much more robust than matching on the
target name.
The OS version depends on the deployment target environment variables,
the access of which we want to move to later in the compilation pipeline
that has access to more information, for example `env_depinfo`.
Apple: Do not specify an SDK version in `rlib` object files
This was added in https://github.com/rust-lang/rust/pull/114114, but is unnecessary, since it ends up being overwritten when linking anyhow, and it feels wrong to embed some arbitrary SDK version in here. The object files produced by LLVM also do not set this, and the tooling shows `n/a` when it's `0`, so it seems to genuinely be optional in object files.
I've also added a test for the different places the SDK version shows up, and documented a bit more in the code how SDK versions work.
See https://github.com/rust-lang/rust/issues/129432 for the bigger picture.
Tested with (excludes the same few targets as in https://github.com/rust-lang/rust/pull/130435):
```console
./x test tests/run-make/apple-sdk-version --target aarch64-apple-darwin,aarch64-apple-ios,aarch64-apple-ios-macabi,aarch64-apple-ios-sim,aarch64-apple-tvos,aarch64-apple-tvos-sim,aarch64-apple-visionos,aarch64-apple-visionos-sim,aarch64-apple-watchos,aarch64-apple-watchos-sim,arm64_32-apple-watchos,armv7k-apple-watchos,armv7s-apple-ios,x86_64-apple-darwin,x86_64-apple-ios,x86_64-apple-ios-macabi,x86_64-apple-tvos,x86_64-apple-watchos-sim,x86_64h-apple-darwin
IPHONEOS_DEPLOYMENT_TARGET=10.0 ./x test tests/run-make/apple-sdk-version --target=i386-apple-ios
```
CC `@BlackHoleFox,` you [originally commented on these values](https://github.com/rust-lang/rust/pull/114114#discussion_r1300599445).
`@rustbot` label O-apple
Simplify some nested `if` statements
Applies some but not all instances of `clippy::collapsible_if`. Some ended up looking worse afterwards, though, so I left those out. Also applies instances of `clippy::collapsible_else_if`
Review with whitespace disabled please.
rustc: Simplify getting sysroot library directory
It was very non-obvious that `sess.target_tlib_path`, `make_target_lib_path(...)`, and `sess.target_filesearch(...).search_paths()` result in the same sysroot library directory paths.
They are however, indeed the same, because `sess.target_tlib_path` is initialized to `make_target_lib_path(...)` on `Session` creation, and they are used interchangeably.
There are still some redundant calls to `make_target_lib_path` and other inconsistent ways to obtain sysroot directories, but fixing that requires some behavior changes, while this PR is a pure refactoring.
Some places in the compiler even disagree on the number of sysroots - 1 (explicit `--sysroot` *or* default sysroot), 2 (explicit `--sysroot` *and* default sysroot), or an unclear number of `sysroot_candidates` every of which is considered.
The logic currently using `sess.target_tlib_path` or equivalents assumes one sysroot.
Make create_dll_import_lib easier to implement
This will make it easier to implement raw-dylib support in cg_clif and cg_gcc. This PR doesn't yet include an create_dll_import_lib implementation for cg_clif as I need to correctly implement dllimport in cg_clif first before raw-dylib can work at all with cg_clif.
Required for https://github.com/rust-lang/rustc_codegen_cranelift/issues/1345
When an archive fails to build, print the path
Currently the output on failure is as follows:
Compiling block-buffer v0.10.4
Compiling crypto-common v0.1.6
Compiling digest v0.10.7
Compiling sha2 v0.10.8
Compiling xz2 v0.1.7
error: failed to build archive: No such file or directory
error: could not compile `bootstrap` (lib) due to 1 previous error
Change this to print which file is being constructed, to give some hint about what is going on.
error: failed to build archive at `path/to/output`: No such file or directory
Clean up a few minor refs in `format!` macro, as it has a performance cost. Apparently the compiler is unable to inline `format!("{}", &variable)`, and does a run-time double-reference instead (format macro already does one level referencing). Inlining format args prevents accidental `&` misuse.
Currently the output on failure is as follows:
Compiling block-buffer v0.10.4
Compiling crypto-common v0.1.6
Compiling digest v0.10.7
Compiling sha2 v0.10.8
Compiling xz2 v0.1.7
error: failed to build archive: No such file or directory
error: could not compile `bootstrap` (lib) due to 1 previous error
Print which file is being constructed to give some hint about what is
going on.
De-duplicate all consecutive native libs regardless of their options
Address https://github.com/rust-lang/rust/pull/126913#issuecomment-2188184011 by no longer de-duplicating based on the "options" but by only looking at the generated link args, as to avoid consecutive libs that originated from different native-lib with different options (like `raw-dylib` on Windows) but isn't relevant for `--print=native-static-libs`.
r? ``@petrochenkov``