11//! Implementation of compiling the compiler and standard library, in "check"-based modes.
22
33use std:: fs;
4- use std:: path:: PathBuf ;
4+ use std:: path:: { Path , PathBuf } ;
55
66use crate :: core:: build_steps:: compile:: {
77 add_to_sysroot, run_cargo, rustc_cargo, rustc_cargo_env, std_cargo, std_crates_for_run_make,
@@ -36,7 +36,7 @@ impl Std {
3636}
3737
3838impl Step for Std {
39- type Output = ( ) ;
39+ type Output = BuildStamp ;
4040 const DEFAULT : bool = true ;
4141
4242 fn should_run ( run : ShouldRun < ' _ > ) -> ShouldRun < ' _ > {
@@ -70,7 +70,7 @@ impl Step for Std {
7070 } ) ;
7171 }
7272
73- fn run ( self , builder : & Builder < ' _ > ) {
73+ fn run ( self , builder : & Builder < ' _ > ) -> Self :: Output {
7474 let build_compiler = self . build_compiler ;
7575 let target = self . target ;
7676
@@ -101,14 +101,23 @@ impl Step for Std {
101101 target,
102102 ) ;
103103
104- let stamp = build_stamp:: libstd_stamp ( builder, build_compiler, target) . with_prefix ( "check" ) ;
105- run_cargo ( builder, cargo, builder. config . free_args . clone ( ) , & stamp, vec ! [ ] , true , false ) ;
104+ let check_stamp =
105+ build_stamp:: libstd_stamp ( builder, build_compiler, target) . with_prefix ( "check" ) ;
106+ run_cargo (
107+ builder,
108+ cargo,
109+ builder. config . free_args . clone ( ) ,
110+ & check_stamp,
111+ vec ! [ ] ,
112+ true ,
113+ false ,
114+ ) ;
106115
107116 drop ( _guard) ;
108117
109118 // don't check test dependencies if we haven't built libtest
110119 if !self . crates . iter ( ) . any ( |krate| krate == "test" ) {
111- return ;
120+ return check_stamp ;
112121 }
113122
114123 // Then run cargo again, once we've put the rmeta files for the library
@@ -145,6 +154,7 @@ impl Step for Std {
145154 target,
146155 ) ;
147156 run_cargo ( builder, cargo, builder. config . free_args . clone ( ) , & stamp, vec ! [ ] , true , false ) ;
157+ check_stamp
148158 }
149159
150160 fn metadata ( & self ) -> Option < StepMetadata > {
@@ -156,12 +166,28 @@ impl Step for Std {
156166/// Contains directories with .rmeta files generated by checking rustc for a specific
157167/// target.
158168#[ derive( Debug , Clone , PartialEq , Eq , Hash ) ]
159- struct RustcRmetaSysroot {
169+ struct RmetaSysroot {
160170 host_dir : PathBuf ,
161171 target_dir : PathBuf ,
162172}
163173
164- impl RustcRmetaSysroot {
174+ impl RmetaSysroot {
175+ /// Copy rmeta artifacts from the given `stamp` into a sysroot located at `directory`.
176+ fn from_stamp (
177+ builder : & Builder < ' _ > ,
178+ stamp : BuildStamp ,
179+ target : TargetSelection ,
180+ directory : & Path ,
181+ ) -> Self {
182+ let host_dir = directory. join ( "host" ) ;
183+ let target_dir = directory. join ( target) ;
184+ let _ = fs:: remove_dir_all ( directory) ;
185+ t ! ( fs:: create_dir_all( directory) ) ;
186+ add_to_sysroot ( builder, & target_dir, & host_dir, & stamp) ;
187+
188+ Self { host_dir, target_dir }
189+ }
190+
165191 /// Configure the given cargo invocation so that the compiled crate will be able to use
166192 /// rustc .rmeta artifacts that were previously generated.
167193 fn configure_cargo ( & self , cargo : & mut Cargo ) {
@@ -180,42 +206,90 @@ impl RustcRmetaSysroot {
180206/// "pollute" it (that is especially problematic for the external stage0 rustc).
181207#[ derive( Debug , Clone , PartialEq , Eq , Hash ) ]
182208struct PrepareRustcRmetaSysroot {
183- build_compiler : Compiler ,
209+ build_compiler : CompilerForCheck ,
184210 target : TargetSelection ,
185211}
186212
213+ impl PrepareRustcRmetaSysroot {
214+ fn new ( build_compiler : CompilerForCheck , target : TargetSelection ) -> Self {
215+ Self { build_compiler, target }
216+ }
217+ }
218+
187219impl Step for PrepareRustcRmetaSysroot {
188- type Output = RustcRmetaSysroot ;
220+ type Output = RmetaSysroot ;
189221
190222 fn should_run ( run : ShouldRun < ' _ > ) -> ShouldRun < ' _ > {
191223 run. never ( )
192224 }
193225
194226 fn run ( self , builder : & Builder < ' _ > ) -> Self :: Output {
195227 // Check rustc
196- let stamp =
197- builder. ensure ( Rustc :: from_build_compiler ( self . build_compiler , self . target , vec ! [ ] ) ) ;
228+ let stamp = builder. ensure ( Rustc :: from_build_compiler (
229+ self . build_compiler . clone ( ) ,
230+ self . target ,
231+ vec ! [ ] ,
232+ ) ) ;
233+
234+ let build_compiler = self . build_compiler . build_compiler ( ) ;
235+
236+ // Copy the generated rmeta artifacts to a separate directory
237+ let dir = builder
238+ . out
239+ . join ( build_compiler. host )
240+ . join ( format ! ( "stage{}-rustc-rmeta-artifacts" , build_compiler. stage + 1 ) ) ;
241+ RmetaSysroot :: from_stamp ( builder, stamp, self . target , & dir)
242+ }
243+ }
244+
245+ /// Checks std using the given `build_compiler` for the given `target`, and produces
246+ /// a sysroot in the build directory that stores the generated .rmeta files.
247+ ///
248+ /// This step exists so that we can store the generated .rmeta artifacts into a separate
249+ /// directory, instead of copying them into the sysroot of `build_compiler`, which would
250+ /// "pollute" it (that is especially problematic for the external stage0 rustc).
251+ #[ derive( Debug , Clone , PartialEq , Eq , Hash ) ]
252+ struct PrepareStdRmetaSysroot {
253+ build_compiler : Compiler ,
254+ target : TargetSelection ,
255+ }
256+
257+ impl PrepareStdRmetaSysroot {
258+ fn new ( build_compiler : Compiler , target : TargetSelection ) -> Self {
259+ Self { build_compiler, target }
260+ }
261+ }
262+
263+ impl Step for PrepareStdRmetaSysroot {
264+ type Output = RmetaSysroot ;
265+
266+ fn should_run ( run : ShouldRun < ' _ > ) -> ShouldRun < ' _ > {
267+ run. never ( )
268+ }
269+
270+ fn run ( self , builder : & Builder < ' _ > ) -> Self :: Output {
271+ // Check std
272+ let stamp = builder. ensure ( Std {
273+ build_compiler : self . build_compiler ,
274+ target : self . target ,
275+ crates : vec ! [ ] ,
276+ } ) ;
198277
199278 // Copy the generated rmeta artifacts to a separate directory
200279 let dir = builder
201280 . out
202281 . join ( self . build_compiler . host )
203- . join ( format ! ( "stage{}-rustc-check-artifacts" , self . build_compiler. stage + 1 ) ) ;
204- let host_dir = dir. join ( "host" ) ;
205- let target_dir = dir. join ( self . target ) ;
206- let _ = fs:: remove_dir_all ( & dir) ;
207- t ! ( fs:: create_dir_all( & dir) ) ;
208- add_to_sysroot ( builder, & target_dir, & host_dir, & stamp) ;
282+ . join ( format ! ( "stage{}-std-rmeta-artifacts" , self . build_compiler. stage) ) ;
209283
210- RustcRmetaSysroot { host_dir , target_dir }
284+ RmetaSysroot :: from_stamp ( builder , stamp , self . target , & dir )
211285 }
212286}
213287
214288/// Checks rustc using `build_compiler`.
215289#[ derive( Debug , Clone , PartialEq , Eq , Hash ) ]
216290pub struct Rustc {
217291 /// Compiler that will check this rustc.
218- pub build_compiler : Compiler ,
292+ pub build_compiler : CompilerForCheck ,
219293 pub target : TargetSelection ,
220294 /// Whether to build only a subset of crates.
221295 ///
@@ -227,13 +301,12 @@ pub struct Rustc {
227301
228302impl Rustc {
229303 pub fn new ( builder : & Builder < ' _ > , target : TargetSelection , crates : Vec < String > ) -> Self {
230- let build_compiler =
231- prepare_compiler_for_check ( builder, target, Mode :: Rustc ) . build_compiler ;
304+ let build_compiler = prepare_compiler_for_check ( builder, target, Mode :: Rustc ) ;
232305 Self :: from_build_compiler ( build_compiler, target, crates)
233306 }
234307
235308 fn from_build_compiler (
236- build_compiler : Compiler ,
309+ build_compiler : CompilerForCheck ,
237310 target : TargetSelection ,
238311 crates : Vec < String > ,
239312 ) -> Self {
@@ -263,7 +336,7 @@ impl Step for Rustc {
263336 ///
264337 /// If we check a stage 2 compiler, we will have to first build a stage 1 compiler to check it.
265338 fn run ( self , builder : & Builder < ' _ > ) -> Self :: Output {
266- let build_compiler = self . build_compiler ;
339+ let build_compiler = self . build_compiler . build_compiler ;
267340 let target = self . target ;
268341
269342 let mut cargo = builder:: Cargo :: new (
@@ -276,6 +349,7 @@ impl Step for Rustc {
276349 ) ;
277350
278351 rustc_cargo ( builder, & mut cargo, target, & build_compiler, & self . crates ) ;
352+ self . build_compiler . configure_cargo ( & mut cargo) ;
279353
280354 // Explicitly pass -p for all compiler crates -- this will force cargo
281355 // to also check the tests/benches/examples for these crates, rather
@@ -288,7 +362,7 @@ impl Step for Rustc {
288362 Kind :: Check ,
289363 format_args ! ( "compiler artifacts{}" , crate_description( & self . crates) ) ,
290364 Mode :: Rustc ,
291- self . build_compiler ,
365+ self . build_compiler . build_compiler ( ) ,
292366 target,
293367 ) ;
294368
@@ -301,7 +375,8 @@ impl Step for Rustc {
301375 }
302376
303377 fn metadata ( & self ) -> Option < StepMetadata > {
304- let metadata = StepMetadata :: check ( "rustc" , self . target ) . built_by ( self . build_compiler ) ;
378+ let metadata = StepMetadata :: check ( "rustc" , self . target )
379+ . built_by ( self . build_compiler . build_compiler ( ) ) ;
305380 let metadata = if self . crates . is_empty ( ) {
306381 metadata
307382 } else {
@@ -322,7 +397,8 @@ impl Step for Rustc {
322397#[ derive( Debug , Clone , PartialEq , Eq , Hash ) ]
323398pub struct CompilerForCheck {
324399 build_compiler : Compiler ,
325- rustc_rmeta_sysroot : Option < RustcRmetaSysroot > ,
400+ rustc_rmeta_sysroot : Option < RmetaSysroot > ,
401+ std_rmeta_sysroot : Option < RmetaSysroot > ,
326402}
327403
328404impl CompilerForCheck {
@@ -336,6 +412,30 @@ impl CompilerForCheck {
336412 if let Some ( sysroot) = & self . rustc_rmeta_sysroot {
337413 sysroot. configure_cargo ( cargo) ;
338414 }
415+ if let Some ( sysroot) = & self . std_rmeta_sysroot {
416+ sysroot. configure_cargo ( cargo) ;
417+ }
418+ }
419+ }
420+
421+ /// Prepare the standard library for checking something (that requires stdlib) using
422+ /// `build_compiler`.
423+ fn prepare_std (
424+ builder : & Builder < ' _ > ,
425+ build_compiler : Compiler ,
426+ target : TargetSelection ,
427+ ) -> Option < RmetaSysroot > {
428+ // We need to build the host stdlib even if we only check, to compile build scripts and proc
429+ // macros
430+ builder. std ( build_compiler, builder. host_target ) ;
431+
432+ // If we're cross-compiling, we generate the rmeta files for the given target
433+ // This check has to be here, because if we generate both .so and .rmeta files, rustc will fail,
434+ // as it will have multiple candidates for linking.
435+ if builder. host_target != target {
436+ Some ( builder. ensure ( PrepareStdRmetaSysroot :: new ( build_compiler, target) ) )
437+ } else {
438+ None
339439 }
340440}
341441
@@ -347,9 +447,13 @@ pub fn prepare_compiler_for_check(
347447) -> CompilerForCheck {
348448 let host = builder. host_target ;
349449
350- let mut rmeta_sysroot = None ;
450+ let mut rustc_rmeta_sysroot = None ;
451+ let mut std_rmeta_sysroot = None ;
351452 let build_compiler = match mode {
352453 Mode :: ToolBootstrap => builder. compiler ( 0 , host) ,
454+ // We could also only check std here and use `prepare_std`, but `ToolTarget` is currently
455+ // only used for running in-tree Clippy on bootstrap tools, so it does not seem worth it to
456+ // optimize it. Therefore, here we build std for the target, instead of just checking it.
353457 Mode :: ToolTarget => get_tool_target_compiler ( builder, ToolTargetBuildMode :: Build ( target) ) ,
354458 Mode :: ToolStd => {
355459 if builder. config . compile_time_deps {
@@ -360,14 +464,7 @@ pub fn prepare_compiler_for_check(
360464 } else {
361465 // These tools require the local standard library to be checked
362466 let build_compiler = builder. compiler ( builder. top_stage , host) ;
363-
364- // We need to build the host stdlib to check the tool itself.
365- // We need to build the target stdlib so that the tool can link to it.
366- builder. std ( build_compiler, host) ;
367- // We could only check this library in theory, but `check::Std` doesn't copy rmetas
368- // into `build_compiler`'s sysroot to avoid clashes with `.rlibs`, so we build it
369- // instead.
370- builder. std ( build_compiler, target) ;
467+ std_rmeta_sysroot = prepare_std ( builder, build_compiler, target) ;
371468 build_compiler
372469 }
373470 }
@@ -376,11 +473,14 @@ pub fn prepare_compiler_for_check(
376473 // return the build compiler that was used to check rustc.
377474 // We do not need to check examples/tests/etc. of Rustc for rustc_private, so we pass
378475 // an empty set of crates, which will avoid using `cargo -p`.
379- let check = Rustc :: new ( builder, target, vec ! [ ] ) ;
380- let build_compiler = check. build_compiler ;
381- builder. ensure ( check) ;
382- rmeta_sysroot =
383- Some ( builder. ensure ( PrepareRustcRmetaSysroot { build_compiler, target } ) ) ;
476+ let compiler_for_rustc = prepare_compiler_for_check ( builder, target, Mode :: Rustc ) ;
477+ rustc_rmeta_sysroot = Some (
478+ builder. ensure ( PrepareRustcRmetaSysroot :: new ( compiler_for_rustc. clone ( ) , target) ) ,
479+ ) ;
480+ let build_compiler = compiler_for_rustc. build_compiler ( ) ;
481+
482+ // To check a rustc_private tool, we also need to check std that it will link to
483+ std_rmeta_sysroot = prepare_std ( builder, build_compiler, target) ;
384484 build_compiler
385485 }
386486 Mode :: Rustc => {
@@ -394,15 +494,8 @@ pub fn prepare_compiler_for_check(
394494 let stage = if host == target { builder. top_stage - 1 } else { builder. top_stage } ;
395495 let build_compiler = builder. compiler ( stage, host) ;
396496
397- // Build host std for compiling build scripts
398- builder. std ( build_compiler, build_compiler. host ) ;
399-
400- // Build target std so that the checked rustc can link to it during the check
401- // FIXME: maybe we can a way to only do a check of std here?
402- // But for that we would have to copy the stdlib rmetas to the sysroot of the build
403- // compiler, which conflicts with std rlibs, if we also build std.
404- builder. std ( build_compiler, target) ;
405-
497+ // To check rustc, we need to check std that it will link to
498+ std_rmeta_sysroot = prepare_std ( builder, build_compiler, target) ;
406499 build_compiler
407500 }
408501 Mode :: Std => {
@@ -412,7 +505,7 @@ pub fn prepare_compiler_for_check(
412505 builder. compiler ( builder. top_stage , host)
413506 }
414507 } ;
415- CompilerForCheck { build_compiler, rustc_rmeta_sysroot : rmeta_sysroot }
508+ CompilerForCheck { build_compiler, rustc_rmeta_sysroot, std_rmeta_sysroot }
416509}
417510
418511/// Check the Cranelift codegen backend.
0 commit comments