about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRamon de C Valle <rcvalle@users.noreply.github.com>2020-11-20 20:11:54 -0800
committerRamon de C Valle <rcvalle@users.noreply.github.com>2021-01-27 19:27:23 -0800
commit3f679fef23cd006c336e2a4f7c6707e119d22206 (patch)
tree43f60f9b9b2a884e6aab8a53188f170a1d8b79ff
parent432d116a5c2565774bae4c42fcacab8b685608b5 (diff)
downloadrust-3f679fef23cd006c336e2a4f7c6707e119d22206.tar.gz
rust-3f679fef23cd006c336e2a4f7c6707e119d22206.zip
Fix rustc sysroot in systems using CAS
Change filesearch::get_or_default_sysroot() to check if sysroot is found
using env::args().next() if rustc in argv[0] is a symlink; otherwise, or
if it is not found, use env::current_exe() to imply sysroot. This makes
the rustc binary able to locate Rust libraries in systems using
content-addressable storage (CAS).
-rw-r--r--compiler/rustc_session/src/filesearch.rs52
1 files changed, 45 insertions, 7 deletions
diff --git a/compiler/rustc_session/src/filesearch.rs b/compiler/rustc_session/src/filesearch.rs
index 55ee4e52082..13080c2bcd0 100644
--- a/compiler/rustc_session/src/filesearch.rs
+++ b/compiler/rustc_session/src/filesearch.rs
@@ -113,6 +113,8 @@ pub fn make_target_lib_path(sysroot: &Path, target_triple: &str) -> PathBuf {
     sysroot.join(&relative_target_lib_path(sysroot, target_triple))
 }
 
+// This function checks if sysroot is found using env::args().next(), and if it
+// is not found, uses env::current_exe() to imply sysroot.
 pub fn get_or_default_sysroot() -> PathBuf {
     // Follow symlinks.  If the resolved path is relative, make it absolute.
     fn canonicalize(path: PathBuf) -> PathBuf {
@@ -123,15 +125,51 @@ pub fn get_or_default_sysroot() -> PathBuf {
         fix_windows_verbatim_for_gcc(&path)
     }
 
-    match env::current_exe() {
-        Ok(exe) => {
-            let mut p = canonicalize(exe);
-            p.pop();
-            p.pop();
-            p
+    // Use env::current_exe() to get the path of the executable following
+    // symlinks/canonicalizing components.
+    fn from_current_exe() -> PathBuf {
+        match env::current_exe() {
+            Ok(exe) => {
+                let mut p = canonicalize(exe);
+                p.pop();
+                p.pop();
+                p
+            }
+            Err(e) => panic!("failed to get current_exe: {}", e),
+        }
+    }
+
+    // Use env::args().next() to get the path of the executable without
+    // following symlinks/canonicalizing any component. This makes the rustc
+    // binary able to locate Rust libraries in systems using content-addressable
+    // storage (CAS).
+    fn from_env_args_next() -> Option<PathBuf> {
+        match env::args_os().next() {
+            Some(first_arg) => {
+                let mut p = PathBuf::from(first_arg);
+
+                // Check if sysroot is found using env::args().next() only if the rustc in argv[0]
+                // is a symlink (see #79253). We might want to change/remove it to conform with
+                // https://www.gnu.org/prep/standards/standards.html#Finding-Program-Files in the
+                // future.
+                if fs::read_link(&p).is_err() {
+                    // Path is not a symbolic link or does not exist.
+                    return None;
+                }
+
+                p.pop();
+                p.pop();
+                let mut libdir = PathBuf::from(&p);
+                libdir.push(find_libdir(&p).as_ref());
+                if libdir.exists() { Some(p) } else { None }
+            }
+            None => None,
         }
-        Err(e) => panic!("failed to get current_exe: {}", e),
     }
+
+    // Check if sysroot is found using env::args().next(), and if is not found,
+    // use env::current_exe() to imply sysroot.
+    from_env_args_next().unwrap_or(from_current_exe())
 }
 
 // The name of the directory rustc expects libraries to be located.