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::{
8 COMPILETEST_ALLOW_FEATURES, SourceType, ToolTargetBuildMode, get_tool_target_compiler,
9 prepare_tool_cargo,
10};
11use crate::core::builder::{
12 self, Alias, Builder, Kind, RunConfig, ShouldRun, Step, StepMetadata, crate_description,
13};
14use crate::core::config::TargetSelection;
15use crate::utils::build_stamp::{self, BuildStamp};
16use crate::{CodegenBackendKind, Compiler, Mode, Subcommand};
17
18#[derive(Debug, Clone, PartialEq, Eq, Hash)]
19pub struct Std {
20 pub build_compiler: Compiler,
22 pub target: TargetSelection,
23 crates: Vec<String>,
29}
30
31impl Std {
32 const CRATE_OR_DEPS: &[&str] = &["sysroot", "coretests", "alloctests"];
33}
34
35impl Step for Std {
36 type Output = ();
37 const DEFAULT: bool = true;
38
39 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
40 let mut run = run;
41 for c in Std::CRATE_OR_DEPS {
42 run = run.crate_or_deps(c);
43 }
44
45 run.path("library")
46 }
47
48 fn make_run(run: RunConfig<'_>) {
49 if !run.builder.download_rustc() && run.builder.config.skip_std_check_if_no_download_rustc {
50 eprintln!(
51 "WARNING: `--skip-std-check-if-no-download-rustc` flag was passed and `rust.download-rustc` is not available. Skipping."
52 );
53 return;
54 }
55
56 if run.builder.config.compile_time_deps {
57 return;
59 }
60
61 let crates = std_crates_for_run_make(&run);
62 run.builder.ensure(Std {
63 build_compiler: prepare_compiler_for_check(run.builder, run.target, Mode::Std),
64 target: run.target,
65 crates,
66 });
67 }
68
69 fn run(self, builder: &Builder<'_>) {
70 let build_compiler = self.build_compiler;
71 let target = self.target;
72
73 let mut cargo = builder::Cargo::new(
74 builder,
75 build_compiler,
76 Mode::Std,
77 SourceType::InTree,
78 target,
79 Kind::Check,
80 );
81
82 std_cargo(builder, target, &mut cargo);
83 if matches!(builder.config.cmd, Subcommand::Fix) {
84 cargo.arg("--lib");
86 }
87
88 for krate in &*self.crates {
89 cargo.arg("-p").arg(krate);
90 }
91
92 let _guard = builder.msg(
93 Kind::Check,
94 format_args!("library artifacts{}", crate_description(&self.crates)),
95 Mode::Std,
96 self.build_compiler,
97 target,
98 );
99
100 let stamp = build_stamp::libstd_stamp(builder, build_compiler, target).with_prefix("check");
101 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
102
103 drop(_guard);
104
105 if !self.crates.iter().any(|krate| krate == "test") {
107 return;
108 }
109
110 let mut cargo = builder::Cargo::new(
117 builder,
118 build_compiler,
119 Mode::Std,
120 SourceType::InTree,
121 target,
122 Kind::Check,
123 );
124
125 std_cargo(builder, target, &mut cargo);
126
127 for krate in &*self.crates {
131 cargo.arg("-p").arg(krate);
132 }
133
134 let stamp =
135 build_stamp::libstd_stamp(builder, build_compiler, target).with_prefix("check-test");
136 let _guard = builder.msg(
137 Kind::Check,
138 "library test/bench/example targets",
139 Mode::Std,
140 self.build_compiler,
141 target,
142 );
143 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
144 }
145
146 fn metadata(&self) -> Option<StepMetadata> {
147 Some(StepMetadata::check("std", self.target).built_by(self.build_compiler))
148 }
149}
150
151#[derive(Debug, Clone, PartialEq, Eq, Hash)]
154pub struct Rustc {
155 pub build_compiler: Compiler,
157 pub target: TargetSelection,
158 crates: Vec<String>,
164}
165
166impl Rustc {
167 pub fn new(builder: &Builder<'_>, target: TargetSelection, crates: Vec<String>) -> Self {
168 let build_compiler = prepare_compiler_for_check(builder, target, Mode::Rustc);
169 Self { build_compiler, target, crates }
170 }
171}
172
173impl Step for Rustc {
174 type Output = ();
175 const IS_HOST: bool = true;
176 const DEFAULT: bool = true;
177
178 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
179 run.crate_or_deps("rustc-main").path("compiler")
180 }
181
182 fn make_run(run: RunConfig<'_>) {
183 let crates = run.make_run_crates(Alias::Compiler);
184 run.builder.ensure(Rustc::new(run.builder, run.target, crates));
185 }
186
187 fn run(self, builder: &Builder<'_>) {
195 let build_compiler = self.build_compiler;
196 let target = self.target;
197
198 let mut cargo = builder::Cargo::new(
199 builder,
200 build_compiler,
201 Mode::Rustc,
202 SourceType::InTree,
203 target,
204 Kind::Check,
205 );
206
207 rustc_cargo(builder, &mut cargo, target, &build_compiler, &self.crates);
208
209 for krate in &*self.crates {
213 cargo.arg("-p").arg(krate);
214 }
215
216 let _guard = builder.msg(
217 Kind::Check,
218 format_args!("compiler artifacts{}", crate_description(&self.crates)),
219 Mode::Rustc,
220 self.build_compiler,
221 target,
222 );
223
224 let stamp =
225 build_stamp::librustc_stamp(builder, build_compiler, target).with_prefix("check");
226
227 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
228
229 let libdir = builder.sysroot_target_libdir(build_compiler, target);
230 let hostdir = builder.sysroot_target_libdir(build_compiler, build_compiler.host);
231 add_to_sysroot(builder, &libdir, &hostdir, &stamp);
232 }
233
234 fn metadata(&self) -> Option<StepMetadata> {
235 let metadata = StepMetadata::check("rustc", self.target).built_by(self.build_compiler);
236 let metadata = if self.crates.is_empty() {
237 metadata
238 } else {
239 metadata.with_metadata(format!("({} crates)", self.crates.len()))
240 };
241 Some(metadata)
242 }
243}
244
245pub fn prepare_compiler_for_check(
247 builder: &Builder<'_>,
248 target: TargetSelection,
249 mode: Mode,
250) -> Compiler {
251 let host = builder.host_target;
252
253 match mode {
254 Mode::ToolBootstrap => builder.compiler(0, host),
255 Mode::ToolTarget => get_tool_target_compiler(builder, ToolTargetBuildMode::Build(target)),
256 Mode::ToolStd => {
257 if builder.config.compile_time_deps {
258 return builder.compiler(0, host);
262 }
263
264 let build_compiler = builder.compiler(builder.top_stage, host);
266
267 builder.std(build_compiler, host);
270 builder.std(build_compiler, target);
274 build_compiler
275 }
276 Mode::ToolRustc | Mode::Codegen => {
277 let check = Rustc::new(builder, target, vec![]);
282 let build_compiler = check.build_compiler;
283 builder.ensure(check);
284 build_compiler
285 }
286 Mode::Rustc => {
287 let stage = if host == target { builder.top_stage - 1 } else { builder.top_stage };
295 let build_compiler = builder.compiler(stage, host);
296
297 builder.std(build_compiler, build_compiler.host);
299
300 builder.std(build_compiler, target);
305
306 build_compiler
307 }
308 Mode::Std => {
309 builder.compiler(builder.top_stage, host)
313 }
314 }
315}
316
317#[derive(Debug, Clone, PartialEq, Eq, Hash)]
319pub struct CraneliftCodegenBackend {
320 build_compiler: Compiler,
321 target: TargetSelection,
322}
323
324impl Step for CraneliftCodegenBackend {
325 type Output = ();
326
327 const IS_HOST: bool = true;
328 const DEFAULT: bool = true;
329
330 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
331 run.alias("rustc_codegen_cranelift").alias("cg_clif")
332 }
333
334 fn make_run(run: RunConfig<'_>) {
335 let build_compiler = prepare_compiler_for_check(run.builder, run.target, Mode::Codegen);
336 run.builder.ensure(CraneliftCodegenBackend { build_compiler, target: run.target });
337 }
338
339 fn run(self, builder: &Builder<'_>) {
340 let build_compiler = self.build_compiler;
341 let target = self.target;
342
343 let mut cargo = builder::Cargo::new(
344 builder,
345 build_compiler,
346 Mode::Codegen,
347 SourceType::InTree,
348 target,
349 builder.kind,
350 );
351
352 cargo
353 .arg("--manifest-path")
354 .arg(builder.src.join("compiler/rustc_codegen_cranelift/Cargo.toml"));
355 rustc_cargo_env(builder, &mut cargo, target);
356
357 let _guard = builder.msg(
358 Kind::Check,
359 "rustc_codegen_cranelift",
360 Mode::Codegen,
361 self.build_compiler,
362 target,
363 );
364
365 let stamp = build_stamp::codegen_backend_stamp(
366 builder,
367 build_compiler,
368 target,
369 &CodegenBackendKind::Cranelift,
370 )
371 .with_prefix("check");
372
373 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
374 }
375
376 fn metadata(&self) -> Option<StepMetadata> {
377 Some(
378 StepMetadata::check("rustc_codegen_cranelift", self.target)
379 .built_by(self.build_compiler),
380 )
381 }
382}
383
384#[derive(Debug, Clone, PartialEq, Eq, Hash)]
386pub struct GccCodegenBackend {
387 build_compiler: Compiler,
388 target: TargetSelection,
389}
390
391impl Step for GccCodegenBackend {
392 type Output = ();
393
394 const IS_HOST: bool = true;
395 const DEFAULT: bool = true;
396
397 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
398 run.alias("rustc_codegen_gcc").alias("cg_gcc")
399 }
400
401 fn make_run(run: RunConfig<'_>) {
402 let build_compiler = prepare_compiler_for_check(run.builder, run.target, Mode::Codegen);
403 run.builder.ensure(GccCodegenBackend { build_compiler, target: run.target });
404 }
405
406 fn run(self, builder: &Builder<'_>) {
407 if builder.build.config.vendor {
409 println!("Skipping checking of `rustc_codegen_gcc` with vendoring enabled.");
410 return;
411 }
412
413 let build_compiler = self.build_compiler;
414 let target = self.target;
415
416 let mut cargo = builder::Cargo::new(
417 builder,
418 build_compiler,
419 Mode::Codegen,
420 SourceType::InTree,
421 target,
422 builder.kind,
423 );
424
425 cargo.arg("--manifest-path").arg(builder.src.join("compiler/rustc_codegen_gcc/Cargo.toml"));
426 rustc_cargo_env(builder, &mut cargo, target);
427
428 let _guard = builder.msg(
429 Kind::Check,
430 "rustc_codegen_gcc",
431 Mode::Codegen,
432 self.build_compiler,
433 target,
434 );
435
436 let stamp = build_stamp::codegen_backend_stamp(
437 builder,
438 build_compiler,
439 target,
440 &CodegenBackendKind::Gcc,
441 )
442 .with_prefix("check");
443
444 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
445 }
446
447 fn metadata(&self) -> Option<StepMetadata> {
448 Some(StepMetadata::check("rustc_codegen_gcc", self.target).built_by(self.build_compiler))
449 }
450}
451
452macro_rules! tool_check_step {
453 (
454 $name:ident {
455 path: $path:literal
457 $(, alt_path: $alt_path:literal )*
458 , mode: $mode:expr
460 $(, allow_features: $allow_features:expr )?
462 $(, enable_features: [$($enable_features:expr),*] )?
464 $(, default: $default:literal )?
465 $( , )?
466 }
467 ) => {
468 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
469 pub struct $name {
470 pub build_compiler: Compiler,
471 pub target: TargetSelection,
472 }
473
474 impl Step for $name {
475 type Output = ();
476 const IS_HOST: bool = true;
477 const DEFAULT: bool = true $( && $default )?;
479
480 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
481 run.paths(&[ $path, $( $alt_path ),* ])
482 }
483
484 fn make_run(run: RunConfig<'_>) {
485 let target = run.target;
486 let builder = run.builder;
487 let mode = $mode(builder);
488
489 let build_compiler = prepare_compiler_for_check(run.builder, target, mode);
490
491 if mode == Mode::ToolBootstrap && target != run.builder.host_target {
493 println!("WARNING: not checking bootstrap tool {} for target {target} as it is a bootstrap (host-only) tool", stringify!($path));
494 return;
495 };
496
497 run.builder.ensure($name { target, build_compiler });
498 }
499
500 fn run(self, builder: &Builder<'_>) {
501 let Self { target, build_compiler } = self;
502 let allow_features = {
503 let mut _value = "";
504 $( _value = $allow_features; )?
505 _value
506 };
507 let extra_features: &[&str] = &[$($($enable_features),*)?];
508 let mode = $mode(builder);
509 run_tool_check_step(builder, build_compiler, target, $path, mode, allow_features, extra_features);
510 }
511
512 fn metadata(&self) -> Option<StepMetadata> {
513 Some(StepMetadata::check(stringify!($name), self.target).built_by(self.build_compiler))
514 }
515 }
516 }
517}
518
519fn run_tool_check_step(
521 builder: &Builder<'_>,
522 build_compiler: Compiler,
523 target: TargetSelection,
524 path: &str,
525 mode: Mode,
526 allow_features: &str,
527 extra_features: &[&str],
528) {
529 let display_name = path.rsplit('/').next().unwrap();
530
531 let extra_features = extra_features.iter().map(|f| f.to_string()).collect::<Vec<String>>();
532 let mut cargo = prepare_tool_cargo(
533 builder,
534 build_compiler,
535 mode,
536 target,
537 builder.kind,
538 path,
539 SourceType::InTree,
544 &extra_features,
545 );
546 cargo.allow_features(allow_features);
547
548 if display_name == "rust-analyzer" {
551 cargo.arg("--bins");
552 cargo.arg("--tests");
553 cargo.arg("--benches");
554 } else {
555 cargo.arg("--all-targets");
556 }
557
558 let stamp = BuildStamp::new(&builder.cargo_out(build_compiler, mode, target))
559 .with_prefix(&format!("{display_name}-check"));
560
561 let _guard = builder.msg(builder.kind, display_name, mode, build_compiler, target);
562 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
563}
564
565tool_check_step!(Rustdoc {
566 path: "src/tools/rustdoc",
567 alt_path: "src/librustdoc",
568 mode: |_builder| Mode::ToolRustc
569});
570tool_check_step!(Clippy { path: "src/tools/clippy", mode: |_builder| Mode::ToolRustc });
575tool_check_step!(Miri { path: "src/tools/miri", mode: |_builder| Mode::ToolRustc });
576tool_check_step!(CargoMiri { path: "src/tools/miri/cargo-miri", mode: |_builder| Mode::ToolRustc });
577tool_check_step!(Rustfmt { path: "src/tools/rustfmt", mode: |_builder| Mode::ToolRustc });
578tool_check_step!(RustAnalyzer {
579 path: "src/tools/rust-analyzer",
580 mode: |_builder| Mode::ToolRustc,
581 allow_features: tool::RustAnalyzer::ALLOW_FEATURES,
582 enable_features: ["in-rust-tree"],
583});
584tool_check_step!(MiroptTestTools {
585 path: "src/tools/miropt-test-tools",
586 mode: |_builder| Mode::ToolBootstrap
587});
588tool_check_step!(TestFloatParse {
590 path: "src/tools/test-float-parse",
591 mode: |_builder| Mode::ToolStd,
592 allow_features: tool::TestFloatParse::ALLOW_FEATURES
593});
594tool_check_step!(FeaturesStatusDump {
595 path: "src/tools/features-status-dump",
596 mode: |_builder| Mode::ToolBootstrap
597});
598
599tool_check_step!(Bootstrap {
600 path: "src/bootstrap",
601 mode: |_builder| Mode::ToolBootstrap,
602 default: false
603});
604
605tool_check_step!(RunMakeSupport {
608 path: "src/tools/run-make-support",
609 mode: |_builder| Mode::ToolBootstrap,
610 default: false
611});
612
613tool_check_step!(CoverageDump {
614 path: "src/tools/coverage-dump",
615 mode: |_builder| Mode::ToolBootstrap,
616 default: false
617});
618
619tool_check_step!(Compiletest {
622 path: "src/tools/compiletest",
623 mode: |builder: &Builder<'_>| if builder.config.compiletest_use_stage0_libtest {
624 Mode::ToolBootstrap
625 } else {
626 Mode::ToolStd
627 },
628 allow_features: COMPILETEST_ALLOW_FEATURES,
629 default: false,
630});
631
632tool_check_step!(Linkchecker {
633 path: "src/tools/linkchecker",
634 mode: |_builder| Mode::ToolBootstrap,
635 default: false
636});