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 let crates = std_crates_for_run_make(&run);
51 run.builder.ensure(Std {
52 build_compiler: prepare_compiler_for_check(run.builder, run.target, Mode::Std),
53 target: run.target,
54 crates,
55 });
56 }
57
58 fn run(self, builder: &Builder<'_>) {
59 if !builder.download_rustc() && builder.config.skip_std_check_if_no_download_rustc {
60 eprintln!(
61 "WARNING: `--skip-std-check-if-no-download-rustc` flag was passed and `rust.download-rustc` is not available. Skipping."
62 );
63 return;
64 }
65
66 let build_compiler = self.build_compiler;
67 let stage = build_compiler.stage;
68 let target = self.target;
69
70 let mut cargo = builder::Cargo::new(
71 builder,
72 build_compiler,
73 Mode::Std,
74 SourceType::InTree,
75 target,
76 Kind::Check,
77 );
78
79 std_cargo(builder, target, stage, &mut cargo);
80 if matches!(builder.config.cmd, Subcommand::Fix) {
81 cargo.arg("--lib");
83 }
84
85 for krate in &*self.crates {
86 cargo.arg("-p").arg(krate);
87 }
88
89 let _guard = builder.msg_check(
90 format_args!("library artifacts{}", crate_description(&self.crates)),
91 target,
92 Some(stage),
93 );
94
95 let stamp = build_stamp::libstd_stamp(builder, build_compiler, target).with_prefix("check");
96 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
97
98 drop(_guard);
99
100 if !self.crates.iter().any(|krate| krate == "test") {
102 return;
103 }
104
105 let mut cargo = builder::Cargo::new(
112 builder,
113 build_compiler,
114 Mode::Std,
115 SourceType::InTree,
116 target,
117 Kind::Check,
118 );
119
120 std_cargo(builder, target, build_compiler.stage, &mut cargo);
121
122 for krate in &*self.crates {
126 cargo.arg("-p").arg(krate);
127 }
128
129 let stamp =
130 build_stamp::libstd_stamp(builder, build_compiler, target).with_prefix("check-test");
131 let _guard = builder.msg_check("library test/bench/example targets", target, Some(stage));
132 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
133 }
134
135 fn metadata(&self) -> Option<StepMetadata> {
136 Some(StepMetadata::check("std", self.target).built_by(self.build_compiler))
137 }
138}
139
140#[derive(Debug, Clone, PartialEq, Eq, Hash)]
143pub struct Rustc {
144 pub build_compiler: Compiler,
146 pub target: TargetSelection,
147 crates: Vec<String>,
153}
154
155impl Rustc {
156 pub fn new(builder: &Builder<'_>, build_compiler: Compiler, target: TargetSelection) -> Self {
157 let crates = builder
158 .in_tree_crates("rustc-main", Some(target))
159 .into_iter()
160 .map(|krate| krate.name.to_string())
161 .collect();
162 Self { build_compiler, target, crates }
163 }
164}
165
166impl Step for Rustc {
167 type Output = ();
168 const ONLY_HOSTS: bool = true;
169 const DEFAULT: bool = true;
170
171 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
172 run.crate_or_deps("rustc-main").path("compiler")
173 }
174
175 fn make_run(run: RunConfig<'_>) {
176 let crates = run.make_run_crates(Alias::Compiler);
177 run.builder.ensure(Rustc {
178 target: run.target,
179 build_compiler: prepare_compiler_for_check(run.builder, run.target, Mode::Rustc),
180 crates,
181 });
182 }
183
184 fn run(self, builder: &Builder<'_>) {
192 let build_compiler = self.build_compiler;
193 let target = self.target;
194
195 builder.std(build_compiler, build_compiler.host);
197
198 builder.std(build_compiler, target);
203
204 let mut cargo = builder::Cargo::new(
205 builder,
206 build_compiler,
207 Mode::Rustc,
208 SourceType::InTree,
209 target,
210 Kind::Check,
211 );
212
213 rustc_cargo(builder, &mut cargo, target, &build_compiler, &self.crates);
214
215 for krate in &*self.crates {
219 cargo.arg("-p").arg(krate);
220 }
221
222 let _guard = builder.msg_check(
223 format_args!("compiler artifacts{}", crate_description(&self.crates)),
224 target,
225 None,
226 );
227
228 let stamp =
229 build_stamp::librustc_stamp(builder, build_compiler, target).with_prefix("check");
230
231 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
232
233 let libdir = builder.sysroot_target_libdir(build_compiler, target);
234 let hostdir = builder.sysroot_target_libdir(build_compiler, build_compiler.host);
235 add_to_sysroot(builder, &libdir, &hostdir, &stamp);
236 }
237
238 fn metadata(&self) -> Option<StepMetadata> {
239 Some(StepMetadata::check("rustc", self.target).built_by(self.build_compiler))
240 }
241}
242
243fn prepare_compiler_for_check(
245 builder: &Builder<'_>,
246 target: TargetSelection,
247 mode: Mode,
248) -> Compiler {
249 let host = builder.host_target;
250 match mode {
251 Mode::ToolBootstrap => builder.compiler(0, host),
252 Mode::ToolStd => {
253 let build_compiler = builder.compiler(builder.top_stage, host);
255
256 builder.std(build_compiler, host);
259 builder.std(build_compiler, target);
263 build_compiler
264 }
265 Mode::ToolRustc | Mode::Codegen => {
266 let stage = if host == target { builder.top_stage - 1 } else { builder.top_stage };
268 let build_compiler = builder.compiler(stage, host);
270 builder.ensure(Rustc::new(builder, build_compiler, target));
271 build_compiler
272 }
273 Mode::Rustc => {
274 let stage = if host == target { builder.top_stage - 1 } else { builder.top_stage };
282 builder.compiler(stage, host)
283 }
284 Mode::Std => {
285 builder.compiler(builder.top_stage, host)
289 }
290 }
291}
292
293#[derive(Debug, Clone, PartialEq, Eq, Hash)]
295pub struct CodegenBackend {
296 pub build_compiler: Compiler,
297 pub target: TargetSelection,
298 pub backend: &'static str,
299}
300
301impl Step for CodegenBackend {
302 type Output = ();
303 const ONLY_HOSTS: bool = true;
304 const DEFAULT: bool = true;
305
306 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
307 run.paths(&["compiler/rustc_codegen_cranelift", "compiler/rustc_codegen_gcc"])
308 }
309
310 fn make_run(run: RunConfig<'_>) {
311 let build_compiler = prepare_compiler_for_check(run.builder, run.target, Mode::Codegen);
313 for &backend in &["cranelift", "gcc"] {
314 run.builder.ensure(CodegenBackend { build_compiler, target: run.target, backend });
315 }
316 }
317
318 fn run(self, builder: &Builder<'_>) {
319 if builder.build.config.vendor && self.backend == "gcc" {
321 println!("Skipping checking of `rustc_codegen_gcc` with vendoring enabled.");
322 return;
323 }
324
325 let build_compiler = self.build_compiler;
326 let target = self.target;
327 let backend = self.backend;
328
329 let mut cargo = builder::Cargo::new(
330 builder,
331 build_compiler,
332 Mode::Codegen,
333 SourceType::InTree,
334 target,
335 builder.kind,
336 );
337
338 cargo
339 .arg("--manifest-path")
340 .arg(builder.src.join(format!("compiler/rustc_codegen_{backend}/Cargo.toml")));
341 rustc_cargo_env(builder, &mut cargo, target, build_compiler.stage);
342
343 let _guard = builder.msg_check(format!("rustc_codegen_{backend}"), target, None);
344
345 let stamp = build_stamp::codegen_backend_stamp(builder, build_compiler, target, backend)
346 .with_prefix("check");
347
348 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
349 }
350
351 fn metadata(&self) -> Option<StepMetadata> {
352 Some(StepMetadata::check(self.backend, self.target).built_by(self.build_compiler))
353 }
354}
355
356#[derive(Debug, Clone, PartialEq, Eq, Hash)]
358pub struct RustAnalyzer {
359 pub build_compiler: Compiler,
360 pub target: TargetSelection,
361}
362
363impl Step for RustAnalyzer {
364 type Output = ();
365 const ONLY_HOSTS: bool = true;
366 const DEFAULT: bool = true;
367
368 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
369 let builder = run.builder;
370 run.path("src/tools/rust-analyzer").default_condition(
371 builder
372 .config
373 .tools
374 .as_ref()
375 .is_none_or(|tools| tools.iter().any(|tool| tool == "rust-analyzer")),
376 )
377 }
378
379 fn make_run(run: RunConfig<'_>) {
380 let build_compiler = prepare_compiler_for_check(run.builder, run.target, Mode::ToolRustc);
381 run.builder.ensure(RustAnalyzer { build_compiler, target: run.target });
382 }
383
384 fn run(self, builder: &Builder<'_>) {
385 let build_compiler = self.build_compiler;
386 let target = self.target;
387
388 let mut cargo = prepare_tool_cargo(
389 builder,
390 build_compiler,
391 Mode::ToolRustc,
392 target,
393 builder.kind,
394 "src/tools/rust-analyzer",
395 SourceType::InTree,
396 &["in-rust-tree".to_owned()],
397 );
398
399 cargo.allow_features(crate::core::build_steps::tool::RustAnalyzer::ALLOW_FEATURES);
400
401 cargo.arg("--bins");
402 cargo.arg("--tests");
403 cargo.arg("--benches");
404
405 let stamp = BuildStamp::new(&builder.cargo_out(build_compiler, Mode::ToolRustc, target))
408 .with_prefix("rust-analyzer-check");
409
410 let _guard = builder.msg_check("rust-analyzer artifacts", target, None);
411 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
412 }
413
414 fn metadata(&self) -> Option<StepMetadata> {
415 Some(StepMetadata::check("rust-analyzer", self.target).built_by(self.build_compiler))
416 }
417}
418
419#[derive(Debug, Clone, PartialEq, Eq, Hash)]
422pub struct Compiletest {
423 pub target: TargetSelection,
424}
425
426impl Step for Compiletest {
427 type Output = ();
428 const ONLY_HOSTS: bool = true;
429 const DEFAULT: bool = false;
430
431 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
432 run.path("src/tools/compiletest")
433 }
434
435 fn make_run(run: RunConfig<'_>) {
436 run.builder.ensure(Compiletest { target: run.target });
437 }
438
439 fn run(self, builder: &Builder<'_>) {
440 let mode = if builder.config.compiletest_use_stage0_libtest {
441 Mode::ToolBootstrap
442 } else {
443 Mode::ToolStd
444 };
445 let build_compiler = prepare_compiler_for_check(builder, self.target, mode);
446
447 let mut cargo = prepare_tool_cargo(
448 builder,
449 build_compiler,
450 mode,
451 self.target,
452 builder.kind,
453 "src/tools/compiletest",
454 SourceType::InTree,
455 &[],
456 );
457
458 cargo.allow_features(COMPILETEST_ALLOW_FEATURES);
459
460 cargo.arg("--all-targets");
461
462 let stamp = BuildStamp::new(&builder.cargo_out(build_compiler, mode, self.target))
463 .with_prefix("compiletest-check");
464
465 let _guard = builder.msg_check("compiletest artifacts", self.target, None);
466 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
467 }
468
469 fn metadata(&self) -> Option<StepMetadata> {
470 Some(StepMetadata::check("compiletest", self.target))
471 }
472}
473
474macro_rules! tool_check_step {
475 (
476 $name:ident {
477 path: $path:literal
479 $(, alt_path: $alt_path:literal )*
480 , mode: $mode:path
481 $(, allow_features: $allow_features:expr )?
482 $(, default: $default:literal )?
483 $( , )?
484 }
485 ) => {
486 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
487 pub struct $name {
488 pub build_compiler: Compiler,
489 pub target: TargetSelection,
490 }
491
492 impl Step for $name {
493 type Output = ();
494 const ONLY_HOSTS: bool = true;
495 const DEFAULT: bool = true $( && $default )?;
497
498 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
499 run.paths(&[ $path, $( $alt_path ),* ])
500 }
501
502 fn make_run(run: RunConfig<'_>) {
503 let target = run.target;
504 let build_compiler = prepare_compiler_for_check(run.builder, target, $mode);
505
506 if $mode == Mode::ToolBootstrap && target != run.builder.host_target {
508 println!("WARNING: not checking bootstrap tool {} for target {target} as it is a bootstrap (host-only) tool", stringify!($path));
509 return;
510 };
511
512 run.builder.ensure($name { target, build_compiler });
513 }
514
515 fn run(self, builder: &Builder<'_>) {
516 let Self { target, build_compiler } = self;
517 let allow_features = {
518 let mut _value = "";
519 $( _value = $allow_features; )?
520 _value
521 };
522 run_tool_check_step(builder, build_compiler, target, $path, $mode, allow_features);
523 }
524
525 fn metadata(&self) -> Option<StepMetadata> {
526 Some(StepMetadata::check(stringify!($name), self.target).built_by(self.build_compiler))
527 }
528 }
529 }
530}
531
532fn run_tool_check_step(
534 builder: &Builder<'_>,
535 build_compiler: Compiler,
536 target: TargetSelection,
537 path: &str,
538 mode: Mode,
539 allow_features: &str,
540) {
541 let display_name = path.rsplit('/').next().unwrap();
542
543 let mut cargo = prepare_tool_cargo(
544 builder,
545 build_compiler,
546 mode,
547 target,
548 builder.kind,
549 path,
550 SourceType::InTree,
555 &[],
556 );
557 cargo.allow_features(allow_features);
558
559 cargo.arg("--all-targets");
561
562 let stamp = BuildStamp::new(&builder.cargo_out(build_compiler, mode, target))
563 .with_prefix(&format!("{display_name}-check"));
564
565 let stage = match mode {
566 Mode::Std | Mode::ToolRustc => build_compiler.stage,
568 _ => build_compiler.stage + 1,
569 };
570
571 let _guard =
572 builder.msg_tool(builder.kind, mode, display_name, stage, &build_compiler.host, &target);
573 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
574}
575
576tool_check_step!(Rustdoc {
577 path: "src/tools/rustdoc",
578 alt_path: "src/librustdoc",
579 mode: Mode::ToolRustc
580});
581tool_check_step!(Clippy { path: "src/tools/clippy", mode: Mode::ToolRustc });
586tool_check_step!(Miri { path: "src/tools/miri", mode: Mode::ToolRustc });
587tool_check_step!(CargoMiri { path: "src/tools/miri/cargo-miri", mode: Mode::ToolRustc });
588tool_check_step!(Rustfmt { path: "src/tools/rustfmt", mode: Mode::ToolRustc });
589tool_check_step!(MiroptTestTools {
590 path: "src/tools/miropt-test-tools",
591 mode: Mode::ToolBootstrap
592});
593tool_check_step!(TestFloatParse {
595 path: "src/tools/test-float-parse",
596 mode: Mode::ToolStd,
597 allow_features: tool::TestFloatParse::ALLOW_FEATURES
598});
599tool_check_step!(FeaturesStatusDump {
600 path: "src/tools/features-status-dump",
601 mode: Mode::ToolBootstrap
602});
603
604tool_check_step!(Bootstrap { path: "src/bootstrap", mode: Mode::ToolBootstrap, default: false });
605
606tool_check_step!(RunMakeSupport {
609 path: "src/tools/run-make-support",
610 mode: Mode::ToolBootstrap,
611 default: false
612});
613
614tool_check_step!(CoverageDump {
615 path: "src/tools/coverage-dump",
616 mode: Mode::ToolBootstrap,
617 default: false
618});