1
1
//! Implementation of compiling the compiler and standard library, in "check"-based modes.
2
2
3
+ use build_helper:: exit;
4
+
3
5
use crate :: core:: build_steps:: compile:: {
4
6
add_to_sysroot, run_cargo, rustc_cargo, rustc_cargo_env, std_cargo, std_crates_for_run_make,
5
7
} ;
@@ -9,10 +11,12 @@ use crate::core::builder::{
9
11
} ;
10
12
use crate :: core:: config:: TargetSelection ;
11
13
use crate :: utils:: build_stamp:: { self , BuildStamp } ;
12
- use crate :: { Mode , Subcommand } ;
14
+ use crate :: { Compiler , Mode , Subcommand } ;
13
15
14
16
#[ derive( Debug , Clone , PartialEq , Eq , Hash ) ]
15
17
pub struct Std {
18
+ /// Compiler that will check this std.
19
+ pub build_compiler : Compiler ,
16
20
pub target : TargetSelection ,
17
21
/// Whether to build only a subset of crates.
18
22
///
@@ -25,8 +29,8 @@ pub struct Std {
25
29
impl Std {
26
30
const CRATE_OR_DEPS : & [ & str ] = & [ "sysroot" , "coretests" , "alloctests" ] ;
27
31
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 ! [ ] }
30
34
}
31
35
}
32
36
@@ -45,7 +49,11 @@ impl Step for Std {
45
49
46
50
fn make_run ( run : RunConfig < ' _ > ) {
47
51
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
+ } ) ;
49
57
}
50
58
51
59
fn run ( self , builder : & Builder < ' _ > ) {
@@ -58,9 +66,9 @@ impl Step for Std {
58
66
59
67
builder. require_submodule ( "library/stdarch" , None ) ;
60
68
61
- let stage = builder. top_stage ;
69
+ let build_compiler = self . build_compiler ;
70
+ let stage = build_compiler. stage ;
62
71
let target = self . target ;
63
- let build_compiler = builder. compiler ( stage, builder. config . host_target ) ;
64
72
65
73
let mut cargo = builder:: Cargo :: new (
66
74
builder,
@@ -71,7 +79,7 @@ impl Step for Std {
71
79
Kind :: Check ,
72
80
) ;
73
81
74
- std_cargo ( builder, target, build_compiler . stage , & mut cargo) ;
82
+ std_cargo ( builder, target, stage, & mut cargo) ;
75
83
if matches ! ( builder. config. cmd, Subcommand :: Fix ) {
76
84
// By default, cargo tries to fix all targets. Tell it not to fix tests until we've added `test` to the sysroot.
77
85
cargo. arg ( "--lib" ) ;
@@ -132,8 +140,17 @@ impl Step for Std {
132
140
}
133
141
}
134
142
143
+ fn default_compiler_for_checking_rustc ( builder : & Builder < ' _ > ) -> Compiler {
144
+ // When checking the stage N compiler, we want to do it with the stage N-1 compiler,
145
+ builder. compiler ( builder. top_stage - 1 , builder. config . host_target )
146
+ }
147
+
148
+ /// Checks rustc using `build_compiler` and copies the built
149
+ /// .rmeta files into the sysroot of `build_copoiler`.
135
150
#[ derive( Debug , Clone , PartialEq , Eq , Hash ) ]
136
151
pub struct Rustc {
152
+ /// Compiler that will check this rustc.
153
+ pub build_compiler : Compiler ,
137
154
pub target : TargetSelection ,
138
155
/// Whether to build only a subset of crates.
139
156
///
@@ -144,13 +161,13 @@ pub struct Rustc {
144
161
}
145
162
146
163
impl Rustc {
147
- pub fn new ( target : TargetSelection , builder : & Builder < ' _ > ) -> Self {
164
+ pub fn new ( builder : & Builder < ' _ > , build_compiler : Compiler , target : TargetSelection ) -> Self {
148
165
let crates = builder
149
166
. in_tree_crates ( "rustc-main" , Some ( target) )
150
167
. into_iter ( )
151
168
. map ( |krate| krate. name . to_string ( ) )
152
169
. collect ( ) ;
153
- Self { target, crates }
170
+ Self { build_compiler , target, crates }
154
171
}
155
172
}
156
173
@@ -165,40 +182,46 @@ impl Step for Rustc {
165
182
166
183
fn make_run ( run : RunConfig < ' _ > ) {
167
184
let crates = run. make_run_crates ( Alias :: Compiler ) ;
168
- run. builder . ensure ( Rustc { target : run. target , crates } ) ;
185
+ run. builder . ensure ( Rustc {
186
+ target : run. target ,
187
+ build_compiler : default_compiler_for_checking_rustc ( run. builder ) ,
188
+ crates,
189
+ } ) ;
169
190
}
170
191
171
- /// Builds the compiler.
192
+ /// Check the compiler.
172
193
///
173
- /// This will build the compiler for a particular stage of the build using
194
+ /// This will check the compiler for a particular stage of the build using
174
195
/// the `compiler` targeting the `target` architecture. The artifacts
175
196
/// created will also be linked into the sysroot directory.
176
197
fn run ( self , builder : & Builder < ' _ > ) {
177
- let compiler = builder. compiler ( builder. top_stage , builder. config . host_target ) ;
198
+ if builder. top_stage < 2 && builder. config . host_target != self . target {
199
+ eprintln ! ( "Cannot do a cross-compilation check on stage 1, use stage 2" ) ;
200
+ exit ! ( 1 ) ;
201
+ }
202
+
203
+ let build_compiler = self . build_compiler ;
178
204
let target = self . target ;
179
205
180
- if compiler. stage != 0 {
181
- // If we're not in stage 0, then we won't have a std from the beta
182
- // compiler around. That means we need to make sure there's one in
183
- // the sysroot for the compiler to find. Otherwise, we're going to
184
- // fail when building crates that need to generate code (e.g., build
185
- // scripts and their dependencies).
186
- builder. std ( compiler, compiler. host ) ;
187
- builder. std ( compiler, target) ;
188
- } else {
189
- builder. ensure ( Std :: new ( target) ) ;
190
- }
206
+ // Build host std for compiling build scripts
207
+ builder. std ( build_compiler, build_compiler. host ) ;
208
+
209
+ // Build target std so that the checked rustc can link to it during the check
210
+ // FIXME: maybe we can a way to only do a check of std here?
211
+ // But for that we would have to copy the stdlib rmetas to the sysroot of the build
212
+ // compiler, which conflicts with std rlibs, if we also build std.
213
+ builder. std ( build_compiler, target) ;
191
214
192
215
let mut cargo = builder:: Cargo :: new (
193
216
builder,
194
- compiler ,
217
+ build_compiler ,
195
218
Mode :: Rustc ,
196
219
SourceType :: InTree ,
197
220
target,
198
221
Kind :: Check ,
199
222
) ;
200
223
201
- rustc_cargo ( builder, & mut cargo, target, & compiler , & self . crates ) ;
224
+ rustc_cargo ( builder, & mut cargo, target, & build_compiler , & self . crates ) ;
202
225
203
226
// Explicitly pass -p for all compiler crates -- this will force cargo
204
227
// to also check the tests/benches/examples for these crates, rather
@@ -213,12 +236,13 @@ impl Step for Rustc {
213
236
None ,
214
237
) ;
215
238
216
- let stamp = build_stamp:: librustc_stamp ( builder, compiler, target) . with_prefix ( "check" ) ;
239
+ let stamp =
240
+ build_stamp:: librustc_stamp ( builder, build_compiler, target) . with_prefix ( "check" ) ;
217
241
218
242
run_cargo ( builder, cargo, builder. config . free_args . clone ( ) , & stamp, vec ! [ ] , true , false ) ;
219
243
220
- let libdir = builder. sysroot_target_libdir ( compiler , target) ;
221
- let hostdir = builder. sysroot_target_libdir ( compiler , compiler . host ) ;
244
+ let libdir = builder. sysroot_target_libdir ( build_compiler , target) ;
245
+ let hostdir = builder. sysroot_target_libdir ( build_compiler , build_compiler . host ) ;
222
246
add_to_sysroot ( builder, & libdir, & hostdir, & stamp) ;
223
247
}
224
248
@@ -456,7 +480,7 @@ fn run_tool_check_step(
456
480
let display_name = path. rsplit ( '/' ) . next ( ) . unwrap ( ) ;
457
481
let compiler = builder. compiler ( builder. top_stage , builder. config . host_target ) ;
458
482
459
- builder. ensure ( Rustc :: new ( target , builder ) ) ;
483
+ builder. ensure ( Rustc :: new ( builder , compiler , target ) ) ;
460
484
461
485
let mut cargo = prepare_tool_cargo (
462
486
builder,
0 commit comments