Skip to content

Commit b221d03

Browse files
authored
Unrolled build for rust-lang#123436
Rollup merge of rust-lang#123436 - amyspark:allow-msvc-to-use-meson-and-mingw-import-libraries, r=petrochenkov linker: Allow MSVC to use import libraries following the Meson/MinGW convention Hi all, This PR implements support for `MsvcLinker` to use import libraries following Meson and the MinGW toolchain's naming convention. Meson [follows the `libfoo.dll.a` naming convention](https://mesonbuild.com/FAQ.html#why-does-building-my-project-with-msvc-output-static-libraries-called-libfooa) to disambiguate between static and import libraries. This support already existed for static libraries (see rust-lang#100101), but not for dynamic libraries. The latter case was added by duplicating the logic in `native_libs::find_native_static_library`, but a separate case was added in `link_dylib_by_name` for the Windows CRT libraries which must be handled by the linker itself. See for prerequisites rust-lang#129366, rust-lang#126094, and rust-lang#128370. All feedback is appreciated! Fixes rust-lang#122455 cc `@sdroege` `@nirbheek`
2 parents 3a22be3 + 98481be commit b221d03

File tree

3 files changed

+50
-3
lines changed

3 files changed

+50
-3
lines changed

compiler/rustc_codegen_ssa/src/back/linker.rs

+10-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ use std::{env, iter, mem, str};
77

88
use cc::windows_registry;
99
use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
10-
use rustc_metadata::{find_native_static_library, try_find_native_static_library};
10+
use rustc_metadata::{
11+
find_native_static_library, try_find_native_dynamic_library, try_find_native_static_library,
12+
};
1113
use rustc_middle::bug;
1214
use rustc_middle::middle::dependency_format::Linkage;
1315
use rustc_middle::middle::exported_symbols;
@@ -876,7 +878,13 @@ impl<'a> Linker for MsvcLinker<'a> {
876878
}
877879

878880
fn link_dylib_by_name(&mut self, name: &str, verbatim: bool, _as_needed: bool) {
879-
self.link_arg(format!("{}{}", name, if verbatim { "" } else { ".lib" }));
881+
// On MSVC-like targets rustc supports import libraries using alternative naming
882+
// scheme (`libfoo.a`) unsupported by linker, search for such libraries manually.
883+
if let Some(path) = try_find_native_dynamic_library(self.sess, name, verbatim) {
884+
self.link_arg(path);
885+
} else {
886+
self.link_arg(format!("{}{}", name, if verbatim { "" } else { ".lib" }));
887+
}
880888
}
881889

882890
fn link_dylib_by_path(&mut self, path: &Path, _as_needed: bool) {

compiler/rustc_metadata/src/lib.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ pub mod locator;
3737
pub use creader::{load_symbol_from_dylib, DylibError};
3838
pub use fs::{emit_wrapper_file, METADATA_FILENAME};
3939
pub use native_libs::{
40-
find_native_static_library, try_find_native_static_library, walk_native_lib_search_dirs,
40+
find_native_static_library, try_find_native_dynamic_library, try_find_native_static_library,
41+
walk_native_lib_search_dirs,
4142
};
4243
pub use rmeta::{encode_metadata, rendered_const, EncodedMetadata, METADATA_HEADER};
4344

compiler/rustc_metadata/src/native_libs.rs

+38
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,44 @@ pub fn try_find_native_static_library(
109109
.break_value()
110110
}
111111

112+
pub fn try_find_native_dynamic_library(
113+
sess: &Session,
114+
name: &str,
115+
verbatim: bool,
116+
) -> Option<PathBuf> {
117+
let formats = if verbatim {
118+
vec![("".into(), "".into())]
119+
} else {
120+
// While the official naming convention for MSVC import libraries
121+
// is foo.lib...
122+
let os = (sess.target.staticlib_prefix.clone(), sess.target.staticlib_suffix.clone());
123+
// ... Meson follows the libfoo.dll.a convention to
124+
// disambiguate .a for static libraries
125+
let meson = ("lib".into(), ".dll.a".into());
126+
// and MinGW uses .a altogether
127+
let mingw = ("lib".into(), ".a".into());
128+
vec![os, meson, mingw]
129+
};
130+
131+
walk_native_lib_search_dirs(
132+
sess,
133+
LinkSelfContainedComponents::empty(),
134+
None,
135+
|dir, is_framework| {
136+
if !is_framework {
137+
for (prefix, suffix) in &formats {
138+
let test = dir.join(format!("{prefix}{name}{suffix}"));
139+
if test.exists() {
140+
return ControlFlow::Break(test);
141+
}
142+
}
143+
}
144+
ControlFlow::Continue(())
145+
},
146+
)
147+
.break_value()
148+
}
149+
112150
pub fn find_native_static_library(name: &str, verbatim: bool, sess: &Session) -> PathBuf {
113151
try_find_native_static_library(sess, name, verbatim)
114152
.unwrap_or_else(|| sess.dcx().emit_fatal(errors::MissingNativeLibrary::new(name, verbatim)))

0 commit comments

Comments
 (0)