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}
32
33impl Std {
34 const CRATE_OR_DEPS: &[&str] = &["sysroot", "coretests", "alloctests"];
35
36 pub fn new(target: TargetSelection) -> Self {
37 Self { target, crates: vec![], override_build_kind: None }
38 }
39
40 pub fn build_kind(mut self, kind: Option<Kind>) -> Self {
41 self.override_build_kind = kind;
42 self
43 }
44}
45
46impl Step for Std {
47 type Output = ();
48 const DEFAULT: bool = true;
49
50 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
51 let builder = run.builder;
52 let stage = if builder.config.is_explicit_stage() || builder.top_stage >= 1 {
53 builder.top_stage
54 } else {
55 1
56 };
57
58 let mut run = run;
59 for c in Std::CRATE_OR_DEPS {
60 run = run.crate_or_deps(c);
61 }
62
63 run.path("library").default_condition(stage != 0)
64 }
65
66 fn make_run(run: RunConfig<'_>) {
67 let crates = std_crates_for_run_make(&run);
68 run.builder.ensure(Std { target: run.target, crates, override_build_kind: None });
69 }
70
71 fn run(self, builder: &Builder<'_>) {
72 builder.require_submodule("library/stdarch", None);
73
74 let stage = if builder.config.is_explicit_stage() || builder.top_stage >= 1 {
75 builder.top_stage
76 } else {
77 1
78 };
79
80 let target = self.target;
81 let compiler = builder.compiler(stage, builder.config.build);
82
83 if stage == 0 {
84 let mut is_explicitly_called =
85 builder.paths.iter().any(|p| p.starts_with("library") || p.starts_with("std"));
86
87 if !is_explicitly_called {
88 for c in Std::CRATE_OR_DEPS {
89 is_explicitly_called = builder.paths.iter().any(|p| p.starts_with(c));
90 }
91 }
92
93 if is_explicitly_called {
94 eprintln!("WARNING: stage 0 std is precompiled and does nothing during `x check`.");
95 }
96
97 builder.ensure(compile::Std::new(compiler, target));
99 return;
100 }
101
102 let mut cargo = builder::Cargo::new(
103 builder,
104 compiler,
105 Mode::Std,
106 SourceType::InTree,
107 target,
108 self.override_build_kind.unwrap_or(builder.kind),
109 );
110
111 std_cargo(builder, target, compiler.stage, &mut cargo);
112 if matches!(builder.config.cmd, Subcommand::Fix) {
113 cargo.arg("--lib");
115 }
116
117 for krate in &*self.crates {
118 cargo.arg("-p").arg(krate);
119 }
120
121 let _guard = builder.msg_check(
122 format_args!("library artifacts{}", crate_description(&self.crates)),
123 target,
124 Some(stage),
125 );
126
127 let stamp = build_stamp::libstd_stamp(builder, compiler, target).with_prefix("check");
128 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
129
130 if compiler.stage == 0 {
133 let libdir = builder.sysroot_target_libdir(compiler, target);
134 let hostdir = builder.sysroot_target_libdir(compiler, compiler.host);
135 add_to_sysroot(builder, &libdir, &hostdir, &stamp);
136 }
137 drop(_guard);
138
139 if builder.kind == Kind::Clippy || !self.crates.iter().any(|krate| krate == "test") {
142 return;
143 }
144
145 let mut cargo = builder::Cargo::new(
152 builder,
153 compiler,
154 Mode::Std,
155 SourceType::InTree,
156 target,
157 self.override_build_kind.unwrap_or(builder.kind),
158 );
159
160 if compiler.stage == 0 {
164 cargo.arg("--all-targets");
165 }
166
167 std_cargo(builder, target, compiler.stage, &mut cargo);
168
169 for krate in &*self.crates {
173 cargo.arg("-p").arg(krate);
174 }
175
176 let stamp = build_stamp::libstd_stamp(builder, compiler, target).with_prefix("check-test");
177 let _guard = builder.msg_check("library test/bench/example targets", target, Some(stage));
178 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
179 }
180}
181
182#[derive(Debug, Clone, PartialEq, Eq, Hash)]
183pub struct Rustc {
184 pub target: TargetSelection,
185 crates: Vec<String>,
191 override_build_kind: Option<Kind>,
198}
199
200impl Rustc {
201 pub fn new(target: TargetSelection, builder: &Builder<'_>) -> Self {
202 let crates = builder
203 .in_tree_crates("rustc-main", Some(target))
204 .into_iter()
205 .map(|krate| krate.name.to_string())
206 .collect();
207 Self { target, crates, override_build_kind: None }
208 }
209
210 pub fn build_kind(mut self, build_kind: Option<Kind>) -> Self {
211 self.override_build_kind = build_kind;
212 self
213 }
214}
215
216impl Step for Rustc {
217 type Output = ();
218 const ONLY_HOSTS: bool = true;
219 const DEFAULT: bool = true;
220
221 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
222 run.crate_or_deps("rustc-main").path("compiler")
223 }
224
225 fn make_run(run: RunConfig<'_>) {
226 let crates = run.make_run_crates(Alias::Compiler);
227 run.builder.ensure(Rustc { target: run.target, crates, override_build_kind: None });
228 }
229
230 fn run(self, builder: &Builder<'_>) {
236 let compiler = builder.compiler(builder.top_stage, builder.config.build);
237 let target = self.target;
238
239 if compiler.stage != 0 {
240 builder.ensure(crate::core::build_steps::compile::Std::new(compiler, compiler.host));
246 builder.ensure(crate::core::build_steps::compile::Std::new(compiler, target));
247 } else {
248 builder.ensure(Std::new(target).build_kind(self.override_build_kind));
249 }
250
251 let mut cargo = builder::Cargo::new(
252 builder,
253 compiler,
254 Mode::Rustc,
255 SourceType::InTree,
256 target,
257 self.override_build_kind.unwrap_or(builder.kind),
258 );
259
260 rustc_cargo(builder, &mut cargo, target, &compiler, &self.crates);
261
262 if builder.kind != Kind::Clippy {
265 cargo.arg("--all-targets");
266 }
267
268 for krate in &*self.crates {
272 cargo.arg("-p").arg(krate);
273 }
274
275 let _guard = builder.msg_check(
276 format_args!("compiler artifacts{}", crate_description(&self.crates)),
277 target,
278 None,
279 );
280
281 let stamp = build_stamp::librustc_stamp(builder, compiler, target).with_prefix("check");
282
283 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
284
285 let libdir = builder.sysroot_target_libdir(compiler, target);
286 let hostdir = builder.sysroot_target_libdir(compiler, compiler.host);
287 add_to_sysroot(builder, &libdir, &hostdir, &stamp);
288 }
289}
290
291#[derive(Debug, Clone, PartialEq, Eq, Hash)]
292pub struct CodegenBackend {
293 pub target: TargetSelection,
294 pub backend: &'static str,
295}
296
297impl Step for CodegenBackend {
298 type Output = ();
299 const ONLY_HOSTS: bool = true;
300 const DEFAULT: bool = true;
301
302 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
303 run.paths(&["compiler/rustc_codegen_cranelift", "compiler/rustc_codegen_gcc"])
304 }
305
306 fn make_run(run: RunConfig<'_>) {
307 for &backend in &["cranelift", "gcc"] {
308 run.builder.ensure(CodegenBackend { target: run.target, backend });
309 }
310 }
311
312 fn run(self, builder: &Builder<'_>) {
313 if builder.build.config.vendor && self.backend == "gcc" {
315 println!("Skipping checking of `rustc_codegen_gcc` with vendoring enabled.");
316 return;
317 }
318
319 let compiler = builder.compiler(builder.top_stage, builder.config.build);
320 let target = self.target;
321 let backend = self.backend;
322
323 builder.ensure(Rustc::new(target, builder));
324
325 let mut cargo = builder::Cargo::new(
326 builder,
327 compiler,
328 Mode::Codegen,
329 SourceType::InTree,
330 target,
331 builder.kind,
332 );
333
334 cargo
335 .arg("--manifest-path")
336 .arg(builder.src.join(format!("compiler/rustc_codegen_{backend}/Cargo.toml")));
337 rustc_cargo_env(builder, &mut cargo, target, compiler.stage);
338
339 let _guard = builder.msg_check(backend, target, None);
340
341 let stamp = build_stamp::codegen_backend_stamp(builder, compiler, target, backend)
342 .with_prefix("check");
343
344 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
345 }
346}
347
348#[derive(Debug, Clone, PartialEq, Eq, Hash)]
349pub struct RustAnalyzer {
350 pub target: TargetSelection,
351}
352
353impl Step for RustAnalyzer {
354 type Output = ();
355 const ONLY_HOSTS: bool = true;
356 const DEFAULT: bool = true;
357
358 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
359 let builder = run.builder;
360 run.path("src/tools/rust-analyzer").default_condition(
361 builder
362 .config
363 .tools
364 .as_ref()
365 .is_none_or(|tools| tools.iter().any(|tool| tool == "rust-analyzer")),
366 )
367 }
368
369 fn make_run(run: RunConfig<'_>) {
370 run.builder.ensure(RustAnalyzer { target: run.target });
371 }
372
373 fn run(self, builder: &Builder<'_>) {
374 let compiler = builder.compiler(builder.top_stage, builder.config.build);
375 let target = self.target;
376
377 builder.ensure(Rustc::new(target, builder));
378
379 let mut cargo = prepare_tool_cargo(
380 builder,
381 compiler,
382 Mode::ToolRustc,
383 target,
384 builder.kind,
385 "src/tools/rust-analyzer",
386 SourceType::InTree,
387 &["in-rust-tree".to_owned()],
388 );
389
390 cargo.allow_features(crate::core::build_steps::tool::RustAnalyzer::ALLOW_FEATURES);
391
392 if builder.kind != Kind::Clippy {
395 cargo.arg("--bins");
397 cargo.arg("--tests");
398 cargo.arg("--benches");
399 }
400
401 let stamp = BuildStamp::new(&builder.cargo_out(compiler, Mode::ToolRustc, target))
404 .with_prefix("rust-analyzer-check");
405
406 let _guard = builder.msg_check("rust-analyzer artifacts", target, None);
407 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
408 }
409}
410
411#[derive(Debug, Clone, PartialEq, Eq, Hash)]
414pub struct Compiletest {
415 pub target: TargetSelection,
416}
417
418impl Step for Compiletest {
419 type Output = ();
420 const ONLY_HOSTS: bool = true;
421 const DEFAULT: bool = false;
422
423 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
424 run.path("src/tools/compiletest")
425 }
426
427 fn make_run(run: RunConfig<'_>) {
428 run.builder.ensure(Compiletest { target: run.target });
429 }
430
431 fn run(self, builder: &Builder<'_>) {
432 let mode = if builder.config.compiletest_use_stage0_libtest {
433 Mode::ToolBootstrap
434 } else {
435 Mode::ToolStd
436 };
437
438 let compiler = builder.compiler(
439 if mode == Mode::ToolBootstrap { 0 } else { builder.top_stage },
440 builder.config.build,
441 );
442
443 if mode != Mode::ToolBootstrap {
444 builder.ensure(Rustc::new(self.target, builder));
445 }
446
447 let mut cargo = prepare_tool_cargo(
448 builder,
449 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 if builder.kind != Kind::Clippy {
463 cargo.arg("--all-targets");
464 }
465
466 let stamp = BuildStamp::new(&builder.cargo_out(compiler, mode, self.target))
467 .with_prefix("compiletest-check");
468
469 let _guard = builder.msg_check("compiletest artifacts", self.target, None);
470 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
471 }
472}
473
474macro_rules! tool_check_step {
475 (
476 $name:ident {
477 path: $path:literal
479 $(, alt_path: $alt_path:literal )*
480 $(, default: $default:literal )?
481 $( , )?
482 }
483 ) => {
484 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
485 pub struct $name {
486 pub target: TargetSelection,
487 }
488
489 impl Step for $name {
490 type Output = ();
491 const ONLY_HOSTS: bool = true;
492 const DEFAULT: bool = true $( && $default )?;
494
495 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
496 run.paths(&[ $path, $( $alt_path ),* ])
497 }
498
499 fn make_run(run: RunConfig<'_>) {
500 run.builder.ensure($name { target: run.target });
501 }
502
503 fn run(self, builder: &Builder<'_>) {
504 let Self { target } = self;
505 run_tool_check_step(builder, target, stringify!($name), $path);
506 }
507 }
508 }
509}
510
511fn run_tool_check_step(
513 builder: &Builder<'_>,
514 target: TargetSelection,
515 step_type_name: &str,
516 path: &str,
517) {
518 let display_name = path.rsplit('/').next().unwrap();
519 let compiler = builder.compiler(builder.top_stage, builder.config.build);
520
521 builder.ensure(Rustc::new(target, builder));
522
523 let mut cargo = prepare_tool_cargo(
524 builder,
525 compiler,
526 Mode::ToolRustc,
527 target,
528 builder.kind,
529 path,
530 SourceType::InTree,
535 &[],
536 );
537
538 if builder.kind != Kind::Clippy {
541 cargo.arg("--all-targets");
542 }
543
544 let stamp = BuildStamp::new(&builder.cargo_out(compiler, Mode::ToolRustc, target))
545 .with_prefix(&format!("{}-check", step_type_name.to_lowercase()));
546
547 let _guard = builder.msg_check(format!("{display_name} artifacts"), target, None);
548 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
549}
550
551tool_check_step!(Rustdoc { path: "src/tools/rustdoc", alt_path: "src/librustdoc" });
552tool_check_step!(Clippy { path: "src/tools/clippy" });
557tool_check_step!(Miri { path: "src/tools/miri" });
558tool_check_step!(CargoMiri { path: "src/tools/miri/cargo-miri" });
559tool_check_step!(Rustfmt { path: "src/tools/rustfmt" });
560tool_check_step!(MiroptTestTools { path: "src/tools/miropt-test-tools" });
561tool_check_step!(TestFloatParse { path: "src/tools/test-float-parse" });
562tool_check_step!(FeaturesStatusDump { path: "src/tools/features-status-dump" });
563
564tool_check_step!(Bootstrap { path: "src/bootstrap", default: false });
565
566tool_check_step!(RunMakeSupport { path: "src/tools/run-make-support", default: false });
569
570#[derive(Debug, Clone, PartialEq, Eq, Hash)]
580pub(crate) struct CoverageDump;
581
582impl CoverageDump {
583 const PATH: &str = "src/tools/coverage-dump";
584}
585
586impl Step for CoverageDump {
587 type Output = ();
588
589 const DEFAULT: bool = false;
592 const ONLY_HOSTS: bool = true;
593
594 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
595 run.path(Self::PATH)
596 }
597
598 fn make_run(run: RunConfig<'_>) {
599 run.builder.ensure(Self {});
600 }
601
602 fn run(self, builder: &Builder<'_>) -> Self::Output {
603 let Self {} = self;
605 let display_name = "coverage-dump";
606 let host = builder.config.build;
607 let target = host;
608 let mode = Mode::ToolBootstrap;
609
610 let compiler = builder.compiler(0, host);
611 let cargo = prepare_tool_cargo(
612 builder,
613 compiler,
614 mode,
615 target,
616 builder.kind,
617 Self::PATH,
618 SourceType::InTree,
619 &[],
620 );
621
622 let stamp = BuildStamp::new(&builder.cargo_out(compiler, mode, target))
623 .with_prefix(&format!("{display_name}-check"));
624
625 let _guard = builder.msg_tool(
626 builder.kind,
627 mode,
628 display_name,
629 compiler.stage,
630 &compiler.host,
631 &target,
632 );
633 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
634 }
635}