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 < ' _ > ) {
@@ -56,9 +64,9 @@ impl Step for Std {
5664 return ;
5765 }
5866
59- let stage = builder. top_stage ;
67+ let build_compiler = self . build_compiler ;
68+ let stage = build_compiler. stage ;
6069 let target = self . target ;
61- let build_compiler = builder. compiler ( stage, builder. config . host_target ) ;
6270
6371 let mut cargo = builder:: Cargo :: new (
6472 builder,
@@ -69,7 +77,7 @@ impl Step for Std {
6977 Kind :: Check ,
7078 ) ;
7179
72- std_cargo ( builder, target, build_compiler . stage , & mut cargo) ;
80+ std_cargo ( builder, target, stage, & mut cargo) ;
7381 if matches ! ( builder. config. cmd, Subcommand :: Fix ) {
7482 // By default, cargo tries to fix all targets. Tell it not to fix tests until we've added `test` to the sysroot.
7583 cargo. arg ( "--lib" ) ;
@@ -130,8 +138,17 @@ impl Step for Std {
130138 }
131139}
132140
141+ fn default_compiler_for_checking_rustc ( builder : & Builder < ' _ > ) -> Compiler {
142+ // When checking the stage N compiler, we want to do it with the stage N-1 compiler,
143+ builder. compiler ( builder. top_stage - 1 , builder. config . host_target )
144+ }
145+
146+ /// Checks rustc using `build_compiler` and copies the built
147+ /// .rmeta files into the sysroot of `build_copoiler`.
133148#[ derive( Debug , Clone , PartialEq , Eq , Hash ) ]
134149pub struct Rustc {
150+ /// Compiler that will check this rustc.
151+ pub build_compiler : Compiler ,
135152 pub target : TargetSelection ,
136153 /// Whether to build only a subset of crates.
137154 ///
@@ -142,13 +159,13 @@ pub struct Rustc {
142159}
143160
144161impl Rustc {
145- pub fn new ( target : TargetSelection , builder : & Builder < ' _ > ) -> Self {
162+ pub fn new ( builder : & Builder < ' _ > , build_compiler : Compiler , target : TargetSelection ) -> Self {
146163 let crates = builder
147164 . in_tree_crates ( "rustc-main" , Some ( target) )
148165 . into_iter ( )
149166 . map ( |krate| krate. name . to_string ( ) )
150167 . collect ( ) ;
151- Self { target, crates }
168+ Self { build_compiler , target, crates }
152169 }
153170}
154171
@@ -163,40 +180,46 @@ impl Step for Rustc {
163180
164181 fn make_run ( run : RunConfig < ' _ > ) {
165182 let crates = run. make_run_crates ( Alias :: Compiler ) ;
166- run. builder . ensure ( Rustc { target : run. target , crates } ) ;
183+ run. builder . ensure ( Rustc {
184+ target : run. target ,
185+ build_compiler : default_compiler_for_checking_rustc ( run. builder ) ,
186+ crates,
187+ } ) ;
167188 }
168189
169- /// Builds the compiler.
190+ /// Check the compiler.
170191 ///
171- /// This will build the compiler for a particular stage of the build using
192+ /// This will check the compiler for a particular stage of the build using
172193 /// the `compiler` targeting the `target` architecture. The artifacts
173194 /// created will also be linked into the sysroot directory.
174195 fn run ( self , builder : & Builder < ' _ > ) {
175- let compiler = builder. compiler ( builder. top_stage , builder. config . host_target ) ;
196+ if builder. top_stage < 2 && builder. config . host_target != self . target {
197+ eprintln ! ( "Cannot do a cross-compilation check on stage 1, use stage 2" ) ;
198+ exit ! ( 1 ) ;
199+ }
200+
201+ let build_compiler = self . build_compiler ;
176202 let target = self . target ;
177203
178- if compiler. stage != 0 {
179- // If we're not in stage 0, then we won't have a std from the beta
180- // compiler around. That means we need to make sure there's one in
181- // the sysroot for the compiler to find. Otherwise, we're going to
182- // fail when building crates that need to generate code (e.g., build
183- // scripts and their dependencies).
184- builder. std ( compiler, compiler. host ) ;
185- builder. std ( compiler, target) ;
186- } else {
187- builder. ensure ( Std :: new ( target) ) ;
188- }
204+ // Build host std for compiling build scripts
205+ builder. std ( build_compiler, build_compiler. host ) ;
206+
207+ // Build target std so that the checked rustc can link to it during the check
208+ // FIXME: maybe we can a way to only do a check of std here?
209+ // But for that we would have to copy the stdlib rmetas to the sysroot of the build
210+ // compiler, which conflicts with std rlibs, if we also build std.
211+ builder. std ( build_compiler, target) ;
189212
190213 let mut cargo = builder:: Cargo :: new (
191214 builder,
192- compiler ,
215+ build_compiler ,
193216 Mode :: Rustc ,
194217 SourceType :: InTree ,
195218 target,
196219 Kind :: Check ,
197220 ) ;
198221
199- rustc_cargo ( builder, & mut cargo, target, & compiler , & self . crates ) ;
222+ rustc_cargo ( builder, & mut cargo, target, & build_compiler , & self . crates ) ;
200223
201224 // Explicitly pass -p for all compiler crates -- this will force cargo
202225 // to also check the tests/benches/examples for these crates, rather
@@ -211,12 +234,13 @@ impl Step for Rustc {
211234 None ,
212235 ) ;
213236
214- let stamp = build_stamp:: librustc_stamp ( builder, compiler, target) . with_prefix ( "check" ) ;
237+ let stamp =
238+ build_stamp:: librustc_stamp ( builder, build_compiler, target) . with_prefix ( "check" ) ;
215239
216240 run_cargo ( builder, cargo, builder. config . free_args . clone ( ) , & stamp, vec ! [ ] , true , false ) ;
217241
218- let libdir = builder. sysroot_target_libdir ( compiler , target) ;
219- let hostdir = builder. sysroot_target_libdir ( compiler , compiler . host ) ;
242+ let libdir = builder. sysroot_target_libdir ( build_compiler , target) ;
243+ let hostdir = builder. sysroot_target_libdir ( build_compiler , build_compiler . host ) ;
220244 add_to_sysroot ( builder, & libdir, & hostdir, & stamp) ;
221245 }
222246
@@ -454,7 +478,7 @@ fn run_tool_check_step(
454478 let display_name = path. rsplit ( '/' ) . next ( ) . unwrap ( ) ;
455479 let compiler = builder. compiler ( builder. top_stage , builder. config . host_target ) ;
456480
457- builder. ensure ( Rustc :: new ( target , builder ) ) ;
481+ builder. ensure ( Rustc :: new ( builder , compiler , target ) ) ;
458482
459483 let mut cargo = prepare_tool_cargo (
460484 builder,
0 commit comments