about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_codegen_ssa/src/back/link.rs29
1 files changed, 27 insertions, 2 deletions
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)