Skip to content

Commit

Permalink
Rollup merge of rust-lang#125263 - lqd:lld-fallback, r=petrochenkov
Browse files Browse the repository at this point in the history
rust-lld: fallback to rustc's sysroot if there's no path to the linker in the target sysroot

As seen in rust-lang#125246, some sysroots don't expect to contain `rust-lld` and want to keep it that way, so we fallback to the default rustc sysroot if there is no path to the linker in any of the sysroot tools search paths. This is how we locate codegen-backends' dylibs already.

People also have requested an error if none of these search paths contain the self-contained linker directory, so there's also an error in that case.

r? `@petrochenkov` cc `@ehuss` `@RalfJung`

I'm not sure where we check for `rust-lld`'s existence on the targets where we use it by default, and if we just ignore it when missing or emit a warning (as I assume we don't emit an error), so I just checked for the existence of `gcc-ld`, where `cc` will look for the lld-wrapper binaries.

<sub>*Feel free to point out better ways to do this, it's the middle of the night here.*</sub>

Fixes rust-lang#125246
  • Loading branch information
GuillaumeGomez authored May 23, 2024
2 parents 5baee04 + d64a8bd commit d6a1f1d
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 9 deletions.
2 changes: 2 additions & 0 deletions compiler/rustc_codegen_ssa/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,8 @@ codegen_ssa_rlib_only_rmeta_found = could not find rlib for: `{$crate_name}`, fo
codegen_ssa_select_cpp_build_tool_workload = in the Visual Studio installer, ensure the "C++ build tools" workload is selected
codegen_ssa_self_contained_linker_missing = the self-contained linker was requested, but it wasn't found in the target's sysroot, or in rustc's sysroot
codegen_ssa_shuffle_indices_evaluation = could not evaluate shuffle_indices at compile time
codegen_ssa_specify_libraries_to_link = use the `-l` flag to specify native libraries to link
Expand Down
10 changes: 9 additions & 1 deletion compiler/rustc_codegen_ssa/src/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3140,13 +3140,21 @@ fn add_lld_args(

let self_contained_linker = self_contained_cli || self_contained_target;
if self_contained_linker && !sess.opts.cg.link_self_contained.is_linker_disabled() {
let mut linker_path_exists = false;
for path in sess.get_tools_search_paths(false) {
let linker_path = path.join("gcc-ld");
linker_path_exists |= linker_path.exists();
cmd.arg({
let mut arg = OsString::from("-B");
arg.push(path.join("gcc-ld"));
arg.push(linker_path);
arg
});
}
if !linker_path_exists {
// As a sanity check, we emit an error if none of these paths exist: we want
// self-contained linking and have no linker.
sess.dcx().emit_fatal(errors::SelfContainedLinkerMissing);
}
}

// 2. Implement the "linker flavor" part of this feature by asking `cc` to use some kind of
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_codegen_ssa/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,10 @@ pub struct UnableToExeLinker {
#[diag(codegen_ssa_msvc_missing_linker)]
pub struct MsvcMissingLinker;

#[derive(Diagnostic)]
#[diag(codegen_ssa_self_contained_linker_missing)]
pub struct SelfContainedLinkerMissing;

#[derive(Diagnostic)]
#[diag(codegen_ssa_check_installed_visual_studio)]
pub struct CheckInstalledVisualStudio;
Expand Down
8 changes: 8 additions & 0 deletions compiler/rustc_session/src/filesearch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,14 @@ pub fn make_target_lib_path(sysroot: &Path, target_triple: &str) -> PathBuf {
PathBuf::from_iter([sysroot, Path::new(&rustlib_path), Path::new("lib")])
}

/// Returns a path to the target's `bin` folder within its `rustlib` path in the sysroot. This is
/// where binaries are usually installed, e.g. the self-contained linkers, lld-wrappers, LLVM tools,
/// etc.
pub fn make_target_bin_path(sysroot: &Path, target_triple: &str) -> PathBuf {
let rustlib_path = rustc_target::target_rustlib_path(sysroot, target_triple);
PathBuf::from_iter([sysroot, Path::new(&rustlib_path), Path::new("bin")])
}

#[cfg(unix)]
fn current_dll_path() -> Result<PathBuf, String> {
use std::ffi::{CStr, OsStr};
Expand Down
25 changes: 17 additions & 8 deletions compiler/rustc_session/src/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -449,15 +449,24 @@ impl Session {
)
}

/// Returns a list of directories where target-specific tool binaries are located.
/// Returns a list of directories where target-specific tool binaries are located. Some fallback
/// directories are also returned, for example if `--sysroot` is used but tools are missing
/// (#125246): we also add the bin directories to the sysroot where rustc is located.
pub fn get_tools_search_paths(&self, self_contained: bool) -> Vec<PathBuf> {
let rustlib_path = rustc_target::target_rustlib_path(&self.sysroot, config::host_triple());
let p = PathBuf::from_iter([
Path::new(&self.sysroot),
Path::new(&rustlib_path),
Path::new("bin"),
]);
if self_contained { vec![p.clone(), p.join("self-contained")] } else { vec![p] }
let bin_path = filesearch::make_target_bin_path(&self.sysroot, config::host_triple());
let fallback_sysroot_paths = filesearch::sysroot_candidates()
.into_iter()
.map(|sysroot| filesearch::make_target_bin_path(&sysroot, config::host_triple()));
let search_paths = std::iter::once(bin_path).chain(fallback_sysroot_paths);

if self_contained {
// The self-contained tools are expected to be e.g. in `bin/self-contained` in the
// sysroot's `rustlib` path, so we add such a subfolder to the bin path, and the
// fallback paths.
search_paths.flat_map(|path| [path.clone(), path.join("self-contained")]).collect()
} else {
search_paths.collect()
}
}

pub fn init_incr_comp_session(&self, session_dir: PathBuf, lock_file: flock::Lock) {
Expand Down

0 comments on commit d6a1f1d

Please sign in to comment.