Skip to content

Commit 98481be

Browse files
committed
MsvcLinker: allow linking dynamically to Meson and MinGW-style named libraries
Fixes#122455
1 parent a7399ba commit 98481be

3 files changed

Lines changed: 50 additions & 3 deletions

File tree

‎compiler/rustc_codegen_ssa/src/back/linker.rs‎

Lines changed: 10 additions & 2 deletions
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;
@@ -878,7 +880,13 @@ impl<'a> Linker for MsvcLinker<'a> {
878880
}
879881

880882
fnlink_dylib_by_name(&mutself,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+
ifletSome(path) = try_find_native_dynamic_library(self.sess, name, verbatim){
886+
self.link_arg(path);
887+
}else{
888+
self.link_arg(format!("{}{}", name,if verbatim {""} else {".lib"}));
889+
}
882890
}
883891

884892
fnlink_dylib_by_path(&mutself,path:&Path,_as_needed:bool){

‎compiler/rustc_metadata/src/lib.rs‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ pub mod locator;
3737
pubuse creader::{load_symbol_from_dylib,DylibError};
3838
pubuse fs::{emit_wrapper_file,METADATA_FILENAME};
3939
pubuse 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
pubuse rmeta::{encode_metadata, rendered_const,EncodedMetadata,METADATA_HEADER};
4344

‎compiler/rustc_metadata/src/native_libs.rs‎

Lines changed: 38 additions & 0 deletions
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+
pubfntry_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+
returnControlFlow::Break(test);
141+
}
142+
}
143+
}
144+
ControlFlow::Continue(())
145+
},
146+
)
147+
.break_value()
148+
}
149+
112150
pubfnfind_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)