Skip to content

Commit

Permalink
Search codegen backends based on target libdir instead of sysroot.
Browse files Browse the repository at this point in the history
Fixes cases with custom libdir when it consists of two or more parts.
  • Loading branch information
o01eg committed Dec 24, 2018
1 parent 94bf2c1 commit 4e7d53d
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 21 deletions.
7 changes: 7 additions & 0 deletions src/librustc/session/filesearch.rs
Expand Up @@ -124,6 +124,13 @@ pub fn make_target_lib_path(sysroot: &Path, target_triple: &str) -> PathBuf {
sysroot.join(&relative_target_lib_path(sysroot, target_triple))
}

pub fn target_lib_path(target_triple: &str) -> PathBuf {
let mut p = PathBuf::from(RUST_LIB_DIR);
p.push(target_triple);
p.push("lib");
p
}

pub fn get_or_default_sysroot() -> PathBuf {
// Follow symlinks. If the resolved path is relative, make it absolute.
fn canonicalize(path: Option<PathBuf>) -> Option<PathBuf> {
Expand Down
40 changes: 19 additions & 21 deletions src/librustc_driver/lib.rs
Expand Up @@ -294,37 +294,35 @@ fn get_codegen_sysroot(backend_name: &str) -> fn() -> Box<dyn CodegenBackend> {
}

let target = session::config::host_triple();
let mut sysroot_candidates = vec![filesearch::get_or_default_sysroot()];
// get target libdir path based on executable binary path
let sysroot = filesearch::get_or_default_sysroot();
let mut libdir_candidates = vec![filesearch::make_target_lib_path(&sysroot, &target)];
let path = current_dll_path()
.and_then(|s| s.canonicalize().ok());
if let Some(dll) = path {
// use `parent` twice to chop off the file name and then also the
// directory containing the dll which should be either `lib` or `bin`.
if let Some(path) = dll.parent().and_then(|p| p.parent()) {
// use `parent` once to chop off the file name
if let Some(path) = dll.parent() {
// The original `path` pointed at the `rustc_driver` crate's dll.
// Now that dll should only be in one of two locations. The first is
// in the compiler's libdir, for example `$sysroot/lib/*.dll`. The
// in the compiler's libdir, for example `$sysroot/$libdir/*.dll`. The
// other is the target's libdir, for example
// `$sysroot/lib/rustlib/$target/lib/*.dll`.
// `$sysroot/$libdir/rustlib/$target/lib/*.dll`.
//
// We don't know which, so let's assume that if our `path` above
// ends in `$target` we *could* be in the target libdir, and always
// assume that we may be in the main libdir.
sysroot_candidates.push(path.to_owned());

if path.ends_with(target) {
sysroot_candidates.extend(path.parent() // chop off `$target`
.and_then(|p| p.parent()) // chop off `rustlib`
.and_then(|p| p.parent()) // chop off `lib`
.map(|s| s.to_owned()));
// doesn't end in `$target` we *could* be in the main libdir, and always
// assume that we may be in the target libdir.
libdir_candidates.push(path.to_owned());

if !path.parent().map_or(false, |p| p.ends_with(target)) {
libdir_candidates.push(path.join(filesearch::target_lib_path(target)));
}
}
}

let sysroot = sysroot_candidates.iter()
.map(|sysroot| {
let libdir = filesearch::relative_target_lib_path(&sysroot, &target);
sysroot.join(libdir).with_file_name(
let sysroot = libdir_candidates.iter()
.map(|libdir| {
debug!("Trying target libdir: {}", libdir.display());
libdir.with_file_name(
option_env!("CFG_CODEGEN_BACKENDS_DIR").unwrap_or("codegen-backends"))
})
.filter(|f| {
Expand All @@ -333,12 +331,12 @@ fn get_codegen_sysroot(backend_name: &str) -> fn() -> Box<dyn CodegenBackend> {
})
.next();
let sysroot = sysroot.unwrap_or_else(|| {
let candidates = sysroot_candidates.iter()
let candidates = libdir_candidates.iter()
.map(|p| p.display().to_string())
.collect::<Vec<_>>()
.join("\n* ");
let err = format!("failed to find a `codegen-backends` folder \
in the sysroot candidates:\n* {}", candidates);
in the libdir candidates:\n* {}", candidates);
early_error(ErrorOutputType::default(), &err);
});
info!("probing {} for a codegen backend", sysroot.display());
Expand Down

0 comments on commit 4e7d53d

Please sign in to comment.