Skip to content

Commit 73d776d

Browse files
committed
Library: Allow using Meson-built Windows libraries
Although there's a clear MSVC convention of calling import libraries "xxxx.lib", when a build system creates both static and shared libraries, a race condition will be caused [1]. To this end, the Meson build system decided to also apply the GNU convention for the MSVC ABI [2], which is not considered in pkg-config-rs. [1]: https://aomedia-review.googlesource.com/c/aom/+/173603 [2]: mesonbuild/meson#8153
1 parent 333771e commit 73d776d

File tree

1 file changed

+29
-25
lines changed

1 file changed

+29
-25
lines changed

src/lib.rs

Lines changed: 29 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -776,34 +776,38 @@ impl Library {
776776
}
777777

778778
let prefix = "lib";
779-
if target.contains("msvc") {
780-
// According to link.exe documentation:
781-
// https://learn.microsoft.com/en-us/cpp/build/reference/link-input-files?view=msvc-170
782-
//
783-
// LINK doesn't use file extensions to make assumptions about the contents of a file.
784-
// Instead, LINK examines each input file to determine what kind of file it is.
785-
//
786-
// However, rustc appends `.lib` to the string it receives from the -l command line argument,
787-
// which it receives from Cargo via cargo:rustc-link-lib:
788-
// https://github.com/rust-lang/rust/blob/657f246812ab2684e3c3954b1c77f98fd59e0b21/compiler/rustc_codegen_ssa/src/back/linker.rs#L828
789-
// https://github.com/rust-lang/rust/blob/657f246812ab2684e3c3954b1c77f98fd59e0b21/compiler/rustc_codegen_ssa/src/back/linker.rs#L843
790-
// So the only file extension that works for MSVC targets is `.lib`
791-
return test_suffixes(filename, &[".lib"]);
792-
} else if target.contains("windows") && target.contains("gnu") {
793-
// GNU targets for Windows, including gnullvm, use `LinkerFlavor::Gcc` internally in rustc,
794-
// which tells rustc to use the GNU linker. rustc does not prepend/append to the string it
795-
// receives via the -l command line argument before passing it to the linker:
796-
// https://github.com/rust-lang/rust/blob/657f246812ab2684e3c3954b1c77f98fd59e0b21/compiler/rustc_codegen_ssa/src/back/linker.rs#L446
797-
// https://github.com/rust-lang/rust/blob/657f246812ab2684e3c3954b1c77f98fd59e0b21/compiler/rustc_codegen_ssa/src/back/linker.rs#L457
798-
// GNU ld can work with more types of files than just the .lib files that MSVC's link.exe needs.
799-
// GNU ld will prepend the `lib` prefix to the filename if necessary, so it is okay to remove
800-
// the `lib` prefix from the filename. The `.a` suffix *requires* the `lib` prefix.
801-
// https://sourceware.org/binutils/docs-2.39/ld.html#index-direct-linking-to-a-dll
802-
if filename.starts_with(prefix) {
779+
if target.contains("windows") {
780+
if target.contains("gnu") && filename.starts_with(prefix) {
781+
// GNU targets for Windows, including gnullvm, use `LinkerFlavor::Gcc` internally in rustc,
782+
// which tells rustc to use the GNU linker. rustc does not prepend/append to the string it
783+
// receives via the -l command line argument before passing it to the linker:
784+
// https://github.com/rust-lang/rust/blob/657f246812ab2684e3c3954b1c77f98fd59e0b21/compiler/rustc_codegen_ssa/src/back/linker.rs#L446
785+
// https://github.com/rust-lang/rust/blob/657f246812ab2684e3c3954b1c77f98fd59e0b21/compiler/rustc_codegen_ssa/src/back/linker.rs#L457
786+
// GNU ld can work with more types of files than just the .lib files that MSVC's link.exe needs.
787+
// GNU ld will prepend the `lib` prefix to the filename if necessary, so it is okay to remove
788+
// the `lib` prefix from the filename. The `.a` suffix *requires* the `lib` prefix.
789+
// https://sourceware.org/binutils/docs-2.39/ld.html#index-direct-linking-to-a-dll
803790
let filename = &filename[prefix.len()..];
804791
return test_suffixes(filename, &[".dll.a", ".dll", ".lib", ".a"]);
805792
} else {
806-
return test_suffixes(filename, &[".dll.a", ".dll", ".lib"]);
793+
// According to link.exe documentation:
794+
// https://learn.microsoft.com/en-us/cpp/build/reference/link-input-files?view=msvc-170
795+
//
796+
// LINK doesn't use file extensions to make assumptions about the contents of a file.
797+
// Instead, LINK examines each input file to determine what kind of file it is.
798+
//
799+
// However, rustc appends `.lib` to the string it receives from the -l command line argument,
800+
// which it receives from Cargo via cargo:rustc-link-lib:
801+
// https://github.com/rust-lang/rust/blob/657f246812ab2684e3c3954b1c77f98fd59e0b21/compiler/rustc_codegen_ssa/src/back/linker.rs#L828
802+
// https://github.com/rust-lang/rust/blob/657f246812ab2684e3c3954b1c77f98fd59e0b21/compiler/rustc_codegen_ssa/src/back/linker.rs#L843
803+
// So the only file extension that works for MSVC targets is `.lib`
804+
// However, for externally created libraries, there's no
805+
// guarantee that the extension is ".lib" so we need to
806+
// consider all options.
807+
// See:
808+
// https://github.com/mesonbuild/meson/issues/8153
809+
// https://github.com/rust-lang/rust/issues/114013
810+
return test_suffixes(filename, &[".dll.a", ".dll", ".lib", ".a"]);
807811
}
808812
} else if target.contains("apple") {
809813
if filename.starts_with(prefix) {

0 commit comments

Comments
 (0)