diff --git a/Cargo.lock b/Cargo.lock index 2c4063a5e565e..0f2351bd7802f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3436,6 +3436,7 @@ dependencies = [ "bitflags", "cc", "jobserver", + "lazy_static 1.4.0", "libc", "log", "memmap", diff --git a/src/ci/azure-pipelines/try.yml b/src/ci/azure-pipelines/try.yml index b6177b2cc9b25..ac57a9d2ada92 100644 --- a/src/ci/azure-pipelines/try.yml +++ b/src/ci/azure-pipelines/try.yml @@ -15,8 +15,19 @@ jobs: strategy: matrix: dist-x86_64-linux: {} - dist-x86_64-linux-alt: - IMAGE: dist-x86_64-linux +- job: Windows + timeoutInMinutes: 600 + pool: + vmImage: 'vs2017-win2016' + steps: + - template: steps/run.yml + strategy: + matrix: + dist-x86_64-mingw: + SCRIPT: python x.py dist + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu --enable-full-tools --enable-profiler + CUSTOM_MINGW: 1 + DIST_REQUIRE_ALL_TOOLS: 1 # The macOS and Windows builds here are currently disabled due to them not being # overly necessary on `try` builds. We also don't actually have anything that diff --git a/src/librustc_codegen_ssa/Cargo.toml b/src/librustc_codegen_ssa/Cargo.toml index 9f8b4e72a9cbf..49f9edc0f0644 100644 --- a/src/librustc_codegen_ssa/Cargo.toml +++ b/src/librustc_codegen_ssa/Cargo.toml @@ -14,6 +14,7 @@ bitflags = "1.2.1" cc = "1.0.1" num_cpus = "1.0" memmap = "0.7" +lazy_static = "1" log = "0.4.5" libc = "0.2.44" jobserver = "0.1.11" diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs index f56a4170c0a4b..53127ca1da72c 100644 --- a/src/librustc_codegen_ssa/back/link.rs +++ b/src/librustc_codegen_ssa/back/link.rs @@ -968,7 +968,81 @@ pub fn print_native_static_libs(sess: &Session, all_native_libs: &[NativeLibrary } } +// Because windows-gnu target is meant to be self-contained for pure Rust code it bundles +// own mingw-w64 libraries. These libraries are often not compatible with mingw-w64 +// installed in the system. This breaks many cases where Rust is mixed with other languages +// (e.g. *-sys crates). +// We prefer system mingw-w64 libraries if they are available to avoid this issue. +fn get_crt_libs_path(sess: &Session) -> Option { + fn find_exe_in_path

(exe_name: P) -> Option + where + P: AsRef, + { + for dir in env::split_paths(&env::var_os("PATH")?) { + let full_path = dir.join(&exe_name); + if full_path.is_file() { + return Some(fix_windows_verbatim_for_gcc(&full_path)); + } + } + None + } + + fn probe(sess: &Session) -> Option { + if let (linker, LinkerFlavor::Gcc) = linker_and_flavor(&sess) { + let linker_path = if cfg!(windows) && !linker.extension().is_some() { + linker.with_extension("exe") + } else { + linker + }; + if let Some(linker_path) = find_exe_in_path(linker_path) { + let mingw_arch = match &sess.target.target.arch { + x if x == "x86" => "i686", + x => x, + }; + let mingw_dir = format!("{}-w64-mingw32", mingw_arch); + // Here we have path/bin/gcc but we need path/ + let mut path = linker_path; + path.pop(); + path.pop(); + // Based on Clang MinGW driver + let probe_path = path.join(&mingw_dir).join("lib"); + if probe_path.exists() { + *SYSTEM_LIBS.lock().unwrap() = Some(Some(probe_path.clone())); + return Some(probe_path); + }; + let probe_path = path.join(&mingw_dir).join("sys-root/mingw/lib"); + if probe_path.exists() { + *SYSTEM_LIBS.lock().unwrap() = Some(Some(probe_path.clone())); + return Some(probe_path); + }; + }; + }; + *SYSTEM_LIBS.lock().unwrap() = Some(None); + None + } + + use std::sync::Mutex; + lazy_static::lazy_static! { + static ref SYSTEM_LIBS: Mutex>> = Mutex::new(None); + } + + let system_libs = SYSTEM_LIBS.lock().unwrap().clone(); + match system_libs { + Some(Some(compiler_libs_path)) => Some(compiler_libs_path), + Some(None) => None, + None => probe(sess), + } +} + pub fn get_file_path(sess: &Session, name: &str) -> PathBuf { + if sess.target.target.llvm_target.contains("windows-gnu") { + if let Some(compiler_libs_path) = get_crt_libs_path(sess) { + let file_path = compiler_libs_path.join(name); + if file_path.exists() { + return file_path; + } + } + } let fs = sess.target_filesearch(PathKind::Native); let file_path = fs.get_lib_path().join(name); if file_path.exists() { @@ -1150,6 +1224,12 @@ fn link_args<'a, B: ArchiveBuilder<'a>>( // target descriptor let t = &sess.target.target; + if sess.target.target.llvm_target.contains("windows-gnu") { + if let Some(compiler_libs_path) = get_crt_libs_path(sess) { + cmd.include_path(&compiler_libs_path); + } + } + cmd.include_path(&fix_windows_verbatim_for_gcc(&lib_path)); for obj in codegen_results.modules.iter().filter_map(|m| m.object.as_ref()) {