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