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;
7use crate::core::build_steps::tool::{COMPILETEST_ALLOW_FEATURES, SourceType, prepare_tool_cargo};
8use crate::core::builder::{
9 self, Alias, Builder, Kind, RunConfig, ShouldRun, Step, StepMetadata, crate_description,
10};
11use crate::core::config::TargetSelection;
12use crate::utils::build_stamp::{self, BuildStamp};
13use crate::{Compiler, Mode, Subcommand};
14
15#[derive(Debug, Clone, PartialEq, Eq, Hash)]
16pub struct Std {
17 pub build_compiler: Compiler,
19 pub target: TargetSelection,
20 crates: Vec<String>,
26}
27
28impl Std {
29 const CRATE_OR_DEPS: &[&str] = &["sysroot", "coretests", "alloctests"];
30
31 pub fn new(build_compiler: Compiler, target: TargetSelection) -> Self {
32 Self { build_compiler, target, crates: vec![] }
33 }
34}
35
36impl Step for Std {
37 type Output = ();
38 const DEFAULT: bool = true;
39
40 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
41 let mut run = run;
42 for c in Std::CRATE_OR_DEPS {
43 run = run.crate_or_deps(c);
44 }
45
46 run.path("library")
47 }
48
49 fn make_run(run: RunConfig<'_>) {
50 if !run.builder.download_rustc() && run.builder.config.skip_std_check_if_no_download_rustc {
51 eprintln!(
52 "WARNING: `--skip-std-check-if-no-download-rustc` flag was passed and `rust.download-rustc` is not available. Skipping."
53 );
54 return;
55 }
56
57 if run.builder.config.compile_time_deps {
58 return;
60 }
61
62 let crates = std_crates_for_run_make(&run);
63 run.builder.ensure(Std {
64 build_compiler: prepare_compiler_for_check(run.builder, run.target, Mode::Std),
65 target: run.target,
66 crates,
67 });
68 }
69
70 fn run(self, builder: &Builder<'_>) {
71 let build_compiler = self.build_compiler;
72 let stage = build_compiler.stage;
73 let target = self.target;
74
75 let mut cargo = builder::Cargo::new(
76 builder,
77 build_compiler,
78 Mode::Std,
79 SourceType::InTree,
80 target,
81 Kind::Check,
82 );
83
84 std_cargo(builder, target, stage, &mut cargo);
85 if matches!(builder.config.cmd, Subcommand::Fix) {
86 cargo.arg("--lib");
88 }
89
90 for krate in &*self.crates {
91 cargo.arg("-p").arg(krate);
92 }
93
94 let _guard = builder.msg_check(
95 format_args!("library artifacts{}", crate_description(&self.crates)),
96 target,
97 Some(stage),
98 );
99
100 let stamp = build_stamp::libstd_stamp(builder, build_compiler, target).with_prefix("check");
101 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
102
103 drop(_guard);
104
105 if !self.crates.iter().any(|krate| krate == "test") {
107 return;
108 }
109
110 let mut cargo = builder::Cargo::new(
117 builder,
118 build_compiler,
119 Mode::Std,
120 SourceType::InTree,
121 target,
122 Kind::Check,
123 );
124
125 std_cargo(builder, target, build_compiler.stage, &mut cargo);
126
127 for krate in &*self.crates {
131 cargo.arg("-p").arg(krate);
132 }
133
134 let stamp =
135 build_stamp::libstd_stamp(builder, build_compiler, target).with_prefix("check-test");
136 let _guard = builder.msg_check("library test/bench/example targets", target, Some(stage));
137 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
138 }
139
140 fn metadata(&self) -> Option<StepMetadata> {
141 Some(StepMetadata::check("std", self.target).built_by(self.build_compiler))
142 }
143}
144
145#[derive(Debug, Clone, PartialEq, Eq, Hash)]
148pub struct Rustc {
149 pub build_compiler: Compiler,
151 pub target: TargetSelection,
152 crates: Vec<String>,
158}
159
160impl Rustc {
161 pub fn new(builder: &Builder<'_>, build_compiler: Compiler, target: TargetSelection) -> Self {
162 let crates = builder
163 .in_tree_crates("rustc-main", Some(target))
164 .into_iter()
165 .map(|krate| krate.name.to_string())
166 .collect();
167 Self { build_compiler, target, crates }
168 }
169}
170
171impl Step for Rustc {
172 type Output = ();
173 const ONLY_HOSTS: bool = true;
174 const DEFAULT: bool = true;
175
176 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
177 run.crate_or_deps("rustc-main").path("compiler")
178 }
179
180 fn make_run(run: RunConfig<'_>) {
181 let crates = run.make_run_crates(Alias::Compiler);
182 run.builder.ensure(Rustc {
183 target: run.target,
184 build_compiler: prepare_compiler_for_check(run.builder, run.target, Mode::Rustc),
185 crates,
186 });
187 }
188
189 fn run(self, builder: &Builder<'_>) {
197 let build_compiler = self.build_compiler;
198 let target = self.target;
199
200 builder.std(build_compiler, build_compiler.host);
202
203 builder.std(build_compiler, target);
208
209 let mut cargo = builder::Cargo::new(
210 builder,
211 build_compiler,
212 Mode::Rustc,
213 SourceType::InTree,
214 target,
215 Kind::Check,
216 );
217
218 rustc_cargo(builder, &mut cargo, target, &build_compiler, &self.crates);
219
220 for krate in &*self.crates {
224 cargo.arg("-p").arg(krate);
225 }
226
227 let _guard = builder.msg_check(
228 format_args!("compiler artifacts{}", crate_description(&self.crates)),
229 target,
230 None,
231 );
232
233 let stamp =
234 build_stamp::librustc_stamp(builder, build_compiler, target).with_prefix("check");
235
236 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
237
238 let libdir = builder.sysroot_target_libdir(build_compiler, target);
239 let hostdir = builder.sysroot_target_libdir(build_compiler, build_compiler.host);
240 add_to_sysroot(builder, &libdir, &hostdir, &stamp);
241 }
242
243 fn metadata(&self) -> Option<StepMetadata> {
244 Some(StepMetadata::check("rustc", self.target).built_by(self.build_compiler))
245 }
246}
247
248fn prepare_compiler_for_check(
250 builder: &Builder<'_>,
251 target: TargetSelection,
252 mode: Mode,
253) -> Compiler {
254 let host = builder.host_target;
255 match mode {
256 Mode::ToolBootstrap => builder.compiler(0, host),
257 Mode::ToolStd => {
258 if builder.config.compile_time_deps {
259 return builder.compiler(0, host);
263 }
264
265 let build_compiler = builder.compiler(builder.top_stage, host);
267
268 builder.std(build_compiler, host);
271 builder.std(build_compiler, target);
275 build_compiler
276 }
277 Mode::ToolRustc | Mode::Codegen => {
278 let stage = if host == target { builder.top_stage - 1 } else { builder.top_stage };
280 let build_compiler = builder.compiler(stage, host);
282 builder.ensure(Rustc::new(builder, build_compiler, target));
283 build_compiler
284 }
285 Mode::Rustc => {
286 let stage = if host == target { builder.top_stage - 1 } else { builder.top_stage };
294 builder.compiler(stage, host)
295 }
296 Mode::Std => {
297 builder.compiler(builder.top_stage, host)
301 }
302 }
303}
304
305#[derive(Debug, Clone, PartialEq, Eq, Hash)]
307pub struct CodegenBackend {
308 pub build_compiler: Compiler,
309 pub target: TargetSelection,
310 pub backend: &'static str,
311}
312
313impl Step for CodegenBackend {
314 type Output = ();
315 const ONLY_HOSTS: bool = true;
316 const DEFAULT: bool = true;
317
318 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
319 run.paths(&["compiler/rustc_codegen_cranelift", "compiler/rustc_codegen_gcc"])
320 }
321
322 fn make_run(run: RunConfig<'_>) {
323 let build_compiler = prepare_compiler_for_check(run.builder, run.target, Mode::Codegen);
325 for &backend in &["cranelift", "gcc"] {
326 run.builder.ensure(CodegenBackend { build_compiler, target: run.target, backend });
327 }
328 }
329
330 fn run(self, builder: &Builder<'_>) {
331 if builder.build.config.vendor && self.backend == "gcc" {
333 println!("Skipping checking of `rustc_codegen_gcc` with vendoring enabled.");
334 return;
335 }
336
337 let build_compiler = self.build_compiler;
338 let target = self.target;
339 let backend = self.backend;
340
341 let mut cargo = builder::Cargo::new(
342 builder,
343 build_compiler,
344 Mode::Codegen,
345 SourceType::InTree,
346 target,
347 builder.kind,
348 );
349
350 cargo
351 .arg("--manifest-path")
352 .arg(builder.src.join(format!("compiler/rustc_codegen_{backend}/Cargo.toml")));
353 rustc_cargo_env(builder, &mut cargo, target, build_compiler.stage);
354
355 let _guard = builder.msg_check(format!("rustc_codegen_{backend}"), target, None);
356
357 let stamp = build_stamp::codegen_backend_stamp(builder, build_compiler, target, backend)
358 .with_prefix("check");
359
360 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
361 }
362
363 fn metadata(&self) -> Option<StepMetadata> {
364 Some(StepMetadata::check(self.backend, self.target).built_by(self.build_compiler))
365 }
366}
367
368#[derive(Debug, Clone, PartialEq, Eq, Hash)]
370pub struct RustAnalyzer {
371 pub build_compiler: Compiler,
372 pub target: TargetSelection,
373}
374
375impl Step for RustAnalyzer {
376 type Output = ();
377 const ONLY_HOSTS: bool = true;
378 const DEFAULT: bool = true;
379
380 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
381 let builder = run.builder;
382 run.path("src/tools/rust-analyzer").default_condition(
383 builder
384 .config
385 .tools
386 .as_ref()
387 .is_none_or(|tools| tools.iter().any(|tool| tool == "rust-analyzer")),
388 )
389 }
390
391 fn make_run(run: RunConfig<'_>) {
392 let build_compiler = prepare_compiler_for_check(run.builder, run.target, Mode::ToolRustc);
393 run.builder.ensure(RustAnalyzer { build_compiler, target: run.target });
394 }
395
396 fn run(self, builder: &Builder<'_>) {
397 let build_compiler = self.build_compiler;
398 let target = self.target;
399
400 let mut cargo = prepare_tool_cargo(
401 builder,
402 build_compiler,
403 Mode::ToolRustc,
404 target,
405 builder.kind,
406 "src/tools/rust-analyzer",
407 SourceType::InTree,
408 &["in-rust-tree".to_owned()],
409 );
410
411 cargo.allow_features(crate::core::build_steps::tool::RustAnalyzer::ALLOW_FEATURES);
412
413 cargo.arg("--bins");
414 cargo.arg("--tests");
415 cargo.arg("--benches");
416
417 let stamp = BuildStamp::new(&builder.cargo_out(build_compiler, Mode::ToolRustc, target))
420 .with_prefix("rust-analyzer-check");
421
422 let _guard = builder.msg_check("rust-analyzer artifacts", target, None);
423 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
424 }
425
426 fn metadata(&self) -> Option<StepMetadata> {
427 Some(StepMetadata::check("rust-analyzer", self.target).built_by(self.build_compiler))
428 }
429}
430
431#[derive(Debug, Clone, PartialEq, Eq, Hash)]
434pub struct Compiletest {
435 pub target: TargetSelection,
436}
437
438impl Step for Compiletest {
439 type Output = ();
440 const ONLY_HOSTS: bool = true;
441 const DEFAULT: bool = false;
442
443 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
444 run.path("src/tools/compiletest")
445 }
446
447 fn make_run(run: RunConfig<'_>) {
448 run.builder.ensure(Compiletest { target: run.target });
449 }
450
451 fn run(self, builder: &Builder<'_>) {
452 let mode = if builder.config.compiletest_use_stage0_libtest {
453 Mode::ToolBootstrap
454 } else {
455 Mode::ToolStd
456 };
457 let build_compiler = prepare_compiler_for_check(builder, self.target, mode);
458
459 let mut cargo = prepare_tool_cargo(
460 builder,
461 build_compiler,
462 mode,
463 self.target,
464 builder.kind,
465 "src/tools/compiletest",
466 SourceType::InTree,
467 &[],
468 );
469
470 cargo.allow_features(COMPILETEST_ALLOW_FEATURES);
471
472 cargo.arg("--all-targets");
473
474 let stamp = BuildStamp::new(&builder.cargo_out(build_compiler, mode, self.target))
475 .with_prefix("compiletest-check");
476
477 let _guard = builder.msg_check("compiletest artifacts", self.target, None);
478 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
479 }
480
481 fn metadata(&self) -> Option<StepMetadata> {
482 Some(StepMetadata::check("compiletest", self.target))
483 }
484}
485
486macro_rules! tool_check_step {
487 (
488 $name:ident {
489 path: $path:literal
491 $(, alt_path: $alt_path:literal )*
492 , mode: $mode:path
493 $(, allow_features: $allow_features:expr )?
494 $(, default: $default:literal )?
495 $( , )?
496 }
497 ) => {
498 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
499 pub struct $name {
500 pub build_compiler: Compiler,
501 pub target: TargetSelection,
502 }
503
504 impl Step for $name {
505 type Output = ();
506 const ONLY_HOSTS: bool = true;
507 const DEFAULT: bool = true $( && $default )?;
509
510 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
511 run.paths(&[ $path, $( $alt_path ),* ])
512 }
513
514 fn make_run(run: RunConfig<'_>) {
515 let target = run.target;
516 let build_compiler = prepare_compiler_for_check(run.builder, target, $mode);
517
518 if $mode == Mode::ToolBootstrap && target != run.builder.host_target {
520 println!("WARNING: not checking bootstrap tool {} for target {target} as it is a bootstrap (host-only) tool", stringify!($path));
521 return;
522 };
523
524 run.builder.ensure($name { target, build_compiler });
525 }
526
527 fn run(self, builder: &Builder<'_>) {
528 let Self { target, build_compiler } = self;
529 let allow_features = {
530 let mut _value = "";
531 $( _value = $allow_features; )?
532 _value
533 };
534 run_tool_check_step(builder, build_compiler, target, $path, $mode, allow_features);
535 }
536
537 fn metadata(&self) -> Option<StepMetadata> {
538 Some(StepMetadata::check(stringify!($name), self.target).built_by(self.build_compiler))
539 }
540 }
541 }
542}
543
544fn run_tool_check_step(
546 builder: &Builder<'_>,
547 build_compiler: Compiler,
548 target: TargetSelection,
549 path: &str,
550 mode: Mode,
551 allow_features: &str,
552) {
553 let display_name = path.rsplit('/').next().unwrap();
554
555 let mut cargo = prepare_tool_cargo(
556 builder,
557 build_compiler,
558 mode,
559 target,
560 builder.kind,
561 path,
562 SourceType::InTree,
567 &[],
568 );
569 cargo.allow_features(allow_features);
570
571 cargo.arg("--all-targets");
573
574 let stamp = BuildStamp::new(&builder.cargo_out(build_compiler, mode, target))
575 .with_prefix(&format!("{display_name}-check"));
576
577 let stage = match mode {
578 Mode::Std | Mode::ToolRustc => build_compiler.stage,
580 _ => build_compiler.stage + 1,
581 };
582
583 let _guard =
584 builder.msg_tool(builder.kind, mode, display_name, stage, &build_compiler.host, &target);
585 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
586}
587
588tool_check_step!(Rustdoc {
589 path: "src/tools/rustdoc",
590 alt_path: "src/librustdoc",
591 mode: Mode::ToolRustc
592});
593tool_check_step!(Clippy { path: "src/tools/clippy", mode: Mode::ToolRustc });
598tool_check_step!(Miri { path: "src/tools/miri", mode: Mode::ToolRustc });
599tool_check_step!(CargoMiri { path: "src/tools/miri/cargo-miri", mode: Mode::ToolRustc });
600tool_check_step!(Rustfmt { path: "src/tools/rustfmt", mode: Mode::ToolRustc });
601tool_check_step!(MiroptTestTools {
602 path: "src/tools/miropt-test-tools",
603 mode: Mode::ToolBootstrap
604});
605tool_check_step!(TestFloatParse {
607 path: "src/tools/test-float-parse",
608 mode: Mode::ToolStd,
609 allow_features: tool::TestFloatParse::ALLOW_FEATURES
610});
611tool_check_step!(FeaturesStatusDump {
612 path: "src/tools/features-status-dump",
613 mode: Mode::ToolBootstrap
614});
615
616tool_check_step!(Bootstrap { path: "src/bootstrap", mode: Mode::ToolBootstrap, default: false });
617
618tool_check_step!(RunMakeSupport {
621 path: "src/tools/run-make-support",
622 mode: Mode::ToolBootstrap,
623 default: false
624});
625
626tool_check_step!(CoverageDump {
627 path: "src/tools/coverage-dump",
628 mode: Mode::ToolBootstrap,
629 default: false
630});