Skip to content

Commit

Permalink
Auto merge of #67429 - mati865:mingw-ultimate-fix, r=<try>
Browse files Browse the repository at this point in the history
[WIP] windows-gnu: prefer system crt libraries if they are available

This is my proposal (based on `Amanieu`'s idea) on how to fix #47048 and related issues.

The origin of the issue is the fact Rust ships mingw-w64 libraries but no headers and prefers own libraries over the system ones.
This leads to situation when headers aren't compatible with libraries (mingw-w64 doesn't provide any forward compatibility and AFAIK backwards compatibility is guaranteed only within major release series).

It's easier to understand how this PR works when looking at the linker invocation before and with this PR: https://www.diffchecker.com/GEuYFmzo
It adds system libraries path before Rust libraries so the linker will prefer them.
It has potential issue when system has files with the same names as Rust but that could be avoided by moving Rust shipped mingw-w64 libraries from `lib/rustlib/x86_64-pc-windows-gnu/lib` to say `lib/rustlib/x86_64-pc-windows-gnu/lib/mingw`. Then adding linker paths in this order: Rust libraries, system libraries, Rust shipped mingw-w64 libraries.

I don't know if it's worth to cache system libraries path. You can look for `cache: ` string during build Rust: https://pastebin.com/kGEQZGWP
I think there are enough calls to justify caching.

Obvious shortcoming here is this version works only on windows-gnu host because of `#[cfg(all(windows, target_env = "gnu"))]` but you should get the idea.
  • Loading branch information
bors committed Dec 29, 2019
2 parents 25434f8 + 0e093bb commit 4069647
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 56 deletions.
1 change: 1 addition & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3392,6 +3392,7 @@ dependencies = [
"bitflags",
"cc",
"jobserver",
"lazy_static 1.3.0",
"libc",
"log",
"memmap",
Expand Down
69 changes: 13 additions & 56 deletions src/ci/azure-pipelines/try.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,59 +15,16 @@ jobs:
strategy:
matrix:
dist-x86_64-linux: {}
dist-x86_64-linux-alt:
IMAGE: dist-x86_64-linux

# 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
# consumes the artifacts currently. Perhaps one day we can reenable, but for now
# it helps free up capacity on Azure.
# - job: macOS
# timeoutInMinutes: 600
# pool:
# vmImage: macos-10.13
# steps:
# - template: steps/run.yml
# strategy:
# matrix:
# dist-x86_64-apple:
# SCRIPT: ./x.py dist
# RUST_CONFIGURE_ARGS: --target=aarch64-apple-ios,armv7-apple-ios,armv7s-apple-ios,i386-apple-ios,x86_64-apple-ios --enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc
# DEPLOY: 1
# RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
# MACOSX_DEPLOYMENT_TARGET: 10.7
# NO_LLVM_ASSERTIONS: 1
# NO_DEBUG_ASSERTIONS: 1
# DIST_REQUIRE_ALL_TOOLS: 1
#
# dist-x86_64-apple-alt:
# SCRIPT: ./x.py dist
# RUST_CONFIGURE_ARGS: --enable-extended --enable-profiler --set rust.jemalloc
# DEPLOY_ALT: 1
# RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
# MACOSX_DEPLOYMENT_TARGET: 10.7
# NO_LLVM_ASSERTIONS: 1
# NO_DEBUG_ASSERTIONS: 1
#
# - job: Windows
# timeoutInMinutes: 600
# pool:
# vmImage: 'vs2017-win2016'
# steps:
# - template: steps/run.yml
# strategy:
# matrix:
# dist-x86_64-msvc:
# RUST_CONFIGURE_ARGS: >
# --build=x86_64-pc-windows-msvc
# --target=x86_64-pc-windows-msvc,aarch64-pc-windows-msvc
# --enable-full-tools
# --enable-profiler
# SCRIPT: python x.py dist
# DIST_REQUIRE_ALL_TOOLS: 1
# DEPLOY: 1
#
# dist-x86_64-msvc-alt:
# RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-extended --enable-profiler
# SCRIPT: python x.py dist
# DEPLOY_ALT: 1
- 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
1 change: 1 addition & 0 deletions src/librustc_codegen_ssa/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
47 changes: 47 additions & 0 deletions src/librustc_codegen_ssa/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -918,7 +918,48 @@ pub fn print_native_static_libs(sess: &Session, all_native_libs: &[NativeLibrary
}
}

fn get_compiler_libs_path(sess: &Session) -> Option<PathBuf> {
use std::sync::Mutex;

lazy_static::lazy_static! {
static ref SYSTEM_LIBS: Mutex<Option<PathBuf>> = Mutex::new(None);
}

let system_libs = SYSTEM_LIBS.lock().unwrap().clone();
if let Some(compiler_libs_path) = system_libs {
println!("cache: hit");
return Some(compiler_libs_path);
} else {
println!("cache: miss");
let compiler = if let Some(linker) = &sess.opts.cg.linker {
linker.clone().into_os_string()
} else if let Some(linker) = &sess.target.target.options.linker {
linker.into()
} else {
return None;
};
if let Ok(output) = Command::new(compiler).arg("-print-file-name=crt2.o").output() {
if let Some(compiler_libs_path) =
PathBuf::from(std::str::from_utf8(&output.stdout).unwrap()).parent()
{
let compiler_libs_path = fix_windows_verbatim_for_gcc(compiler_libs_path);
*SYSTEM_LIBS.lock().unwrap() = Some(compiler_libs_path.clone());
return Some(compiler_libs_path);
}
}
}
None
}

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_compiler_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() {
Expand Down Expand Up @@ -1100,6 +1141,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_compiler_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()) {
Expand Down

0 comments on commit 4069647

Please sign in to comment.