@@ -776,34 +776,38 @@ impl Library {
776
776
}
777
777
778
778
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
803
790
let filename = & filename[ prefix. len ( ) ..] ;
804
791
return test_suffixes ( filename, & [ ".dll.a" , ".dll" , ".lib" , ".a" ] ) ;
805
792
} 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" ] ) ;
807
811
}
808
812
} else if target. contains ( "apple" ) {
809
813
if filename. starts_with ( prefix) {
@@ -901,6 +905,10 @@ impl Library {
901
905
iter. next ( ) . map ( |s| s. to_owned ( ) ) ,
902
906
) ;
903
907
}
908
+ "-u" => {
909
+ let meta = format ! ( "rustc-link-arg=-Wl,-u,{}" , val) ;
910
+ config. print_metadata ( & meta) ;
911
+ }
904
912
_ => { }
905
913
}
906
914
}
@@ -927,6 +935,12 @@ impl Library {
927
935
self . include_paths . push ( PathBuf :: from ( inc) ) ;
928
936
}
929
937
}
938
+ "-undefined" | "--undefined" => {
939
+ if let Some ( symbol) = iter. next ( ) {
940
+ let meta = format ! ( "rustc-link-arg=-Wl,{},{}" , part, symbol) ;
941
+ config. print_metadata ( & meta) ;
942
+ }
943
+ }
930
944
_ => {
931
945
let path = std:: path:: Path :: new ( part) ;
932
946
if path. is_file ( ) {
@@ -1000,10 +1014,19 @@ fn envify(name: &str) -> String {
1000
1014
1001
1015
/// System libraries should only be linked dynamically
1002
1016
fn is_static_available ( name : & str , system_roots : & [ PathBuf ] , dirs : & [ PathBuf ] ) -> bool {
1003
- let libname = format ! ( "lib{}.a" , name) ;
1017
+ let libnames = {
1018
+ let mut names = vec ! [ format!( "lib{}.a" , name) ] ;
1019
+
1020
+ if cfg ! ( target_os = "windows" ) {
1021
+ names. push ( format ! ( "{}.lib" , name) ) ;
1022
+ }
1023
+
1024
+ names
1025
+ } ;
1004
1026
1005
1027
dirs. iter ( ) . any ( |dir| {
1006
- !system_roots. iter ( ) . any ( |sys| dir. starts_with ( sys) ) && dir. join ( & libname) . exists ( )
1028
+ let library_exists = libnames. iter ( ) . any ( |libname| dir. join ( & libname) . exists ( ) ) ;
1029
+ library_exists && !system_roots. iter ( ) . any ( |sys| dir. starts_with ( sys) )
1007
1030
} )
1008
1031
}
1009
1032
0 commit comments