@@ -96,10 +96,36 @@ impl Std {
9696 }
9797 deps
9898 }
99+
100+ /// Returns true if the standard library will be uplifted from stage 1 for the given
101+ /// `build_compiler` (which determines the stdlib stage) and `target`.
102+ ///
103+ /// Uplifting is enabled if we're building a stage2+ libstd, full bootstrap is
104+ /// disabled and we have a stage1 libstd already compiled for the given target.
105+ pub fn should_be_uplifted_from_stage_1 (
106+ builder : & Builder < ' _ > ,
107+ stage : u32 ,
108+ target : TargetSelection ,
109+ ) -> bool {
110+ stage > 1
111+ && !builder. config . full_bootstrap
112+ // This estimates if a stage1 libstd exists for the given target. If we're not
113+ // cross-compiling, it should definitely exist by the time we're building a stage2
114+ // libstd.
115+ // Or if we are cross-compiling, and we are building a cross-compiled rustc, then that
116+ // rustc needs to link to a cross-compiled libstd, so again we should have a stage1
117+ // libstd for the given target prepared.
118+ // Even if we guess wrong in the cross-compiled case, the worst that should happen is
119+ // that we build a fresh stage1 libstd below, and then we immediately uplift it, so we
120+ // don't pay the libstd build cost twice.
121+ && ( target == builder. host_target || builder. config . hosts . contains ( & target) )
122+ }
99123}
100124
101125impl Step for Std {
102- type Output = ( ) ;
126+ /// Build stamp of std, if it was indeed built or uplifted.
127+ type Output = Option < BuildStamp > ;
128+
103129 const DEFAULT : bool = true ;
104130
105131 fn should_run ( run : ShouldRun < ' _ > ) -> ShouldRun < ' _ > {
@@ -136,15 +162,15 @@ impl Step for Std {
136162 /// This will build the standard library for a particular stage of the build
137163 /// using the `compiler` targeting the `target` architecture. The artifacts
138164 /// created will also be linked into the sysroot directory.
139- fn run ( self , builder : & Builder < ' _ > ) {
165+ fn run ( self , builder : & Builder < ' _ > ) -> Self :: Output {
140166 let target = self . target ;
141167
142168 // We already have std ready to be used for stage 0.
143169 if self . build_compiler . stage == 0 {
144170 let compiler = self . build_compiler ;
145171 builder. ensure ( StdLink :: from_std ( self , compiler) ) ;
146172
147- return ;
173+ return None ;
148174 }
149175
150176 let build_compiler = if builder. download_rustc ( ) && self . force_recompile {
@@ -169,7 +195,7 @@ impl Step for Std {
169195 & sysroot,
170196 builder. config . ci_rust_std_contents ( ) ,
171197 ) ;
172- return ;
198+ return None ;
173199 }
174200
175201 if builder. config . keep_stage . contains ( & build_compiler. stage )
@@ -185,32 +211,17 @@ impl Step for Std {
185211 self . copy_extra_objects ( builder, & build_compiler, target) ;
186212
187213 builder. ensure ( StdLink :: from_std ( self , build_compiler) ) ;
188- return ;
214+ return Some ( build_stamp :: libstd_stamp ( builder , build_compiler , target ) ) ;
189215 }
190216
191217 let mut target_deps = builder. ensure ( StartupObjects { compiler : build_compiler, target } ) ;
192218
193219 // Stage of the stdlib that we're building
194220 let stage = build_compiler. stage ;
195221
196- // If we're building a stage2+ libstd, full bootstrap is
197- // disabled and we have a stage1 libstd already compiled for the given target,
198- // then simply uplift a previously built stage1 library.
199- if build_compiler. stage > 1
200- && !builder. config . full_bootstrap
201- // This estimates if a stage1 libstd exists for the given target. If we're not
202- // cross-compiling, it should definitely exist by the time we're building a stage2
203- // libstd.
204- // Or if we are cross-compiling, and we are building a cross-compiled rustc, then that
205- // rustc needs to link to a cross-compiled libstd, so again we should have a stage1
206- // libstd for the given target prepared.
207- // Even if we guess wrong in the cross-compiled case, the worst that should happen is
208- // that we build a fresh stage1 libstd below, and then we immediately uplift it, so we
209- // don't pay the libstd build cost twice.
210- && ( target == builder. host_target || builder. config . hosts . contains ( & target) )
211- {
222+ if Self :: should_be_uplifted_from_stage_1 ( builder, build_compiler. stage , target) {
212223 let build_compiler_for_std_to_uplift = builder. compiler ( 1 , builder. host_target ) ;
213- builder. std ( build_compiler_for_std_to_uplift, target) ;
224+ let stage_1_stamp = builder. std ( build_compiler_for_std_to_uplift, target) ;
214225
215226 let msg = if build_compiler_for_std_to_uplift. host == target {
216227 format ! (
@@ -231,7 +242,7 @@ impl Step for Std {
231242 self . copy_extra_objects ( builder, & build_compiler, target) ;
232243
233244 builder. ensure ( StdLink :: from_std ( self , build_compiler_for_std_to_uplift) ) ;
234- return ;
245+ return stage_1_stamp ;
235246 }
236247
237248 target_deps. extend ( self . copy_extra_objects ( builder, & build_compiler, target) ) ;
@@ -284,11 +295,13 @@ impl Step for Std {
284295 build_compiler,
285296 target,
286297 ) ;
298+
299+ let stamp = build_stamp:: libstd_stamp ( builder, build_compiler, target) ;
287300 run_cargo (
288301 builder,
289302 cargo,
290303 vec ! [ ] ,
291- & build_stamp :: libstd_stamp ( builder , build_compiler , target ) ,
304+ & stamp ,
292305 target_deps,
293306 self . is_for_mir_opt_tests , // is_check
294307 false ,
@@ -298,6 +311,7 @@ impl Step for Std {
298311 self ,
299312 builder. compiler ( build_compiler. stage , builder. config . host_target ) ,
300313 ) ) ;
314+ Some ( stamp)
301315 }
302316
303317 fn metadata ( & self ) -> Option < StepMetadata > {
0 commit comments