@@ -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) {
@@ -901,6 +905,10 @@ impl Library {
901905 iter. next ( ) . map ( |s| s. to_owned ( ) ) ,
902906 ) ;
903907 }
908+ "-u" => {
909+ let meta = format ! ( "rustc-link-arg=-Wl,-u,{}" , val) ;
910+ config. print_metadata ( & meta) ;
911+ }
904912 _ => { }
905913 }
906914 }
@@ -927,6 +935,12 @@ impl Library {
927935 self . include_paths . push ( PathBuf :: from ( inc) ) ;
928936 }
929937 }
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+ }
930944 _ => {
931945 let path = std:: path:: Path :: new ( part) ;
932946 if path. is_file ( ) {
@@ -1000,10 +1014,19 @@ fn envify(name: &str) -> String {
10001014
10011015/// System libraries should only be linked dynamically
10021016fn 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+ } ;
10041026
10051027 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) )
10071030 } )
10081031}
10091032
0 commit comments