about summary refs log tree commit diff
diff options
context:
space:
mode:
authorGuillaume Gomez <guillaume1.gomez@gmail.com>2021-05-10 20:05:27 +0200
committerGitHub <noreply@github.com>2021-05-10 20:05:27 +0200
commit6ec1de7d4f950c7c0b33bae9858157282416591d (patch)
treea22101c2f5f999c09d665a18a2325e2df6d57430
parent3962541dcb4a0e8c6926ea9f426a57f4cde20513 (diff)
parentb7c5599d22018ab6be88442c4668bc1697f85b8e (diff)
downloadrust-6ec1de7d4f950c7c0b33bae9858157282416591d.tar.gz
rust-6ec1de7d4f950c7c0b33bae9858157282416591d.zip
Rollup merge of #85152 - nagisa:target-search-rustlib, r=Mark-Simulacrum
Adjust target search algorithm for rustlib path

With this the concerns expressed in #83800 should be addressed.

r? `@Mark-Simulacrum`
-rw-r--r--compiler/rustc_codegen_ssa/src/back/link.rs2
-rw-r--r--compiler/rustc_interface/src/util.rs3
-rw-r--r--compiler/rustc_session/src/filesearch.rs68
-rw-r--r--compiler/rustc_target/src/lib.rs51
-rw-r--r--compiler/rustc_target/src/spec/mod.rs25
5 files changed, 83 insertions, 66 deletions
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index 59f66c55572..30a56badeb5 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -1576,7 +1576,7 @@ fn add_rpath_args(
         let target_triple = sess.opts.target_triple.triple();
         let mut get_install_prefix_lib_path = || {
             let install_prefix = option_env!("CFG_PREFIX").expect("CFG_PREFIX");
-            let tlib = filesearch::relative_target_lib_path(&sess.sysroot, target_triple);
+            let tlib = rustc_target::target_rustlib_path(&sess.sysroot, target_triple).join("lib");
             let mut path = PathBuf::from(install_prefix);
             path.push(&tlib);
 
diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs
index 59488fc80a5..fd29053433e 100644
--- a/compiler/rustc_interface/src/util.rs
+++ b/compiler/rustc_interface/src/util.rs
@@ -423,8 +423,7 @@ pub fn get_codegen_sysroot(
         .iter()
         .chain(sysroot_candidates.iter())
         .map(|sysroot| {
-            let libdir = filesearch::relative_target_lib_path(&sysroot, &target);
-            sysroot.join(libdir).with_file_name("codegen-backends")
+            filesearch::make_target_lib_path(&sysroot, &target).with_file_name("codegen-backends")
         })
         .find(|f| {
             info!("codegen backend candidate: {}", f.display());
diff --git a/compiler/rustc_session/src/filesearch.rs b/compiler/rustc_session/src/filesearch.rs
index 2df326628e7..6fe6a555f1a 100644
--- a/compiler/rustc_session/src/filesearch.rs
+++ b/compiler/rustc_session/src/filesearch.rs
@@ -1,6 +1,5 @@
 pub use self::FileMatch::*;
 
-use std::borrow::Cow;
 use std::env;
 use std::fs;
 use std::path::{Path, PathBuf};
@@ -91,26 +90,21 @@ impl<'a> FileSearch<'a> {
 
     // Returns a list of directories where target-specific tool binaries are located.
     pub fn get_tools_search_paths(&self, self_contained: bool) -> Vec<PathBuf> {
-        let mut p = PathBuf::from(self.sysroot);
-        p.push(find_libdir(self.sysroot).as_ref());
-        p.push(RUST_LIB_DIR);
-        p.push(&self.triple);
-        p.push("bin");
+        let rustlib_path = rustc_target::target_rustlib_path(self.sysroot, &self.triple);
+        let p = std::array::IntoIter::new([
+            Path::new(&self.sysroot),
+            Path::new(&rustlib_path),
+            Path::new("bin"),
+        ])
+        .collect::<PathBuf>();
         if self_contained { vec![p.clone(), p.join("self-contained")] } else { vec![p] }
     }
 }
 
-pub fn relative_target_lib_path(sysroot: &Path, target_triple: &str) -> PathBuf {
-    let mut p = PathBuf::from(find_libdir(sysroot).as_ref());
-    assert!(p.is_relative());
-    p.push(RUST_LIB_DIR);
-    p.push(target_triple);
-    p.push("lib");
-    p
-}
-
 pub fn make_target_lib_path(sysroot: &Path, target_triple: &str) -> PathBuf {
-    sysroot.join(&relative_target_lib_path(sysroot, target_triple))
+    let rustlib_path = rustc_target::target_rustlib_path(sysroot, target_triple);
+    std::array::IntoIter::new([sysroot, Path::new(&rustlib_path), Path::new("lib")])
+        .collect::<PathBuf>()
 }
 
 // This function checks if sysroot is found using env::args().next(), and if it
@@ -157,11 +151,13 @@ pub fn get_or_default_sysroot() -> PathBuf {
                     return None;
                 }
 
+                // Pop off `bin/rustc`, obtaining the suspected sysroot.
                 p.pop();
                 p.pop();
-                let mut libdir = PathBuf::from(&p);
-                libdir.push(find_libdir(&p).as_ref());
-                if libdir.exists() { Some(p) } else { None }
+                // Look for the target rustlib directory in the suspected sysroot.
+                let mut rustlib_path = rustc_target::target_rustlib_path(&p, "dummy");
+                rustlib_path.pop(); // pop off the dummy target.
+                if rustlib_path.exists() { Some(p) } else { None }
             }
             None => None,
         }
@@ -171,37 +167,3 @@ pub fn get_or_default_sysroot() -> PathBuf {
     // use env::current_exe() to imply sysroot.
     from_env_args_next().unwrap_or_else(from_current_exe)
 }
-
-// The name of the directory rustc expects libraries to be located.
-fn find_libdir(sysroot: &Path) -> Cow<'static, str> {
-    // FIXME: This is a quick hack to make the rustc binary able to locate
-    // Rust libraries in Linux environments where libraries might be installed
-    // to lib64/lib32. This would be more foolproof by basing the sysroot off
-    // of the directory where `librustc_driver` is located, rather than
-    // where the rustc binary is.
-    // If --libdir is set during configuration to the value other than
-    // "lib" (i.e., non-default), this value is used (see issue #16552).
-
-    #[cfg(target_pointer_width = "64")]
-    const PRIMARY_LIB_DIR: &str = "lib64";
-
-    #[cfg(target_pointer_width = "32")]
-    const PRIMARY_LIB_DIR: &str = "lib32";
-
-    const SECONDARY_LIB_DIR: &str = "lib";
-
-    match option_env!("CFG_LIBDIR_RELATIVE") {
-        None | Some("lib") => {
-            if sysroot.join(PRIMARY_LIB_DIR).join(RUST_LIB_DIR).exists() {
-                PRIMARY_LIB_DIR.into()
-            } else {
-                SECONDARY_LIB_DIR.into()
-            }
-        }
-        Some(libdir) => libdir.into(),
-    }
-}
-
-// The name of rustc's own place to organize libraries.
-// Used to be "rustc", now the default is "rustlib"
-const RUST_LIB_DIR: &str = "rustlib";
diff --git a/compiler/rustc_target/src/lib.rs b/compiler/rustc_target/src/lib.rs
index 67025388747..48ace9b65b6 100644
--- a/compiler/rustc_target/src/lib.rs
+++ b/compiler/rustc_target/src/lib.rs
@@ -15,6 +15,8 @@
 #![feature(associated_type_bounds)]
 #![feature(exhaustive_patterns)]
 
+use std::path::{Path, PathBuf};
+
 #[macro_use]
 extern crate rustc_macros;
 
@@ -29,3 +31,52 @@ pub mod spec;
 /// This is a hack to allow using the `HashStable_Generic` derive macro
 /// instead of implementing everything in `rustc_middle`.
 pub trait HashStableContext {}
+
+/// The name of rustc's own place to organize libraries.
+///
+/// Used to be `rustc`, now the default is `rustlib`.
+const RUST_LIB_DIR: &str = "rustlib";
+
+/// Returns a `rustlib` path for this particular target, relative to the provided sysroot.
+///
+/// For example: `target_sysroot_path("/usr", "x86_64-unknown-linux-gnu")` =>
+/// `"lib*/rustlib/x86_64-unknown-linux-gnu"`.
+pub fn target_rustlib_path(sysroot: &Path, target_triple: &str) -> PathBuf {
+    let libdir = find_libdir(sysroot);
+    std::array::IntoIter::new([
+        Path::new(libdir.as_ref()),
+        Path::new(RUST_LIB_DIR),
+        Path::new(target_triple),
+    ])
+    .collect::<PathBuf>()
+}
+
+/// The name of the directory rustc expects libraries to be located.
+fn find_libdir(sysroot: &Path) -> std::borrow::Cow<'static, str> {
+    // FIXME: This is a quick hack to make the rustc binary able to locate
+    // Rust libraries in Linux environments where libraries might be installed
+    // to lib64/lib32. This would be more foolproof by basing the sysroot off
+    // of the directory where `librustc_driver` is located, rather than
+    // where the rustc binary is.
+    // If --libdir is set during configuration to the value other than
+    // "lib" (i.e., non-default), this value is used (see issue #16552).
+
+    #[cfg(target_pointer_width = "64")]
+    const PRIMARY_LIB_DIR: &str = "lib64";
+
+    #[cfg(target_pointer_width = "32")]
+    const PRIMARY_LIB_DIR: &str = "lib32";
+
+    const SECONDARY_LIB_DIR: &str = "lib";
+
+    match option_env!("CFG_LIBDIR_RELATIVE") {
+        None | Some("lib") => {
+            if sysroot.join(PRIMARY_LIB_DIR).join(RUST_LIB_DIR).exists() {
+                PRIMARY_LIB_DIR.into()
+            } else {
+                SECONDARY_LIB_DIR.into()
+            }
+        }
+        Some(libdir) => libdir.into(),
+    }
+}
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index 27ca6a23a96..4bffd6e8ddd 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -1897,15 +1897,15 @@ impl Target {
         Ok(base)
     }
 
-    /// Search RUST_TARGET_PATH for a JSON file specifying the given target
-    /// triple. If none is found, look for a file called `target.json` inside
-    /// the sysroot under the target-triple's `rustlib` directory.
-    /// Note that it could also just be a bare filename already, so also
-    /// check for that. If one of the hardcoded targets we know about, just
-    /// return it directly.
+    /// Search for a JSON file specifying the given target triple.
     ///
-    /// The error string could come from any of the APIs called, including
-    /// filesystem access and JSON decoding.
+    /// If none is found in `$RUST_TARGET_PATH`, look for a file called `target.json` inside the
+    /// sysroot under the target-triple's `rustlib` directory.  Note that it could also just be a
+    /// bare filename already, so also check for that. If one of the hardcoded targets we know
+    /// about, just return it directly.
+    ///
+    /// The error string could come from any of the APIs called, including filesystem access and
+    /// JSON decoding.
     pub fn search(target_triple: &TargetTriple, sysroot: &PathBuf) -> Result<Target, String> {
         use rustc_serialize::json;
         use std::env;
@@ -1942,8 +1942,13 @@ impl Target {
 
                 // Additionally look in the sysroot under `lib/rustlib/<triple>/target.json`
                 // as a fallback.
-                let p =
-                    sysroot.join("lib").join("rustlib").join(&target_triple).join("target.json");
+                let rustlib_path = crate::target_rustlib_path(&sysroot, &target_triple);
+                let p = std::array::IntoIter::new([
+                    Path::new(sysroot),
+                    Path::new(&rustlib_path),
+                    Path::new("target.json"),
+                ])
+                .collect::<PathBuf>();
                 if p.is_file() {
                     return load_file(&p);
                 }