1use crate::core::build_steps::compile;
4use crate::core::build_steps::compile::{
5 add_to_sysroot, run_cargo, rustc_cargo, rustc_cargo_env, std_cargo, std_crates_for_run_make,
6};
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, crate_description,
10};
11use crate::core::config::TargetSelection;
12use crate::utils::build_stamp::{self, BuildStamp};
13use crate::{Mode, Subcommand};
14
15#[derive(Debug, Clone, PartialEq, Eq, Hash)]
16pub struct Std {
17 pub target: TargetSelection,
18 crates: Vec<String>,
24 override_build_kind: Option<Kind>,
31 custom_stage: Option<u32>,
34}
35
36impl Std {
37 const CRATE_OR_DEPS: &[&str] = &["sysroot", "coretests", "alloctests"];
38
39 pub fn new(target: TargetSelection) -> Self {
40 Self { target, crates: vec![], override_build_kind: None, custom_stage: None }
41 }
42
43 pub fn build_kind(mut self, kind: Option<Kind>) -> Self {
44 self.override_build_kind = kind;
45 self
46 }
47}
48
49impl Step for Std {
50 type Output = ();
51 const DEFAULT: bool = true;
52
53 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
54 let mut run = run;
55 for c in Std::CRATE_OR_DEPS {
56 run = run.crate_or_deps(c);
57 }
58
59 run.path("library")
60 }
61
62 fn make_run(run: RunConfig<'_>) {
63 let crates = std_crates_for_run_make(&run);
64
65 let stage = if run.builder.config.is_explicit_stage() || run.builder.top_stage >= 1 {
66 run.builder.top_stage
67 } else {
68 1
69 };
70
71 run.builder.ensure(Std {
72 target: run.target,
73 crates,
74 override_build_kind: None,
75 custom_stage: Some(stage),
76 });
77 }
78
79 fn run(self, builder: &Builder<'_>) {
80 if !builder.download_rustc() && builder.config.skip_std_check_if_no_download_rustc {
81 eprintln!(
82 "WARNING: `--skip-std-check-if-no-download-rustc` flag was passed and `rust.download-rustc` is not available. Skipping."
83 );
84 return;
85 }
86
87 builder.require_submodule("library/stdarch", None);
88
89 let stage = self.custom_stage.unwrap_or(builder.top_stage);
90
91 let target = self.target;
92 let compiler = builder.compiler(stage, builder.config.build);
93
94 if stage == 0 {
95 let mut is_explicitly_called =
96 builder.paths.iter().any(|p| p.starts_with("library") || p.starts_with("std"));
97
98 if !is_explicitly_called {
99 for c in Std::CRATE_OR_DEPS {
100 is_explicitly_called = builder.paths.iter().any(|p| p.starts_with(c));
101 }
102 }
103
104 if is_explicitly_called {
105 eprintln!("WARNING: stage 0 std is precompiled and does nothing during `x check`.");
106 }
107
108 builder.ensure(compile::Std::new(compiler, target));
110 return;
111 }
112
113 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 std_cargo(builder, target, compiler.stage, &mut cargo);
123 if matches!(builder.config.cmd, Subcommand::Fix) {
124 cargo.arg("--lib");
126 }
127
128 for krate in &*self.crates {
129 cargo.arg("-p").arg(krate);
130 }
131
132 let _guard = builder.msg_check(
133 format_args!("library artifacts{}", crate_description(&self.crates)),
134 target,
135 Some(stage),
136 );
137
138 let stamp = build_stamp::libstd_stamp(builder, compiler, target).with_prefix("check");
139 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
140
141 if compiler.stage == 0 {
144 let libdir = builder.sysroot_target_libdir(compiler, target);
145 let hostdir = builder.sysroot_target_libdir(compiler, compiler.host);
146 add_to_sysroot(builder, &libdir, &hostdir, &stamp);
147 }
148 drop(_guard);
149
150 if builder.kind == Kind::Clippy || !self.crates.iter().any(|krate| krate == "test") {
153 return;
154 }
155
156 let mut cargo = builder::Cargo::new(
163 builder,
164 compiler,
165 Mode::Std,
166 SourceType::InTree,
167 target,
168 self.override_build_kind.unwrap_or(builder.kind),
169 );
170
171 if compiler.stage == 0 {
175 cargo.arg("--all-targets");
176 }
177
178 std_cargo(builder, target, compiler.stage, &mut cargo);
179
180 for krate in &*self.crates {
184 cargo.arg("-p").arg(krate);
185 }
186
187 let stamp = build_stamp::libstd_stamp(builder, compiler, target).with_prefix("check-test");
188 let _guard = builder.msg_check("library test/bench/example targets", target, Some(stage));
189 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
190 }
191}
192
193#[derive(Debug, Clone, PartialEq, Eq, Hash)]
194pub struct Rustc {
195 pub target: TargetSelection,
196 crates: Vec<String>,
202 override_build_kind: Option<Kind>,
209}
210
211impl Rustc {
212 pub fn new(target: TargetSelection, builder: &Builder<'_>) -> Self {
213 let crates = builder
214 .in_tree_crates("rustc-main", Some(target))
215 .into_iter()
216 .map(|krate| krate.name.to_string())
217 .collect();
218 Self { target, crates, override_build_kind: None }
219 }
220
221 pub fn build_kind(mut self, build_kind: Option<Kind>) -> Self {
222 self.override_build_kind = build_kind;
223 self
224 }
225}
226
227impl Step for Rustc {
228 type Output = ();
229 const ONLY_HOSTS: bool = true;
230 const DEFAULT: bool = true;
231
232 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
233 run.crate_or_deps("rustc-main").path("compiler")
234 }
235
236 fn make_run(run: RunConfig<'_>) {
237 let crates = run.make_run_crates(Alias::Compiler);
238 run.builder.ensure(Rustc { target: run.target, crates, override_build_kind: None });
239 }
240
241 fn run(self, builder: &Builder<'_>) {
247 let compiler = builder.compiler(builder.top_stage, builder.config.build);
248 let target = self.target;
249
250 if compiler.stage != 0 {
251 builder.ensure(crate::core::build_steps::compile::Std::new(compiler, compiler.host));
257 builder.ensure(crate::core::build_steps::compile::Std::new(compiler, target));
258 } else {
259 builder.ensure(Std::new(target).build_kind(self.override_build_kind));
260 }
261
262 let mut cargo = builder::Cargo::new(
263 builder,
264 compiler,
265 Mode::Rustc,
266 SourceType::InTree,
267 target,
268 self.override_build_kind.unwrap_or(builder.kind),
269 );
270
271 rustc_cargo(builder, &mut cargo, target, &compiler, &self.crates);
272
273 if builder.kind != Kind::Clippy {
276 cargo.arg("--all-targets");
277 }
278
279 for krate in &*self.crates {
283 cargo.arg("-p").arg(krate);
284 }
285
286 let _guard = builder.msg_check(
287 format_args!("compiler artifacts{}", crate_description(&self.crates)),
288 target,
289 None,
290 );
291
292 let stamp = build_stamp::librustc_stamp(builder, compiler, target).with_prefix("check");
293
294 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
295
296 let libdir = builder.sysroot_target_libdir(compiler, target);
297 let hostdir = builder.sysroot_target_libdir(compiler, compiler.host);
298 add_to_sysroot(builder, &libdir, &hostdir, &stamp);
299 }
300}
301
302#[derive(Debug, Clone, PartialEq, Eq, Hash)]
303pub struct CodegenBackend {
304 pub target: TargetSelection,
305 pub backend: &'static str,
306}
307
308impl Step for CodegenBackend {
309 type Output = ();
310 const ONLY_HOSTS: bool = true;
311 const DEFAULT: bool = true;
312
313 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
314 run.paths(&["compiler/rustc_codegen_cranelift", "compiler/rustc_codegen_gcc"])
315 }
316
317 fn make_run(run: RunConfig<'_>) {
318 for &backend in &["cranelift", "gcc"] {
319 run.builder.ensure(CodegenBackend { target: run.target, backend });
320 }
321 }
322
323 fn run(self, builder: &Builder<'_>) {
324 if builder.build.config.vendor && self.backend == "gcc" {
326 println!("Skipping checking of `rustc_codegen_gcc` with vendoring enabled.");
327 return;
328 }
329
330 let compiler = builder.compiler(builder.top_stage, builder.config.build);
331 let target = self.target;
332 let backend = self.backend;
333
334 builder.ensure(Rustc::new(target, builder));
335
336 let mut cargo = builder::Cargo::new(
337 builder,
338 compiler,
339 Mode::Codegen,
340 SourceType::InTree,
341 target,
342 builder.kind,
343 );
344
345 cargo
346 .arg("--manifest-path")
347 .arg(builder.src.join(format!("compiler/rustc_codegen_{backend}/Cargo.toml")));
348 rustc_cargo_env(builder, &mut cargo, target, compiler.stage);
349
350 let _guard = builder.msg_check(backend, target, None);
351
352 let stamp = build_stamp::codegen_backend_stamp(builder, compiler, target, backend)
353 .with_prefix("check");
354
355 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
356 }
357}
358
359#[derive(Debug, Clone, PartialEq, Eq, Hash)]
360pub struct RustAnalyzer {
361 pub target: TargetSelection,
362}
363
364impl Step for RustAnalyzer {
365 type Output = ();
366 const ONLY_HOSTS: bool = true;
367 const DEFAULT: bool = true;
368
369 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
370 let builder = run.builder;
371 run.path("src/tools/rust-analyzer").default_condition(
372 builder
373 .config
374 .tools
375 .as_ref()
376 .is_none_or(|tools| tools.iter().any(|tool| tool == "rust-analyzer")),
377 )
378 }
379
380 fn make_run(run: RunConfig<'_>) {
381 run.builder.ensure(RustAnalyzer { target: run.target });
382 }
383
384 fn run(self, builder: &Builder<'_>) {
385 let compiler = builder.compiler(builder.top_stage, builder.config.build);
386 let target = self.target;
387
388 builder.ensure(Rustc::new(target, builder));
389
390 let mut cargo = prepare_tool_cargo(
391 builder,
392 compiler,
393 Mode::ToolRustc,
394 target,
395 builder.kind,
396 "src/tools/rust-analyzer",
397 SourceType::InTree,
398 &["in-rust-tree".to_owned()],
399 );
400
401 cargo.allow_features(crate::core::build_steps::tool::RustAnalyzer::ALLOW_FEATURES);
402
403 if builder.kind != Kind::Clippy {
406 cargo.arg("--bins");
408 cargo.arg("--tests");
409 cargo.arg("--benches");
410 }
411
412 let stamp = BuildStamp::new(&builder.cargo_out(compiler, Mode::ToolRustc, target))
415 .with_prefix("rust-analyzer-check");
416
417 let _guard = builder.msg_check("rust-analyzer artifacts", target, None);
418 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
419 }
420}
421
422#[derive(Debug, Clone, PartialEq, Eq, Hash)]
425pub struct Compiletest {
426 pub target: TargetSelection,
427}
428
429impl Step for Compiletest {
430 type Output = ();
431 const ONLY_HOSTS: bool = true;
432 const DEFAULT: bool = false;
433
434 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
435 run.path("src/tools/compiletest")
436 }
437
438 fn make_run(run: RunConfig<'_>) {
439 run.builder.ensure(Compiletest { target: run.target });
440 }
441
442 fn run(self, builder: &Builder<'_>) {
443 let mode = if builder.config.compiletest_use_stage0_libtest {
444 Mode::ToolBootstrap
445 } else {
446 Mode::ToolStd
447 };
448
449 let compiler = builder.compiler(
450 if mode == Mode::ToolBootstrap { 0 } else { builder.top_stage },
451 builder.config.build,
452 );
453
454 if mode != Mode::ToolBootstrap {
455 builder.ensure(Rustc::new(self.target, builder));
456 }
457
458 let mut cargo = prepare_tool_cargo(
459 builder,
460 compiler,
461 mode,
462 self.target,
463 builder.kind,
464 "src/tools/compiletest",
465 SourceType::InTree,
466 &[],
467 );
468
469 cargo.allow_features(COMPILETEST_ALLOW_FEATURES);
470
471 if builder.kind != Kind::Clippy {
474 cargo.arg("--all-targets");
475 }
476
477 let stamp = BuildStamp::new(&builder.cargo_out(compiler, mode, self.target))
478 .with_prefix("compiletest-check");
479
480 let _guard = builder.msg_check("compiletest artifacts", self.target, None);
481 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
482 }
483}
484
485macro_rules! tool_check_step {
486 (
487 $name:ident {
488 path: $path:literal
490 $(, alt_path: $alt_path:literal )*
491 $(, default: $default:literal )?
492 $( , )?
493 }
494 ) => {
495 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
496 pub struct $name {
497 pub target: TargetSelection,
498 }
499
500 impl Step for $name {
501 type Output = ();
502 const ONLY_HOSTS: bool = true;
503 const DEFAULT: bool = true $( && $default )?;
505
506 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
507 run.paths(&[ $path, $( $alt_path ),* ])
508 }
509
510 fn make_run(run: RunConfig<'_>) {
511 run.builder.ensure($name { target: run.target });
512 }
513
514 fn run(self, builder: &Builder<'_>) {
515 let Self { target } = self;
516 run_tool_check_step(builder, target, stringify!($name), $path);
517 }
518 }
519 }
520}
521
522fn run_tool_check_step(
524 builder: &Builder<'_>,
525 target: TargetSelection,
526 step_type_name: &str,
527 path: &str,
528) {
529 let display_name = path.rsplit('/').next().unwrap();
530 let compiler = builder.compiler(builder.top_stage, builder.config.build);
531
532 builder.ensure(Rustc::new(target, builder));
533
534 let mut cargo = prepare_tool_cargo(
535 builder,
536 compiler,
537 Mode::ToolRustc,
538 target,
539 builder.kind,
540 path,
541 SourceType::InTree,
546 &[],
547 );
548
549 if builder.kind != Kind::Clippy {
552 cargo.arg("--all-targets");
553 }
554
555 let stamp = BuildStamp::new(&builder.cargo_out(compiler, Mode::ToolRustc, target))
556 .with_prefix(&format!("{}-check", step_type_name.to_lowercase()));
557
558 let _guard = builder.msg_check(format!("{display_name} artifacts"), target, None);
559 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
560}
561
562tool_check_step!(Rustdoc { path: "src/tools/rustdoc", alt_path: "src/librustdoc" });
563tool_check_step!(Clippy { path: "src/tools/clippy" });
568tool_check_step!(Miri { path: "src/tools/miri" });
569tool_check_step!(CargoMiri { path: "src/tools/miri/cargo-miri" });
570tool_check_step!(Rustfmt { path: "src/tools/rustfmt" });
571tool_check_step!(MiroptTestTools { path: "src/tools/miropt-test-tools" });
572tool_check_step!(TestFloatParse { path: "src/tools/test-float-parse" });
573tool_check_step!(FeaturesStatusDump { path: "src/tools/features-status-dump" });
574
575tool_check_step!(Bootstrap { path: "src/bootstrap", default: false });
576
577tool_check_step!(RunMakeSupport { path: "src/tools/run-make-support", default: false });
580
581#[derive(Debug, Clone, PartialEq, Eq, Hash)]
591pub(crate) struct CoverageDump;
592
593impl CoverageDump {
594 const PATH: &str = "src/tools/coverage-dump";
595}
596
597impl Step for CoverageDump {
598 type Output = ();
599
600 const DEFAULT: bool = false;
603 const ONLY_HOSTS: bool = true;
604
605 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
606 run.path(Self::PATH)
607 }
608
609 fn make_run(run: RunConfig<'_>) {
610 run.builder.ensure(Self {});
611 }
612
613 fn run(self, builder: &Builder<'_>) -> Self::Output {
614 let Self {} = self;
616 let display_name = "coverage-dump";
617 let host = builder.config.build;
618 let target = host;
619 let mode = Mode::ToolBootstrap;
620
621 let compiler = builder.compiler(0, host);
622 let cargo = prepare_tool_cargo(
623 builder,
624 compiler,
625 mode,
626 target,
627 builder.kind,
628 Self::PATH,
629 SourceType::InTree,
630 &[],
631 );
632
633 let stamp = BuildStamp::new(&builder.cargo_out(compiler, mode, target))
634 .with_prefix(&format!("{display_name}-check"));
635
636 let _guard = builder.msg_tool(
637 builder.kind,
638 mode,
639 display_name,
640 compiler.stage,
641 &compiler.host,
642 &target,
643 );
644 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
645 }
646}