@@ -37,11 +37,12 @@ use crate::{
3737 debug, trace,
3838} ;
3939
40- /// Build a standard library for the given `target` using the given `compiler `.
40+ /// Build a standard library for the given `target` using the given `build_compiler `.
4141#[ derive( Debug , Clone , PartialEq , Eq , PartialOrd , Ord , Hash ) ]
4242pub struct Std {
4343 pub target : TargetSelection ,
44- pub compiler : Compiler ,
44+ /// Compiler that builds the standard library.
45+ pub build_compiler : Compiler ,
4546 /// Whether to build only a subset of crates in the standard library.
4647 ///
4748 /// This shouldn't be used from other steps; see the comment on [`Rustc`].
@@ -54,10 +55,10 @@ pub struct Std {
5455}
5556
5657impl Std {
57- pub fn new ( compiler : Compiler , target : TargetSelection ) -> Self {
58+ pub fn new ( build_compiler : Compiler , target : TargetSelection ) -> Self {
5859 Self {
5960 target,
60- compiler ,
61+ build_compiler ,
6162 crates : Default :: default ( ) ,
6263 force_recompile : false ,
6364 extra_rust_args : & [ ] ,
@@ -120,7 +121,7 @@ impl Step for Std {
120121 trace ! ( force_recompile) ;
121122
122123 run. builder . ensure ( Std {
123- compiler : run. builder . compiler ( run. builder . top_stage , run. build_triple ( ) ) ,
124+ build_compiler : run. builder . compiler ( run. builder . top_stage , run. build_triple ( ) ) ,
124125 target : run. target ,
125126 crates,
126127 force_recompile,
@@ -138,8 +139,8 @@ impl Step for Std {
138139 let target = self . target ;
139140
140141 // We already have std ready to be used for stage 0.
141- if self . compiler . stage == 0 {
142- let compiler = self . compiler ;
142+ if self . build_compiler . stage == 0 {
143+ let compiler = self . build_compiler ;
143144 builder. ensure ( StdLink :: from_std ( self , compiler) ) ;
144145
145146 return ;
@@ -148,9 +149,10 @@ impl Step for Std {
148149 let build_compiler = if builder. download_rustc ( ) && self . force_recompile {
149150 // When there are changes in the library tree with CI-rustc, we want to build
150151 // the stageN library and that requires using stageN-1 compiler.
151- builder. compiler ( self . compiler . stage . saturating_sub ( 1 ) , builder. config . host_target )
152+ builder
153+ . compiler ( self . build_compiler . stage . saturating_sub ( 1 ) , builder. config . host_target )
152154 } else {
153- self . compiler
155+ self . build_compiler
154156 } ;
155157
156158 // When using `download-rustc`, we already have artifacts for the host available. Don't
@@ -187,51 +189,50 @@ impl Step for Std {
187189
188190 let mut target_deps = builder. ensure ( StartupObjects { compiler : build_compiler, target } ) ;
189191
190- let compiler_to_use =
191- builder. compiler_for ( build_compiler. stage , build_compiler. host , target) ;
192- trace ! ( ?compiler_to_use) ;
193-
194- if compiler_to_use != build_compiler
195- // Never uplift std unless we have compiled stage 1; if stage 1 is compiled,
196- // uplift it from there.
197- //
198- // FIXME: improve `fn compiler_for` to avoid adding stage condition here.
199- && build_compiler. stage > 1
192+ // Stage of the stdlib that we're building
193+ let stage = build_compiler. stage ;
194+
195+ // If we're building a stage2+ libstd, full bootstrap is
196+ // disabled and we have a stage1 libstd already compiled for the given target,
197+ // then simply uplift a previously built stage1 library.
198+ if build_compiler. stage > 1
199+ && !builder. config . full_bootstrap
200+ // This estimates if a stage1 libstd exists for the given target. If we're not
201+ // cross-compiling, it should definitely exist by the time we're building a stage2
202+ // libstd.
203+ // Or if we are cross-compiling, and we are building a cross-compiled rustc, then that
204+ // rustc needs to link to a cross-compiled libstd, so again we should have a stage1
205+ // libstd for the given target prepared.
206+ // Even if we guess wrong in the cross-compiled case, the worst that should happen is
207+ // that we build a fresh stage1 libstd below, and then we immediately uplift it, so we
208+ // don't pay the libstd build cost twice.
209+ && ( target == builder. host_target || builder. config . hosts . contains ( & target) )
200210 {
201- trace ! (
202- ?compiler_to_use,
203- ?build_compiler,
204- "build_compiler != compiler_to_use, uplifting library"
205- ) ;
211+ let build_compiler_for_std_to_uplift = builder. compiler ( 1 , builder. host_target ) ;
212+ builder. std ( build_compiler_for_std_to_uplift, target) ;
206213
207- builder. std ( compiler_to_use, target) ;
208- let msg = if compiler_to_use. host == target {
214+ let msg = if build_compiler_for_std_to_uplift. host == target {
209215 format ! (
210- "Uplifting library (stage{} -> stage{})" ,
211- compiler_to_use . stage , build_compiler . stage
216+ "Uplifting library (stage{} -> stage{stage })" ,
217+ build_compiler_for_std_to_uplift . stage
212218 )
213219 } else {
214220 format ! (
215- "Uplifting library (stage{}:{} -> stage{}:{})" ,
216- compiler_to_use . stage, compiler_to_use . host, build_compiler . stage , target
221+ "Uplifting library (stage{}:{} -> stage{stage }:{target })" ,
222+ build_compiler_for_std_to_uplift . stage, build_compiler_for_std_to_uplift . host,
217223 )
218224 } ;
225+
219226 builder. info ( & msg) ;
220227
221228 // Even if we're not building std this stage, the new sysroot must
222229 // still contain the third party objects needed by various targets.
223230 self . copy_extra_objects ( builder, & build_compiler, target) ;
224231
225- builder. ensure ( StdLink :: from_std ( self , compiler_to_use ) ) ;
232+ builder. ensure ( StdLink :: from_std ( self , build_compiler_for_std_to_uplift ) ) ;
226233 return ;
227234 }
228235
229- trace ! (
230- ?compiler_to_use,
231- ?build_compiler,
232- "compiler == compiler_to_use, handling not-cross-compile scenario"
233- ) ;
234-
235236 target_deps. extend ( self . copy_extra_objects ( builder, & build_compiler, target) ) ;
236237
237238 // We build a sysroot for mir-opt tests using the same trick that Miri does: A check build
@@ -299,7 +300,7 @@ impl Step for Std {
299300 }
300301
301302 fn metadata ( & self ) -> Option < StepMetadata > {
302- Some ( StepMetadata :: build ( "std" , self . target ) . built_by ( self . compiler ) )
303+ Some ( StepMetadata :: build ( "std" , self . target ) . built_by ( self . build_compiler ) )
303304 }
304305}
305306
@@ -665,6 +666,14 @@ pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, cargo: &mut Car
665666 cargo. rustdocflag ( "-Zcrate-attr=warn(rust_2018_idioms)" ) ;
666667}
667668
669+ /// Link all libstd rlibs/dylibs into a sysroot of `target_compiler`.
670+ ///
671+ /// Links those artifacts generated by `compiler` to the `stage` compiler's
672+ /// sysroot for the specified `host` and `target`.
673+ ///
674+ /// Note that this assumes that `compiler` has already generated the libstd
675+ /// libraries for `target`, and this method will find them in the relevant
676+ /// output directory.
668677#[ derive( Debug , Clone , PartialEq , Eq , Hash ) ]
669678pub struct StdLink {
670679 pub compiler : Compiler ,
@@ -680,7 +689,7 @@ impl StdLink {
680689 pub fn from_std ( std : Std , host_compiler : Compiler ) -> Self {
681690 Self {
682691 compiler : host_compiler,
683- target_compiler : std. compiler ,
692+ target_compiler : std. build_compiler ,
684693 target : std. target ,
685694 crates : std. crates ,
686695 force_recompile : std. force_recompile ,
@@ -951,14 +960,8 @@ impl Rustc {
951960}
952961
953962impl Step for Rustc {
954- /// We return the stage of the "actual" compiler (not the uplifted one).
955- ///
956- /// By "actual" we refer to the uplifting logic where we may not compile the requested stage;
957- /// instead, we uplift it from the previous stages. Which can lead to bootstrap failures in
958- /// specific situations where we request stage X from other steps. However we may end up
959- /// uplifting it from stage Y, causing the other stage to fail when attempting to link with
960- /// stage X which was never actually built.
961- type Output = u32 ;
963+ type Output = ( ) ;
964+
962965 const IS_HOST : bool = true ;
963966 const DEFAULT : bool = false ;
964967
@@ -997,7 +1000,7 @@ impl Step for Rustc {
9971000 /// This will build the compiler for a particular stage of the build using
9981001 /// the `build_compiler` targeting the `target` architecture. The artifacts
9991002 /// created will also be linked into the sysroot directory.
1000- fn run ( self , builder : & Builder < ' _ > ) -> u32 {
1003+ fn run ( self , builder : & Builder < ' _ > ) {
10011004 let build_compiler = self . build_compiler ;
10021005 let target = self . target ;
10031006
@@ -1013,7 +1016,7 @@ impl Step for Rustc {
10131016 & sysroot,
10141017 builder. config . ci_rustc_dev_contents ( ) ,
10151018 ) ;
1016- return build_compiler . stage ;
1019+ return ;
10171020 }
10181021
10191022 // Build a standard library for `target` using the `build_compiler`.
@@ -1027,31 +1030,33 @@ impl Step for Rustc {
10271030 builder. info ( "WARNING: Use `--keep-stage-std` if you want to rebuild the compiler when it changes" ) ;
10281031 builder. ensure ( RustcLink :: from_rustc ( self , build_compiler) ) ;
10291032
1030- return build_compiler . stage ;
1033+ return ;
10311034 }
10321035
1033- let compiler_to_use =
1034- builder. compiler_for ( build_compiler. stage , build_compiler. host , target) ;
1035- if compiler_to_use != build_compiler {
1036- builder. ensure ( Rustc :: new ( compiler_to_use, target) ) ;
1037- let msg = if compiler_to_use. host == target {
1038- format ! (
1039- "Uplifting rustc (stage{} -> stage{})" ,
1040- compiler_to_use. stage,
1041- build_compiler. stage + 1
1042- )
1036+ // The stage of the compiler that we're building
1037+ let stage = build_compiler. stage + 1 ;
1038+
1039+ // If we are building a stage3+ compiler, and full bootstrap is disabled, and we have a
1040+ // previous rustc available, we will uplift a compiler from a previous stage.
1041+ if build_compiler. stage >= 2
1042+ && !builder. config . full_bootstrap
1043+ && ( target == builder. host_target || builder. hosts . contains ( & target) )
1044+ {
1045+ // If we're cross-compiling, the earliest rustc that we could have is stage 2.
1046+ // If we're not cross-compiling, then we should have rustc stage 1.
1047+ let stage_to_uplift = if target == builder. host_target { 1 } else { 2 } ;
1048+ let rustc_to_uplift = builder. compiler ( stage_to_uplift, target) ;
1049+ let msg = if rustc_to_uplift. host == target {
1050+ format ! ( "Uplifting rustc (stage{} -> stage{stage})" , rustc_to_uplift. stage, )
10431051 } else {
10441052 format ! (
1045- "Uplifting rustc (stage{}:{} -> stage{}:{})" ,
1046- compiler_to_use. stage,
1047- compiler_to_use. host,
1048- build_compiler. stage + 1 ,
1049- target
1053+ "Uplifting rustc (stage{}:{} -> stage{stage}:{target})" ,
1054+ rustc_to_uplift. stage, rustc_to_uplift. host,
10501055 )
10511056 } ;
10521057 builder. info ( & msg) ;
1053- builder. ensure ( RustcLink :: from_rustc ( self , compiler_to_use ) ) ;
1054- return compiler_to_use . stage ;
1058+ builder. ensure ( RustcLink :: from_rustc ( self , rustc_to_uplift ) ) ;
1059+ return ;
10551060 }
10561061
10571062 // Build a standard library for the current host target using the `build_compiler`.
@@ -1128,8 +1133,6 @@ impl Step for Rustc {
11281133 self ,
11291134 builder. compiler ( build_compiler. stage , builder. config . host_target ) ,
11301135 ) ) ;
1131-
1132- build_compiler. stage
11331136 }
11341137
11351138 fn metadata ( & self ) -> Option < StepMetadata > {
@@ -1909,12 +1912,18 @@ impl Step for Sysroot {
19091912 }
19101913}
19111914
1915+ /// Prepare a compiler sysroot.
1916+ ///
1917+ /// The sysroot may contain various things useful for running the compiler, like linkers and
1918+ /// linker wrappers (LLD, LLVM bitcode linker, etc.).
1919+ ///
1920+ /// This will assemble a compiler in `build/$target/stage$stage`.
19121921#[ derive( Debug , PartialOrd , Ord , Clone , PartialEq , Eq , Hash ) ]
19131922pub struct Assemble {
19141923 /// The compiler which we will produce in this step. Assemble itself will
19151924 /// take care of ensuring that the necessary prerequisites to do so exist,
1916- /// that is, this target can be a stage2 compiler and Assemble will build
1917- /// previous stages for you.
1925+ /// that is, this can be e.g. a stage2 compiler and Assemble will build
1926+ /// the previous stages for you.
19181927 pub target_compiler : Compiler ,
19191928}
19201929
@@ -1932,11 +1941,6 @@ impl Step for Assemble {
19321941 } ) ;
19331942 }
19341943
1935- /// Prepare a new compiler from the artifacts in `stage`
1936- ///
1937- /// This will assemble a compiler in `build/$host/stage$stage`. The compiler
1938- /// must have been previously produced by the `stage - 1` builder.build
1939- /// compiler.
19401944 fn run ( self , builder : & Builder < ' _ > ) -> Compiler {
19411945 let target_compiler = self . target_compiler ;
19421946
@@ -2065,7 +2069,7 @@ impl Step for Assemble {
20652069 target_compiler. stage - 1 ,
20662070 builder. config. host_target,
20672071 ) ;
2068- let mut build_compiler =
2072+ let build_compiler =
20692073 builder. compiler ( target_compiler. stage - 1 , builder. config . host_target ) ;
20702074
20712075 // Build enzyme
@@ -2089,24 +2093,13 @@ impl Step for Assemble {
20892093 }
20902094
20912095 // Build the libraries for this compiler to link to (i.e., the libraries
2092- // it uses at runtime). NOTE: Crates the target compiler compiles don't
2093- // link to these. (FIXME: Is that correct? It seems to be correct most
2094- // of the time but I think we do link to these for stage2/bin compilers
2095- // when not performing a full bootstrap).
2096+ // it uses at runtime).
20962097 debug ! (
20972098 ?build_compiler,
20982099 "target_compiler.host" = ?target_compiler. host,
20992100 "building compiler libraries to link to"
21002101 ) ;
2101- let actual_stage = builder. ensure ( Rustc :: new ( build_compiler, target_compiler. host ) ) ;
2102- // Current build_compiler.stage might be uplifted instead of being built; so update it
2103- // to not fail while linking the artifacts.
2104- debug ! (
2105- "(old) build_compiler.stage" = build_compiler. stage,
2106- "(adjusted) build_compiler.stage" = actual_stage,
2107- "temporarily adjusting `build_compiler.stage` to account for uplifted libraries"
2108- ) ;
2109- build_compiler. stage = actual_stage;
2102+ builder. ensure ( Rustc :: new ( build_compiler, target_compiler. host ) ) ;
21102103
21112104 let stage = target_compiler. stage ;
21122105 let host = target_compiler. host ;
0 commit comments