Skip to content

Commit 92652ed

Browse files
committed
Auto merge of rust-lang#122993 - RalfJung:default-sysroot, r=<try>
give rustc_driver users a chance to overwrite the default sysroot and then use that in Miri. This lets us get rid of an annoying arg-patching hack, and may help with rust-lang/miri#3404. Unfortunately the computation of `real_rust_source_base_dir` depended on knowing the default sysroot, so I had to move that around a bit. I have no idea how all this `Session` and `Options` stuff works so I hope this makes sense.
2 parents fa374a8 + dedcc8b commit 92652ed

File tree

6 files changed

+75
-73
lines changed

6 files changed

+75
-73
lines changed

compiler/rustc_interface/src/tests.rs

-4
Original file line numberDiff line numberDiff line change
@@ -642,10 +642,6 @@ fn test_top_level_options_tracked_no_crate() {
642642

643643
// Make sure that changing a [TRACKED_NO_CRATE_HASH] option leaves the crate hash unchanged but changes the incremental hash.
644644
// tidy-alphabetical-start
645-
tracked!(
646-
real_rust_source_base_dir,
647-
Some("/home/bors/rust/.rustup/toolchains/nightly/lib/rustlib/src/rust".into())
648-
);
649645
tracked!(remap_path_prefix, vec![("/home/bors/rust".into(), "src".into())]);
650646
// tidy-alphabetical-end
651647
}

compiler/rustc_metadata/src/rmeta/decoder.rs

+21-8
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ use rustc_span::{BytePos, Pos, SpanData, SpanDecoder, SyntaxContext, DUMMY_SP};
3030

3131
use proc_macro::bridge::client::ProcMacro;
3232
use std::iter::TrustedLen;
33-
use std::path::Path;
33+
use std::path::{Path, PathBuf};
3434
use std::{io, iter, mem};
3535

3636
pub(super) use cstore_impl::provide;
@@ -1589,10 +1589,14 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
15891589
/// Proc macro crates don't currently export spans, so this function does not have
15901590
/// to work for them.
15911591
fn imported_source_file(self, source_file_index: u32, sess: &Session) -> ImportedSourceFile {
1592-
fn filter<'a>(sess: &Session, path: Option<&'a Path>) -> Option<&'a Path> {
1592+
fn filter<'a>(
1593+
sess: &Session,
1594+
real_rust_source_base_dir: &Option<PathBuf>,
1595+
path: Option<&'a Path>,
1596+
) -> Option<&'a Path> {
15931597
path.filter(|_| {
15941598
// Only spend time on further checks if we have what to translate *to*.
1595-
sess.opts.real_rust_source_base_dir.is_some()
1599+
real_rust_source_base_dir.is_some()
15961600
// Some tests need the translation to be always skipped.
15971601
&& sess.opts.unstable_opts.translate_remapped_path_to_local_path
15981602
})
@@ -1604,25 +1608,34 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
16041608
})
16051609
}
16061610

1611+
let real_rust_source_base_dir = sess.real_rust_source_base_dir();
16071612
let try_to_translate_virtual_to_real = |name: &mut rustc_span::FileName| {
16081613
// Translate the virtual `/rustc/$hash` prefix back to a real directory
16091614
// that should hold actual sources, where possible.
16101615
//
16111616
// NOTE: if you update this, you might need to also update bootstrap's code for generating
16121617
// the `rust-src` component in `Src::run` in `src/bootstrap/dist.rs`.
16131618
let virtual_rust_source_base_dir = [
1614-
filter(sess, option_env!("CFG_VIRTUAL_RUST_SOURCE_BASE_DIR").map(Path::new)),
1615-
filter(sess, sess.opts.unstable_opts.simulate_remapped_rust_src_base.as_deref()),
1619+
filter(
1620+
sess,
1621+
&real_rust_source_base_dir,
1622+
option_env!("CFG_VIRTUAL_RUST_SOURCE_BASE_DIR").map(Path::new),
1623+
),
1624+
filter(
1625+
sess,
1626+
&real_rust_source_base_dir,
1627+
sess.opts.unstable_opts.simulate_remapped_rust_src_base.as_deref(),
1628+
),
16161629
];
16171630

16181631
debug!(
16191632
"try_to_translate_virtual_to_real(name={:?}): \
16201633
virtual_rust_source_base_dir={:?}, real_rust_source_base_dir={:?}",
1621-
name, virtual_rust_source_base_dir, sess.opts.real_rust_source_base_dir,
1634+
name, virtual_rust_source_base_dir, real_rust_source_base_dir,
16221635
);
16231636

16241637
for virtual_dir in virtual_rust_source_base_dir.iter().flatten() {
1625-
if let Some(real_dir) = &sess.opts.real_rust_source_base_dir {
1638+
if let Some(real_dir) = &real_rust_source_base_dir {
16261639
if let rustc_span::FileName::Real(old_name) = name {
16271640
if let rustc_span::RealFileName::Remapped { local_path: _, virtual_name } =
16281641
old_name
@@ -1713,7 +1726,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
17131726
// `try_to_translate_virtual_to_real` don't have to worry about how the
17141727
// compiler is bootstrapped.
17151728
if let Some(virtual_dir) = &sess.opts.unstable_opts.simulate_remapped_rust_src_base
1716-
&& let Some(real_dir) = &sess.opts.real_rust_source_base_dir
1729+
&& let Some(real_dir) = &real_rust_source_base_dir
17171730
&& let rustc_span::FileName::Real(ref mut old_name) = name
17181731
{
17191732
let relative_path = match old_name {

compiler/rustc_session/src/config.rs

+3-25
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ pub use crate::options::*;
88
use crate::errors::FileWriteFail;
99
use crate::search_paths::SearchPath;
1010
use crate::utils::{CanonicalizedPath, NativeLib, NativeLibKind};
11-
use crate::{filesearch, lint, HashStableContext};
11+
use crate::{lint, HashStableContext};
1212
use crate::{EarlyDiagCtxt, Session};
1313
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
1414
use rustc_data_structures::stable_hasher::{StableOrd, ToStableHashKey};
@@ -1066,7 +1066,6 @@ impl Default for Options {
10661066
cli_forced_codegen_units: None,
10671067
cli_forced_local_thinlto_off: false,
10681068
remap_path_prefix: Vec::new(),
1069-
real_rust_source_base_dir: None,
10701069
edition: DEFAULT_EDITION,
10711070
json_artifact_notifications: false,
10721071
json_unused_externs: JsonUnusedExterns::No,
@@ -2780,7 +2779,7 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
27802779

27812780
let cg = cg;
27822781

2783-
let sysroot_opt = matches.opt_str("sysroot").map(|m| PathBuf::from(&m));
2782+
let maybe_sysroot = matches.opt_str("sysroot").map(|m| PathBuf::from(&m));
27842783
let target_triple = parse_target_triple(early_dcx, matches);
27852784
let opt_level = parse_opt_level(early_dcx, matches, &cg);
27862785
// The `-g` and `-C debuginfo` flags specify the same setting, so we want to be able
@@ -2823,26 +2822,6 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
28232822

28242823
let logical_env = parse_logical_env(early_dcx, matches);
28252824

2826-
let sysroot = filesearch::materialize_sysroot(sysroot_opt);
2827-
2828-
let real_rust_source_base_dir = {
2829-
// This is the location used by the `rust-src` `rustup` component.
2830-
let mut candidate = sysroot.join("lib/rustlib/src/rust");
2831-
if let Ok(metadata) = candidate.symlink_metadata() {
2832-
// Replace the symlink rustbuild creates, with its destination.
2833-
// We could try to use `fs::canonicalize` instead, but that might
2834-
// produce unnecessarily verbose path.
2835-
if metadata.file_type().is_symlink() {
2836-
if let Ok(symlink_dest) = std::fs::read_link(&candidate) {
2837-
candidate = symlink_dest;
2838-
}
2839-
}
2840-
}
2841-
2842-
// Only use this directory if it has a file we can expect to always find.
2843-
candidate.join("library/std/src/lib.rs").is_file().then_some(candidate)
2844-
};
2845-
28462825
let working_dir = std::env::current_dir().unwrap_or_else(|e| {
28472826
early_dcx.early_fatal(format!("Current directory is invalid: {e}"));
28482827
});
@@ -2868,7 +2847,7 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
28682847
describe_lints,
28692848
output_types,
28702849
search_paths,
2871-
maybe_sysroot: Some(sysroot),
2850+
maybe_sysroot,
28722851
target_triple,
28732852
test,
28742853
incremental,
@@ -2889,7 +2868,6 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
28892868
cli_forced_codegen_units: codegen_units,
28902869
cli_forced_local_thinlto_off: disable_local_thinlto,
28912870
remap_path_prefix,
2892-
real_rust_source_base_dir,
28932871
edition,
28942872
json_artifact_notifications,
28952873
json_unused_externs,

compiler/rustc_session/src/options.rs

-8
Original file line numberDiff line numberDiff line change
@@ -197,14 +197,6 @@ top_level_options!(
197197

198198
/// Remap source path prefixes in all output (messages, object files, debug, etc.).
199199
remap_path_prefix: Vec<(PathBuf, PathBuf)> [TRACKED_NO_CRATE_HASH],
200-
/// Base directory containing the `src/` for the Rust standard library, and
201-
/// potentially `rustc` as well, if we can find it. Right now it's always
202-
/// `$sysroot/lib/rustlib/src/rust` (i.e. the `rustup` `rust-src` component).
203-
///
204-
/// This directory is what the virtual `/rustc/$hash` is translated back to,
205-
/// if Rust was built with path remapping to `/rustc/$hash` enabled
206-
/// (the `rust.remap-debuginfo` option in `config.toml`).
207-
real_rust_source_base_dir: Option<PathBuf> [TRACKED_NO_CRATE_HASH],
208200

209201
edition: Edition [TRACKED],
210202

compiler/rustc_session/src/session.rs

+26
Original file line numberDiff line numberDiff line change
@@ -616,6 +616,32 @@ impl Session {
616616
.default_hidden_visibility
617617
.unwrap_or(self.target.options.default_hidden_visibility)
618618
}
619+
620+
/// Base directory containing the `src/` for the Rust standard library, and
621+
/// potentially `rustc` as well, if we can find it. Right now it's always
622+
/// `$sysroot/lib/rustlib/src/rust` (i.e. the `rustup` `rust-src` component).
623+
///
624+
/// This directory is what the virtual `/rustc/$hash` is translated back to,
625+
/// if Rust was built with path remapping to `/rustc/$hash` enabled
626+
/// (the `rust.remap-debuginfo` option in `config.toml`).
627+
pub fn real_rust_source_base_dir(&self) -> Option<PathBuf> {
628+
// This is the location used by the `rust-src` `rustup` component.
629+
let sysroot = filesearch::materialize_sysroot(self.opts.maybe_sysroot.clone());
630+
let mut candidate = sysroot.join("lib/rustlib/src/rust");
631+
if let Ok(metadata) = candidate.symlink_metadata() {
632+
// Replace the symlink rustbuild creates, with its destination.
633+
// We could try to use `fs::canonicalize` instead, but that might
634+
// produce an unnecessarily verbose path.
635+
if metadata.file_type().is_symlink() {
636+
if let Ok(symlink_dest) = std::fs::read_link(&candidate) {
637+
candidate = symlink_dest;
638+
}
639+
}
640+
}
641+
642+
// Only use this directory if it has a file we can expect to always find.
643+
candidate.join("library/std/src/lib.rs").is_file().then_some(candidate)
644+
}
619645
}
620646

621647
// JUSTIFICATION: defn of the suggested wrapper fns

src/tools/miri/src/bin/miri.rs

+25-28
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,34 @@ use rustc_session::{CtfeBacktrace, EarlyDiagCtxt};
4545

4646
use miri::{BacktraceStyle, BorrowTrackerMethod, ProvenanceMode, RetagFields};
4747

48+
fn show_error(msg: &impl std::fmt::Display) -> ! {
49+
eprintln!("fatal error: {msg}");
50+
std::process::exit(1)
51+
}
52+
53+
macro_rules! show_error {
54+
($($tt:tt)*) => { show_error(&format_args!($($tt)*)) };
55+
}
56+
4857
struct MiriCompilerCalls {
4958
miri_config: miri::MiriConfig,
5059
}
5160

61+
fn set_default_sysroot_for_target_crate(config: &mut Config) {
62+
if config.opts.maybe_sysroot.is_none() {
63+
// Overwrite the default.
64+
let miri_sysroot = env::var("MIRI_SYSROOT").unwrap_or_else(|_| {
65+
show_error!(
66+
"Miri was invoked in 'target' mode without `MIRI_SYSROOT` or `--sysroot` being set"
67+
)
68+
});
69+
config.opts.maybe_sysroot = Some(PathBuf::from(miri_sysroot));
70+
}
71+
}
72+
5273
impl rustc_driver::Callbacks for MiriCompilerCalls {
5374
fn config(&mut self, config: &mut Config) {
75+
set_default_sysroot_for_target_crate(config);
5476
config.override_queries = Some(|_, providers| {
5577
providers.extern_queries.used_crate_source = |tcx, cnum| {
5678
let mut providers = Providers::default();
@@ -130,6 +152,9 @@ struct MiriBeRustCompilerCalls {
130152
impl rustc_driver::Callbacks for MiriBeRustCompilerCalls {
131153
#[allow(rustc::potential_query_instability)] // rustc_codegen_ssa (where this code is copied from) also allows this lint
132154
fn config(&mut self, config: &mut Config) {
155+
if self.target_crate {
156+
set_default_sysroot_for_target_crate(config);
157+
}
133158
if config.opts.prints.is_empty() && self.target_crate {
134159
// Queries overridden here affect the data stored in `rmeta` files of dependencies,
135160
// which will be used later in non-`MIRI_BE_RUSTC` mode.
@@ -201,15 +226,6 @@ impl rustc_driver::Callbacks for MiriBeRustCompilerCalls {
201226
}
202227
}
203228

204-
fn show_error(msg: &impl std::fmt::Display) -> ! {
205-
eprintln!("fatal error: {msg}");
206-
std::process::exit(1)
207-
}
208-
209-
macro_rules! show_error {
210-
($($tt:tt)*) => { show_error(&format_args!($($tt)*)) };
211-
}
212-
213229
fn rustc_logger_config() -> rustc_log::LoggerConfig {
214230
// Start with the usual env vars.
215231
let mut cfg = rustc_log::LoggerConfig::from_env("RUSTC_LOG");
@@ -271,25 +287,6 @@ fn run_compiler(
271287
callbacks: &mut (dyn rustc_driver::Callbacks + Send),
272288
using_internal_features: std::sync::Arc<std::sync::atomic::AtomicBool>,
273289
) -> ! {
274-
if target_crate {
275-
// Miri needs a custom sysroot for target crates.
276-
// If no `--sysroot` is given, the `MIRI_SYSROOT` env var is consulted to find where
277-
// that sysroot lives, and that is passed to rustc.
278-
let sysroot_flag = "--sysroot";
279-
if !args.iter().any(|e| e == sysroot_flag) {
280-
// Using the built-in default here would be plain wrong, so we *require*
281-
// the env var to make sure things make sense.
282-
let miri_sysroot = env::var("MIRI_SYSROOT").unwrap_or_else(|_| {
283-
show_error!(
284-
"Miri was invoked in 'target' mode without `MIRI_SYSROOT` or `--sysroot` being set"
285-
)
286-
});
287-
288-
args.push(sysroot_flag.to_owned());
289-
args.push(miri_sysroot);
290-
}
291-
}
292-
293290
// Don't insert `MIRI_DEFAULT_ARGS`, in particular, `--cfg=miri`, if we are building
294291
// a "host" crate. That may cause procedural macros (and probably build scripts) to
295292
// depend on Miri-only symbols, such as `miri_resolve_frame`:

0 commit comments

Comments
 (0)