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