@@ -968,7 +968,78 @@ pub fn print_native_static_libs(sess: &Session, all_native_libs: &[NativeLibrary
968
968
}
969
969
}
970
970
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
+
971
1033
pub 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
+ }
972
1043
let fs = sess. target_filesearch ( PathKind :: Native ) ;
973
1044
let file_path = fs. get_lib_path ( ) . join ( name) ;
974
1045
if file_path. exists ( ) {
@@ -1150,6 +1221,13 @@ fn link_args<'a, B: ArchiveBuilder<'a>>(
1150
1221
// target descriptor
1151
1222
let t = & sess. target . target ;
1152
1223
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
+
1153
1231
cmd. include_path ( & fix_windows_verbatim_for_gcc ( & lib_path) ) ;
1154
1232
1155
1233
for obj in codegen_results. modules . iter ( ) . filter_map ( |m| m. object . as_ref ( ) ) {
0 commit comments