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 custom_stage: Option<u32>,
27}
28
29impl Std {
30 const CRATE_OR_DEPS: &[&str] = &["sysroot", "coretests", "alloctests"];
31
32 pub fn new(target: TargetSelection) -> Self {
33 Self { target, crates: vec![], custom_stage: None }
34 }
35}
36
37impl Step for Std {
38 type Output = ();
39 const DEFAULT: bool = true;
40
41 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
42 let mut run = run;
43 for c in Std::CRATE_OR_DEPS {
44 run = run.crate_or_deps(c);
45 }
46
47 run.path("library")
48 }
49
50 fn make_run(run: RunConfig<'_>) {
51 let crates = std_crates_for_run_make(&run);
52
53 let stage = if run.builder.config.is_explicit_stage() || run.builder.top_stage >= 1 {
54 run.builder.top_stage
55 } else {
56 1
57 };
58
59 run.builder.ensure(Std { target: run.target, crates, custom_stage: Some(stage) });
60 }
61
62 fn run(self, builder: &Builder<'_>) {
63 if !builder.download_rustc() && builder.config.skip_std_check_if_no_download_rustc {
64 eprintln!(
65 "WARNING: `--skip-std-check-if-no-download-rustc` flag was passed and `rust.download-rustc` is not available. Skipping."
66 );
67 return;
68 }
69
70 builder.require_submodule("library/stdarch", None);
71
72 let stage = self.custom_stage.unwrap_or(builder.top_stage);
73
74 let target = self.target;
75 let compiler = builder.compiler(stage, builder.config.host_target);
76
77 if stage == 0 {
78 let mut is_explicitly_called =
79 builder.paths.iter().any(|p| p.starts_with("library") || p.starts_with("std"));
80
81 if !is_explicitly_called {
82 for c in Std::CRATE_OR_DEPS {
83 is_explicitly_called = builder.paths.iter().any(|p| p.starts_with(c));
84 }
85 }
86
87 if is_explicitly_called {
88 eprintln!("WARNING: stage 0 std is precompiled and does nothing during `x check`.");
89 }
90
91 builder.ensure(compile::Std::new(compiler, target));
93 return;
94 }
95
96 let mut cargo = builder::Cargo::new(
97 builder,
98 compiler,
99 Mode::Std,
100 SourceType::InTree,
101 target,
102 Kind::Check,
103 );
104
105 std_cargo(builder, target, compiler.stage, &mut cargo);
106 if matches!(builder.config.cmd, Subcommand::Fix) {
107 cargo.arg("--lib");
109 }
110
111 for krate in &*self.crates {
112 cargo.arg("-p").arg(krate);
113 }
114
115 let _guard = builder.msg_check(
116 format_args!("library artifacts{}", crate_description(&self.crates)),
117 target,
118 Some(stage),
119 );
120
121 let stamp = build_stamp::libstd_stamp(builder, compiler, target).with_prefix("check");
122 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
123
124 if compiler.stage == 0 {
127 let libdir = builder.sysroot_target_libdir(compiler, target);
128 let hostdir = builder.sysroot_target_libdir(compiler, compiler.host);
129 add_to_sysroot(builder, &libdir, &hostdir, &stamp);
130 }
131 drop(_guard);
132
133 if !self.crates.iter().any(|krate| krate == "test") {
135 return;
136 }
137
138 let mut cargo = builder::Cargo::new(
145 builder,
146 compiler,
147 Mode::Std,
148 SourceType::InTree,
149 target,
150 Kind::Check,
151 );
152
153 if compiler.stage == 0 {
157 cargo.arg("--all-targets");
158 }
159
160 std_cargo(builder, target, compiler.stage, &mut cargo);
161
162 for krate in &*self.crates {
166 cargo.arg("-p").arg(krate);
167 }
168
169 let stamp = build_stamp::libstd_stamp(builder, compiler, target).with_prefix("check-test");
170 let _guard = builder.msg_check("library test/bench/example targets", target, Some(stage));
171 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
172 }
173}
174
175#[derive(Debug, Clone, PartialEq, Eq, Hash)]
176pub struct Rustc {
177 pub target: TargetSelection,
178 crates: Vec<String>,
184}
185
186impl Rustc {
187 pub fn new(target: TargetSelection, builder: &Builder<'_>) -> Self {
188 let crates = builder
189 .in_tree_crates("rustc-main", Some(target))
190 .into_iter()
191 .map(|krate| krate.name.to_string())
192 .collect();
193 Self { target, crates }
194 }
195}
196
197impl Step for Rustc {
198 type Output = ();
199 const ONLY_HOSTS: bool = true;
200 const DEFAULT: bool = true;
201
202 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
203 run.crate_or_deps("rustc-main").path("compiler")
204 }
205
206 fn make_run(run: RunConfig<'_>) {
207 let crates = run.make_run_crates(Alias::Compiler);
208 run.builder.ensure(Rustc { target: run.target, crates });
209 }
210
211 fn run(self, builder: &Builder<'_>) {
217 let compiler = builder.compiler(builder.top_stage, builder.config.host_target);
218 let target = self.target;
219
220 if compiler.stage != 0 {
221 builder.ensure(crate::core::build_steps::compile::Std::new(compiler, compiler.host));
227 builder.ensure(crate::core::build_steps::compile::Std::new(compiler, target));
228 } else {
229 builder.ensure(Std::new(target));
230 }
231
232 let mut cargo = builder::Cargo::new(
233 builder,
234 compiler,
235 Mode::Rustc,
236 SourceType::InTree,
237 target,
238 Kind::Check,
239 );
240
241 rustc_cargo(builder, &mut cargo, target, &compiler, &self.crates);
242
243 for krate in &*self.crates {
247 cargo.arg("-p").arg(krate);
248 }
249
250 let _guard = builder.msg_check(
251 format_args!("compiler artifacts{}", crate_description(&self.crates)),
252 target,
253 None,
254 );
255
256 let stamp = build_stamp::librustc_stamp(builder, compiler, target).with_prefix("check");
257
258 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
259
260 let libdir = builder.sysroot_target_libdir(compiler, target);
261 let hostdir = builder.sysroot_target_libdir(compiler, compiler.host);
262 add_to_sysroot(builder, &libdir, &hostdir, &stamp);
263 }
264}
265
266#[derive(Debug, Clone, PartialEq, Eq, Hash)]
267pub struct CodegenBackend {
268 pub target: TargetSelection,
269 pub backend: &'static str,
270}
271
272impl Step for CodegenBackend {
273 type Output = ();
274 const ONLY_HOSTS: bool = true;
275 const DEFAULT: bool = true;
276
277 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
278 run.paths(&["compiler/rustc_codegen_cranelift", "compiler/rustc_codegen_gcc"])
279 }
280
281 fn make_run(run: RunConfig<'_>) {
282 for &backend in &["cranelift", "gcc"] {
283 run.builder.ensure(CodegenBackend { target: run.target, backend });
284 }
285 }
286
287 fn run(self, builder: &Builder<'_>) {
288 if builder.build.config.vendor && self.backend == "gcc" {
290 println!("Skipping checking of `rustc_codegen_gcc` with vendoring enabled.");
291 return;
292 }
293
294 let compiler = builder.compiler(builder.top_stage, builder.config.host_target);
295 let target = self.target;
296 let backend = self.backend;
297
298 builder.ensure(Rustc::new(target, builder));
299
300 let mut cargo = builder::Cargo::new(
301 builder,
302 compiler,
303 Mode::Codegen,
304 SourceType::InTree,
305 target,
306 builder.kind,
307 );
308
309 cargo
310 .arg("--manifest-path")
311 .arg(builder.src.join(format!("compiler/rustc_codegen_{backend}/Cargo.toml")));
312 rustc_cargo_env(builder, &mut cargo, target, compiler.stage);
313
314 let _guard = builder.msg_check(backend, target, None);
315
316 let stamp = build_stamp::codegen_backend_stamp(builder, compiler, target, backend)
317 .with_prefix("check");
318
319 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
320 }
321}
322
323#[derive(Debug, Clone, PartialEq, Eq, Hash)]
324pub struct RustAnalyzer {
325 pub target: TargetSelection,
326}
327
328impl Step for RustAnalyzer {
329 type Output = ();
330 const ONLY_HOSTS: bool = true;
331 const DEFAULT: bool = true;
332
333 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
334 let builder = run.builder;
335 run.path("src/tools/rust-analyzer").default_condition(
336 builder
337 .config
338 .tools
339 .as_ref()
340 .is_none_or(|tools| tools.iter().any(|tool| tool == "rust-analyzer")),
341 )
342 }
343
344 fn make_run(run: RunConfig<'_>) {
345 run.builder.ensure(RustAnalyzer { target: run.target });
346 }
347
348 fn run(self, builder: &Builder<'_>) {
349 let compiler = builder.compiler(builder.top_stage, builder.config.host_target);
350 let target = self.target;
351
352 builder.ensure(Rustc::new(target, builder));
353
354 let mut cargo = prepare_tool_cargo(
355 builder,
356 compiler,
357 Mode::ToolRustc,
358 target,
359 builder.kind,
360 "src/tools/rust-analyzer",
361 SourceType::InTree,
362 &["in-rust-tree".to_owned()],
363 );
364
365 cargo.allow_features(crate::core::build_steps::tool::RustAnalyzer::ALLOW_FEATURES);
366
367 cargo.arg("--bins");
368 cargo.arg("--tests");
369 cargo.arg("--benches");
370
371 let stamp = BuildStamp::new(&builder.cargo_out(compiler, Mode::ToolRustc, target))
374 .with_prefix("rust-analyzer-check");
375
376 let _guard = builder.msg_check("rust-analyzer artifacts", target, None);
377 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
378 }
379}
380
381#[derive(Debug, Clone, PartialEq, Eq, Hash)]
384pub struct Compiletest {
385 pub target: TargetSelection,
386}
387
388impl Step for Compiletest {
389 type Output = ();
390 const ONLY_HOSTS: bool = true;
391 const DEFAULT: bool = false;
392
393 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
394 run.path("src/tools/compiletest")
395 }
396
397 fn make_run(run: RunConfig<'_>) {
398 run.builder.ensure(Compiletest { target: run.target });
399 }
400
401 fn run(self, builder: &Builder<'_>) {
402 let mode = if builder.config.compiletest_use_stage0_libtest {
403 Mode::ToolBootstrap
404 } else {
405 Mode::ToolStd
406 };
407
408 let compiler = builder.compiler(
409 if mode == Mode::ToolBootstrap { 0 } else { builder.top_stage },
410 builder.config.host_target,
411 );
412
413 if mode != Mode::ToolBootstrap {
414 builder.ensure(Rustc::new(self.target, builder));
415 }
416
417 let mut cargo = prepare_tool_cargo(
418 builder,
419 compiler,
420 mode,
421 self.target,
422 builder.kind,
423 "src/tools/compiletest",
424 SourceType::InTree,
425 &[],
426 );
427
428 cargo.allow_features(COMPILETEST_ALLOW_FEATURES);
429
430 cargo.arg("--all-targets");
431
432 let stamp = BuildStamp::new(&builder.cargo_out(compiler, mode, self.target))
433 .with_prefix("compiletest-check");
434
435 let _guard = builder.msg_check("compiletest artifacts", self.target, None);
436 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
437 }
438}
439
440macro_rules! tool_check_step {
441 (
442 $name:ident {
443 path: $path:literal
445 $(, alt_path: $alt_path:literal )*
446 $(, default: $default:literal )?
447 $( , )?
448 }
449 ) => {
450 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
451 pub struct $name {
452 pub target: TargetSelection,
453 }
454
455 impl Step for $name {
456 type Output = ();
457 const ONLY_HOSTS: bool = true;
458 const DEFAULT: bool = true $( && $default )?;
460
461 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
462 run.paths(&[ $path, $( $alt_path ),* ])
463 }
464
465 fn make_run(run: RunConfig<'_>) {
466 run.builder.ensure($name { target: run.target });
467 }
468
469 fn run(self, builder: &Builder<'_>) {
470 let Self { target } = self;
471 run_tool_check_step(builder, target, stringify!($name), $path);
472 }
473 }
474 }
475}
476
477fn run_tool_check_step(
479 builder: &Builder<'_>,
480 target: TargetSelection,
481 step_type_name: &str,
482 path: &str,
483) {
484 let display_name = path.rsplit('/').next().unwrap();
485 let compiler = builder.compiler(builder.top_stage, builder.config.host_target);
486
487 builder.ensure(Rustc::new(target, builder));
488
489 let mut cargo = prepare_tool_cargo(
490 builder,
491 compiler,
492 Mode::ToolRustc,
493 target,
494 builder.kind,
495 path,
496 SourceType::InTree,
501 &[],
502 );
503
504 cargo.arg("--all-targets");
505
506 let stamp = BuildStamp::new(&builder.cargo_out(compiler, Mode::ToolRustc, target))
507 .with_prefix(&format!("{}-check", step_type_name.to_lowercase()));
508
509 let _guard = builder.msg_check(format!("{display_name} artifacts"), target, None);
510 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
511}
512
513tool_check_step!(Rustdoc { path: "src/tools/rustdoc", alt_path: "src/librustdoc" });
514tool_check_step!(Clippy { path: "src/tools/clippy" });
519tool_check_step!(Miri { path: "src/tools/miri" });
520tool_check_step!(CargoMiri { path: "src/tools/miri/cargo-miri" });
521tool_check_step!(Rustfmt { path: "src/tools/rustfmt" });
522tool_check_step!(MiroptTestTools { path: "src/tools/miropt-test-tools" });
523tool_check_step!(TestFloatParse { path: "src/tools/test-float-parse" });
524tool_check_step!(FeaturesStatusDump { path: "src/tools/features-status-dump" });
525
526tool_check_step!(Bootstrap { path: "src/bootstrap", default: false });
527
528tool_check_step!(RunMakeSupport { path: "src/tools/run-make-support", default: false });
531
532#[derive(Debug, Clone, PartialEq, Eq, Hash)]
542pub(crate) struct CoverageDump;
543
544impl CoverageDump {
545 const PATH: &str = "src/tools/coverage-dump";
546}
547
548impl Step for CoverageDump {
549 type Output = ();
550
551 const DEFAULT: bool = false;
554 const ONLY_HOSTS: bool = true;
555
556 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
557 run.path(Self::PATH)
558 }
559
560 fn make_run(run: RunConfig<'_>) {
561 run.builder.ensure(Self {});
562 }
563
564 fn run(self, builder: &Builder<'_>) -> Self::Output {
565 let Self {} = self;
567 let display_name = "coverage-dump";
568 let host = builder.config.host_target;
569 let target = host;
570 let mode = Mode::ToolBootstrap;
571
572 let compiler = builder.compiler(0, host);
573 let cargo = prepare_tool_cargo(
574 builder,
575 compiler,
576 mode,
577 target,
578 builder.kind,
579 Self::PATH,
580 SourceType::InTree,
581 &[],
582 );
583
584 let stamp = BuildStamp::new(&builder.cargo_out(compiler, mode, target))
585 .with_prefix(&format!("{display_name}-check"));
586
587 let _guard = builder.msg_tool(
588 builder.kind,
589 mode,
590 display_name,
591 compiler.stage,
592 &compiler.host,
593 &target,
594 );
595 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
596 }
597}