about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2021-02-05 22:58:13 +0000
committerbors <bors@rust-lang.org>2021-02-05 22:58:13 +0000
commit16b805713c4cdb967263b9d59634fddea4372b65 (patch)
tree2d14c5badf900950cd3696360518281978f70e69
parent23adf9fd843da7a3394c824b056f93151aaa40ad (diff)
parent3f679fef23cd006c336e2a4f7c6707e119d22206 (diff)
downloadrust-16b805713c4cdb967263b9d59634fddea4372b65.tar.gz
rust-16b805713c4cdb967263b9d59634fddea4372b65.zip
Auto merge of #79253 - rcvalle:fix-rustc-sysroot-cas, r=nagisa
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 3a757e5f007..47f14fa6b7a 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.