11//! Implementation of compiling the compiler and standard library, in "check"-based modes.
22
3+ use build_helper:: exit;
4+
35use crate :: core:: build_steps:: compile:: {
46 add_to_sysroot, run_cargo, rustc_cargo, rustc_cargo_env, std_cargo, std_crates_for_run_make,
57} ;
@@ -9,10 +11,12 @@ use crate::core::builder::{
911} ;
1012use crate :: core:: config:: TargetSelection ;
1113use crate :: utils:: build_stamp:: { self , BuildStamp } ;
12- use crate :: { Mode , Subcommand } ;
14+ use crate :: { Compiler , Mode , Subcommand } ;
1315
1416#[ derive( Debug , Clone , PartialEq , Eq , Hash ) ]
1517pub struct Std {
18+ /// Compiler that will check this std.
19+ pub build_compiler : Compiler ,
1620 pub target : TargetSelection ,
1721 /// Whether to build only a subset of crates.
1822 ///
@@ -25,8 +29,8 @@ pub struct Std {
2529impl Std {
2630 const CRATE_OR_DEPS : & [ & str ] = & [ "sysroot" , "coretests" , "alloctests" ] ;
2731
28- pub fn new ( target : TargetSelection ) -> Self {
29- Self { target, crates : vec ! [ ] }
32+ pub fn new ( build_compiler : Compiler , target : TargetSelection ) -> Self {
33+ Self { build_compiler , target, crates : vec ! [ ] }
3034 }
3135}
3236
@@ -45,7 +49,11 @@ impl Step for Std {
4549
4650 fn make_run ( run : RunConfig < ' _ > ) {
4751 let crates = std_crates_for_run_make ( & run) ;
48- run. builder . ensure ( Std { target : run. target , crates } ) ;
52+ run. builder . ensure ( Std {
53+ build_compiler : run. builder . compiler ( run. builder . top_stage , run. target ) ,
54+ target : run. target ,
55+ crates,
56+ } ) ;
4957 }
5058
5159 fn run ( self , builder : & Builder < ' _ > ) {
@@ -58,9 +66,9 @@ impl Step for Std {
5866
5967 builder. require_submodule ( "library/stdarch" , None ) ;
6068
61- let stage = builder. top_stage ;
69+ let build_compiler = self . build_compiler ;
70+ let stage = build_compiler. stage ;
6271 let target = self . target ;
63- let build_compiler = builder. compiler ( stage, builder. config . host_target ) ;
6472
6573 let mut cargo = builder:: Cargo :: new (
6674 builder,
@@ -71,7 +79,7 @@ impl Step for Std {
7179 Kind :: Check ,
7280 ) ;
7381
74- std_cargo ( builder, target, build_compiler . stage , & mut cargo) ;
82+ std_cargo ( builder, target, stage, & mut cargo) ;
7583 if matches ! ( builder. config. cmd, Subcommand :: Fix ) {
7684 // By default, cargo tries to fix all targets. Tell it not to fix tests until we've added `test` to the sysroot.
7785 cargo. arg ( "--lib" ) ;
@@ -132,8 +140,17 @@ impl Step for Std {
132140 }
133141}
134142
143+ fn default_compiler_for_checking_rustc ( builder : & Builder < ' _ > ) -> Compiler {
144+ // When checking the stage N compiler, we want to do it with the stage N-1 compiler,
145+ builder. compiler ( builder. top_stage - 1 , builder. config . host_target )
146+ }
147+
148+ /// Checks rustc using `build_compiler` and copies the built
149+ /// .rmeta files into the sysroot of `build_copoiler`.
135150#[ derive( Debug , Clone , PartialEq , Eq , Hash ) ]
136151pub struct Rustc {
152+ /// Compiler that will check this rustc.
153+ pub build_compiler : Compiler ,
137154 pub target : TargetSelection ,
138155 /// Whether to build only a subset of crates.
139156 ///
@@ -144,13 +161,13 @@ pub struct Rustc {
144161}
145162
146163impl Rustc {
147- pub fn new ( target : TargetSelection , builder : & Builder < ' _ > ) -> Self {
164+ pub fn new ( builder : & Builder < ' _ > , build_compiler : Compiler , target : TargetSelection ) -> Self {
148165 let crates = builder
149166 . in_tree_crates ( "rustc-main" , Some ( target) )
150167 . into_iter ( )
151168 . map ( |krate| krate. name . to_string ( ) )
152169 . collect ( ) ;
153- Self { target, crates }
170+ Self { build_compiler , target, crates }
154171 }
155172}
156173
@@ -165,40 +182,46 @@ impl Step for Rustc {
165182
166183 fn make_run ( run : RunConfig < ' _ > ) {
167184 let crates = run. make_run_crates ( Alias :: Compiler ) ;
168- run. builder . ensure ( Rustc { target : run. target , crates } ) ;
185+ run. builder . ensure ( Rustc {
186+ target : run. target ,
187+ build_compiler : default_compiler_for_checking_rustc ( run. builder ) ,
188+ crates,
189+ } ) ;
169190 }
170191
171- /// Builds the compiler.
192+ /// Check the compiler.
172193 ///
173- /// This will build the compiler for a particular stage of the build using
194+ /// This will check the compiler for a particular stage of the build using
174195 /// the `compiler` targeting the `target` architecture. The artifacts
175196 /// created will also be linked into the sysroot directory.
176197 fn run ( self , builder : & Builder < ' _ > ) {
177- let compiler = builder. compiler ( builder. top_stage , builder. config . host_target ) ;
198+ if builder. top_stage < 2 && builder. config . host_target != self . target {
199+ eprintln ! ( "Cannot do a cross-compilation check on stage 1, use stage 2" ) ;
200+ exit ! ( 1 ) ;
201+ }
202+
203+ let build_compiler = self . build_compiler ;
178204 let target = self . target ;
179205
180- if compiler. stage != 0 {
181- // If we're not in stage 0, then we won't have a std from the beta
182- // compiler around. That means we need to make sure there's one in
183- // the sysroot for the compiler to find. Otherwise, we're going to
184- // fail when building crates that need to generate code (e.g., build
185- // scripts and their dependencies).
186- builder. std ( compiler, compiler. host ) ;
187- builder. std ( compiler, target) ;
188- } else {
189- builder. ensure ( Std :: new ( target) ) ;
190- }
206+ // Build host std for compiling build scripts
207+ builder. std ( build_compiler, build_compiler. host ) ;
208+
209+ // Build target std so that the checked rustc can link to it during the check
210+ // FIXME: maybe we can a way to only do a check of std here?
211+ // But for that we would have to copy the stdlib rmetas to the sysroot of the build
212+ // compiler, which conflicts with std rlibs, if we also build std.
213+ builder. std ( build_compiler, target) ;
191214
192215 let mut cargo = builder:: Cargo :: new (
193216 builder,
194- compiler ,
217+ build_compiler ,
195218 Mode :: Rustc ,
196219 SourceType :: InTree ,
197220 target,
198221 Kind :: Check ,
199222 ) ;
200223
201- rustc_cargo ( builder, & mut cargo, target, & compiler , & self . crates ) ;
224+ rustc_cargo ( builder, & mut cargo, target, & build_compiler , & self . crates ) ;
202225
203226 // Explicitly pass -p for all compiler crates -- this will force cargo
204227 // to also check the tests/benches/examples for these crates, rather
@@ -213,12 +236,13 @@ impl Step for Rustc {
213236 None ,
214237 ) ;
215238
216- let stamp = build_stamp:: librustc_stamp ( builder, compiler, target) . with_prefix ( "check" ) ;
239+ let stamp =
240+ build_stamp:: librustc_stamp ( builder, build_compiler, target) . with_prefix ( "check" ) ;
217241
218242 run_cargo ( builder, cargo, builder. config . free_args . clone ( ) , & stamp, vec ! [ ] , true , false ) ;
219243
220- let libdir = builder. sysroot_target_libdir ( compiler , target) ;
221- let hostdir = builder. sysroot_target_libdir ( compiler , compiler . host ) ;
244+ let libdir = builder. sysroot_target_libdir ( build_compiler , target) ;
245+ let hostdir = builder. sysroot_target_libdir ( build_compiler , build_compiler . host ) ;
222246 add_to_sysroot ( builder, & libdir, & hostdir, & stamp) ;
223247 }
224248
@@ -456,7 +480,7 @@ fn run_tool_check_step(
456480 let display_name = path. rsplit ( '/' ) . next ( ) . unwrap ( ) ;
457481 let compiler = builder. compiler ( builder. top_stage , builder. config . host_target ) ;
458482
459- builder. ensure ( Rustc :: new ( target , builder ) ) ;
483+ builder. ensure ( Rustc :: new ( builder , compiler , target ) ) ;
460484
461485 let mut cargo = prepare_tool_cargo (
462486 builder,
0 commit comments