11//! Implementation of compiling the compiler and standard library, in "check"-based modes.
22
3+ use crate :: core:: build_steps:: check;
34use crate :: core:: build_steps:: compile:: {
45 add_to_sysroot, run_cargo, rustc_cargo, rustc_cargo_env, std_cargo, std_crates_for_run_make,
56} ;
@@ -9,7 +10,7 @@ use crate::core::builder::{
910} ;
1011use crate :: core:: config:: TargetSelection ;
1112use crate :: utils:: build_stamp:: { self , BuildStamp } ;
12- use crate :: { Mode , Subcommand } ;
13+ use crate :: { Compiler , Mode , Subcommand } ;
1314
1415#[ derive( Debug , Clone , PartialEq , Eq , Hash ) ]
1516pub struct Std {
@@ -27,17 +28,25 @@ pub struct Std {
2728 /// passing `Builder::kind` to cargo invocations would run clippy on the entire compiler and library,
2829 /// which is not useful if we only want to lint a few crates with specific rules.
2930 override_build_kind : Option < Kind > ,
31+
32+ override_compiler : Option < Compiler > ,
3033}
3134
3235impl Std {
3336 pub fn new ( target : TargetSelection ) -> Self {
34- Self { target, crates : vec ! [ ] , override_build_kind : None }
37+ Self { target, crates : vec ! [ ] , override_build_kind : None , override_compiler : None }
3538 }
3639
3740 pub fn build_kind ( mut self , kind : Option < Kind > ) -> Self {
3841 self . override_build_kind = kind;
3942 self
4043 }
44+
45+ /// Override the compiler used. Needed when checking tools that use [`Mode::ToolStd`].
46+ pub fn with_compiler ( mut self , compiler : Compiler ) -> Self {
47+ self . override_compiler = Some ( compiler) ;
48+ self
49+ }
4150}
4251
4352impl Step for Std {
@@ -53,14 +62,21 @@ impl Step for Std {
5362
5463 fn make_run ( run : RunConfig < ' _ > ) {
5564 let crates = std_crates_for_run_make ( & run) ;
56- run. builder . ensure ( Std { target : run. target , crates, override_build_kind : None } ) ;
65+ run. builder . ensure ( Std {
66+ target : run. target ,
67+ crates,
68+ override_build_kind : None ,
69+ override_compiler : None ,
70+ } ) ;
5771 }
5872
5973 fn run ( self , builder : & Builder < ' _ > ) {
6074 builder. require_submodule ( "library/stdarch" , None ) ;
6175
6276 let target = self . target ;
63- let compiler = builder. compiler ( builder. top_stage , builder. config . build ) ;
77+ let compiler = self
78+ . override_compiler
79+ . unwrap_or_else ( || builder. compiler ( builder. top_stage , builder. config . build ) ) ;
6480
6581 let mut cargo = builder:: Cargo :: new (
6682 builder,
@@ -375,6 +391,8 @@ macro_rules! tool_check_step {
375391 // The part of this path after the final '/' is also used as a display name.
376392 path: $path: literal
377393 $( , alt_path: $alt_path: literal ) *
394+ , mode: $mode: path
395+ $( , allow_features: $allow_features: expr ) ?
378396 $( , default : $default: literal ) ?
379397 $( , ) ?
380398 }
@@ -400,7 +418,14 @@ macro_rules! tool_check_step {
400418
401419 fn run( self , builder: & Builder <' _>) {
402420 let Self { target } = self ;
403- run_tool_check_step( builder, target, stringify!( $name) , $path) ;
421+
422+ let allow_features = {
423+ let mut _value = "" ;
424+ $( _value = $allow_features; ) ?
425+ _value
426+ } ;
427+
428+ run_tool_check_step( builder, target, $path, $mode, allow_features) ;
404429 }
405430 }
406431 }
@@ -410,18 +435,38 @@ macro_rules! tool_check_step {
410435fn run_tool_check_step (
411436 builder : & Builder < ' _ > ,
412437 target : TargetSelection ,
413- step_type_name : & str ,
414438 path : & str ,
439+ mode : Mode ,
440+ allow_features : & str ,
415441) {
416442 let display_name = path. rsplit ( '/' ) . next ( ) . unwrap ( ) ;
417- let compiler = builder. compiler ( builder. top_stage , builder. config . build ) ;
418443
419- builder. ensure ( Rustc :: new ( target, builder) ) ;
444+ let host = builder. config . build ;
445+ let compiler;
446+
447+ match mode {
448+ Mode :: ToolBootstrap => {
449+ // Most "bootstrap tools" just need the bootstrap compiler.
450+ compiler = builder. compiler ( 0 , host) ;
451+ }
452+ Mode :: ToolStd => {
453+ // A small number of bootstrap tools also rely on in-tree standard
454+ // library crates (e.g. compiletest needs libtest), so we use the
455+ // bootstrap compiler to do a check build of the standard library.
456+ compiler = builder. compiler ( 0 , host) ;
457+ builder. ensure ( check:: Std :: new ( target) . with_compiler ( compiler) ) ;
458+ }
459+ Mode :: ToolRustc => {
460+ compiler = builder. compiler ( builder. top_stage , host) ;
461+ builder. ensure ( check:: Rustc :: new ( target, builder) ) ;
462+ }
463+ _ => panic ! ( "unexpected mode for tool check step: {mode:?}" ) ,
464+ }
420465
421466 let mut cargo = prepare_tool_cargo (
422467 builder,
423468 compiler,
424- Mode :: ToolRustc ,
469+ mode ,
425470 target,
426471 builder. kind ,
427472 path,
@@ -432,39 +477,62 @@ fn run_tool_check_step(
432477 SourceType :: InTree ,
433478 & [ ] ,
434479 ) ;
480+ cargo. allow_features ( allow_features) ;
435481
436482 // For ./x.py clippy, don't run with --all-targets because
437483 // linting tests and benchmarks can produce very noisy results
438484 if builder. kind != Kind :: Clippy {
439485 cargo. arg ( "--all-targets" ) ;
440486 }
441487
442- let stamp = BuildStamp :: new ( & builder. cargo_out ( compiler, Mode :: ToolRustc , target) )
443- . with_prefix ( & format ! ( "{}-check" , step_type_name . to_lowercase ( ) ) ) ;
488+ let stamp = BuildStamp :: new ( & builder. cargo_out ( compiler, mode , target) )
489+ . with_prefix ( & format ! ( "{display_name }-check" ) ) ;
444490
445- let _guard = builder. msg_check ( format ! ( "{display_name} artifacts" ) , target) ;
491+ let _guard =
492+ builder. msg_tool ( builder. kind , mode, display_name, compiler. stage , & compiler. host , & target) ;
446493 run_cargo ( builder, cargo, builder. config . free_args . clone ( ) , & stamp, vec ! [ ] , true , false ) ;
447494}
448495
449- tool_check_step ! ( Rustdoc { path: "src/tools/rustdoc" , alt_path: "src/librustdoc" } ) ;
496+ // FIXME: Some of these `Mode::ToolRustc` values might be wrong.
497+ // (Historically, all tools were hardcoded to use `Mode::ToolRustc`.)
498+
499+ tool_check_step ! ( Rustdoc {
500+ path: "src/tools/rustdoc" ,
501+ alt_path: "src/librustdoc" ,
502+ mode: Mode :: ToolRustc ,
503+ } ) ;
450504// Clippy, miri and Rustfmt are hybrids. They are external tools, but use a git subtree instead
451505// of a submodule. Since the SourceType only drives the deny-warnings
452506// behavior, treat it as in-tree so that any new warnings in clippy will be
453507// rejected.
454- tool_check_step ! ( Clippy { path: "src/tools/clippy" } ) ;
455- tool_check_step ! ( Miri { path: "src/tools/miri" } ) ;
456- tool_check_step ! ( CargoMiri { path: "src/tools/miri/cargo-miri" } ) ;
457- tool_check_step ! ( Rustfmt { path: "src/tools/rustfmt" } ) ;
458- tool_check_step ! ( MiroptTestTools { path: "src/tools/miropt-test-tools" } ) ;
459- tool_check_step ! ( TestFloatParse { path: "src/etc/test-float-parse" } ) ;
460- tool_check_step ! ( FeaturesStatusDump { path: "src/tools/features-status-dump" } ) ;
461-
462- tool_check_step ! ( Bootstrap { path: "src/bootstrap" , default : false } ) ;
508+ tool_check_step ! ( Clippy { path: "src/tools/clippy" , mode: Mode :: ToolRustc } ) ;
509+ tool_check_step ! ( Miri { path: "src/tools/miri" , mode: Mode :: ToolRustc } ) ;
510+ tool_check_step ! ( CargoMiri { path: "src/tools/miri/cargo-miri" , mode: Mode :: ToolRustc } ) ;
511+ tool_check_step ! ( Rustfmt { path: "src/tools/rustfmt" , mode: Mode :: ToolRustc } ) ;
512+ tool_check_step ! ( MiroptTestTools { path: "src/tools/miropt-test-tools" , mode: Mode :: ToolRustc } ) ;
513+ tool_check_step ! ( TestFloatParse { path: "src/etc/test-float-parse" , mode: Mode :: ToolRustc } ) ;
514+ tool_check_step ! ( FeaturesStatusDump {
515+ path: "src/tools/features-status-dump" ,
516+ mode: Mode :: ToolRustc ,
517+ } ) ;
518+
519+ tool_check_step ! ( Bootstrap { path: "src/bootstrap" , mode: Mode :: ToolBootstrap , default : false } ) ;
463520
464521// `run-make-support` will be built as part of suitable run-make compiletest test steps, but support
465522// check to make it easier to work on.
466- tool_check_step ! ( RunMakeSupport { path: "src/tools/run-make-support" , default : false } ) ;
523+ tool_check_step ! ( RunMakeSupport {
524+ path: "src/tools/run-make-support" ,
525+ mode: Mode :: ToolBootstrap ,
526+ default : false ,
527+ } ) ;
467528
468529// Compiletest is implicitly "checked" when it gets built in order to run tests,
469530// so this is mainly for people working on compiletest to run locally.
470- tool_check_step ! ( Compiletest { path: "src/tools/compiletest" , default : false } ) ;
531+ //
532+ // Compiletest uses libtest internally, so it needs `Mode::ToolStd` and `#![feature(test)]`.
533+ tool_check_step ! ( Compiletest {
534+ path: "src/tools/compiletest" ,
535+ mode: Mode :: ToolStd ,
536+ allow_features: "test" ,
537+ default : false ,
538+ } ) ;
0 commit comments