@@ -968,7 +968,78 @@ pub fn print_native_static_libs(sess: &Session, all_native_libs: &[NativeLibrary
968968 }
969969}
970970
971+ // Because windows-gnu target is meant to be self-contained for pure Rust code it bundles
972+ // own mingw-w64 libraries. These libraries are usually not compatible with mingw-w64
973+ // installed in the system. This breaks many cases where Rust is mixed with other languages
974+ // (e.g. *-sys crates).
975+ // We prefer system mingw-w64 libraries if they are available to avoid this issue.
976+ fn get_crt_libs_path ( sess : & Session ) -> Option < PathBuf > {
977+ fn find_exe_in_path < P > ( exe_name : P ) -> Option < PathBuf >
978+ where
979+ P : AsRef < Path > ,
980+ {
981+ for dir in env:: split_paths ( & env:: var_os ( "PATH" ) ?) {
982+ let full_path = dir. join ( & exe_name) ;
983+ if full_path. is_file ( ) {
984+ return Some ( fix_windows_verbatim_for_gcc ( & full_path) ) ;
985+ }
986+ }
987+ None
988+ }
989+
990+ fn probe ( sess : & Session ) -> Option < PathBuf > {
991+ if let ( linker, LinkerFlavor :: Gcc ) = linker_and_flavor ( & sess) {
992+ let linker_path = if cfg ! ( windows) && linker. extension ( ) . is_none ( ) {
993+ linker. with_extension ( "exe" )
994+ } else {
995+ linker
996+ } ;
997+ if let Some ( linker_path) = find_exe_in_path ( linker_path) {
998+ let mingw_arch = match & sess. target . target . arch {
999+ x if x == "x86" => "i686" ,
1000+ x => x,
1001+ } ;
1002+ let mingw_dir = format ! ( "{}-w64-mingw32" , mingw_arch) ;
1003+ // Here we have path/bin/gcc but we need path/
1004+ let mut path = linker_path;
1005+ path. pop ( ) ;
1006+ path. pop ( ) ;
1007+ // Based on Clang MinGW driver
1008+ let probe_path = path. join ( & mingw_dir) . join ( "lib" ) ;
1009+ if probe_path. exists ( ) {
1010+ return Some ( probe_path) ;
1011+ } ;
1012+ let probe_path = path. join ( & mingw_dir) . join ( "sys-root/mingw/lib" ) ;
1013+ if probe_path. exists ( ) {
1014+ return Some ( probe_path) ;
1015+ } ;
1016+ } ;
1017+ } ;
1018+ None
1019+ }
1020+
1021+ let mut system_library_path = sess. system_library_path . borrow_mut ( ) ;
1022+ match & * system_library_path {
1023+ Some ( Some ( compiler_libs_path) ) => Some ( compiler_libs_path. clone ( ) ) ,
1024+ Some ( None ) => None ,
1025+ None => {
1026+ let path = probe ( sess) ;
1027+ * system_library_path = Some ( path. clone ( ) ) ;
1028+ path
1029+ }
1030+ }
1031+ }
1032+
9711033pub fn get_file_path ( sess : & Session , name : & str ) -> PathBuf {
1034+ // prefer system {,dll}crt2.o libs, see get_crt_libs_path comment for more details
1035+ if sess. target . target . llvm_target . contains ( "windows-gnu" ) {
1036+ if let Some ( compiler_libs_path) = get_crt_libs_path ( sess) {
1037+ let file_path = compiler_libs_path. join ( name) ;
1038+ if file_path. exists ( ) {
1039+ return file_path;
1040+ }
1041+ }
1042+ }
9721043 let fs = sess. target_filesearch ( PathKind :: Native ) ;
9731044 let file_path = fs. get_lib_path ( ) . join ( name) ;
9741045 if file_path. exists ( ) {
@@ -1150,6 +1221,13 @@ fn link_args<'a, B: ArchiveBuilder<'a>>(
11501221 // target descriptor
11511222 let t = & sess. target . target ;
11521223
1224+ // prefer system mingw-w64 libs, see get_crt_libs_path comment for more details
1225+ if cfg ! ( windows) && sess. target . target . llvm_target . contains ( "windows-gnu" ) {
1226+ if let Some ( compiler_libs_path) = get_crt_libs_path ( sess) {
1227+ cmd. include_path ( & compiler_libs_path) ;
1228+ }
1229+ }
1230+
11531231 cmd. include_path ( & fix_windows_verbatim_for_gcc ( & lib_path) ) ;
11541232
11551233 for obj in codegen_results. modules . iter ( ) . filter_map ( |m| m. object . as_ref ( ) ) {
0 commit comments