Skip to content

Commit 5a70908

Browse files
committed
rustc_target: Add TargetOption.check_environment
This function gets called after a Target is created, and can be used to verify that the environment is suitable for building for a given target. E.g. it's a place to check for environment variables, executables in the path, libraries required for linking, and so on. If the check fails, the user gets a simple error message instead of a backtrace culminating in a message to file a bug against the Rust team.
1 parent ac91805 commit 5a70908

File tree

6 files changed

+63
-7
lines changed

6 files changed

+63
-7
lines changed

Diff for: compiler/rustc_driver_impl/src/lib.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ pub fn run_compiler(at_args: &[String], callbacks: &mut (dyn Callbacks + Send))
271271

272272
let registered_lints = config.register_lints.is_some();
273273

274-
interface::run_compiler(config, |compiler| {
274+
if let Err(error_msg) = interface::run_compiler(config, |compiler| {
275275
let sess = &compiler.sess;
276276
let codegen_backend = &*compiler.codegen_backend;
277277

@@ -379,7 +379,9 @@ pub fn run_compiler(at_args: &[String], callbacks: &mut (dyn Callbacks + Send))
379379
if let Some(linker) = linker {
380380
linker.link(sess, codegen_backend);
381381
}
382-
})
382+
}) {
383+
eprintln!("Error: {error_msg}");
384+
}
383385
}
384386

385387
fn dump_feature_usage_metrics(tcxt: TyCtxt<'_>, metrics_dir: &Path) {

Diff for: compiler/rustc_interface/src/interface.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,10 @@ pub(crate) fn initialize_checked_jobserver(early_dcx: &EarlyDiagCtxt) {
378378

379379
// JUSTIFICATION: before session exists, only config
380380
#[allow(rustc::bad_opt_access)]
381-
pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Send) -> R {
381+
pub fn run_compiler<R: Send>(
382+
config: Config,
383+
f: impl FnOnce(&Compiler) -> R + Send,
384+
) -> result::Result<R, String> {
382385
trace!("run_compiler");
383386

384387
// Set parallel mode before thread pool creation, which will create `Lock`s.
@@ -392,12 +395,13 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
392395

393396
let sysroot = filesearch::materialize_sysroot(config.opts.maybe_sysroot.clone());
394397
let target = config::build_target_config(&early_dcx, &config.opts.target_triple, &sysroot);
398+
target.options.check_environment()?;
395399
let file_loader = config.file_loader.unwrap_or_else(|| Box::new(RealFileLoader));
396400
let path_mapping = config.opts.file_path_mapping();
397401
let hash_kind = config.opts.unstable_opts.src_hash_algorithm(&target);
398402
let checksum_hash_kind = config.opts.unstable_opts.checksum_hash_algorithm();
399403

400-
util::run_in_thread_pool_with_globals(
404+
Ok(util::run_in_thread_pool_with_globals(
401405
&early_dcx,
402406
config.opts.edition,
403407
config.opts.unstable_opts.threads,
@@ -537,7 +541,7 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
537541

538542
res
539543
},
540-
)
544+
))
541545
}
542546

543547
pub fn try_print_query_stack(

Diff for: compiler/rustc_target/src/spec/json.rs

+11
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,15 @@ impl Target {
261261
Some(Ok(()))
262262
})).unwrap_or(Ok(()))
263263
} );
264+
($key_name:ident, CheckEnvironment) => ( {
265+
obj.remove("check-environment").and_then(|o| o.as_str().and_then(|s| {
266+
match s.parse::<super::CheckEnvironment>() {
267+
Ok(support) => base.check_environment = support,
268+
_ => return Some(Err(format!("'{s}' is not a valid value for check-environment."))),
269+
}
270+
Some(Ok(()))
271+
})).unwrap_or(Ok(()))
272+
} );
264273
($key_name:ident, list) => ( {
265274
let name = (stringify!($key_name)).replace("_", "-");
266275
if let Some(j) = obj.remove(&name) {
@@ -655,6 +664,7 @@ impl Target {
655664
key!(entry_name);
656665
key!(entry_abi, Conv)?;
657666
key!(supports_xray, bool);
667+
key!(check_environment, CheckEnvironment)?;
658668

659669
base.update_from_cli();
660670
base.check_consistency(TargetKind::Json)?;
@@ -834,6 +844,7 @@ impl ToJson for Target {
834844
target_option_val!(entry_name);
835845
target_option_val!(entry_abi);
836846
target_option_val!(supports_xray);
847+
target_option_val!(check_environment);
837848

838849
// Serializing `-Clink-self-contained` needs a dynamic key to support the
839850
// backwards-compatible variants.

Diff for: compiler/rustc_target/src/spec/mod.rs

+36
Original file line numberDiff line numberDiff line change
@@ -933,6 +933,27 @@ impl ToJson for SmallDataThresholdSupport {
933933
}
934934
}
935935

936+
#[derive(Clone, Debug, PartialEq, Hash)]
937+
pub enum CheckEnvironment {
938+
None,
939+
}
940+
941+
impl FromStr for CheckEnvironment {
942+
type Err = ();
943+
944+
fn from_str(s: &str) -> Result<Self, Self::Err> {
945+
if s == "none" { Ok(Self::None) } else { Err(()) }
946+
}
947+
}
948+
949+
impl ToJson for CheckEnvironment {
950+
fn to_json(&self) -> Value {
951+
match self {
952+
Self::None => "none".to_json(),
953+
}
954+
}
955+
}
956+
936957
#[derive(Clone, Copy, Debug, PartialEq, Hash)]
937958
pub enum MergeFunctions {
938959
Disabled,
@@ -2657,6 +2678,14 @@ pub struct TargetOptions {
26572678

26582679
/// Whether the targets supports -Z small-data-threshold
26592680
small_data_threshold_support: SmallDataThresholdSupport,
2681+
2682+
/// Function to check that the environment is correct for compiling for this
2683+
/// target. E.g. it can check that environment variables are set, that the
2684+
/// right linker is available, that the right libraries are available, and
2685+
/// so on.
2686+
/// We don't put the function in here directly because this structure can be
2687+
/// converted to/from json and functions can't do that.
2688+
pub check_environment: CheckEnvironment,
26602689
}
26612690

26622691
/// Add arguments for the given flavor and also for its "twin" flavors
@@ -2759,6 +2788,12 @@ impl TargetOptions {
27592788
.collect();
27602789
}
27612790
}
2791+
2792+
pub fn check_environment(&self) -> Result<(), String> {
2793+
match self.check_environment {
2794+
CheckEnvironment::None => Ok(()),
2795+
}
2796+
}
27622797
}
27632798

27642799
impl Default for TargetOptions {
@@ -2884,6 +2919,7 @@ impl Default for TargetOptions {
28842919
entry_abi: Conv::C,
28852920
supports_xray: false,
28862921
small_data_threshold_support: SmallDataThresholdSupport::DefaultForArch,
2922+
check_environment: CheckEnvironment::None,
28872923
}
28882924
}
28892925
}

Diff for: src/librustdoc/doctest.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,8 @@ pub(crate) fn run(dcx: DiagCtxtHandle<'_>, input: Input, options: RustdocOptions
248248
compiler.sess.dcx().abort_if_errors();
249249

250250
collector
251-
});
251+
})
252+
.unwrap();
252253

253254
let CreateRunnableDocTests {
254255
standalone_tests,

Diff for: src/librustdoc/lib.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -834,7 +834,8 @@ fn main_args(early_dcx: &mut EarlyDiagCtxt, at_args: &[String]) {
834834
dcx,
835835
interface::run_compiler(config, |_compiler| {
836836
markdown::render_and_write(&md_input, render_options, edition)
837-
}),
837+
})
838+
.unwrap(),
838839
);
839840
}
840841
(false, None) => {}
@@ -908,4 +909,5 @@ fn main_args(early_dcx: &mut EarlyDiagCtxt, at_args: &[String]) {
908909
}
909910
})
910911
})
912+
.unwrap()
911913
}

0 commit comments

Comments
 (0)