From 7e07271eaf6f8ae1f3b2c3ffeb46bf1c13f36bc1 Mon Sep 17 00:00:00 2001 From: danakj Date: Wed, 14 Jun 2023 10:44:00 -0400 Subject: [PATCH 1/3] Avoid absolute sysroot paths in the MSVC linker command line When the `--sysroot` is specified as relative to the current working directory, the sysroot's rlibs should also be specified as relative paths. Otherwise, the current working directory ends up in the absolute paths, and in the linker command line. And the entire linker command line appears in the PDB file generated by the MSVC linker. When adding an rlib to the linker command line, if the rlib's canonical path is in the sysroot's canonical path, then use the current sysroot path + filename instead of the full absolute path to the rlib. This means that when `--sysroot=foo` is specified, the linker command line will contain `foo/rustlib/target/lib/lib*.rlib` instead of the full absolute path to the same. This addresses https://github.com/rust-lang/rust/issues/112586 --- compiler/rustc_codegen_ssa/src/back/link.rs | 29 +++++++++++++++++++-- 1 file 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 8d346c8c0d0de..9c53e5c05313d 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) From 4b83156a5c503174e7b4ce130edbe348fcd82817 Mon Sep 17 00:00:00 2001 From: danakj Date: Wed, 14 Jun 2023 10:58:08 -0400 Subject: [PATCH 2/3] Move the comment on fixing paths to where it belongs --- compiler/rustc_codegen_ssa/src/back/link.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 9c53e5c05313d..6369116ece3aa 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -2688,9 +2688,6 @@ fn add_upstream_native_libraries( // 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 = @@ -2700,6 +2697,8 @@ fn rehome_sysroot_rlib_path<'a>(sess: &'a Session, rlib_path: PathBuf) -> PathBu canonical_rlib_dir.pop(); if canonical_rlib_dir == canonical_sysroot_lib_path { + // The `susroot_lib_path` returned by `target_filesearch().get_lib_path()` has + // already had `fix_windows_verbatim_for_gcc()` applied if needed. sysroot_lib_path .join(rlib_path.file_name().expect("rlib path has no file name path component")) } else { From c340325ebf348914c67fc62e868db8833845eeb9 Mon Sep 17 00:00:00 2001 From: danakj Date: Thu, 15 Jun 2023 11:13:03 -0400 Subject: [PATCH 3/3] Remap dylib paths into the sysroot to be relative to the sysroot Like for rlibs, the paths on the linker command line need to be relative paths if the sysroot was specified by the user to be a relative path. Dylibs put the path in /LIBPATH instead of into the file path of the library itself, so we rehome the libpath and adjust the rehoming function to be able to support both use cases, rlibs and dylibs. --- compiler/rustc_codegen_ssa/src/back/link.rs | 38 ++++++++++++--------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 6369116ece3aa..557b120b2c8f9 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -2682,27 +2682,27 @@ 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. -fn rehome_sysroot_rlib_path<'a>(sess: &'a Session, rlib_path: PathBuf) -> PathBuf { +// Rehome lib paths (which exclude the library file name) that point into the sysroot lib directory +// to be relative to the sysroot directory, which may be a relative path specified by the user. +// +// If the sysroot is a relative path, and the sysroot libs 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. +// +// The returned path will always have `fix_windows_verbatim_for_gcc()` applied to it. +fn rehome_sysroot_lib_dir<'a>(sess: &'a Session, lib_dir: &Path) -> 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 { - // The `susroot_lib_path` returned by `target_filesearch().get_lib_path()` has + let canonical_lib_dir = try_canonicalize(lib_dir).unwrap_or_else(|_| lib_dir.to_path_buf()); + if canonical_lib_dir == canonical_sysroot_lib_path { + // This path, returned by `target_filesearch().get_lib_path()`, has // already had `fix_windows_verbatim_for_gcc()` applied if needed. sysroot_lib_path - .join(rlib_path.file_name().expect("rlib path has no file name path component")) } else { - rlib_path + fix_windows_verbatim_for_gcc(&lib_dir) } } @@ -2737,7 +2737,13 @@ fn add_static_crate<'a>( let cratepath = &src.rlib.as_ref().unwrap().0; let mut link_upstream = |path: &Path| { - cmd.link_rlib(&rehome_sysroot_rlib_path(sess, fix_windows_verbatim_for_gcc(path))); + let rlib_path = if let Some(dir) = path.parent() { + let file_name = path.file_name().expect("rlib path has no file name path component"); + rehome_sysroot_lib_dir(sess, &dir).join(file_name) + } else { + fix_windows_verbatim_for_gcc(path) + }; + cmd.link_rlib(&rlib_path); }; if !are_upstream_rust_objects_already_included(sess) @@ -2806,7 +2812,7 @@ fn add_dynamic_crate(cmd: &mut dyn Linker, sess: &Session, cratepath: &Path) { // what its name is let parent = cratepath.parent(); if let Some(dir) = parent { - cmd.include_path(&fix_windows_verbatim_for_gcc(dir)); + cmd.include_path(&rehome_sysroot_lib_dir(sess, dir)); } let stem = cratepath.file_stem().unwrap().to_str().unwrap(); // Convert library file-stem into a cc -l argument.