@@ -37,11 +37,12 @@ use crate::{
37
37
debug, trace,
38
38
} ;
39
39
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 `.
41
41
#[ derive( Debug , Clone , PartialEq , Eq , PartialOrd , Ord , Hash ) ]
42
42
pub struct Std {
43
43
pub target : TargetSelection ,
44
- pub compiler : Compiler ,
44
+ /// Compiler that builds the standard library.
45
+ pub build_compiler : Compiler ,
45
46
/// Whether to build only a subset of crates in the standard library.
46
47
///
47
48
/// This shouldn't be used from other steps; see the comment on [`Rustc`].
@@ -54,10 +55,10 @@ pub struct Std {
54
55
}
55
56
56
57
impl Std {
57
- pub fn new ( compiler : Compiler , target : TargetSelection ) -> Self {
58
+ pub fn new ( build_compiler : Compiler , target : TargetSelection ) -> Self {
58
59
Self {
59
60
target,
60
- compiler ,
61
+ build_compiler ,
61
62
crates : Default :: default ( ) ,
62
63
force_recompile : false ,
63
64
extra_rust_args : & [ ] ,
@@ -120,7 +121,7 @@ impl Step for Std {
120
121
trace ! ( force_recompile) ;
121
122
122
123
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 ( ) ) ,
124
125
target : run. target ,
125
126
crates,
126
127
force_recompile,
@@ -138,8 +139,8 @@ impl Step for Std {
138
139
let target = self . target ;
139
140
140
141
// 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 ;
143
144
builder. ensure ( StdLink :: from_std ( self , compiler) ) ;
144
145
145
146
return ;
@@ -148,9 +149,10 @@ impl Step for Std {
148
149
let build_compiler = if builder. download_rustc ( ) && self . force_recompile {
149
150
// When there are changes in the library tree with CI-rustc, we want to build
150
151
// 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 )
152
154
} else {
153
- self . compiler
155
+ self . build_compiler
154
156
} ;
155
157
156
158
// When using `download-rustc`, we already have artifacts for the host available. Don't
@@ -187,51 +189,50 @@ impl Step for Std {
187
189
188
190
let mut target_deps = builder. ensure ( StartupObjects { compiler : build_compiler, target } ) ;
189
191
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) )
200
210
{
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) ;
206
213
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 {
209
215
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
212
218
)
213
219
} else {
214
220
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,
217
223
)
218
224
} ;
225
+
219
226
builder. info ( & msg) ;
220
227
221
228
// Even if we're not building std this stage, the new sysroot must
222
229
// still contain the third party objects needed by various targets.
223
230
self . copy_extra_objects ( builder, & build_compiler, target) ;
224
231
225
- builder. ensure ( StdLink :: from_std ( self , compiler_to_use ) ) ;
232
+ builder. ensure ( StdLink :: from_std ( self , build_compiler_for_std_to_uplift ) ) ;
226
233
return ;
227
234
}
228
235
229
- trace ! (
230
- ?compiler_to_use,
231
- ?build_compiler,
232
- "compiler == compiler_to_use, handling not-cross-compile scenario"
233
- ) ;
234
-
235
236
target_deps. extend ( self . copy_extra_objects ( builder, & build_compiler, target) ) ;
236
237
237
238
// 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 {
299
300
}
300
301
301
302
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 ) )
303
304
}
304
305
}
305
306
@@ -665,6 +666,14 @@ pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, cargo: &mut Car
665
666
cargo. rustdocflag ( "-Zcrate-attr=warn(rust_2018_idioms)" ) ;
666
667
}
667
668
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.
668
677
#[ derive( Debug , Clone , PartialEq , Eq , Hash ) ]
669
678
pub struct StdLink {
670
679
pub compiler : Compiler ,
@@ -680,7 +689,7 @@ impl StdLink {
680
689
pub fn from_std ( std : Std , host_compiler : Compiler ) -> Self {
681
690
Self {
682
691
compiler : host_compiler,
683
- target_compiler : std. compiler ,
692
+ target_compiler : std. build_compiler ,
684
693
target : std. target ,
685
694
crates : std. crates ,
686
695
force_recompile : std. force_recompile ,
@@ -951,14 +960,8 @@ impl Rustc {
951
960
}
952
961
953
962
impl 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
+
962
965
const IS_HOST : bool = true ;
963
966
const DEFAULT : bool = false ;
964
967
@@ -997,7 +1000,7 @@ impl Step for Rustc {
997
1000
/// This will build the compiler for a particular stage of the build using
998
1001
/// the `build_compiler` targeting the `target` architecture. The artifacts
999
1002
/// created will also be linked into the sysroot directory.
1000
- fn run ( self , builder : & Builder < ' _ > ) -> u32 {
1003
+ fn run ( self , builder : & Builder < ' _ > ) {
1001
1004
let build_compiler = self . build_compiler ;
1002
1005
let target = self . target ;
1003
1006
@@ -1013,7 +1016,7 @@ impl Step for Rustc {
1013
1016
& sysroot,
1014
1017
builder. config . ci_rustc_dev_contents ( ) ,
1015
1018
) ;
1016
- return build_compiler . stage ;
1019
+ return ;
1017
1020
}
1018
1021
1019
1022
// Build a standard library for `target` using the `build_compiler`.
@@ -1027,31 +1030,33 @@ impl Step for Rustc {
1027
1030
builder. info ( "WARNING: Use `--keep-stage-std` if you want to rebuild the compiler when it changes" ) ;
1028
1031
builder. ensure ( RustcLink :: from_rustc ( self , build_compiler) ) ;
1029
1032
1030
- return build_compiler . stage ;
1033
+ return ;
1031
1034
}
1032
1035
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, )
1043
1051
} else {
1044
1052
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,
1050
1055
)
1051
1056
} ;
1052
1057
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 ;
1055
1060
}
1056
1061
1057
1062
// Build a standard library for the current host target using the `build_compiler`.
@@ -1128,8 +1133,6 @@ impl Step for Rustc {
1128
1133
self ,
1129
1134
builder. compiler ( build_compiler. stage , builder. config . host_target ) ,
1130
1135
) ) ;
1131
-
1132
- build_compiler. stage
1133
1136
}
1134
1137
1135
1138
fn metadata ( & self ) -> Option < StepMetadata > {
@@ -1909,12 +1912,18 @@ impl Step for Sysroot {
1909
1912
}
1910
1913
}
1911
1914
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`.
1912
1921
#[ derive( Debug , PartialOrd , Ord , Clone , PartialEq , Eq , Hash ) ]
1913
1922
pub struct Assemble {
1914
1923
/// The compiler which we will produce in this step. Assemble itself will
1915
1924
/// 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.
1918
1927
pub target_compiler : Compiler ,
1919
1928
}
1920
1929
@@ -1932,11 +1941,6 @@ impl Step for Assemble {
1932
1941
} ) ;
1933
1942
}
1934
1943
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.
1940
1944
fn run ( self , builder : & Builder < ' _ > ) -> Compiler {
1941
1945
let target_compiler = self . target_compiler ;
1942
1946
@@ -2065,7 +2069,7 @@ impl Step for Assemble {
2065
2069
target_compiler. stage - 1 ,
2066
2070
builder. config. host_target,
2067
2071
) ;
2068
- let mut build_compiler =
2072
+ let build_compiler =
2069
2073
builder. compiler ( target_compiler. stage - 1 , builder. config . host_target ) ;
2070
2074
2071
2075
// Build enzyme
@@ -2089,24 +2093,13 @@ impl Step for Assemble {
2089
2093
}
2090
2094
2091
2095
// 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).
2096
2097
debug ! (
2097
2098
?build_compiler,
2098
2099
"target_compiler.host" = ?target_compiler. host,
2099
2100
"building compiler libraries to link to"
2100
2101
) ;
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 ) ) ;
2110
2103
2111
2104
let stage = target_compiler. stage ;
2112
2105
let host = target_compiler. host ;
0 commit comments