From 43653c1835d59de69c6a5977b52df4708e6fddca Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 23 Mar 2025 22:13:52 +0300 Subject: [PATCH 1/3] linker: Fix staticlib naming for UEFI It uses `libname.a` instead of the standard MSVC naming `name.lib`. Naming for import libraries isn't touched. --- compiler/rustc_codegen_ssa/src/back/link.rs | 7 ++++++- compiler/rustc_codegen_ssa/src/back/linker.rs | 10 +++++++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 74597f6263d4f..99b4591051af1 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -1494,7 +1494,12 @@ fn print_native_static_libs( | NativeLibKind::Unspecified => { let verbatim = lib.verbatim; if sess.target.is_like_msvc { - Some(format!("{}{}", name, if verbatim { "" } else { ".lib" })) + let (prefix, suffix) = if verbatim { + ("", "") + } else { + (&*sess.target.staticlib_prefix, &*sess.target.staticlib_suffix) + }; + Some(format!("{prefix}{name}{suffix}")) } else if sess.target.linker_flavor.is_gnu() { Some(format!("-l{}{}", if verbatim { ":" } else { "" }, name)) } else { diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index 3f5e0c1bce9c1..7f24d79b83b28 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -958,9 +958,13 @@ impl<'a> Linker for MsvcLinker<'a> { if let Some(path) = try_find_native_static_library(self.sess, name, verbatim) { self.link_staticlib_by_path(&path, whole_archive); } else { - let prefix = if whole_archive { "/WHOLEARCHIVE:" } else { "" }; - let suffix = if verbatim { "" } else { ".lib" }; - self.link_arg(format!("{prefix}{name}{suffix}")); + let opts = if whole_archive { "/WHOLEARCHIVE:" } else { "" }; + let (prefix, suffix) = if verbatim { + ("", "") + } else { + (&*self.sess.target.staticlib_prefix, &*self.sess.target.staticlib_suffix) + }; + self.link_arg(format!("{opts}{prefix}{name}{suffix}")); } } From 27e95f95e6dfcc1effa1f106c90fe53ab2236b76 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 23 Mar 2025 22:18:21 +0300 Subject: [PATCH 2/3] linker: Avoid calling `linker_and_flavor` twice --- compiler/rustc_codegen_ssa/src/back/link.rs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 99b4591051af1..360f6d82dbc32 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -670,7 +670,7 @@ fn link_natively( ) { info!("preparing {:?} to {:?}", crate_type, out_filename); let (linker_path, flavor) = linker_and_flavor(sess); - let self_contained_components = self_contained_components(sess, crate_type); + let self_contained_components = self_contained_components(sess, crate_type, &linker_path); // On AIX, we ship all libraries as .a big_af archive // the expected format is lib.a(libname.so) for the actual @@ -1788,8 +1788,7 @@ fn link_output_kind(sess: &Session, crate_type: CrateType) -> LinkOutputKind { } // Returns true if linker is located within sysroot -fn detect_self_contained_mingw(sess: &Session) -> bool { - let (linker, _) = linker_and_flavor(sess); +fn detect_self_contained_mingw(sess: &Session, linker: &Path) -> bool { // Assume `-C linker=rust-lld` as self-contained mode if linker == Path::new("rust-lld") { return true; @@ -1797,7 +1796,7 @@ fn detect_self_contained_mingw(sess: &Session) -> bool { let linker_with_extension = if cfg!(windows) && linker.extension().is_none() { linker.with_extension("exe") } else { - linker + linker.to_path_buf() }; for dir in env::split_paths(&env::var_os("PATH").unwrap_or_default()) { let full_path = dir.join(&linker_with_extension); @@ -1812,7 +1811,11 @@ fn detect_self_contained_mingw(sess: &Session) -> bool { /// Various toolchain components used during linking are used from rustc distribution /// instead of being found somewhere on the host system. /// We only provide such support for a very limited number of targets. -fn self_contained_components(sess: &Session, crate_type: CrateType) -> LinkSelfContainedComponents { +fn self_contained_components( + sess: &Session, + crate_type: CrateType, + linker: &Path, +) -> LinkSelfContainedComponents { // Turn the backwards compatible bool values for `self_contained` into fully inferred // `LinkSelfContainedComponents`. let self_contained = @@ -1841,7 +1844,7 @@ fn self_contained_components(sess: &Session, crate_type: CrateType) -> LinkSelfC LinkSelfContainedDefault::InferredForMingw => { sess.host == sess.target && sess.target.vendor != "uwp" - && detect_self_contained_mingw(sess) + && detect_self_contained_mingw(sess, linker) } } }; From 7c55782e0c1d01dfd7ceab3b4e682c12e24308d8 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Tue, 25 Mar 2025 00:00:10 +0300 Subject: [PATCH 3/3] rustc_session: Add a helper function for obtaining staticlib prefix and suffix --- compiler/rustc_codegen_ssa/src/back/link.rs | 6 +----- compiler/rustc_codegen_ssa/src/back/linker.rs | 11 ++++------ compiler/rustc_metadata/src/native_libs.rs | 21 +++++++++---------- compiler/rustc_session/src/output.rs | 2 +- compiler/rustc_session/src/session.rs | 8 +++++++ 5 files changed, 24 insertions(+), 24 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 360f6d82dbc32..a564e0e391fee 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -1494,11 +1494,7 @@ fn print_native_static_libs( | NativeLibKind::Unspecified => { let verbatim = lib.verbatim; if sess.target.is_like_msvc { - let (prefix, suffix) = if verbatim { - ("", "") - } else { - (&*sess.target.staticlib_prefix, &*sess.target.staticlib_suffix) - }; + let (prefix, suffix) = sess.staticlib_components(verbatim); Some(format!("{prefix}{name}{suffix}")) } else if sess.target.linker_flavor.is_gnu() { Some(format!("-l{}{}", if verbatim { ":" } else { "" }, name)) diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index 7f24d79b83b28..bcf18cf57be23 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -450,9 +450,10 @@ impl<'a> GccLinker<'a> { // The output filename already contains `dll_suffix` so // the resulting import library will have a name in the // form of libfoo.dll.a - let mut implib_name = OsString::from(&*self.sess.target.staticlib_prefix); + let (prefix, suffix) = self.sess.staticlib_components(false); + let mut implib_name = OsString::from(prefix); implib_name.push(name); - implib_name.push(&*self.sess.target.staticlib_suffix); + implib_name.push(suffix); let mut out_implib = OsString::from("--out-implib="); out_implib.push(out_filename.with_file_name(implib_name)); self.link_arg(out_implib); @@ -959,11 +960,7 @@ impl<'a> Linker for MsvcLinker<'a> { self.link_staticlib_by_path(&path, whole_archive); } else { let opts = if whole_archive { "/WHOLEARCHIVE:" } else { "" }; - let (prefix, suffix) = if verbatim { - ("", "") - } else { - (&*self.sess.target.staticlib_prefix, &*self.sess.target.staticlib_suffix) - }; + let (prefix, suffix) = self.sess.staticlib_components(verbatim); self.link_arg(format!("{opts}{prefix}{name}{suffix}")); } } diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index 1671b7e06b0af..f63ae8079dcd4 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -95,14 +95,14 @@ pub fn try_find_native_static_library( name: &str, verbatim: bool, ) -> Option { + let default = sess.staticlib_components(verbatim); let formats = if verbatim { - vec![("".into(), "".into())] + vec![default] } else { - let os = (sess.target.staticlib_prefix.clone(), sess.target.staticlib_suffix.clone()); // On Windows, static libraries sometimes show up as libfoo.a and other // times show up as foo.lib - let unix = ("lib".into(), ".a".into()); - if os == unix { vec![os] } else { vec![os, unix] } + let unix = ("lib", ".a"); + if default == unix { vec![default] } else { vec![default, unix] } }; walk_native_lib_search_dirs(sess, None, |dir, is_framework| { @@ -124,18 +124,17 @@ pub fn try_find_native_dynamic_library( name: &str, verbatim: bool, ) -> Option { + let default = sess.staticlib_components(verbatim); let formats = if verbatim { - vec![("".into(), "".into())] + vec![default] } else { // While the official naming convention for MSVC import libraries - // is foo.lib... - let os = (sess.target.staticlib_prefix.clone(), sess.target.staticlib_suffix.clone()); - // ... Meson follows the libfoo.dll.a convention to + // is foo.lib, Meson follows the libfoo.dll.a convention to // disambiguate .a for static libraries - let meson = ("lib".into(), ".dll.a".into()); + let meson = ("lib", ".dll.a"); // and MinGW uses .a altogether - let mingw = ("lib".into(), ".a".into()); - vec![os, meson, mingw] + let mingw = ("lib", ".a"); + vec![default, meson, mingw] }; walk_native_lib_search_dirs(sess, None, |dir, is_framework| { diff --git a/compiler/rustc_session/src/output.rs b/compiler/rustc_session/src/output.rs index b37a80274c0cb..a24919e434cc5 100644 --- a/compiler/rustc_session/src/output.rs +++ b/compiler/rustc_session/src/output.rs @@ -103,7 +103,7 @@ pub fn filename_for_input( OutFileName::Real(outputs.out_directory.join(&format!("{prefix}{libname}{suffix}"))) } CrateType::Staticlib => { - let (prefix, suffix) = (&sess.target.staticlib_prefix, &sess.target.staticlib_suffix); + let (prefix, suffix) = sess.staticlib_components(false); OutFileName::Real(outputs.out_directory.join(&format!("{prefix}{libname}{suffix}"))) } CrateType::Executable => { diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 1c9adea281dc7..a87b1961a9951 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -586,6 +586,14 @@ impl Session { .or(self.target.options.default_visibility) .unwrap_or(SymbolVisibility::Interposable) } + + pub fn staticlib_components(&self, verbatim: bool) -> (&str, &str) { + if verbatim { + ("", "") + } else { + (&*self.target.staticlib_prefix, &*self.target.staticlib_suffix) + } + } } // JUSTIFICATION: defn of the suggested wrapper fns