From b7c5599d22018ab6be88442c4668bc1697f85b8e Mon Sep 17 00:00:00 2001 From: Simonas Kazlauskas Date: Mon, 10 May 2021 19:15:19 +0300 Subject: [PATCH] Adjust target search algorithm for rustlib path With this the concerns expressed in #83800 should be addressed. --- compiler/rustc_codegen_ssa/src/back/link.rs | 2 +- compiler/rustc_interface/src/util.rs | 3 +- compiler/rustc_session/src/filesearch.rs | 68 +++++---------------- compiler/rustc_target/src/lib.rs | 51 ++++++++++++++++ compiler/rustc_target/src/spec/mod.rs | 25 +++++--- 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 59f66c55572af..30a56badeb52e 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 59488fc80a5e2..fd29053433e55 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 2df326628e787..6fe6a555f1af8 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 { - 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::(); 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::() } // 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 6702538874705..48ace9b65b678 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::() +} + +/// 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 27ca6a23a96bc..4bffd6e8ddd35 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 { use rustc_serialize::json; use std::env; @@ -1942,8 +1942,13 @@ impl Target { // Additionally look in the sysroot under `lib/rustlib//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::(); if p.is_file() { return load_file(&p); }