Skip to content

Replace all uses of sysroot_candidates with get_or_default_sysroot #142089

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jun 9, 2025
Merged
Show file tree
Hide file tree
Changes from all 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
1 change: 1 addition & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3640,6 +3640,7 @@ dependencies = [
"rustc_macros",
"rustc_serialize",
"rustc_span",
"smallvec",
"tracing",
"unic-langid",
]
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_error_messages/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ rustc_data_structures = { path = "../rustc_data_structures" }
rustc_macros = { path = "../rustc_macros" }
rustc_serialize = { path = "../rustc_serialize" }
rustc_span = { path = "../rustc_span" }
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
tracing = "0.1"
unic-langid = { version = "0.9.0", features = ["macros"] }
# tidy-alphabetical-end
6 changes: 3 additions & 3 deletions compiler/rustc_error_messages/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use intl_memoizer::concurrent::IntlLangMemoizer;
use rustc_data_structures::sync::IntoDynSyncSend;
use rustc_macros::{Decodable, Encodable};
use rustc_span::Span;
use smallvec::SmallVec;
use tracing::{instrument, trace};
pub use unic_langid::{LanguageIdentifier, langid};

Expand Down Expand Up @@ -106,8 +107,7 @@ impl From<Vec<FluentError>> for TranslationBundleError {
/// (overriding any conflicting messages).
#[instrument(level = "trace")]
pub fn fluent_bundle(
sysroot: PathBuf,
sysroot_candidates: Vec<PathBuf>,
sysroot_candidates: SmallVec<[PathBuf; 2]>,
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_candidates {
sysroot.push("share");
sysroot.push("locale");
sysroot.push(requested_locale.to_string());
Expand Down
5 changes: 2 additions & 3 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::sysroot_with_fallback;
use rustc_session::parse::ParseSess;
use rustc_session::{CompilerIO, EarlyDiagCtxt, Session, lint};
use rustc_span::source_map::{FileLoader, RealFileLoader, SourceMapInputs};
Expand Down Expand Up @@ -442,8 +442,7 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
let temps_dir = config.opts.unstable_opts.temps_dir.as_deref().map(PathBuf::from);

let bundle = match rustc_errors::fluent_bundle(
config.opts.sysroot.clone(),
sysroot_candidates().to_vec(),
sysroot_with_fallback(&config.opts.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
21 changes: 8 additions & 13 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,14 +345,10 @@ pub fn rustc_path<'a>() -> Option<&'a Path> {
}

fn get_rustc_path_inner(bin_path: &str) -> Option<PathBuf> {
sysroot_candidates().iter().find_map(|sysroot| {
let candidate = sysroot.join(bin_path).join(if cfg!(target_os = "windows") {
"rustc.exe"
} else {
"rustc"
});
candidate.exists().then_some(candidate)
})
let candidate = filesearch::get_or_default_sysroot()
.join(bin_path)
.join(if cfg!(target_os = "windows") { "rustc.exe" } else { "rustc" });
candidate.exists().then_some(candidate)
}

#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
Expand All @@ -374,10 +369,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