diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 8d346c8c0d0..9c53e5c0531 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -5,7 +5,7 @@ use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::memmap::Mmap; use rustc_data_structures::temp_dir::MaybeTempDir; use rustc_errors::{ErrorGuaranteed, Handler}; -use rustc_fs_util::fix_windows_verbatim_for_gcc; +use rustc_fs_util::{fix_windows_verbatim_for_gcc, try_canonicalize}; use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; use rustc_metadata::find_native_static_library; use rustc_metadata::fs::{copy_to_stdout, emit_wrapper_file, METADATA_FILENAME}; @@ -2682,6 +2682,31 @@ fn add_upstream_native_libraries( } } +// Rehome sysroot lib paths to be relative to the sysroot, which may be a relative +// path specified by the user. If the sysroot is a relative path, and the sysroot rlibs +// are specified as an absolute path, the linker command line can be non-deterministic +// due to the paths including the current working directory. The linker command line +// needs to be deterministic since it appears inside the PDB file generated by the MSVC +// linker. See https://github.com/rust-lang/rust/issues/112586. +// +// Note that the `susroot_lib_path` returned by `target_filesearch().get_lib_path()` has +// already had `fix_windows_verbatim_for_gcc()` applied if needed. +fn rehome_sysroot_rlib_path<'a>(sess: &'a Session, rlib_path: PathBuf) -> PathBuf { + let sysroot_lib_path = sess.target_filesearch(PathKind::All).get_lib_path(); + let canonical_sysroot_lib_path = + { try_canonicalize(&sysroot_lib_path).unwrap_or_else(|_| sysroot_lib_path.clone()) }; + + let mut canonical_rlib_dir = try_canonicalize(&rlib_path).unwrap_or_else(|_| rlib_path.clone()); + canonical_rlib_dir.pop(); + + if canonical_rlib_dir == canonical_sysroot_lib_path { + sysroot_lib_path + .join(rlib_path.file_name().expect("rlib path has no file name path component")) + } else { + rlib_path + } +} + // Adds the static "rlib" versions of all crates to the command line. // There's a bit of magic which happens here specifically related to LTO, // namely that we remove upstream object files. @@ -2713,7 +2738,7 @@ fn add_static_crate<'a>( let cratepath = &src.rlib.as_ref().unwrap().0; let mut link_upstream = |path: &Path| { - cmd.link_rlib(&fix_windows_verbatim_for_gcc(path)); + cmd.link_rlib(&rehome_sysroot_rlib_path(sess, fix_windows_verbatim_for_gcc(path))); }; if !are_upstream_rust_objects_already_included(sess)