From cd8bdb5eb9a7440fa64500218f43b04429e64fc1 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 29 Jul 2020 09:10:07 -0700 Subject: [PATCH] rustc: Ignore fs::canonicalize errors in metadata This commit updates the metadata location logic to ignore errors when calling `fs::canonicalize`. Canonicalization was added historically so multiple `-L` paths to the same directory don't print errors about multiple candidates (since rustc can deduplicate same-named paths), but canonicalization doesn't work on all filesystems. Cargo, for example, always uses this sort of fallback where it will opportunitistically try to canonicalize but fall back to using the input path if it otherwise doesn't work. If rustc is run on a filesystem that doesn't support canonicalization then the effect of this change will be that `-L` paths which logically point to the same directory will cause errors, but that's a rare enough occurrence it shouldn't cause much issue in practice. Otherwise rustc doesn't work at all today on those sorts of filesystem where canonicalization isn't supported! --- src/librustc_metadata/creader.rs | 6 +++--- src/librustc_metadata/locator.rs | 32 ++++++++++++++---------------- src/librustc_session/filesearch.rs | 32 ++++++++++++------------------ 3 files changed, 31 insertions(+), 39 deletions(-) diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 724b4123fab6c..8dc842cc9d496 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -236,9 +236,9 @@ impl<'a> CrateLoader<'a> { // Only use `--extern crate_name=path` here, not `--extern crate_name`. if let Some(mut files) = entry.files() { if files.any(|l| { - let l = fs::canonicalize(l).ok(); - source.dylib.as_ref().map(|p| &p.0) == l.as_ref() - || source.rlib.as_ref().map(|p| &p.0) == l.as_ref() + let l = fs::canonicalize(l).unwrap_or(l.clone().into()); + source.dylib.as_ref().map(|p| &p.0) == Some(&l) + || source.rlib.as_ref().map(|p| &p.0) == Some(&l) }) { ret = Some(cnum); } diff --git a/src/librustc_metadata/locator.rs b/src/librustc_metadata/locator.rs index 371ec4cd91148..8828b318d1ea6 100644 --- a/src/librustc_metadata/locator.rs +++ b/src/librustc_metadata/locator.rs @@ -426,20 +426,17 @@ impl<'a> CrateLocator<'a> { info!("lib candidate: {}", spf.path.display()); let (rlibs, rmetas, dylibs) = candidates.entry(hash.to_string()).or_default(); - fs::canonicalize(&spf.path) - .map(|p| { - if seen_paths.contains(&p) { - return FileDoesntMatch; - }; - seen_paths.insert(p.clone()); - match found_kind { - CrateFlavor::Rlib => rlibs.insert(p, kind), - CrateFlavor::Rmeta => rmetas.insert(p, kind), - CrateFlavor::Dylib => dylibs.insert(p, kind), - }; - FileMatches - }) - .unwrap_or(FileDoesntMatch) + let path = fs::canonicalize(&spf.path).unwrap_or_else(|_| spf.path.clone()); + if seen_paths.contains(&path) { + return FileDoesntMatch; + }; + seen_paths.insert(path.clone()); + match found_kind { + CrateFlavor::Rlib => rlibs.insert(path, kind), + CrateFlavor::Rmeta => rmetas.insert(path, kind), + CrateFlavor::Dylib => dylibs.insert(path, kind), + }; + FileMatches }); self.rejected_via_kind.extend(staticlibs); @@ -688,12 +685,13 @@ impl<'a> CrateLocator<'a> { && file.ends_with(&self.target.options.dll_suffix) { // Make sure there's at most one rlib and at most one dylib. + let loc = fs::canonicalize(&loc).unwrap_or_else(|_| loc.clone()); if loc.file_name().unwrap().to_str().unwrap().ends_with(".rlib") { - rlibs.insert(fs::canonicalize(&loc).unwrap(), PathKind::ExternFlag); + rlibs.insert(loc, PathKind::ExternFlag); } else if loc.file_name().unwrap().to_str().unwrap().ends_with(".rmeta") { - rmetas.insert(fs::canonicalize(&loc).unwrap(), PathKind::ExternFlag); + rmetas.insert(loc, PathKind::ExternFlag); } else { - dylibs.insert(fs::canonicalize(&loc).unwrap(), PathKind::ExternFlag); + dylibs.insert(loc, PathKind::ExternFlag); } } else { self.rejected_via_filename diff --git a/src/librustc_session/filesearch.rs b/src/librustc_session/filesearch.rs index 27396c524f4e6..504490d938cfa 100644 --- a/src/librustc_session/filesearch.rs +++ b/src/librustc_session/filesearch.rs @@ -117,28 +117,22 @@ pub fn make_target_lib_path(sysroot: &Path, target_triple: &str) -> PathBuf { pub fn get_or_default_sysroot() -> PathBuf { // Follow symlinks. If the resolved path is relative, make it absolute. - fn canonicalize(path: Option) -> Option { - path.and_then(|path| { - match fs::canonicalize(&path) { - // See comments on this target function, but the gist is that - // gcc chokes on verbatim paths which fs::canonicalize generates - // so we try to avoid those kinds of paths. - Ok(canon) => Some(fix_windows_verbatim_for_gcc(&canon)), - Err(e) => panic!("failed to get realpath: {}", e), - } - }) + fn canonicalize(path: PathBuf) -> PathBuf { + let path = fs::canonicalize(&path).unwrap_or(path); + // See comments on this target function, but the gist is that + // gcc chokes on verbatim paths which fs::canonicalize generates + // so we try to avoid those kinds of paths. + fix_windows_verbatim_for_gcc(&path) } match env::current_exe() { - Ok(exe) => match canonicalize(Some(exe)) { - Some(mut p) => { - p.pop(); - p.pop(); - p - } - None => panic!("can't determine value for sysroot"), - }, - Err(ref e) => panic!(format!("failed to get current_exe: {}", e)), + Ok(exe) => { + let mut p = canonicalize(exe); + p.pop(); + p.pop(); + p + } + Err(e) => panic!("failed to get current_exe: {}", e), } }