Skip to content

Commit

Permalink
MsvcLinker: allow linking dynamically to Meson and MinGW-style named …
Browse files Browse the repository at this point in the history
…libraries

Fixes rust-lang#122455
  • Loading branch information
amyspark committed Sep 8, 2024
1 parent a7399ba commit 98481be
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 3 deletions.
12 changes: 10 additions & 2 deletions compiler/rustc_codegen_ssa/src/back/linker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ use std::{env, iter, mem, str};

use cc::windows_registry;
use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
use rustc_metadata::{find_native_static_library, try_find_native_static_library};
use rustc_metadata::{
find_native_static_library, try_find_native_dynamic_library, try_find_native_static_library,
};
use rustc_middle::bug;
use rustc_middle::middle::dependency_format::Linkage;
use rustc_middle::middle::exported_symbols;
Expand Down Expand Up @@ -878,7 +880,13 @@ impl<'a> Linker for MsvcLinker<'a> {
}

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

fn link_dylib_by_path(&mut self, path: &Path, _as_needed: bool) {
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_metadata/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ pub mod locator;
pub use creader::{load_symbol_from_dylib, DylibError};
pub use fs::{emit_wrapper_file, METADATA_FILENAME};
pub use native_libs::{
find_native_static_library, try_find_native_static_library, walk_native_lib_search_dirs,
find_native_static_library, try_find_native_dynamic_library, try_find_native_static_library,
walk_native_lib_search_dirs,
};
pub use rmeta::{encode_metadata, rendered_const, EncodedMetadata, METADATA_HEADER};

Expand Down
38 changes: 38 additions & 0 deletions compiler/rustc_metadata/src/native_libs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,44 @@ pub fn try_find_native_static_library(
.break_value()
}

pub fn try_find_native_dynamic_library(
sess: &Session,
name: &str,
verbatim: bool,
) -> Option<PathBuf> {
let formats = if verbatim {
vec![("".into(), "".into())]
} 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
// disambiguate .a for static libraries
let meson = ("lib".into(), ".dll.a".into());
// and MinGW uses .a altogether
let mingw = ("lib".into(), ".a".into());
vec![os, meson, mingw]
};

walk_native_lib_search_dirs(
sess,
LinkSelfContainedComponents::empty(),
None,
|dir, is_framework| {
if !is_framework {
for (prefix, suffix) in &formats {
let test = dir.join(format!("{prefix}{name}{suffix}"));
if test.exists() {
return ControlFlow::Break(test);
}
}
}
ControlFlow::Continue(())
},
)
.break_value()
}

pub fn find_native_static_library(name: &str, verbatim: bool, sess: &Session) -> PathBuf {
try_find_native_static_library(sess, name, verbatim)
.unwrap_or_else(|| sess.dcx().emit_fatal(errors::MissingNativeLibrary::new(name, verbatim)))
Expand Down

0 comments on commit 98481be

Please sign in to comment.