From 50501c6fbaea5db4d9fed7e2df83b25c264f57a9 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Wed, 17 Jan 2024 23:14:14 +0300 Subject: [PATCH 1/7] linker: Refactor APIs for linking dynamic libraries Rename `link_(dylib,framework)`, remove `link_rust_dylib`. --- compiler/rustc_codegen_ssa/src/back/link.rs | 17 ++- compiler/rustc_codegen_ssa/src/back/linker.rs | 109 ++++-------------- 2 files changed, 33 insertions(+), 93 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 959653c932653..411f727a9f87b 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -1265,7 +1265,7 @@ fn link_sanitizer_runtime( let path = find_sanitizer_runtime(sess, &filename); let rpath = path.to_str().expect("non-utf8 component in path"); linker.args(&["-Wl,-rpath", "-Xlinker", rpath]); - linker.link_dylib(&filename, false, true); + linker.link_dylib_by_name(&filename, false, true); } else if sess.target.is_like_msvc && flavor == LinkerFlavor::Msvc(Lld::No) && name == "asan" { // MSVC provides the `/INFERASANLIBS` argument to automatically find the // compatible ASAN library. @@ -2526,7 +2526,7 @@ fn add_native_libs_from_crate( } NativeLibKind::Dylib { as_needed } => { if link_dynamic { - cmd.link_dylib(name, verbatim, as_needed.unwrap_or(true)) + cmd.link_dylib_by_name(name, verbatim, as_needed.unwrap_or(true)) } } NativeLibKind::Unspecified => { @@ -2538,13 +2538,13 @@ fn add_native_libs_from_crate( } } else { if link_dynamic { - cmd.link_dylib(name, verbatim, true); + cmd.link_dylib_by_name(name, verbatim, true); } } } NativeLibKind::Framework { as_needed } => { if link_dynamic { - cmd.link_framework(name, as_needed.unwrap_or(true)) + cmd.link_framework_by_name(name, verbatim, as_needed.unwrap_or(true)) } } NativeLibKind::RawDylib => { @@ -2859,13 +2859,20 @@ fn add_dynamic_crate(cmd: &mut dyn Linker, sess: &Session, cratepath: &Path) { // Just need to tell the linker about where the library lives and // what its name is let parent = cratepath.parent(); + // When producing a dll, the MSVC linker may not actually emit a + // `foo.lib` file if the dll doesn't actually export any symbols, so we + // check to see if the file is there and just omit linking to it if it's + // not present. + if sess.target.is_like_msvc && !cratepath.with_extension("dll.lib").exists() { + return; + } if let Some(dir) = parent { 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. let prefix = if stem.starts_with("lib") && !sess.target.is_like_windows { 3 } else { 0 }; - cmd.link_rust_dylib(&stem[prefix..], parent.unwrap_or_else(|| Path::new(""))); + cmd.link_dylib_by_name(&stem[prefix..], false, true); } fn relevant_lib(sess: &Session, lib: &NativeLib) -> bool { diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index 90f5027c26494..9a854bb7101dd 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -166,9 +166,10 @@ pub fn get_linker<'a>( pub trait Linker { fn cmd(&mut self) -> &mut Command; fn set_output_kind(&mut self, output_kind: LinkOutputKind, out_filename: &Path); - fn link_dylib(&mut self, lib: &str, verbatim: bool, as_needed: bool); - fn link_rust_dylib(&mut self, lib: &str, path: &Path); - fn link_framework(&mut self, framework: &str, as_needed: bool); + fn link_dylib_by_name(&mut self, name: &str, verbatim: bool, as_needed: bool); + fn link_framework_by_name(&mut self, _name: &str, _verbatim: bool, _as_needed: bool) { + bug!("framework linked with unsupported linker") + } fn link_staticlib(&mut self, lib: &str, verbatim: bool); fn link_rlib(&mut self, lib: &Path); fn link_whole_rlib(&mut self, lib: &Path); @@ -432,8 +433,8 @@ impl<'a> Linker for GccLinker<'a> { } } - fn link_dylib(&mut self, lib: &str, verbatim: bool, as_needed: bool) { - if self.sess.target.os == "illumos" && lib == "c" { + fn link_dylib_by_name(&mut self, name: &str, verbatim: bool, as_needed: bool) { + if self.sess.target.os == "illumos" && name == "c" { // libc will be added via late_link_args on illumos so that it will // appear last in the library search order. // FIXME: This should be replaced by a more complete and generic @@ -454,7 +455,7 @@ impl<'a> Linker for GccLinker<'a> { } } self.hint_dynamic(); - self.cmd.arg(format!("-l{}{lib}", if verbatim && self.is_gnu { ":" } else { "" },)); + self.cmd.arg(format!("-l{}{name}", if verbatim && self.is_gnu { ":" } else { "" },)); if !as_needed { if self.sess.target.is_like_osx { // See above FIXME comment @@ -493,20 +494,15 @@ impl<'a> Linker for GccLinker<'a> { self.linker_args(&["-z", "norelro"]); } - fn link_rust_dylib(&mut self, lib: &str, _path: &Path) { - self.hint_dynamic(); - self.cmd.arg(format!("-l{lib}")); - } - - fn link_framework(&mut self, framework: &str, as_needed: bool) { + fn link_framework_by_name(&mut self, name: &str, _verbatim: bool, as_needed: bool) { self.hint_dynamic(); if !as_needed { // FIXME(81490): ld64 as of macOS 11 supports the -needed_framework // flag but we have no way to detect that here. - // self.cmd.arg("-needed_framework").arg(framework); + // self.cmd.arg("-needed_framework").arg(name); self.sess.dcx().emit_warn(errors::Ld64UnimplementedModifier); } - self.cmd.arg("-framework").arg(framework); + self.cmd.arg("-framework").arg(name); } // Here we explicitly ask that the entire archive is included into the @@ -845,19 +841,8 @@ impl<'a> Linker for MsvcLinker<'a> { self.cmd.arg("/OPT:NOREF,NOICF"); } - fn link_dylib(&mut self, lib: &str, verbatim: bool, _as_needed: bool) { - self.cmd.arg(format!("{}{}", lib, if verbatim { "" } else { ".lib" })); - } - - fn link_rust_dylib(&mut self, lib: &str, path: &Path) { - // When producing a dll, the MSVC linker may not actually emit a - // `foo.lib` file if the dll doesn't actually export any symbols, so we - // check to see if the file is there and just omit linking to it if it's - // not present. - let name = format!("{lib}.dll.lib"); - if path.join(&name).exists() { - self.cmd.arg(name); - } + fn link_dylib_by_name(&mut self, name: &str, verbatim: bool, _as_needed: bool) { + self.cmd.arg(format!("{}{}", name, if verbatim { "" } else { ".lib" })); } fn link_staticlib(&mut self, lib: &str, verbatim: bool) { @@ -899,9 +884,6 @@ impl<'a> Linker for MsvcLinker<'a> { fn framework_path(&mut self, _path: &Path) { bug!("frameworks are not supported on windows") } - fn link_framework(&mut self, _framework: &str, _as_needed: bool) { - bug!("frameworks are not supported on windows") - } fn link_whole_staticlib(&mut self, lib: &str, verbatim: bool, _search_path: &[PathBuf]) { self.cmd.arg(format!("/WHOLEARCHIVE:{}{}", lib, if verbatim { "" } else { ".lib" })); @@ -1073,9 +1055,9 @@ impl<'a> Linker for EmLinker<'a> { self.cmd.arg(path); } - fn link_dylib(&mut self, lib: &str, verbatim: bool, _as_needed: bool) { + fn link_dylib_by_name(&mut self, name: &str, verbatim: bool, _as_needed: bool) { // Emscripten always links statically - self.link_staticlib(lib, verbatim); + self.link_staticlib(name, verbatim); } fn link_whole_staticlib(&mut self, lib: &str, verbatim: bool, _search_path: &[PathBuf]) { @@ -1088,10 +1070,6 @@ impl<'a> Linker for EmLinker<'a> { self.link_rlib(lib); } - fn link_rust_dylib(&mut self, lib: &str, _path: &Path) { - self.link_dylib(lib, false, true); - } - fn link_rlib(&mut self, lib: &Path) { self.add_object(lib); } @@ -1112,10 +1090,6 @@ impl<'a> Linker for EmLinker<'a> { bug!("frameworks are not supported on Emscripten") } - fn link_framework(&mut self, _framework: &str, _as_needed: bool) { - bug!("frameworks are not supported on Emscripten") - } - fn gc_sections(&mut self, _keep_metadata: bool) { // noop } @@ -1249,8 +1223,8 @@ impl<'a> Linker for WasmLd<'a> { } } - fn link_dylib(&mut self, lib: &str, _verbatim: bool, _as_needed: bool) { - self.cmd.arg("-l").arg(lib); + fn link_dylib_by_name(&mut self, name: &str, _verbatim: bool, _as_needed: bool) { + self.cmd.arg("-l").arg(name); } fn link_staticlib(&mut self, lib: &str, _verbatim: bool) { @@ -1283,14 +1257,6 @@ impl<'a> Linker for WasmLd<'a> { fn no_relro(&mut self) {} - fn link_rust_dylib(&mut self, lib: &str, _path: &Path) { - self.cmd.arg("-l").arg(lib); - } - - fn link_framework(&mut self, _framework: &str, _as_needed: bool) { - panic!("frameworks not supported") - } - fn link_whole_staticlib(&mut self, lib: &str, _verbatim: bool, _search_path: &[PathBuf]) { self.cmd.arg("--whole-archive").arg("-l").arg(lib).arg("--no-whole-archive"); } @@ -1398,7 +1364,7 @@ pub struct L4Bender<'a> { } impl<'a> Linker for L4Bender<'a> { - fn link_dylib(&mut self, _lib: &str, _verbatim: bool, _as_needed: bool) { + fn link_dylib_by_name(&mut self, _name: &str, _verbatim: bool, _as_needed: bool) { bug!("dylibs are not supported on L4Re"); } fn link_staticlib(&mut self, lib: &str, _verbatim: bool) { @@ -1442,14 +1408,6 @@ impl<'a> Linker for L4Bender<'a> { fn set_output_kind(&mut self, _output_kind: LinkOutputKind, _out_filename: &Path) {} - fn link_rust_dylib(&mut self, _: &str, _: &Path) { - panic!("Rust dylibs not supported"); - } - - fn link_framework(&mut self, _framework: &str, _as_needed: bool) { - bug!("frameworks not supported on L4Re"); - } - fn link_whole_staticlib(&mut self, lib: &str, _verbatim: bool, _search_path: &[PathBuf]) { self.hint_static(); self.cmd.arg("--whole-archive").arg(format!("-l{lib}")); @@ -1571,9 +1529,9 @@ impl<'a> AixLinker<'a> { } impl<'a> Linker for AixLinker<'a> { - fn link_dylib(&mut self, lib: &str, _verbatim: bool, _as_needed: bool) { + fn link_dylib_by_name(&mut self, name: &str, _verbatim: bool, _as_needed: bool) { self.hint_dynamic(); - self.cmd.arg(format!("-l{lib}")); + self.cmd.arg(format!("-l{name}")); } fn link_staticlib(&mut self, lib: &str, _verbatim: bool) { @@ -1626,15 +1584,6 @@ impl<'a> Linker for AixLinker<'a> { } } - fn link_rust_dylib(&mut self, lib: &str, _: &Path) { - self.hint_dynamic(); - self.cmd.arg(format!("-l{lib}")); - } - - fn link_framework(&mut self, _framework: &str, _as_needed: bool) { - bug!("frameworks not supported on AIX"); - } - fn link_whole_staticlib(&mut self, lib: &str, verbatim: bool, search_path: &[PathBuf]) { self.hint_static(); let lib = find_native_static_library(lib, verbatim, search_path, self.sess); @@ -1844,11 +1793,7 @@ impl<'a> Linker for PtxLinker<'a> { self.cmd.arg("-o").arg(path); } - fn link_dylib(&mut self, _lib: &str, _verbatim: bool, _as_needed: bool) { - panic!("external dylibs not supported") - } - - fn link_rust_dylib(&mut self, _lib: &str, _path: &Path) { + fn link_dylib_by_name(&mut self, _name: &str, _verbatim: bool, _as_needed: bool) { panic!("external dylibs not supported") } @@ -1864,10 +1809,6 @@ impl<'a> Linker for PtxLinker<'a> { panic!("frameworks not supported") } - fn link_framework(&mut self, _framework: &str, _as_needed: bool) { - panic!("frameworks not supported") - } - fn full_relro(&mut self) {} fn partial_relro(&mut self) {} @@ -1942,11 +1883,7 @@ impl<'a> Linker for BpfLinker<'a> { self.cmd.arg("-o").arg(path); } - fn link_dylib(&mut self, _lib: &str, _verbatim: bool, _as_needed: bool) { - panic!("external dylibs not supported") - } - - fn link_rust_dylib(&mut self, _lib: &str, _path: &Path) { + fn link_dylib_by_name(&mut self, _name: &str, _verbatim: bool, _as_needed: bool) { panic!("external dylibs not supported") } @@ -1962,10 +1899,6 @@ impl<'a> Linker for BpfLinker<'a> { panic!("frameworks not supported") } - fn link_framework(&mut self, _framework: &str, _as_needed: bool) { - panic!("frameworks not supported") - } - fn full_relro(&mut self) {} fn partial_relro(&mut self) {} From 0e38a65612570bb0cabcf77a55d6f171c42413a5 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 18 Jan 2024 00:28:56 +0300 Subject: [PATCH 2/7] linker: Refactor APIs for linking static libraries Rename `link(_whole)(staticlib,rlib)` to something more suitable. --- compiler/rustc_codegen_ssa/src/back/link.rs | 14 +- compiler/rustc_codegen_ssa/src/back/linker.rs | 169 +++++++++++------- 2 files changed, 114 insertions(+), 69 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 411f727a9f87b..18fa8a41c4622 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -1273,7 +1273,7 @@ fn link_sanitizer_runtime( } else { let filename = format!("librustc{channel}_rt.{name}.a"); let path = find_sanitizer_runtime(sess, &filename).join(&filename); - linker.link_whole_rlib(&path); + linker.link_whole_staticlib_by_path(&path); } } @@ -2506,20 +2506,20 @@ fn add_native_libs_from_crate( // If rlib contains native libs as archives, they are unpacked to tmpdir. let path = tmpdir.join(filename.as_str()); if whole_archive { - cmd.link_whole_rlib(&path); + cmd.link_whole_staticlib_by_path(&path); } else { - cmd.link_rlib(&path); + cmd.link_staticlib_by_path(&path); } } } else { if whole_archive { - cmd.link_whole_staticlib( + cmd.link_whole_staticlib_by_name( name, verbatim, search_paths.get_or_init(|| archive_search_paths(sess)), ); } else { - cmd.link_staticlib(name, verbatim) + cmd.link_staticlib_by_name(name, verbatim) } } } @@ -2534,7 +2534,7 @@ fn add_native_libs_from_crate( // link kind is unspecified. if !link_output_kind.can_link_dylib() && !sess.target.crt_static_allows_dylibs { if link_static { - cmd.link_staticlib(name, verbatim) + cmd.link_staticlib_by_name(name, verbatim) } } else { if link_dynamic { @@ -2791,7 +2791,7 @@ fn add_static_crate<'a>( } else { fix_windows_verbatim_for_gcc(path) }; - cmd.link_rlib(&rlib_path); + cmd.link_staticlib_by_path(&rlib_path); }; if !are_upstream_rust_objects_already_included(sess) diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index 9a854bb7101dd..4360c10edc30a 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -170,10 +170,15 @@ pub trait Linker { fn link_framework_by_name(&mut self, _name: &str, _verbatim: bool, _as_needed: bool) { bug!("framework linked with unsupported linker") } - fn link_staticlib(&mut self, lib: &str, verbatim: bool); - fn link_rlib(&mut self, lib: &Path); - fn link_whole_rlib(&mut self, lib: &Path); - fn link_whole_staticlib(&mut self, lib: &str, verbatim: bool, search_path: &[PathBuf]); + fn link_staticlib_by_name(&mut self, name: &str, verbatim: bool); + fn link_staticlib_by_path(&mut self, path: &Path); + fn link_whole_staticlib_by_name( + &mut self, + name: &str, + verbatim: bool, + search_paths: &[PathBuf], + ); + fn link_whole_staticlib_by_path(&mut self, path: &Path); fn include_path(&mut self, path: &Path); fn framework_path(&mut self, path: &Path); fn output_filename(&mut self, path: &Path); @@ -464,13 +469,13 @@ impl<'a> Linker for GccLinker<'a> { } } } - fn link_staticlib(&mut self, lib: &str, verbatim: bool) { + fn link_staticlib_by_name(&mut self, name: &str, verbatim: bool) { self.hint_static(); - self.cmd.arg(format!("-l{}{lib}", if verbatim && self.is_gnu { ":" } else { "" },)); + self.cmd.arg(format!("-l{}{name}", if verbatim && self.is_gnu { ":" } else { "" },)); } - fn link_rlib(&mut self, lib: &Path) { + fn link_staticlib_by_path(&mut self, path: &Path) { self.hint_static(); - self.cmd.arg(lib); + self.cmd.arg(path); } fn include_path(&mut self, path: &Path) { self.cmd.arg("-L").arg(path); @@ -511,29 +516,34 @@ impl<'a> Linker for GccLinker<'a> { // don't otherwise explicitly reference them. This can occur for // libraries which are just providing bindings, libraries with generic // functions, etc. - fn link_whole_staticlib(&mut self, lib: &str, verbatim: bool, search_path: &[PathBuf]) { + fn link_whole_staticlib_by_name( + &mut self, + name: &str, + verbatim: bool, + search_paths: &[PathBuf], + ) { self.hint_static(); let target = &self.sess.target; if !target.is_like_osx { self.linker_arg("--whole-archive"); - self.cmd.arg(format!("-l{}{lib}", if verbatim && self.is_gnu { ":" } else { "" },)); + self.cmd.arg(format!("-l{}{name}", if verbatim && self.is_gnu { ":" } else { "" })); self.linker_arg("--no-whole-archive"); } else { // -force_load is the macOS equivalent of --whole-archive, but it // involves passing the full path to the library to link. self.linker_arg("-force_load"); - let lib = find_native_static_library(lib, verbatim, search_path, self.sess); + let lib = find_native_static_library(name, verbatim, search_paths, self.sess); self.linker_arg(&lib); } } - fn link_whole_rlib(&mut self, lib: &Path) { + fn link_whole_staticlib_by_path(&mut self, path: &Path) { self.hint_static(); if self.sess.target.is_like_osx { self.linker_arg("-force_load"); - self.linker_arg(&lib); + self.linker_arg(&path); } else { - self.linker_args(&[OsString::from("--whole-archive"), lib.into()]); + self.linker_args(&[OsString::from("--whole-archive"), path.into()]); self.linker_arg("--no-whole-archive"); } } @@ -817,8 +827,8 @@ impl<'a> Linker for MsvcLinker<'a> { } } - fn link_rlib(&mut self, lib: &Path) { - self.cmd.arg(lib); + fn link_staticlib_by_path(&mut self, path: &Path) { + self.cmd.arg(path); } fn add_object(&mut self, path: &Path) { self.cmd.arg(path); @@ -845,8 +855,8 @@ impl<'a> Linker for MsvcLinker<'a> { self.cmd.arg(format!("{}{}", name, if verbatim { "" } else { ".lib" })); } - fn link_staticlib(&mut self, lib: &str, verbatim: bool) { - self.cmd.arg(format!("{}{}", lib, if verbatim { "" } else { ".lib" })); + fn link_staticlib_by_name(&mut self, name: &str, verbatim: bool) { + self.cmd.arg(format!("{}{}", name, if verbatim { "" } else { ".lib" })); } fn full_relro(&mut self) { @@ -885,10 +895,15 @@ impl<'a> Linker for MsvcLinker<'a> { bug!("frameworks are not supported on windows") } - fn link_whole_staticlib(&mut self, lib: &str, verbatim: bool, _search_path: &[PathBuf]) { - self.cmd.arg(format!("/WHOLEARCHIVE:{}{}", lib, if verbatim { "" } else { ".lib" })); + fn link_whole_staticlib_by_name( + &mut self, + name: &str, + verbatim: bool, + _search_paths: &[PathBuf], + ) { + self.cmd.arg(format!("/WHOLEARCHIVE:{}{}", name, if verbatim { "" } else { ".lib" })); } - fn link_whole_rlib(&mut self, path: &Path) { + fn link_whole_staticlib_by_path(&mut self, path: &Path) { let mut arg = OsString::from("/WHOLEARCHIVE:"); arg.push(path); self.cmd.arg(arg); @@ -1043,8 +1058,8 @@ impl<'a> Linker for EmLinker<'a> { self.cmd.arg("-L").arg(path); } - fn link_staticlib(&mut self, lib: &str, _verbatim: bool) { - self.cmd.arg("-l").arg(lib); + fn link_staticlib_by_name(&mut self, name: &str, _verbatim: bool) { + self.cmd.arg("-l").arg(name); } fn output_filename(&mut self, path: &Path) { @@ -1057,21 +1072,26 @@ impl<'a> Linker for EmLinker<'a> { fn link_dylib_by_name(&mut self, name: &str, verbatim: bool, _as_needed: bool) { // Emscripten always links statically - self.link_staticlib(name, verbatim); + self.link_staticlib_by_name(name, verbatim); } - fn link_whole_staticlib(&mut self, lib: &str, verbatim: bool, _search_path: &[PathBuf]) { + fn link_whole_staticlib_by_name( + &mut self, + name: &str, + verbatim: bool, + _search_paths: &[PathBuf], + ) { // not supported? - self.link_staticlib(lib, verbatim); + self.link_staticlib_by_name(name, verbatim); } - fn link_whole_rlib(&mut self, lib: &Path) { + fn link_whole_staticlib_by_path(&mut self, path: &Path) { // not supported? - self.link_rlib(lib); + self.link_staticlib_by_path(path); } - fn link_rlib(&mut self, lib: &Path) { - self.add_object(lib); + fn link_staticlib_by_path(&mut self, path: &Path) { + self.add_object(path); } fn full_relro(&mut self) { @@ -1227,12 +1247,12 @@ impl<'a> Linker for WasmLd<'a> { self.cmd.arg("-l").arg(name); } - fn link_staticlib(&mut self, lib: &str, _verbatim: bool) { - self.cmd.arg("-l").arg(lib); + fn link_staticlib_by_name(&mut self, name: &str, _verbatim: bool) { + self.cmd.arg("-l").arg(name); } - fn link_rlib(&mut self, lib: &Path) { - self.cmd.arg(lib); + fn link_staticlib_by_path(&mut self, path: &Path) { + self.cmd.arg(path); } fn include_path(&mut self, path: &Path) { @@ -1257,12 +1277,17 @@ impl<'a> Linker for WasmLd<'a> { fn no_relro(&mut self) {} - fn link_whole_staticlib(&mut self, lib: &str, _verbatim: bool, _search_path: &[PathBuf]) { - self.cmd.arg("--whole-archive").arg("-l").arg(lib).arg("--no-whole-archive"); + fn link_whole_staticlib_by_name( + &mut self, + name: &str, + _verbatim: bool, + _search_paths: &[PathBuf], + ) { + self.cmd.arg("--whole-archive").arg("-l").arg(name).arg("--no-whole-archive"); } - fn link_whole_rlib(&mut self, lib: &Path) { - self.cmd.arg("--whole-archive").arg(lib).arg("--no-whole-archive"); + fn link_whole_staticlib_by_path(&mut self, path: &Path) { + self.cmd.arg("--whole-archive").arg(path).arg("--no-whole-archive"); } fn gc_sections(&mut self, _keep_metadata: bool) { @@ -1367,13 +1392,13 @@ impl<'a> Linker for L4Bender<'a> { fn link_dylib_by_name(&mut self, _name: &str, _verbatim: bool, _as_needed: bool) { bug!("dylibs are not supported on L4Re"); } - fn link_staticlib(&mut self, lib: &str, _verbatim: bool) { + fn link_staticlib_by_name(&mut self, name: &str, _verbatim: bool) { self.hint_static(); - self.cmd.arg(format!("-PC{lib}")); + self.cmd.arg(format!("-PC{name}")); } - fn link_rlib(&mut self, lib: &Path) { + fn link_staticlib_by_path(&mut self, path: &Path) { self.hint_static(); - self.cmd.arg(lib); + self.cmd.arg(path); } fn include_path(&mut self, path: &Path) { self.cmd.arg("-L").arg(path); @@ -1408,15 +1433,20 @@ impl<'a> Linker for L4Bender<'a> { fn set_output_kind(&mut self, _output_kind: LinkOutputKind, _out_filename: &Path) {} - fn link_whole_staticlib(&mut self, lib: &str, _verbatim: bool, _search_path: &[PathBuf]) { + fn link_whole_staticlib_by_name( + &mut self, + name: &str, + _verbatim: bool, + _search_paths: &[PathBuf], + ) { self.hint_static(); - self.cmd.arg("--whole-archive").arg(format!("-l{lib}")); + self.cmd.arg("--whole-archive").arg(format!("-l{name}")); self.cmd.arg("--no-whole-archive"); } - fn link_whole_rlib(&mut self, lib: &Path) { + fn link_whole_staticlib_by_path(&mut self, path: &Path) { self.hint_static(); - self.cmd.arg("--whole-archive").arg(lib).arg("--no-whole-archive"); + self.cmd.arg("--whole-archive").arg(path).arg("--no-whole-archive"); } fn gc_sections(&mut self, keep_metadata: bool) { @@ -1534,14 +1564,14 @@ impl<'a> Linker for AixLinker<'a> { self.cmd.arg(format!("-l{name}")); } - fn link_staticlib(&mut self, lib: &str, _verbatim: bool) { + fn link_staticlib_by_name(&mut self, name: &str, _verbatim: bool) { self.hint_static(); - self.cmd.arg(format!("-l{lib}")); + self.cmd.arg(format!("-l{name}")); } - fn link_rlib(&mut self, lib: &Path) { + fn link_staticlib_by_path(&mut self, path: &Path) { self.hint_static(); - self.cmd.arg(lib); + self.cmd.arg(path); } fn include_path(&mut self, path: &Path) { @@ -1584,15 +1614,20 @@ impl<'a> Linker for AixLinker<'a> { } } - fn link_whole_staticlib(&mut self, lib: &str, verbatim: bool, search_path: &[PathBuf]) { + fn link_whole_staticlib_by_name( + &mut self, + name: &str, + verbatim: bool, + search_paths: &[PathBuf], + ) { self.hint_static(); - let lib = find_native_static_library(lib, verbatim, search_path, self.sess); + let lib = find_native_static_library(name, verbatim, search_paths, self.sess); self.cmd.arg(format!("-bkeepfile:{}", lib.to_str().unwrap())); } - fn link_whole_rlib(&mut self, lib: &Path) { + fn link_whole_staticlib_by_path(&mut self, path: &Path) { self.hint_static(); - self.cmd.arg(format!("-bkeepfile:{}", lib.to_str().unwrap())); + self.cmd.arg(format!("-bkeepfile:{}", path.to_str().unwrap())); } fn gc_sections(&mut self, _keep_metadata: bool) { @@ -1759,11 +1794,11 @@ impl<'a> Linker for PtxLinker<'a> { fn set_output_kind(&mut self, _output_kind: LinkOutputKind, _out_filename: &Path) {} - fn link_rlib(&mut self, path: &Path) { + fn link_staticlib_by_path(&mut self, path: &Path) { self.cmd.arg("--rlib").arg(path); } - fn link_whole_rlib(&mut self, path: &Path) { + fn link_whole_staticlib_by_path(&mut self, path: &Path) { self.cmd.arg("--rlib").arg(path); } @@ -1797,11 +1832,16 @@ impl<'a> Linker for PtxLinker<'a> { panic!("external dylibs not supported") } - fn link_staticlib(&mut self, _lib: &str, _verbatim: bool) { + fn link_staticlib_by_name(&mut self, _name: &str, _verbatim: bool) { panic!("staticlibs not supported") } - fn link_whole_staticlib(&mut self, _lib: &str, _verbatim: bool, _search_path: &[PathBuf]) { + fn link_whole_staticlib_by_name( + &mut self, + _name: &str, + _verbatim: bool, + _search_paths: &[PathBuf], + ) { panic!("staticlibs not supported") } @@ -1848,11 +1888,11 @@ impl<'a> Linker for BpfLinker<'a> { fn set_output_kind(&mut self, _output_kind: LinkOutputKind, _out_filename: &Path) {} - fn link_rlib(&mut self, path: &Path) { + fn link_staticlib_by_path(&mut self, path: &Path) { self.cmd.arg(path); } - fn link_whole_rlib(&mut self, path: &Path) { + fn link_whole_staticlib_by_path(&mut self, path: &Path) { self.cmd.arg(path); } @@ -1887,11 +1927,16 @@ impl<'a> Linker for BpfLinker<'a> { panic!("external dylibs not supported") } - fn link_staticlib(&mut self, _lib: &str, _verbatim: bool) { + fn link_staticlib_by_name(&mut self, _name: &str, _verbatim: bool) { panic!("staticlibs not supported") } - fn link_whole_staticlib(&mut self, _lib: &str, _verbatim: bool, _search_path: &[PathBuf]) { + fn link_whole_staticlib_by_name( + &mut self, + _name: &str, + _verbatim: bool, + _search_paths: &[PathBuf], + ) { panic!("staticlibs not supported") } From 14cd3fd6f909c2c75edd333f41a1e6c69558d4e6 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 18 Jan 2024 15:47:41 +0300 Subject: [PATCH 3/7] linker: Group library linking methods together and sort them consistently --- compiler/rustc_codegen_ssa/src/back/linker.rs | 351 +++++++++--------- 1 file changed, 180 insertions(+), 171 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index 4360c10edc30a..2bddd473702e8 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -171,13 +171,13 @@ pub trait Linker { bug!("framework linked with unsupported linker") } fn link_staticlib_by_name(&mut self, name: &str, verbatim: bool); - fn link_staticlib_by_path(&mut self, path: &Path); fn link_whole_staticlib_by_name( &mut self, name: &str, verbatim: bool, search_paths: &[PathBuf], ); + fn link_staticlib_by_path(&mut self, path: &Path); fn link_whole_staticlib_by_path(&mut self, path: &Path); fn include_path(&mut self, path: &Path); fn framework_path(&mut self, path: &Path); @@ -469,35 +469,6 @@ impl<'a> Linker for GccLinker<'a> { } } } - fn link_staticlib_by_name(&mut self, name: &str, verbatim: bool) { - self.hint_static(); - self.cmd.arg(format!("-l{}{name}", if verbatim && self.is_gnu { ":" } else { "" },)); - } - fn link_staticlib_by_path(&mut self, path: &Path) { - self.hint_static(); - self.cmd.arg(path); - } - fn include_path(&mut self, path: &Path) { - self.cmd.arg("-L").arg(path); - } - fn framework_path(&mut self, path: &Path) { - self.cmd.arg("-F").arg(path); - } - fn output_filename(&mut self, path: &Path) { - self.cmd.arg("-o").arg(path); - } - fn add_object(&mut self, path: &Path) { - self.cmd.arg(path); - } - fn full_relro(&mut self) { - self.linker_args(&["-z", "relro", "-z", "now"]); - } - fn partial_relro(&mut self) { - self.linker_args(&["-z", "relro"]); - } - fn no_relro(&mut self) { - self.linker_args(&["-z", "norelro"]); - } fn link_framework_by_name(&mut self, name: &str, _verbatim: bool, as_needed: bool) { self.hint_dynamic(); @@ -510,6 +481,11 @@ impl<'a> Linker for GccLinker<'a> { self.cmd.arg("-framework").arg(name); } + fn link_staticlib_by_name(&mut self, name: &str, verbatim: bool) { + self.hint_static(); + self.cmd.arg(format!("-l{}{name}", if verbatim && self.is_gnu { ":" } else { "" },)); + } + // Here we explicitly ask that the entire archive is included into the // result artifact. For more details see #15460, but the gist is that // the linker will strip away any unused objects in the archive if we @@ -537,6 +513,11 @@ impl<'a> Linker for GccLinker<'a> { } } + fn link_staticlib_by_path(&mut self, path: &Path) { + self.hint_static(); + self.cmd.arg(path); + } + fn link_whole_staticlib_by_path(&mut self, path: &Path) { self.hint_static(); if self.sess.target.is_like_osx { @@ -548,6 +529,28 @@ impl<'a> Linker for GccLinker<'a> { } } + fn include_path(&mut self, path: &Path) { + self.cmd.arg("-L").arg(path); + } + fn framework_path(&mut self, path: &Path) { + self.cmd.arg("-F").arg(path); + } + fn output_filename(&mut self, path: &Path) { + self.cmd.arg("-o").arg(path); + } + fn add_object(&mut self, path: &Path) { + self.cmd.arg(path); + } + fn full_relro(&mut self) { + self.linker_args(&["-z", "relro", "-z", "now"]); + } + fn partial_relro(&mut self) { + self.linker_args(&["-z", "relro"]); + } + fn no_relro(&mut self) { + self.linker_args(&["-z", "norelro"]); + } + fn gc_sections(&mut self, keep_metadata: bool) { // The dead_strip option to the linker specifies that functions and data // unreachable by the entry point will be removed. This is quite useful @@ -827,9 +830,33 @@ impl<'a> Linker for MsvcLinker<'a> { } } + fn link_dylib_by_name(&mut self, name: &str, verbatim: bool, _as_needed: bool) { + self.cmd.arg(format!("{}{}", name, if verbatim { "" } else { ".lib" })); + } + + fn link_staticlib_by_name(&mut self, name: &str, verbatim: bool) { + self.cmd.arg(format!("{}{}", name, if verbatim { "" } else { ".lib" })); + } + + fn link_whole_staticlib_by_name( + &mut self, + name: &str, + verbatim: bool, + _search_paths: &[PathBuf], + ) { + self.cmd.arg(format!("/WHOLEARCHIVE:{}{}", name, if verbatim { "" } else { ".lib" })); + } + fn link_staticlib_by_path(&mut self, path: &Path) { self.cmd.arg(path); } + + fn link_whole_staticlib_by_path(&mut self, path: &Path) { + let mut arg = OsString::from("/WHOLEARCHIVE:"); + arg.push(path); + self.cmd.arg(arg); + } + fn add_object(&mut self, path: &Path) { self.cmd.arg(path); } @@ -851,14 +878,6 @@ impl<'a> Linker for MsvcLinker<'a> { self.cmd.arg("/OPT:NOREF,NOICF"); } - fn link_dylib_by_name(&mut self, name: &str, verbatim: bool, _as_needed: bool) { - self.cmd.arg(format!("{}{}", name, if verbatim { "" } else { ".lib" })); - } - - fn link_staticlib_by_name(&mut self, name: &str, verbatim: bool) { - self.cmd.arg(format!("{}{}", name, if verbatim { "" } else { ".lib" })); - } - fn full_relro(&mut self) { // noop } @@ -895,19 +914,6 @@ impl<'a> Linker for MsvcLinker<'a> { bug!("frameworks are not supported on windows") } - fn link_whole_staticlib_by_name( - &mut self, - name: &str, - verbatim: bool, - _search_paths: &[PathBuf], - ) { - self.cmd.arg(format!("/WHOLEARCHIVE:{}{}", name, if verbatim { "" } else { ".lib" })); - } - fn link_whole_staticlib_by_path(&mut self, path: &Path) { - let mut arg = OsString::from("/WHOLEARCHIVE:"); - arg.push(path); - self.cmd.arg(arg); - } fn optimize(&mut self) { // Needs more investigation of `/OPT` arguments } @@ -1054,27 +1060,15 @@ impl<'a> Linker for EmLinker<'a> { fn set_output_kind(&mut self, _output_kind: LinkOutputKind, _out_filename: &Path) {} - fn include_path(&mut self, path: &Path) { - self.cmd.arg("-L").arg(path); + fn link_dylib_by_name(&mut self, name: &str, verbatim: bool, _as_needed: bool) { + // Emscripten always links statically + self.link_staticlib_by_name(name, verbatim); } fn link_staticlib_by_name(&mut self, name: &str, _verbatim: bool) { self.cmd.arg("-l").arg(name); } - fn output_filename(&mut self, path: &Path) { - self.cmd.arg("-o").arg(path); - } - - fn add_object(&mut self, path: &Path) { - self.cmd.arg(path); - } - - fn link_dylib_by_name(&mut self, name: &str, verbatim: bool, _as_needed: bool) { - // Emscripten always links statically - self.link_staticlib_by_name(name, verbatim); - } - fn link_whole_staticlib_by_name( &mut self, name: &str, @@ -1085,13 +1079,25 @@ impl<'a> Linker for EmLinker<'a> { self.link_staticlib_by_name(name, verbatim); } + fn link_staticlib_by_path(&mut self, path: &Path) { + self.add_object(path); + } + fn link_whole_staticlib_by_path(&mut self, path: &Path) { // not supported? self.link_staticlib_by_path(path); } - fn link_staticlib_by_path(&mut self, path: &Path) { - self.add_object(path); + fn include_path(&mut self, path: &Path) { + self.cmd.arg("-L").arg(path); + } + + fn output_filename(&mut self, path: &Path) { + self.cmd.arg("-o").arg(path); + } + + fn add_object(&mut self, path: &Path) { + self.cmd.arg(path); } fn full_relro(&mut self) { @@ -1251,10 +1257,23 @@ impl<'a> Linker for WasmLd<'a> { self.cmd.arg("-l").arg(name); } + fn link_whole_staticlib_by_name( + &mut self, + name: &str, + _verbatim: bool, + _search_paths: &[PathBuf], + ) { + self.cmd.arg("--whole-archive").arg("-l").arg(name).arg("--no-whole-archive"); + } + fn link_staticlib_by_path(&mut self, path: &Path) { self.cmd.arg(path); } + fn link_whole_staticlib_by_path(&mut self, path: &Path) { + self.cmd.arg("--whole-archive").arg(path).arg("--no-whole-archive"); + } + fn include_path(&mut self, path: &Path) { self.cmd.arg("-L").arg(path); } @@ -1277,19 +1296,6 @@ impl<'a> Linker for WasmLd<'a> { fn no_relro(&mut self) {} - fn link_whole_staticlib_by_name( - &mut self, - name: &str, - _verbatim: bool, - _search_paths: &[PathBuf], - ) { - self.cmd.arg("--whole-archive").arg("-l").arg(name).arg("--no-whole-archive"); - } - - fn link_whole_staticlib_by_path(&mut self, path: &Path) { - self.cmd.arg("--whole-archive").arg(path).arg("--no-whole-archive"); - } - fn gc_sections(&mut self, _keep_metadata: bool) { self.cmd.arg("--gc-sections"); } @@ -1389,17 +1395,42 @@ pub struct L4Bender<'a> { } impl<'a> Linker for L4Bender<'a> { + fn cmd(&mut self) -> &mut Command { + &mut self.cmd + } + + fn set_output_kind(&mut self, _output_kind: LinkOutputKind, _out_filename: &Path) {} + fn link_dylib_by_name(&mut self, _name: &str, _verbatim: bool, _as_needed: bool) { bug!("dylibs are not supported on L4Re"); } + fn link_staticlib_by_name(&mut self, name: &str, _verbatim: bool) { self.hint_static(); self.cmd.arg(format!("-PC{name}")); } + + fn link_whole_staticlib_by_name( + &mut self, + name: &str, + _verbatim: bool, + _search_paths: &[PathBuf], + ) { + self.hint_static(); + self.cmd.arg("--whole-archive").arg(format!("-l{name}")); + self.cmd.arg("--no-whole-archive"); + } + fn link_staticlib_by_path(&mut self, path: &Path) { self.hint_static(); self.cmd.arg(path); } + + fn link_whole_staticlib_by_path(&mut self, path: &Path) { + self.hint_static(); + self.cmd.arg("--whole-archive").arg(path).arg("--no-whole-archive"); + } + fn include_path(&mut self, path: &Path) { self.cmd.arg("-L").arg(path); } @@ -1427,28 +1458,6 @@ impl<'a> Linker for L4Bender<'a> { self.cmd.arg("-z").arg("norelro"); } - fn cmd(&mut self) -> &mut Command { - &mut self.cmd - } - - fn set_output_kind(&mut self, _output_kind: LinkOutputKind, _out_filename: &Path) {} - - fn link_whole_staticlib_by_name( - &mut self, - name: &str, - _verbatim: bool, - _search_paths: &[PathBuf], - ) { - self.hint_static(); - self.cmd.arg("--whole-archive").arg(format!("-l{name}")); - self.cmd.arg("--no-whole-archive"); - } - - fn link_whole_staticlib_by_path(&mut self, path: &Path) { - self.hint_static(); - self.cmd.arg("--whole-archive").arg(path).arg("--no-whole-archive"); - } - fn gc_sections(&mut self, keep_metadata: bool) { if !keep_metadata { self.cmd.arg("--gc-sections"); @@ -1559,6 +1568,24 @@ impl<'a> AixLinker<'a> { } impl<'a> Linker for AixLinker<'a> { + fn cmd(&mut self) -> &mut Command { + &mut self.cmd + } + + fn set_output_kind(&mut self, output_kind: LinkOutputKind, out_filename: &Path) { + match output_kind { + LinkOutputKind::DynamicDylib => { + self.hint_dynamic(); + self.build_dylib(out_filename); + } + LinkOutputKind::StaticDylib => { + self.hint_static(); + self.build_dylib(out_filename); + } + _ => {} + } + } + fn link_dylib_by_name(&mut self, name: &str, _verbatim: bool, _as_needed: bool) { self.hint_dynamic(); self.cmd.arg(format!("-l{name}")); @@ -1569,11 +1596,27 @@ impl<'a> Linker for AixLinker<'a> { self.cmd.arg(format!("-l{name}")); } + fn link_whole_staticlib_by_name( + &mut self, + name: &str, + verbatim: bool, + search_paths: &[PathBuf], + ) { + self.hint_static(); + let lib = find_native_static_library(name, verbatim, search_paths, self.sess); + self.cmd.arg(format!("-bkeepfile:{}", lib.to_str().unwrap())); + } + fn link_staticlib_by_path(&mut self, path: &Path) { self.hint_static(); self.cmd.arg(path); } + fn link_whole_staticlib_by_path(&mut self, path: &Path) { + self.hint_static(); + self.cmd.arg(format!("-bkeepfile:{}", path.to_str().unwrap())); + } + fn include_path(&mut self, path: &Path) { self.cmd.arg("-L").arg(path); } @@ -1596,40 +1639,6 @@ impl<'a> Linker for AixLinker<'a> { fn no_relro(&mut self) {} - fn cmd(&mut self) -> &mut Command { - &mut self.cmd - } - - fn set_output_kind(&mut self, output_kind: LinkOutputKind, out_filename: &Path) { - match output_kind { - LinkOutputKind::DynamicDylib => { - self.hint_dynamic(); - self.build_dylib(out_filename); - } - LinkOutputKind::StaticDylib => { - self.hint_static(); - self.build_dylib(out_filename); - } - _ => {} - } - } - - fn link_whole_staticlib_by_name( - &mut self, - name: &str, - verbatim: bool, - search_paths: &[PathBuf], - ) { - self.hint_static(); - let lib = find_native_static_library(name, verbatim, search_paths, self.sess); - self.cmd.arg(format!("-bkeepfile:{}", lib.to_str().unwrap())); - } - - fn link_whole_staticlib_by_path(&mut self, path: &Path) { - self.hint_static(); - self.cmd.arg(format!("-bkeepfile:{}", path.to_str().unwrap())); - } - fn gc_sections(&mut self, _keep_metadata: bool) { self.cmd.arg("-bgc"); } @@ -1794,6 +1803,23 @@ impl<'a> Linker for PtxLinker<'a> { fn set_output_kind(&mut self, _output_kind: LinkOutputKind, _out_filename: &Path) {} + fn link_dylib_by_name(&mut self, _name: &str, _verbatim: bool, _as_needed: bool) { + panic!("external dylibs not supported") + } + + fn link_staticlib_by_name(&mut self, _name: &str, _verbatim: bool) { + panic!("staticlibs not supported") + } + + fn link_whole_staticlib_by_name( + &mut self, + _name: &str, + _verbatim: bool, + _search_paths: &[PathBuf], + ) { + panic!("staticlibs not supported") + } + fn link_staticlib_by_path(&mut self, path: &Path) { self.cmd.arg("--rlib").arg(path); } @@ -1828,23 +1854,6 @@ impl<'a> Linker for PtxLinker<'a> { self.cmd.arg("-o").arg(path); } - fn link_dylib_by_name(&mut self, _name: &str, _verbatim: bool, _as_needed: bool) { - panic!("external dylibs not supported") - } - - fn link_staticlib_by_name(&mut self, _name: &str, _verbatim: bool) { - panic!("staticlibs not supported") - } - - fn link_whole_staticlib_by_name( - &mut self, - _name: &str, - _verbatim: bool, - _search_paths: &[PathBuf], - ) { - panic!("staticlibs not supported") - } - fn framework_path(&mut self, _path: &Path) { panic!("frameworks not supported") } @@ -1888,6 +1897,23 @@ impl<'a> Linker for BpfLinker<'a> { fn set_output_kind(&mut self, _output_kind: LinkOutputKind, _out_filename: &Path) {} + fn link_dylib_by_name(&mut self, _name: &str, _verbatim: bool, _as_needed: bool) { + panic!("external dylibs not supported") + } + + fn link_staticlib_by_name(&mut self, _name: &str, _verbatim: bool) { + panic!("staticlibs not supported") + } + + fn link_whole_staticlib_by_name( + &mut self, + _name: &str, + _verbatim: bool, + _search_paths: &[PathBuf], + ) { + panic!("staticlibs not supported") + } + fn link_staticlib_by_path(&mut self, path: &Path) { self.cmd.arg(path); } @@ -1923,23 +1949,6 @@ impl<'a> Linker for BpfLinker<'a> { self.cmd.arg("-o").arg(path); } - fn link_dylib_by_name(&mut self, _name: &str, _verbatim: bool, _as_needed: bool) { - panic!("external dylibs not supported") - } - - fn link_staticlib_by_name(&mut self, _name: &str, _verbatim: bool) { - panic!("staticlibs not supported") - } - - fn link_whole_staticlib_by_name( - &mut self, - _name: &str, - _verbatim: bool, - _search_paths: &[PathBuf], - ) { - panic!("staticlibs not supported") - } - fn framework_path(&mut self, _path: &Path) { panic!("frameworks not supported") } From 859f37ae869bcfe059b1f6ecdf10174d9d87d5b5 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 18 Jan 2024 16:13:13 +0300 Subject: [PATCH 4/7] linker: Do not collect search paths unless necessary --- compiler/rustc_codegen_ssa/src/back/link.rs | 25 +++++++++++-------- compiler/rustc_codegen_ssa/src/back/linker.rs | 25 +++++++++++-------- 2 files changed, 29 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 18fa8a41c4622..5507f04fea1f7 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -52,6 +52,15 @@ use std::path::{Path, PathBuf}; use std::process::{ExitStatus, Output, Stdio}; use std::{env, fmt, fs, io, mem, str}; +#[derive(Default)] +pub struct SearchPaths(OnceCell>); + +impl SearchPaths { + pub(super) fn get(&self, sess: &Session) -> &[PathBuf] { + self.0.get_or_init(|| archive_search_paths(sess)) + } +} + pub fn ensure_removed(dcx: &DiagCtxt, path: &Path) { if let Err(e) = fs::remove_file(path) { if e.kind() != io::ErrorKind::NotFound { @@ -2445,7 +2454,7 @@ fn add_native_libs_from_crate( archive_builder_builder: &dyn ArchiveBuilderBuilder, codegen_results: &CodegenResults, tmpdir: &Path, - search_paths: &OnceCell>, + search_paths: &SearchPaths, bundled_libs: &FxHashSet, cnum: CrateNum, link_static: bool, @@ -2513,11 +2522,7 @@ fn add_native_libs_from_crate( } } else { if whole_archive { - cmd.link_whole_staticlib_by_name( - name, - verbatim, - search_paths.get_or_init(|| archive_search_paths(sess)), - ); + cmd.link_whole_staticlib_by_name(name, verbatim, search_paths); } else { cmd.link_staticlib_by_name(name, verbatim) } @@ -2581,7 +2586,7 @@ fn add_local_native_libraries( } } - let search_paths = OnceCell::new(); + let search_paths = SearchPaths::default(); // All static and dynamic native library dependencies are linked to the local crate. let link_static = true; let link_dynamic = true; @@ -2623,7 +2628,7 @@ fn add_upstream_rust_crates<'a>( .find(|(ty, _)| *ty == crate_type) .expect("failed to find crate type in dependency format list"); - let search_paths = OnceCell::new(); + let search_paths = SearchPaths::default(); for &cnum in &codegen_results.crate_info.used_crates { // We may not pass all crates through to the linker. Some crates may appear statically in // an existing dylib, meaning we'll pick up all the symbols from the dylib. @@ -2698,7 +2703,7 @@ fn add_upstream_native_libraries( tmpdir: &Path, link_output_kind: LinkOutputKind, ) { - let search_path = OnceCell::new(); + let search_paths = SearchPaths::default(); for &cnum in &codegen_results.crate_info.used_crates { // Static libraries are not linked here, they are linked in `add_upstream_rust_crates`. // FIXME: Merge this function to `add_upstream_rust_crates` so that all native libraries @@ -2720,7 +2725,7 @@ fn add_upstream_native_libraries( archive_builder_builder, codegen_results, tmpdir, - &search_path, + &search_paths, &Default::default(), cnum, link_static, diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index 2bddd473702e8..4b38be6f1889a 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -1,5 +1,6 @@ use super::command::Command; use super::symbol_export; +use crate::back::link::SearchPaths; use crate::errors; use rustc_span::symbol::sym; @@ -175,7 +176,7 @@ pub trait Linker { &mut self, name: &str, verbatim: bool, - search_paths: &[PathBuf], + search_paths: &SearchPaths, ); fn link_staticlib_by_path(&mut self, path: &Path); fn link_whole_staticlib_by_path(&mut self, path: &Path); @@ -496,7 +497,7 @@ impl<'a> Linker for GccLinker<'a> { &mut self, name: &str, verbatim: bool, - search_paths: &[PathBuf], + search_paths: &SearchPaths, ) { self.hint_static(); let target = &self.sess.target; @@ -508,7 +509,8 @@ impl<'a> Linker for GccLinker<'a> { // -force_load is the macOS equivalent of --whole-archive, but it // involves passing the full path to the library to link. self.linker_arg("-force_load"); - let lib = find_native_static_library(name, verbatim, search_paths, self.sess); + let lib = + find_native_static_library(name, verbatim, search_paths.get(self.sess), self.sess); self.linker_arg(&lib); } } @@ -842,7 +844,7 @@ impl<'a> Linker for MsvcLinker<'a> { &mut self, name: &str, verbatim: bool, - _search_paths: &[PathBuf], + _search_paths: &SearchPaths, ) { self.cmd.arg(format!("/WHOLEARCHIVE:{}{}", name, if verbatim { "" } else { ".lib" })); } @@ -1073,7 +1075,7 @@ impl<'a> Linker for EmLinker<'a> { &mut self, name: &str, verbatim: bool, - _search_paths: &[PathBuf], + _search_paths: &SearchPaths, ) { // not supported? self.link_staticlib_by_name(name, verbatim); @@ -1261,7 +1263,7 @@ impl<'a> Linker for WasmLd<'a> { &mut self, name: &str, _verbatim: bool, - _search_paths: &[PathBuf], + _search_paths: &SearchPaths, ) { self.cmd.arg("--whole-archive").arg("-l").arg(name).arg("--no-whole-archive"); } @@ -1414,7 +1416,7 @@ impl<'a> Linker for L4Bender<'a> { &mut self, name: &str, _verbatim: bool, - _search_paths: &[PathBuf], + _search_paths: &SearchPaths, ) { self.hint_static(); self.cmd.arg("--whole-archive").arg(format!("-l{name}")); @@ -1600,10 +1602,11 @@ impl<'a> Linker for AixLinker<'a> { &mut self, name: &str, verbatim: bool, - search_paths: &[PathBuf], + search_paths: &SearchPaths, ) { self.hint_static(); - let lib = find_native_static_library(name, verbatim, search_paths, self.sess); + let lib = + find_native_static_library(name, verbatim, search_paths.get(self.sess), self.sess); self.cmd.arg(format!("-bkeepfile:{}", lib.to_str().unwrap())); } @@ -1815,7 +1818,7 @@ impl<'a> Linker for PtxLinker<'a> { &mut self, _name: &str, _verbatim: bool, - _search_paths: &[PathBuf], + _search_paths: &SearchPaths, ) { panic!("staticlibs not supported") } @@ -1909,7 +1912,7 @@ impl<'a> Linker for BpfLinker<'a> { &mut self, _name: &str, _verbatim: bool, - _search_paths: &[PathBuf], + _search_paths: &SearchPaths, ) { panic!("staticlibs not supported") } From d15db6b26071b4d9550c2237283ba602bb4c1a53 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 18 Jan 2024 17:41:18 +0300 Subject: [PATCH 5/7] linker: Merge `link_staticlib_*` and `link_whole_staticlib_*` --- compiler/rustc_codegen_ssa/src/back/link.rs | 18 +- compiler/rustc_codegen_ssa/src/back/linker.rs | 198 +++++++----------- 2 files changed, 86 insertions(+), 130 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 5507f04fea1f7..e3b4189b3f5a3 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -1282,7 +1282,7 @@ fn link_sanitizer_runtime( } else { let filename = format!("librustc{channel}_rt.{name}.a"); let path = find_sanitizer_runtime(sess, &filename).join(&filename); - linker.link_whole_staticlib_by_path(&path); + linker.link_staticlib_by_path(&path, true); } } @@ -2514,18 +2514,10 @@ fn add_native_libs_from_crate( if let Some(filename) = lib.filename { // If rlib contains native libs as archives, they are unpacked to tmpdir. let path = tmpdir.join(filename.as_str()); - if whole_archive { - cmd.link_whole_staticlib_by_path(&path); - } else { - cmd.link_staticlib_by_path(&path); - } + cmd.link_staticlib_by_path(&path, whole_archive); } } else { - if whole_archive { - cmd.link_whole_staticlib_by_name(name, verbatim, search_paths); - } else { - cmd.link_staticlib_by_name(name, verbatim) - } + cmd.link_staticlib_by_name(name, verbatim, whole_archive, search_paths); } } } @@ -2539,7 +2531,7 @@ fn add_native_libs_from_crate( // link kind is unspecified. if !link_output_kind.can_link_dylib() && !sess.target.crt_static_allows_dylibs { if link_static { - cmd.link_staticlib_by_name(name, verbatim) + cmd.link_staticlib_by_name(name, verbatim, false, search_paths); } } else { if link_dynamic { @@ -2796,7 +2788,7 @@ fn add_static_crate<'a>( } else { fix_windows_verbatim_for_gcc(path) }; - cmd.link_staticlib_by_path(&rlib_path); + cmd.link_staticlib_by_path(&rlib_path, false); }; if !are_upstream_rust_objects_already_included(sess) diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index 4b38be6f1889a..092b66e386867 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -171,15 +171,14 @@ pub trait Linker { fn link_framework_by_name(&mut self, _name: &str, _verbatim: bool, _as_needed: bool) { bug!("framework linked with unsupported linker") } - fn link_staticlib_by_name(&mut self, name: &str, verbatim: bool); - fn link_whole_staticlib_by_name( + fn link_staticlib_by_name( &mut self, name: &str, verbatim: bool, + whole_archive: bool, search_paths: &SearchPaths, ); - fn link_staticlib_by_path(&mut self, path: &Path); - fn link_whole_staticlib_by_path(&mut self, path: &Path); + fn link_staticlib_by_path(&mut self, path: &Path, whole_archive: bool); fn include_path(&mut self, path: &Path); fn framework_path(&mut self, path: &Path); fn output_filename(&mut self, path: &Path); @@ -482,26 +481,17 @@ impl<'a> Linker for GccLinker<'a> { self.cmd.arg("-framework").arg(name); } - fn link_staticlib_by_name(&mut self, name: &str, verbatim: bool) { - self.hint_static(); - self.cmd.arg(format!("-l{}{name}", if verbatim && self.is_gnu { ":" } else { "" },)); - } - - // Here we explicitly ask that the entire archive is included into the - // result artifact. For more details see #15460, but the gist is that - // the linker will strip away any unused objects in the archive if we - // don't otherwise explicitly reference them. This can occur for - // libraries which are just providing bindings, libraries with generic - // functions, etc. - fn link_whole_staticlib_by_name( + fn link_staticlib_by_name( &mut self, name: &str, verbatim: bool, + whole_archive: bool, search_paths: &SearchPaths, ) { self.hint_static(); - let target = &self.sess.target; - if !target.is_like_osx { + if !whole_archive { + self.cmd.arg(format!("-l{}{name}", if verbatim && self.is_gnu { ":" } else { "" })); + } else if !self.sess.target.is_like_osx { self.linker_arg("--whole-archive"); self.cmd.arg(format!("-l{}{name}", if verbatim && self.is_gnu { ":" } else { "" })); self.linker_arg("--no-whole-archive"); @@ -515,14 +505,11 @@ impl<'a> Linker for GccLinker<'a> { } } - fn link_staticlib_by_path(&mut self, path: &Path) { + fn link_staticlib_by_path(&mut self, path: &Path, whole_archive: bool) { self.hint_static(); - self.cmd.arg(path); - } - - fn link_whole_staticlib_by_path(&mut self, path: &Path) { - self.hint_static(); - if self.sess.target.is_like_osx { + if !whole_archive { + self.cmd.arg(path); + } else if self.sess.target.is_like_osx { self.linker_arg("-force_load"); self.linker_arg(&path); } else { @@ -836,27 +823,28 @@ impl<'a> Linker for MsvcLinker<'a> { self.cmd.arg(format!("{}{}", name, if verbatim { "" } else { ".lib" })); } - fn link_staticlib_by_name(&mut self, name: &str, verbatim: bool) { - self.cmd.arg(format!("{}{}", name, if verbatim { "" } else { ".lib" })); - } - - fn link_whole_staticlib_by_name( + fn link_staticlib_by_name( &mut self, name: &str, verbatim: bool, + whole_archive: bool, _search_paths: &SearchPaths, ) { - self.cmd.arg(format!("/WHOLEARCHIVE:{}{}", name, if verbatim { "" } else { ".lib" })); - } - - fn link_staticlib_by_path(&mut self, path: &Path) { - self.cmd.arg(path); + if !whole_archive { + self.cmd.arg(format!("{}{}", name, if verbatim { "" } else { ".lib" })); + } else { + self.cmd.arg(format!("/WHOLEARCHIVE:{}{}", name, if verbatim { "" } else { ".lib" })); + } } - fn link_whole_staticlib_by_path(&mut self, path: &Path) { - let mut arg = OsString::from("/WHOLEARCHIVE:"); - arg.push(path); - self.cmd.arg(arg); + fn link_staticlib_by_path(&mut self, path: &Path, whole_archive: bool) { + if !whole_archive { + self.cmd.arg(path); + } else { + let mut arg = OsString::from("/WHOLEARCHIVE:"); + arg.push(path); + self.cmd.arg(arg); + } } fn add_object(&mut self, path: &Path) { @@ -1062,34 +1050,25 @@ impl<'a> Linker for EmLinker<'a> { fn set_output_kind(&mut self, _output_kind: LinkOutputKind, _out_filename: &Path) {} - fn link_dylib_by_name(&mut self, name: &str, verbatim: bool, _as_needed: bool) { + fn link_dylib_by_name(&mut self, name: &str, _verbatim: bool, _as_needed: bool) { // Emscripten always links statically - self.link_staticlib_by_name(name, verbatim); - } - - fn link_staticlib_by_name(&mut self, name: &str, _verbatim: bool) { self.cmd.arg("-l").arg(name); } - fn link_whole_staticlib_by_name( + fn link_staticlib_by_name( &mut self, name: &str, - verbatim: bool, + _verbatim: bool, + _whole_archive: bool, _search_paths: &SearchPaths, ) { - // not supported? - self.link_staticlib_by_name(name, verbatim); + self.cmd.arg("-l").arg(name); } - fn link_staticlib_by_path(&mut self, path: &Path) { + fn link_staticlib_by_path(&mut self, path: &Path, _whole_archive: bool) { self.add_object(path); } - fn link_whole_staticlib_by_path(&mut self, path: &Path) { - // not supported? - self.link_staticlib_by_path(path); - } - fn include_path(&mut self, path: &Path) { self.cmd.arg("-L").arg(path); } @@ -1255,25 +1234,26 @@ impl<'a> Linker for WasmLd<'a> { self.cmd.arg("-l").arg(name); } - fn link_staticlib_by_name(&mut self, name: &str, _verbatim: bool) { - self.cmd.arg("-l").arg(name); - } - - fn link_whole_staticlib_by_name( + fn link_staticlib_by_name( &mut self, name: &str, _verbatim: bool, + whole_archive: bool, _search_paths: &SearchPaths, ) { - self.cmd.arg("--whole-archive").arg("-l").arg(name).arg("--no-whole-archive"); - } - - fn link_staticlib_by_path(&mut self, path: &Path) { - self.cmd.arg(path); + if !whole_archive { + self.cmd.arg("-l").arg(name); + } else { + self.cmd.arg("--whole-archive").arg("-l").arg(name).arg("--no-whole-archive"); + } } - fn link_whole_staticlib_by_path(&mut self, path: &Path) { - self.cmd.arg("--whole-archive").arg(path).arg("--no-whole-archive"); + fn link_staticlib_by_path(&mut self, path: &Path, whole_archive: bool) { + if !whole_archive { + self.cmd.arg(path); + } else { + self.cmd.arg("--whole-archive").arg(path).arg("--no-whole-archive"); + } } fn include_path(&mut self, path: &Path) { @@ -1407,30 +1387,29 @@ impl<'a> Linker for L4Bender<'a> { bug!("dylibs are not supported on L4Re"); } - fn link_staticlib_by_name(&mut self, name: &str, _verbatim: bool) { - self.hint_static(); - self.cmd.arg(format!("-PC{name}")); - } - - fn link_whole_staticlib_by_name( + fn link_staticlib_by_name( &mut self, name: &str, _verbatim: bool, + whole_archive: bool, _search_paths: &SearchPaths, ) { self.hint_static(); - self.cmd.arg("--whole-archive").arg(format!("-l{name}")); - self.cmd.arg("--no-whole-archive"); - } - - fn link_staticlib_by_path(&mut self, path: &Path) { - self.hint_static(); - self.cmd.arg(path); + if !whole_archive { + self.cmd.arg(format!("-PC{name}")); + } else { + self.cmd.arg("--whole-archive").arg(format!("-l{name}")); + self.cmd.arg("--no-whole-archive"); + } } - fn link_whole_staticlib_by_path(&mut self, path: &Path) { + fn link_staticlib_by_path(&mut self, path: &Path, whole_archive: bool) { self.hint_static(); - self.cmd.arg("--whole-archive").arg(path).arg("--no-whole-archive"); + if !whole_archive { + self.cmd.arg(path); + } else { + self.cmd.arg("--whole-archive").arg(path).arg("--no-whole-archive"); + } } fn include_path(&mut self, path: &Path) { @@ -1593,31 +1572,30 @@ impl<'a> Linker for AixLinker<'a> { self.cmd.arg(format!("-l{name}")); } - fn link_staticlib_by_name(&mut self, name: &str, _verbatim: bool) { - self.hint_static(); - self.cmd.arg(format!("-l{name}")); - } - - fn link_whole_staticlib_by_name( + fn link_staticlib_by_name( &mut self, name: &str, verbatim: bool, + whole_archive: bool, search_paths: &SearchPaths, ) { self.hint_static(); - let lib = - find_native_static_library(name, verbatim, search_paths.get(self.sess), self.sess); - self.cmd.arg(format!("-bkeepfile:{}", lib.to_str().unwrap())); - } - - fn link_staticlib_by_path(&mut self, path: &Path) { - self.hint_static(); - self.cmd.arg(path); + if !whole_archive { + self.cmd.arg(format!("-l{name}")); + } else { + let lib = + find_native_static_library(name, verbatim, search_paths.get(self.sess), self.sess); + self.cmd.arg(format!("-bkeepfile:{}", lib.to_str().unwrap())); + } } - fn link_whole_staticlib_by_path(&mut self, path: &Path) { + fn link_staticlib_by_path(&mut self, path: &Path, whole_archive: bool) { self.hint_static(); - self.cmd.arg(format!("-bkeepfile:{}", path.to_str().unwrap())); + if !whole_archive { + self.cmd.arg(path); + } else { + self.cmd.arg(format!("-bkeepfile:{}", path.to_str().unwrap())); + } } fn include_path(&mut self, path: &Path) { @@ -1810,24 +1788,17 @@ impl<'a> Linker for PtxLinker<'a> { panic!("external dylibs not supported") } - fn link_staticlib_by_name(&mut self, _name: &str, _verbatim: bool) { - panic!("staticlibs not supported") - } - - fn link_whole_staticlib_by_name( + fn link_staticlib_by_name( &mut self, _name: &str, _verbatim: bool, + _whole_archive: bool, _search_paths: &SearchPaths, ) { panic!("staticlibs not supported") } - fn link_staticlib_by_path(&mut self, path: &Path) { - self.cmd.arg("--rlib").arg(path); - } - - fn link_whole_staticlib_by_path(&mut self, path: &Path) { + fn link_staticlib_by_path(&mut self, path: &Path, _whole_archive: bool) { self.cmd.arg("--rlib").arg(path); } @@ -1904,24 +1875,17 @@ impl<'a> Linker for BpfLinker<'a> { panic!("external dylibs not supported") } - fn link_staticlib_by_name(&mut self, _name: &str, _verbatim: bool) { - panic!("staticlibs not supported") - } - - fn link_whole_staticlib_by_name( + fn link_staticlib_by_name( &mut self, _name: &str, _verbatim: bool, + _whole_archive: bool, _search_paths: &SearchPaths, ) { panic!("staticlibs not supported") } - fn link_staticlib_by_path(&mut self, path: &Path) { - self.cmd.arg(path); - } - - fn link_whole_staticlib_by_path(&mut self, path: &Path) { + fn link_staticlib_by_path(&mut self, path: &Path, _whole_archive: bool) { self.cmd.arg(path); } From 1b8e871f1c3b2aca174ac1a4d46613355a956fcc Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 18 Jan 2024 18:09:59 +0300 Subject: [PATCH 6/7] linker: Cleanup implementations of `link_staticlib_*` --- compiler/rustc_codegen_ssa/src/back/linker.rs | 47 ++++++++++--------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index 092b66e386867..9f06f398288f2 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -489,19 +489,19 @@ impl<'a> Linker for GccLinker<'a> { search_paths: &SearchPaths, ) { self.hint_static(); + let colon = if verbatim && self.is_gnu { ":" } else { "" }; if !whole_archive { - self.cmd.arg(format!("-l{}{name}", if verbatim && self.is_gnu { ":" } else { "" })); - } else if !self.sess.target.is_like_osx { - self.linker_arg("--whole-archive"); - self.cmd.arg(format!("-l{}{name}", if verbatim && self.is_gnu { ":" } else { "" })); - self.linker_arg("--no-whole-archive"); - } else { + self.cmd.arg(format!("-l{colon}{name}")); + } else if self.sess.target.is_like_osx { // -force_load is the macOS equivalent of --whole-archive, but it // involves passing the full path to the library to link. self.linker_arg("-force_load"); - let lib = - find_native_static_library(name, verbatim, search_paths.get(self.sess), self.sess); - self.linker_arg(&lib); + let search_paths = search_paths.get(self.sess); + self.linker_arg(find_native_static_library(name, verbatim, search_paths, self.sess)); + } else { + self.linker_arg("--whole-archive"); + self.cmd.arg(format!("-l{colon}{name}")); + self.linker_arg("--no-whole-archive"); } } @@ -511,9 +511,10 @@ impl<'a> Linker for GccLinker<'a> { self.cmd.arg(path); } else if self.sess.target.is_like_osx { self.linker_arg("-force_load"); - self.linker_arg(&path); + self.linker_arg(path); } else { - self.linker_args(&[OsString::from("--whole-archive"), path.into()]); + self.linker_arg("--whole-archive"); + self.linker_arg(path); self.linker_arg("--no-whole-archive"); } } @@ -830,11 +831,9 @@ impl<'a> Linker for MsvcLinker<'a> { whole_archive: bool, _search_paths: &SearchPaths, ) { - if !whole_archive { - self.cmd.arg(format!("{}{}", name, if verbatim { "" } else { ".lib" })); - } else { - self.cmd.arg(format!("/WHOLEARCHIVE:{}{}", name, if verbatim { "" } else { ".lib" })); - } + let prefix = if whole_archive { "/WHOLEARCHIVE:" } else { "" }; + let suffix = if verbatim { "" } else { ".lib" }; + self.cmd.arg(format!("{prefix}{name}{suffix}")); } fn link_staticlib_by_path(&mut self, path: &Path, whole_archive: bool) { @@ -1066,7 +1065,7 @@ impl<'a> Linker for EmLinker<'a> { } fn link_staticlib_by_path(&mut self, path: &Path, _whole_archive: bool) { - self.add_object(path); + self.cmd.arg(path); } fn include_path(&mut self, path: &Path) { @@ -1398,8 +1397,7 @@ impl<'a> Linker for L4Bender<'a> { if !whole_archive { self.cmd.arg(format!("-PC{name}")); } else { - self.cmd.arg("--whole-archive").arg(format!("-l{name}")); - self.cmd.arg("--no-whole-archive"); + self.cmd.arg("--whole-archive").arg(format!("-l{name}")).arg("--no-whole-archive"); } } @@ -1583,9 +1581,10 @@ impl<'a> Linker for AixLinker<'a> { if !whole_archive { self.cmd.arg(format!("-l{name}")); } else { - let lib = - find_native_static_library(name, verbatim, search_paths.get(self.sess), self.sess); - self.cmd.arg(format!("-bkeepfile:{}", lib.to_str().unwrap())); + let mut arg = OsString::from("-bkeepfile:"); + let search_path = search_paths.get(self.sess); + arg.push(find_native_static_library(name, verbatim, search_path, self.sess)); + self.cmd.arg(arg); } } @@ -1594,7 +1593,9 @@ impl<'a> Linker for AixLinker<'a> { if !whole_archive { self.cmd.arg(path); } else { - self.cmd.arg(format!("-bkeepfile:{}", path.to_str().unwrap())); + let mut arg = OsString::from("-bkeepfile:"); + arg.push(path); + self.cmd.arg(arg); } } From 03f23c1a2fd36b33820750ddf41246ad322baef7 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Wed, 24 Jan 2024 01:50:04 +0300 Subject: [PATCH 7/7] linker: Fix Rust dylib crate extension on windows-msvc --- compiler/rustc_codegen_ssa/src/back/link.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index e3b4189b3f5a3..f098fc9cb5970 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -2866,7 +2866,11 @@ fn add_dynamic_crate(cmd: &mut dyn Linker, sess: &Session, cratepath: &Path) { if let Some(dir) = parent { cmd.include_path(&rehome_sysroot_lib_dir(sess, dir)); } - let stem = cratepath.file_stem().unwrap().to_str().unwrap(); + // "/name.dll -> name.dll" on windows-msvc + // "/name.dll -> name" on windows-gnu + // "/libname. -> name" elsewhere + let stem = if sess.target.is_like_msvc { cratepath.file_name() } else { cratepath.file_stem() }; + let stem = stem.unwrap().to_str().unwrap(); // Convert library file-stem into a cc -l argument. let prefix = if stem.starts_with("lib") && !sess.target.is_like_windows { 3 } else { 0 }; cmd.link_dylib_by_name(&stem[prefix..], false, true);