Rollup merge of #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 #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 #129366, #126094, and #128370. All feedback is appreciated! Fixes #122455 cc `@sdroege` `@nirbheek`
This commit is contained in:
commit
eac6f07380
@ -7,7 +7,9 @@
|
|||||||
|
|
||||||
use cc::windows_registry;
|
use cc::windows_registry;
|
||||||
use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
|
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::bug;
|
||||||
use rustc_middle::middle::dependency_format::Linkage;
|
use rustc_middle::middle::dependency_format::Linkage;
|
||||||
use rustc_middle::middle::exported_symbols;
|
use rustc_middle::middle::exported_symbols;
|
||||||
@ -876,7 +878,13 @@ fn set_output_kind(&mut self, output_kind: LinkOutputKind, out_filename: &Path)
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn link_dylib_by_name(&mut self, name: &str, verbatim: bool, _as_needed: bool) {
|
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) {
|
fn link_dylib_by_path(&mut self, path: &Path, _as_needed: bool) {
|
||||||
|
@ -37,7 +37,8 @@
|
|||||||
pub use creader::{load_symbol_from_dylib, DylibError};
|
pub use creader::{load_symbol_from_dylib, DylibError};
|
||||||
pub use fs::{emit_wrapper_file, METADATA_FILENAME};
|
pub use fs::{emit_wrapper_file, METADATA_FILENAME};
|
||||||
pub use native_libs::{
|
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};
|
pub use rmeta::{encode_metadata, rendered_const, EncodedMetadata, METADATA_HEADER};
|
||||||
|
|
||||||
|
@ -109,6 +109,44 @@ pub fn try_find_native_static_library(
|
|||||||
.break_value()
|
.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 {
|
pub fn find_native_static_library(name: &str, verbatim: bool, sess: &Session) -> PathBuf {
|
||||||
try_find_native_static_library(sess, name, verbatim)
|
try_find_native_static_library(sess, name, verbatim)
|
||||||
.unwrap_or_else(|| sess.dcx().emit_fatal(errors::MissingNativeLibrary::new(name, verbatim)))
|
.unwrap_or_else(|| sess.dcx().emit_fatal(errors::MissingNativeLibrary::new(name, verbatim)))
|
||||||
|
Loading…
Reference in New Issue
Block a user