Skip to content

Commit

Permalink
Prefer system MinGW libs when available
Browse files Browse the repository at this point in the history
  • Loading branch information
mati865 committed Feb 4, 2020
1 parent b1cb3c0 commit 1fad337
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 0 deletions.
78 changes: 78 additions & 0 deletions src/librustc_codegen_ssa/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -968,7 +968,78 @@ 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 usually 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<PathBuf> {
fn find_exe_in_path<P>(exe_name: P) -> Option<PathBuf>
where
P: AsRef<Path>,
{
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<PathBuf> {
if let (linker, LinkerFlavor::Gcc) = linker_and_flavor(&sess) {
let linker_path = if cfg!(windows) && linker.extension().is_none() {
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() {
return Some(probe_path);
};
let probe_path = path.join(&mingw_dir).join("sys-root/mingw/lib");
if probe_path.exists() {
return Some(probe_path);
};
};
};
None
}

let mut system_library_path = sess.system_library_path.borrow_mut();
match &*system_library_path {
Some(Some(compiler_libs_path)) => Some(compiler_libs_path.clone()),
Some(None) => None,
None => {
let path = probe(sess);
*system_library_path = Some(path.clone());
path
}
}
}

pub fn get_file_path(sess: &Session, name: &str) -> PathBuf {
// prefer system {,dll}crt2.o libs, see get_crt_libs_path comment for more details
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() {
Expand Down Expand Up @@ -1150,6 +1221,13 @@ fn link_args<'a, B: ArchiveBuilder<'a>>(
// target descriptor
let t = &sess.target.target;

// prefer system mingw-w64 libs, see get_crt_libs_path comment for more details
if cfg!(windows) && 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()) {
Expand Down
5 changes: 5 additions & 0 deletions src/librustc_session/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,10 @@ pub struct Session {
/// Mapping from ident span to path span for paths that don't exist as written, but that
/// exist under `std`. For example, wrote `str::from_utf8` instead of `std::str::from_utf8`.
pub confused_type_with_std_module: Lock<FxHashMap<Span, Span>>,

/// Path for libraries that will take preference over libraries shipped by Rust.
/// Used by windows-gnu targets to priortize system mingw-w64 libraries.
pub system_library_path: OneThread<RefCell<Option<Option<PathBuf>>>>,
}

pub struct PerfStats {
Expand Down Expand Up @@ -1069,6 +1073,7 @@ fn build_session_(
driver_lint_caps,
trait_methods_not_found: Lock::new(Default::default()),
confused_type_with_std_module: Lock::new(Default::default()),
system_library_path: OneThread::new(RefCell::new(Default::default())),
};

validate_commandline_args_with_session_available(&sess);
Expand Down

0 comments on commit 1fad337

Please sign in to comment.