about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_codegen_ssa/src/back/linker.rs12
-rw-r--r--compiler/rustc_metadata/src/lib.rs3
-rw-r--r--compiler/rustc_metadata/src/native_libs.rs38
3 files changed, 50 insertions, 3 deletions
diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs
index 7f5f9f03868..bda22255705 100644
--- a/compiler/rustc_codegen_ssa/src/back/linker.rs
+++ b/compiler/rustc_codegen_ssa/src/back/linker.rs
@@ -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;
@@ -876,7 +878,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) {
diff --git a/compiler/rustc_metadata/src/lib.rs b/compiler/rustc_metadata/src/lib.rs
index 58b352f263d..02a9ce455b2 100644
--- a/compiler/rustc_metadata/src/lib.rs
+++ b/compiler/rustc_metadata/src/lib.rs
@@ -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};
 
diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs
index a6ad449cb53..0329a193d89 100644
--- a/compiler/rustc_metadata/src/native_libs.rs
+++ b/compiler/rustc_metadata/src/native_libs.rs
@@ -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)))