Skip to content

Commit 857ce5d

Browse files
committed
MsvcLinker: allow linking dynamically to Meson and MinGW-style named libraries
Fixes rust-lang#122455
1 parent a7399ba commit 857ce5d

File tree

3 files changed

+57
-3
lines changed

3 files changed

+57
-3
lines changed

compiler/rustc_codegen_ssa/src/back/linker.rs

+7-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_dynamic_library, find_native_static_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;
@@ -878,7 +880,10 @@ impl<'a> Linker for MsvcLinker<'a> {
878880
}
879881

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

884889
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_dynamic_library, find_native_static_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

+48
Original file line numberDiff line numberDiff line change
@@ -109,11 +109,59 @@ pub fn try_find_native_static_library(
109109
.break_value()
110110
}
111111

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

160+
pub fn find_native_dynamic_library(name: &str, verbatim: bool, sess: &Session) -> PathBuf {
161+
try_find_native_dynamic_library(sess, name, verbatim)
162+
.unwrap_or_else(|| sess.dcx().emit_fatal(errors::MissingNativeLibrary::new(name, verbatim)))
163+
}
164+
117165
fn find_bundled_library(
118166
name: Symbol,
119167
verbatim: Option<bool>,

0 commit comments

Comments
 (0)