@@ -5,7 +5,7 @@ use rustc_data_structures::fx::FxIndexMap;
55use rustc_data_structures:: memmap:: Mmap ;
66use rustc_data_structures:: temp_dir:: MaybeTempDir ;
77use rustc_errors:: { ErrorGuaranteed , Handler } ;
8- use rustc_fs_util:: fix_windows_verbatim_for_gcc;
8+ use rustc_fs_util:: { fix_windows_verbatim_for_gcc, try_canonicalize } ;
99use rustc_hir:: def_id:: { CrateNum , LOCAL_CRATE } ;
1010use rustc_metadata:: find_native_static_library;
1111use rustc_metadata:: fs:: { copy_to_stdout, emit_wrapper_file, METADATA_FILENAME } ;
@@ -2682,6 +2682,30 @@ fn add_upstream_native_libraries(
26822682 }
26832683}
26842684
2685+ // Rehome lib paths (which exclude the library file name) that point into the sysroot lib directory
2686+ // to be relative to the sysroot directory, which may be a relative path specified by the user.
2687+ //
2688+ // If the sysroot is a relative path, and the sysroot libs are specified as an absolute path, the
2689+ // linker command line can be non-deterministic due to the paths including the current working
2690+ // directory. The linker command line needs to be deterministic since it appears inside the PDB
2691+ // file generated by the MSVC linker. See https://github.com/rust-lang/rust/issues/112586.
2692+ //
2693+ // The returned path will always have `fix_windows_verbatim_for_gcc()` applied to it.
2694+ fn rehome_sysroot_lib_dir < ' a > ( sess : & ' a Session , lib_dir : & Path ) -> PathBuf {
2695+ let sysroot_lib_path = sess. target_filesearch ( PathKind :: All ) . get_lib_path ( ) ;
2696+ let canonical_sysroot_lib_path =
2697+ { try_canonicalize ( & sysroot_lib_path) . unwrap_or_else ( |_| sysroot_lib_path. clone ( ) ) } ;
2698+
2699+ let canonical_lib_dir = try_canonicalize ( lib_dir) . unwrap_or_else ( |_| lib_dir. to_path_buf ( ) ) ;
2700+ if canonical_lib_dir == canonical_sysroot_lib_path {
2701+ // This path, returned by `target_filesearch().get_lib_path()`, has
2702+ // already had `fix_windows_verbatim_for_gcc()` applied if needed.
2703+ sysroot_lib_path
2704+ } else {
2705+ fix_windows_verbatim_for_gcc ( & lib_dir)
2706+ }
2707+ }
2708+
26852709// Adds the static "rlib" versions of all crates to the command line.
26862710// There's a bit of magic which happens here specifically related to LTO,
26872711// namely that we remove upstream object files.
@@ -2713,7 +2737,13 @@ fn add_static_crate<'a>(
27132737 let cratepath = & src. rlib . as_ref ( ) . unwrap ( ) . 0 ;
27142738
27152739 let mut link_upstream = |path : & Path | {
2716- cmd. link_rlib ( & fix_windows_verbatim_for_gcc ( path) ) ;
2740+ let rlib_path = if let Some ( dir) = path. parent ( ) {
2741+ let file_name = path. file_name ( ) . expect ( "rlib path has no file name path component" ) ;
2742+ rehome_sysroot_lib_dir ( sess, & dir) . join ( file_name)
2743+ } else {
2744+ fix_windows_verbatim_for_gcc ( path)
2745+ } ;
2746+ cmd. link_rlib ( & rlib_path) ;
27172747 } ;
27182748
27192749 if !are_upstream_rust_objects_already_included ( sess)
@@ -2782,7 +2812,7 @@ fn add_dynamic_crate(cmd: &mut dyn Linker, sess: &Session, cratepath: &Path) {
27822812 // what its name is
27832813 let parent = cratepath. parent ( ) ;
27842814 if let Some ( dir) = parent {
2785- cmd. include_path ( & fix_windows_verbatim_for_gcc ( dir) ) ;
2815+ cmd. include_path ( & rehome_sysroot_lib_dir ( sess , dir) ) ;
27862816 }
27872817 let stem = cratepath. file_stem ( ) . unwrap ( ) . to_str ( ) . unwrap ( ) ;
27882818 // Convert library file-stem into a cc -l argument.
0 commit comments