bootstrap/core/build_steps/
check.rs
1use crate::core::build_steps::compile::{
4 add_to_sysroot, run_cargo, rustc_cargo, rustc_cargo_env, std_cargo, std_crates_for_run_make,
5};
6use crate::core::build_steps::tool::{SourceType, prepare_tool_cargo};
7use crate::core::builder::{
8 self, Alias, Builder, Kind, RunConfig, ShouldRun, Step, crate_description,
9};
10use crate::core::config::TargetSelection;
11use crate::utils::build_stamp::{self, BuildStamp};
12use crate::{Mode, Subcommand};
13
14#[derive(Debug, Clone, PartialEq, Eq, Hash)]
15pub struct Std {
16 pub target: TargetSelection,
17 crates: Vec<String>,
23 override_build_kind: Option<Kind>,
30}
31
32impl Std {
33 pub fn new(target: TargetSelection) -> Self {
34 Self { target, crates: vec![], override_build_kind: None }
35 }
36
37 pub fn build_kind(mut self, kind: Option<Kind>) -> Self {
38 self.override_build_kind = kind;
39 self
40 }
41}
42
43impl Step for Std {
44 type Output = ();
45 const DEFAULT: bool = true;
46
47 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
48 run.crate_or_deps("sysroot")
49 .crate_or_deps("coretests")
50 .crate_or_deps("alloctests")
51 .path("library")
52 }
53
54 fn make_run(run: RunConfig<'_>) {
55 let crates = std_crates_for_run_make(&run);
56 run.builder.ensure(Std { target: run.target, crates, override_build_kind: None });
57 }
58
59 fn run(self, builder: &Builder<'_>) {
60 builder.require_submodule("library/stdarch", None);
61
62 let target = self.target;
63 let compiler = builder.compiler(builder.top_stage, builder.config.build);
64
65 let mut cargo = builder::Cargo::new(
66 builder,
67 compiler,
68 Mode::Std,
69 SourceType::InTree,
70 target,
71 self.override_build_kind.unwrap_or(builder.kind),
72 );
73
74 std_cargo(builder, target, compiler.stage, &mut cargo);
75 if matches!(builder.config.cmd, Subcommand::Fix) {
76 cargo.arg("--lib");
78 }
79
80 for krate in &*self.crates {
81 cargo.arg("-p").arg(krate);
82 }
83
84 let _guard = builder.msg_check(
85 format_args!("library artifacts{}", crate_description(&self.crates)),
86 target,
87 );
88
89 let stamp = build_stamp::libstd_stamp(builder, compiler, target).with_prefix("check");
90 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
91
92 if compiler.stage == 0 {
95 let libdir = builder.sysroot_target_libdir(compiler, target);
96 let hostdir = builder.sysroot_target_libdir(compiler, compiler.host);
97 add_to_sysroot(builder, &libdir, &hostdir, &stamp);
98 }
99 drop(_guard);
100
101 if builder.kind == Kind::Clippy || !self.crates.iter().any(|krate| krate == "test") {
104 return;
105 }
106
107 let mut cargo = builder::Cargo::new(
114 builder,
115 compiler,
116 Mode::Std,
117 SourceType::InTree,
118 target,
119 self.override_build_kind.unwrap_or(builder.kind),
120 );
121
122 if compiler.stage == 0 {
126 cargo.arg("--all-targets");
127 }
128
129 std_cargo(builder, target, compiler.stage, &mut cargo);
130
131 for krate in &*self.crates {
135 cargo.arg("-p").arg(krate);
136 }
137
138 let stamp = build_stamp::libstd_stamp(builder, compiler, target).with_prefix("check-test");
139 let _guard = builder.msg_check("library test/bench/example targets", target);
140 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
141 }
142}
143
144#[derive(Debug, Clone, PartialEq, Eq, Hash)]
145pub struct Rustc {
146 pub target: TargetSelection,
147 crates: Vec<String>,
153 override_build_kind: Option<Kind>,
160}
161
162impl Rustc {
163 pub fn new(target: TargetSelection, builder: &Builder<'_>) -> Self {
164 let crates = builder
165 .in_tree_crates("rustc-main", Some(target))
166 .into_iter()
167 .map(|krate| krate.name.to_string())
168 .collect();
169 Self { target, crates, override_build_kind: None }
170 }
171
172 pub fn build_kind(mut self, build_kind: Option<Kind>) -> Self {
173 self.override_build_kind = build_kind;
174 self
175 }
176}
177
178impl Step for Rustc {
179 type Output = ();
180 const ONLY_HOSTS: bool = true;
181 const DEFAULT: bool = true;
182
183 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
184 run.crate_or_deps("rustc-main").path("compiler")
185 }
186
187 fn make_run(run: RunConfig<'_>) {
188 let crates = run.make_run_crates(Alias::Compiler);
189 run.builder.ensure(Rustc { target: run.target, crates, override_build_kind: None });
190 }
191
192 fn run(self, builder: &Builder<'_>) {
198 let compiler = builder.compiler(builder.top_stage, builder.config.build);
199 let target = self.target;
200
201 if compiler.stage != 0 {
202 builder.ensure(crate::core::build_steps::compile::Std::new(compiler, compiler.host));
208 builder.ensure(crate::core::build_steps::compile::Std::new(compiler, target));
209 } else {
210 builder.ensure(Std::new(target).build_kind(self.override_build_kind));
211 }
212
213 let mut cargo = builder::Cargo::new(
214 builder,
215 compiler,
216 Mode::Rustc,
217 SourceType::InTree,
218 target,
219 self.override_build_kind.unwrap_or(builder.kind),
220 );
221
222 rustc_cargo(builder, &mut cargo, target, &compiler, &self.crates);
223
224 if builder.kind != Kind::Clippy {
227 cargo.arg("--all-targets");
228 }
229
230 for krate in &*self.crates {
234 cargo.arg("-p").arg(krate);
235 }
236
237 let _guard = builder.msg_check(
238 format_args!("compiler artifacts{}", crate_description(&self.crates)),
239 target,
240 );
241
242 let stamp = build_stamp::librustc_stamp(builder, compiler, target).with_prefix("check");
243
244 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
245
246 let libdir = builder.sysroot_target_libdir(compiler, target);
247 let hostdir = builder.sysroot_target_libdir(compiler, compiler.host);
248 add_to_sysroot(builder, &libdir, &hostdir, &stamp);
249 }
250}
251
252#[derive(Debug, Clone, PartialEq, Eq, Hash)]
253pub struct CodegenBackend {
254 pub target: TargetSelection,
255 pub backend: &'static str,
256}
257
258impl Step for CodegenBackend {
259 type Output = ();
260 const ONLY_HOSTS: bool = true;
261 const DEFAULT: bool = true;
262
263 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
264 run.paths(&["compiler/rustc_codegen_cranelift", "compiler/rustc_codegen_gcc"])
265 }
266
267 fn make_run(run: RunConfig<'_>) {
268 for &backend in &["cranelift", "gcc"] {
269 run.builder.ensure(CodegenBackend { target: run.target, backend });
270 }
271 }
272
273 fn run(self, builder: &Builder<'_>) {
274 if builder.build.config.vendor && self.backend == "gcc" {
276 println!("Skipping checking of `rustc_codegen_gcc` with vendoring enabled.");
277 return;
278 }
279
280 let compiler = builder.compiler(builder.top_stage, builder.config.build);
281 let target = self.target;
282 let backend = self.backend;
283
284 builder.ensure(Rustc::new(target, builder));
285
286 let mut cargo = builder::Cargo::new(
287 builder,
288 compiler,
289 Mode::Codegen,
290 SourceType::InTree,
291 target,
292 builder.kind,
293 );
294
295 cargo
296 .arg("--manifest-path")
297 .arg(builder.src.join(format!("compiler/rustc_codegen_{backend}/Cargo.toml")));
298 rustc_cargo_env(builder, &mut cargo, target, compiler.stage);
299
300 let _guard = builder.msg_check(backend, target);
301
302 let stamp = build_stamp::codegen_backend_stamp(builder, compiler, target, backend)
303 .with_prefix("check");
304
305 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
306 }
307}
308
309#[derive(Debug, Clone, PartialEq, Eq, Hash)]
310pub struct RustAnalyzer {
311 pub target: TargetSelection,
312}
313
314impl Step for RustAnalyzer {
315 type Output = ();
316 const ONLY_HOSTS: bool = true;
317 const DEFAULT: bool = true;
318
319 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
320 let builder = run.builder;
321 run.path("src/tools/rust-analyzer").default_condition(
322 builder
323 .config
324 .tools
325 .as_ref()
326 .is_none_or(|tools| tools.iter().any(|tool| tool == "rust-analyzer")),
327 )
328 }
329
330 fn make_run(run: RunConfig<'_>) {
331 run.builder.ensure(RustAnalyzer { target: run.target });
332 }
333
334 fn run(self, builder: &Builder<'_>) {
335 let compiler = builder.compiler(builder.top_stage, builder.config.build);
336 let target = self.target;
337
338 builder.ensure(Rustc::new(target, builder));
339
340 let mut cargo = prepare_tool_cargo(
341 builder,
342 compiler,
343 Mode::ToolRustc,
344 target,
345 builder.kind,
346 "src/tools/rust-analyzer",
347 SourceType::InTree,
348 &["in-rust-tree".to_owned()],
349 );
350
351 cargo.allow_features(crate::core::build_steps::tool::RustAnalyzer::ALLOW_FEATURES);
352
353 if builder.kind != Kind::Clippy {
356 cargo.arg("--bins");
358 cargo.arg("--tests");
359 cargo.arg("--benches");
360 }
361
362 let stamp = BuildStamp::new(&builder.cargo_out(compiler, Mode::ToolRustc, target))
365 .with_prefix("rust-analyzer-check");
366
367 let _guard = builder.msg_check("rust-analyzer artifacts", target);
368 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
369 }
370}
371
372macro_rules! tool_check_step {
373 (
374 $name:ident {
375 path: $path:literal
377 $(, alt_path: $alt_path:literal )*
378 $(, default: $default:literal )?
379 $( , )?
380 }
381 ) => {
382 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
383 pub struct $name {
384 pub target: TargetSelection,
385 }
386
387 impl Step for $name {
388 type Output = ();
389 const ONLY_HOSTS: bool = true;
390 const DEFAULT: bool = true $( && $default )?;
392
393 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
394 run.paths(&[ $path, $( $alt_path ),* ])
395 }
396
397 fn make_run(run: RunConfig<'_>) {
398 run.builder.ensure($name { target: run.target });
399 }
400
401 fn run(self, builder: &Builder<'_>) {
402 let Self { target } = self;
403 run_tool_check_step(builder, target, stringify!($name), $path);
404 }
405 }
406 }
407}
408
409fn run_tool_check_step(
411 builder: &Builder<'_>,
412 target: TargetSelection,
413 step_type_name: &str,
414 path: &str,
415) {
416 let display_name = path.rsplit('/').next().unwrap();
417 let compiler = builder.compiler(builder.top_stage, builder.config.build);
418
419 builder.ensure(Rustc::new(target, builder));
420
421 let mut cargo = prepare_tool_cargo(
422 builder,
423 compiler,
424 Mode::ToolRustc,
425 target,
426 builder.kind,
427 path,
428 SourceType::InTree,
433 &[],
434 );
435
436 if builder.kind != Kind::Clippy {
439 cargo.arg("--all-targets");
440 }
441
442 let stamp = BuildStamp::new(&builder.cargo_out(compiler, Mode::ToolRustc, target))
443 .with_prefix(&format!("{}-check", step_type_name.to_lowercase()));
444
445 let _guard = builder.msg_check(format!("{display_name} artifacts"), target);
446 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
447}
448
449tool_check_step!(Rustdoc { path: "src/tools/rustdoc", alt_path: "src/librustdoc" });
450tool_check_step!(Clippy { path: "src/tools/clippy" });
455tool_check_step!(Miri { path: "src/tools/miri" });
456tool_check_step!(CargoMiri { path: "src/tools/miri/cargo-miri" });
457tool_check_step!(Rustfmt { path: "src/tools/rustfmt" });
458tool_check_step!(MiroptTestTools { path: "src/tools/miropt-test-tools" });
459tool_check_step!(TestFloatParse { path: "src/etc/test-float-parse" });
460tool_check_step!(FeaturesStatusDump { path: "src/tools/features-status-dump" });
461
462tool_check_step!(Bootstrap { path: "src/bootstrap", default: false });
463
464tool_check_step!(RunMakeSupport { path: "src/tools/run-make-support", default: false });
467
468tool_check_step!(Compiletest { path: "src/tools/compiletest", default: false });