Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions compiler/rustc_error_messages/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ impl From<Vec<FluentError>> for TranslationBundleError {
#[instrument(level = "trace")]
pub fn fluent_bundle(
sysroot: PathBuf,
sysroot_candidates: Vec<PathBuf>,
default_sysroot: PathBuf,
requested_locale: Option<LanguageIdentifier>,
additional_ftl_path: Option<&Path>,
with_directionality_markers: bool,
Expand Down Expand Up @@ -141,7 +141,7 @@ pub fn fluent_bundle(
// If the user requests the default locale then don't try to load anything.
if let Some(requested_locale) = requested_locale {
let mut found_resources = false;
for mut sysroot in Some(sysroot).into_iter().chain(sysroot_candidates.into_iter()) {
for mut sysroot in [sysroot, default_sysroot] {
sysroot.push("share");
sysroot.push("locale");
sysroot.push(requested_locale.to_string());
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_interface/src/interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use rustc_parse::parser::attr::AllowLeadingUnsafe;
use rustc_query_impl::QueryCtxt;
use rustc_query_system::query::print_query_stack;
use rustc_session::config::{self, Cfg, CheckCfg, ExpectedValues, Input, OutFileName};
use rustc_session::filesearch::sysroot_candidates;
use rustc_session::filesearch::get_or_default_sysroot;
use rustc_session::parse::ParseSess;
use rustc_session::{CompilerIO, EarlyDiagCtxt, Session, lint};
use rustc_span::source_map::{FileLoader, RealFileLoader, SourceMapInputs};
Expand Down Expand Up @@ -443,7 +443,7 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se

let bundle = match rustc_errors::fluent_bundle(
config.opts.sysroot.clone(),
sysroot_candidates().to_vec(),
get_or_default_sysroot(),
config.opts.unstable_opts.translate_lang.clone(),
config.opts.unstable_opts.translate_additional_ftl.as_deref(),
config.opts.unstable_opts.translate_directionality_markers,
Expand Down
11 changes: 5 additions & 6 deletions compiler/rustc_interface/src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::env::consts::{DLL_PREFIX, DLL_SUFFIX};
use std::path::{Path, PathBuf};
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Arc, OnceLock};
use std::{env, iter, thread};
use std::{env, thread};

use rustc_ast as ast;
use rustc_codegen_ssa::traits::CodegenBackend;
Expand All @@ -12,7 +12,6 @@ use rustc_metadata::{DylibError, load_symbol_from_dylib};
use rustc_middle::ty::CurrentGcx;
use rustc_parse::validate_attr;
use rustc_session::config::{Cfg, OutFileName, OutputFilenames, OutputTypes, host_tuple};
use rustc_session::filesearch::sysroot_candidates;
use rustc_session::lint::{self, BuiltinLintDiag, LintBuffer};
use rustc_session::output::{CRATE_TYPES, categorize_crate_type};
use rustc_session::{EarlyDiagCtxt, Session, filesearch};
Expand Down Expand Up @@ -346,7 +345,7 @@ pub fn rustc_path<'a>() -> Option<&'a Path> {
}

fn get_rustc_path_inner(bin_path: &str) -> Option<PathBuf> {
sysroot_candidates().iter().find_map(|sysroot| {
Some(filesearch::get_or_default_sysroot()).iter().find_map(|sysroot| {
let candidate = sysroot.join(bin_path).join(if cfg!(target_os = "windows") {
"rustc.exe"
} else {
Expand Down Expand Up @@ -374,10 +373,10 @@ fn get_codegen_sysroot(
);

let target = host_tuple();
let sysroot_candidates = sysroot_candidates();
let sysroot_candidates = filesearch::sysroot_with_fallback(&sysroot);

let sysroot = iter::once(sysroot)
.chain(sysroot_candidates.iter().map(<_>::as_ref))
let sysroot = sysroot_candidates
.iter()
.map(|sysroot| {
filesearch::make_target_lib_path(sysroot, target).with_file_name("codegen-backends")
})
Expand Down
62 changes: 17 additions & 45 deletions compiler/rustc_session/src/filesearch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
use std::path::{Path, PathBuf};
use std::{env, fs};

use rustc_fs_util::{fix_windows_verbatim_for_gcc, try_canonicalize};
use rustc_fs_util::try_canonicalize;
use rustc_target::spec::Target;
use smallvec::{SmallVec, smallvec};

Expand Down Expand Up @@ -87,7 +87,7 @@ fn current_dll_path() -> Result<PathBuf, String> {
};
let bytes = CStr::from_ptr(fname_ptr).to_bytes();
let os = OsStr::from_bytes(bytes);
Ok(PathBuf::from(os))
try_canonicalize(Path::new(os)).map_err(|e| e.to_string())
}

#[cfg(target_os = "aix")]
Expand Down Expand Up @@ -122,7 +122,7 @@ fn current_dll_path() -> Result<PathBuf, String> {
if (data_base..data_end).contains(&addr) {
let bytes = CStr::from_ptr(&(*current).ldinfo_filename[0]).to_bytes();
let os = OsStr::from_bytes(bytes);
return Ok(PathBuf::from(os));
return try_canonicalize(Path::new(os)).map_err(|e| e.to_string());
}
if (*current).ldinfo_next == 0 {
break;
Expand Down Expand Up @@ -169,45 +169,26 @@ fn current_dll_path() -> Result<PathBuf, String> {

filename.truncate(n);

Ok(OsString::from_wide(&filename).into())
let path = try_canonicalize(OsString::from_wide(&filename)).map_err(|e| e.to_string())?;

// 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(rustc_fs_util::fix_windows_verbatim_for_gcc(&path))
}

#[cfg(target_os = "wasi")]
fn current_dll_path() -> Result<PathBuf, String> {
Err("current_dll_path is not supported on WASI".to_string())
}

pub fn sysroot_candidates() -> SmallVec<[PathBuf; 2]> {
let target = crate::config::host_tuple();
let mut sysroot_candidates: SmallVec<[PathBuf; 2]> = smallvec![get_or_default_sysroot()];
let path = current_dll_path().and_then(|s| try_canonicalize(s).map_err(|e| e.to_string()));
if let Ok(dll) = path {
// use `parent` twice to chop off the file name and then also the
// directory containing the dll which should be either `lib` or `bin`.
if let Some(path) = dll.parent().and_then(|p| p.parent()) {
// The original `path` pointed at the `rustc_driver` crate's dll.
// Now that dll should only be in one of two locations. The first is
// in the compiler's libdir, for example `$sysroot/lib/*.dll`. The
// other is the target's libdir, for example
// `$sysroot/lib/rustlib/$target/lib/*.dll`.
//
// We don't know which, so let's assume that if our `path` above
// ends in `$target` we *could* be in the target libdir, and always
// assume that we may be in the main libdir.
sysroot_candidates.push(path.to_owned());

if path.ends_with(target) {
sysroot_candidates.extend(
path.parent() // chop off `$target`
.and_then(|p| p.parent()) // chop off `rustlib`
.and_then(|p| p.parent()) // chop off `lib`
.map(|s| s.to_owned()),
);
}
}
pub fn sysroot_with_fallback(sysroot: &Path) -> SmallVec<[PathBuf; 2]> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an improvement, but it still feels a bit sub-optimal.
The passed sysroot here can only be --sysroot or get_or_default_sysroot(), so perhaps it makes sense to make a structure like

struct Sysroot {
  explicit: Option<PathBuf>,
  default: PathBuf,
}

with two methods for accessing either the main path or both, and then pass that structure around.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Session only stores the result of materialize_sysroot(), which does maybe_sysroot.unwrap_or_else(|| get_or_default_sysroot()).

let mut candidates = smallvec![sysroot.to_owned()];
let default_sysroot = get_or_default_sysroot();
if default_sysroot != sysroot {
candidates.push(default_sysroot);
}

sysroot_candidates
candidates
}

/// Returns the provided sysroot or calls [`get_or_default_sysroot`] if it's none.
Expand All @@ -219,17 +200,8 @@ pub fn materialize_sysroot(maybe_sysroot: Option<PathBuf>) -> PathBuf {
/// This function checks if sysroot is found using env::args().next(), and if it
/// is not found, finds sysroot from current rustc_driver dll.
pub fn get_or_default_sysroot() -> PathBuf {
// Follow symlinks. If the resolved path is relative, make it absolute.
fn canonicalize(path: PathBuf) -> PathBuf {
let path = try_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)
}

fn default_from_rustc_driver_dll() -> Result<PathBuf, String> {
let dll = current_dll_path().map(|s| canonicalize(s))?;
let dll = current_dll_path()?;

// `dll` will be in one of the following two:
// - compiler's libdir: $sysroot/lib/*.dll
Expand All @@ -242,7 +214,7 @@ pub fn get_or_default_sysroot() -> PathBuf {
dll.display()
))?;

// if `dir` points target's dir, move up to the sysroot
// if `dir` points to target's dir, move up to the sysroot
let mut sysroot_dir = if dir.ends_with(crate::config::host_tuple()) {
dir.parent() // chop off `$target`
.and_then(|p| p.parent()) // chop off `rustlib`
Expand Down
6 changes: 1 addition & 5 deletions compiler/rustc_session/src/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -458,13 +458,9 @@ impl Session {
/// directories are also returned, for example if `--sysroot` is used but tools are missing
/// (#125246): we also add the bin directories to the sysroot where rustc is located.
pub fn get_tools_search_paths(&self, self_contained: bool) -> Vec<PathBuf> {
let bin_path = filesearch::make_target_bin_path(&self.sysroot, config::host_tuple());
let fallback_sysroot_paths = filesearch::sysroot_candidates()
let search_paths = filesearch::sysroot_with_fallback(&self.sysroot)
.into_iter()
// Ignore sysroot candidate if it was the same as the sysroot path we just used.
.filter(|sysroot| *sysroot != self.sysroot)
.map(|sysroot| filesearch::make_target_bin_path(&sysroot, config::host_tuple()));
let search_paths = std::iter::once(bin_path).chain(fallback_sysroot_paths);

if self_contained {
// The self-contained tools are expected to be e.g. in `bin/self-contained` in the
Expand Down
Loading