1use std::fs;
4use std::path::{Path, PathBuf};
5
6use crate::core::build_steps::compile::{
7 add_to_sysroot, run_cargo, rustc_cargo, rustc_cargo_env, std_cargo, std_crates_for_run_make,
8};
9use crate::core::build_steps::tool;
10use crate::core::build_steps::tool::{
11 COMPILETEST_ALLOW_FEATURES, SourceType, TEST_FLOAT_PARSE_ALLOW_FEATURES, ToolTargetBuildMode,
12 get_tool_target_compiler, prepare_tool_cargo,
13};
14use crate::core::builder::{
15 self, Alias, Builder, Cargo, Kind, RunConfig, ShouldRun, Step, StepMetadata, crate_description,
16};
17use crate::core::config::TargetSelection;
18use crate::utils::build_stamp::{self, BuildStamp};
19use crate::{CodegenBackendKind, Compiler, Mode, Subcommand, t};
20
21#[derive(Debug, Clone, PartialEq, Eq, Hash)]
22pub struct Std {
23 pub build_compiler: Compiler,
25 pub target: TargetSelection,
26 crates: Vec<String>,
32}
33
34impl Std {
35 const CRATE_OR_DEPS: &[&str] = &["sysroot", "coretests", "alloctests"];
36}
37
38impl Step for Std {
39 type Output = BuildStamp;
40 const DEFAULT: bool = true;
41
42 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
43 let mut run = run;
44 for c in Std::CRATE_OR_DEPS {
45 run = run.crate_or_deps(c);
46 }
47
48 run.path("library")
49 }
50
51 fn make_run(run: RunConfig<'_>) {
52 if !run.builder.download_rustc() && run.builder.config.skip_std_check_if_no_download_rustc {
53 eprintln!(
54 "WARNING: `--skip-std-check-if-no-download-rustc` flag was passed and `rust.download-rustc` is not available. Skipping."
55 );
56 return;
57 }
58
59 if run.builder.config.compile_time_deps {
60 return;
62 }
63
64 let crates = std_crates_for_run_make(&run);
65 run.builder.ensure(Std {
66 build_compiler: prepare_compiler_for_check(run.builder, run.target, Mode::Std)
67 .build_compiler(),
68 target: run.target,
69 crates,
70 });
71 }
72
73 fn run(self, builder: &Builder<'_>) -> Self::Output {
74 let build_compiler = self.build_compiler;
75 let target = self.target;
76
77 let mut cargo = builder::Cargo::new(
78 builder,
79 build_compiler,
80 Mode::Std,
81 SourceType::InTree,
82 target,
83 Kind::Check,
84 );
85
86 std_cargo(builder, target, &mut cargo);
87 if matches!(builder.config.cmd, Subcommand::Fix) {
88 cargo.arg("--lib");
90 }
91
92 for krate in &*self.crates {
93 cargo.arg("-p").arg(krate);
94 }
95
96 let _guard = builder.msg(
97 Kind::Check,
98 format_args!("library artifacts{}", crate_description(&self.crates)),
99 Mode::Std,
100 build_compiler,
101 target,
102 );
103
104 let check_stamp =
105 build_stamp::libstd_stamp(builder, build_compiler, target).with_prefix("check");
106 run_cargo(
107 builder,
108 cargo,
109 builder.config.free_args.clone(),
110 &check_stamp,
111 vec![],
112 true,
113 false,
114 );
115
116 drop(_guard);
117
118 if !self.crates.iter().any(|krate| krate == "test") {
120 return check_stamp;
121 }
122
123 let mut cargo = builder::Cargo::new(
130 builder,
131 build_compiler,
132 Mode::Std,
133 SourceType::InTree,
134 target,
135 Kind::Check,
136 );
137
138 std_cargo(builder, target, &mut cargo);
139
140 for krate in &*self.crates {
144 cargo.arg("-p").arg(krate);
145 }
146
147 let stamp =
148 build_stamp::libstd_stamp(builder, build_compiler, target).with_prefix("check-test");
149 let _guard = builder.msg(
150 Kind::Check,
151 "library test/bench/example targets",
152 Mode::Std,
153 build_compiler,
154 target,
155 );
156 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
157 check_stamp
158 }
159
160 fn metadata(&self) -> Option<StepMetadata> {
161 Some(StepMetadata::check("std", self.target).built_by(self.build_compiler))
162 }
163}
164
165#[derive(Debug, Clone, PartialEq, Eq, Hash)]
169struct RmetaSysroot {
170 host_dir: PathBuf,
171 target_dir: PathBuf,
172}
173
174impl RmetaSysroot {
175 fn from_stamp(
177 builder: &Builder<'_>,
178 stamp: BuildStamp,
179 target: TargetSelection,
180 directory: &Path,
181 ) -> Self {
182 let host_dir = directory.join("host");
183 let target_dir = directory.join(target);
184 let _ = fs::remove_dir_all(directory);
185 t!(fs::create_dir_all(directory));
186 add_to_sysroot(builder, &target_dir, &host_dir, &stamp);
187
188 Self { host_dir, target_dir }
189 }
190
191 fn configure_cargo(&self, cargo: &mut Cargo) {
194 cargo.append_to_env(
195 "RUSTC_ADDITIONAL_SYSROOT_PATHS",
196 format!("{},{}", self.host_dir.to_str().unwrap(), self.target_dir.to_str().unwrap()),
197 ",",
198 );
199 }
200}
201
202#[derive(Debug, Clone, PartialEq, Eq, Hash)]
209struct PrepareRustcRmetaSysroot {
210 build_compiler: CompilerForCheck,
211 target: TargetSelection,
212}
213
214impl PrepareRustcRmetaSysroot {
215 fn new(build_compiler: CompilerForCheck, target: TargetSelection) -> Self {
216 Self { build_compiler, target }
217 }
218}
219
220impl Step for PrepareRustcRmetaSysroot {
221 type Output = RmetaSysroot;
222
223 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
224 run.never()
225 }
226
227 fn run(self, builder: &Builder<'_>) -> Self::Output {
228 let stamp = builder.ensure(Rustc::from_build_compiler(
230 self.build_compiler.clone(),
231 self.target,
232 vec![],
233 ));
234
235 let build_compiler = self.build_compiler.build_compiler();
236
237 let dir = builder
239 .out
240 .join(build_compiler.host)
241 .join(format!("stage{}-rustc-rmeta-artifacts", build_compiler.stage + 1));
242 RmetaSysroot::from_stamp(builder, stamp, self.target, &dir)
243 }
244}
245
246#[derive(Debug, Clone, PartialEq, Eq, Hash)]
253struct PrepareStdRmetaSysroot {
254 build_compiler: Compiler,
255 target: TargetSelection,
256}
257
258impl PrepareStdRmetaSysroot {
259 fn new(build_compiler: Compiler, target: TargetSelection) -> Self {
260 Self { build_compiler, target }
261 }
262}
263
264impl Step for PrepareStdRmetaSysroot {
265 type Output = RmetaSysroot;
266
267 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
268 run.never()
269 }
270
271 fn run(self, builder: &Builder<'_>) -> Self::Output {
272 let stamp = builder.ensure(Std {
274 build_compiler: self.build_compiler,
275 target: self.target,
276 crates: vec![],
277 });
278
279 let dir = builder
281 .out
282 .join(self.build_compiler.host)
283 .join(format!("stage{}-std-rmeta-artifacts", self.build_compiler.stage));
284
285 RmetaSysroot::from_stamp(builder, stamp, self.target, &dir)
286 }
287}
288
289#[derive(Debug, Clone, PartialEq, Eq, Hash)]
291pub struct Rustc {
292 pub build_compiler: CompilerForCheck,
294 pub target: TargetSelection,
295 crates: Vec<String>,
301}
302
303impl Rustc {
304 pub fn new(builder: &Builder<'_>, target: TargetSelection, crates: Vec<String>) -> Self {
305 let build_compiler = prepare_compiler_for_check(builder, target, Mode::Rustc);
306 Self::from_build_compiler(build_compiler, target, crates)
307 }
308
309 fn from_build_compiler(
310 build_compiler: CompilerForCheck,
311 target: TargetSelection,
312 crates: Vec<String>,
313 ) -> Self {
314 Self { build_compiler, target, crates }
315 }
316}
317
318impl Step for Rustc {
319 type Output = BuildStamp;
320 const IS_HOST: bool = true;
321 const DEFAULT: bool = true;
322
323 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
324 run.crate_or_deps("rustc-main").path("compiler")
325 }
326
327 fn make_run(run: RunConfig<'_>) {
328 let crates = run.make_run_crates(Alias::Compiler);
329 run.builder.ensure(Rustc::new(run.builder, run.target, crates));
330 }
331
332 fn run(self, builder: &Builder<'_>) -> Self::Output {
340 let build_compiler = self.build_compiler.build_compiler;
341 let target = self.target;
342
343 let mut cargo = builder::Cargo::new(
344 builder,
345 build_compiler,
346 Mode::Rustc,
347 SourceType::InTree,
348 target,
349 Kind::Check,
350 );
351
352 rustc_cargo(builder, &mut cargo, target, &build_compiler, &self.crates);
353 self.build_compiler.configure_cargo(&mut cargo);
354
355 for krate in &*self.crates {
359 cargo.arg("-p").arg(krate);
360 }
361
362 let _guard = builder.msg(
363 Kind::Check,
364 format_args!("compiler artifacts{}", crate_description(&self.crates)),
365 Mode::Rustc,
366 self.build_compiler.build_compiler(),
367 target,
368 );
369
370 let stamp =
371 build_stamp::librustc_stamp(builder, build_compiler, target).with_prefix("check");
372
373 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
374
375 stamp
376 }
377
378 fn metadata(&self) -> Option<StepMetadata> {
379 let metadata = StepMetadata::check("rustc", self.target)
380 .built_by(self.build_compiler.build_compiler());
381 let metadata = if self.crates.is_empty() {
382 metadata
383 } else {
384 metadata.with_metadata(format!("({} crates)", self.crates.len()))
385 };
386 Some(metadata)
387 }
388}
389
390#[derive(Debug, Clone, PartialEq, Eq, Hash)]
399pub struct CompilerForCheck {
400 build_compiler: Compiler,
401 rustc_rmeta_sysroot: Option<RmetaSysroot>,
402 std_rmeta_sysroot: Option<RmetaSysroot>,
403}
404
405impl CompilerForCheck {
406 pub fn build_compiler(&self) -> Compiler {
407 self.build_compiler
408 }
409
410 pub fn configure_cargo(&self, cargo: &mut Cargo) {
413 if let Some(sysroot) = &self.rustc_rmeta_sysroot {
414 sysroot.configure_cargo(cargo);
415 }
416 if let Some(sysroot) = &self.std_rmeta_sysroot {
417 sysroot.configure_cargo(cargo);
418 }
419 }
420}
421
422fn prepare_std(
425 builder: &Builder<'_>,
426 build_compiler: Compiler,
427 target: TargetSelection,
428) -> Option<RmetaSysroot> {
429 builder.std(build_compiler, builder.host_target);
432
433 if builder.host_target != target {
437 Some(builder.ensure(PrepareStdRmetaSysroot::new(build_compiler, target)))
438 } else {
439 None
440 }
441}
442
443pub fn prepare_compiler_for_check(
445 builder: &Builder<'_>,
446 target: TargetSelection,
447 mode: Mode,
448) -> CompilerForCheck {
449 let host = builder.host_target;
450
451 let mut rustc_rmeta_sysroot = None;
452 let mut std_rmeta_sysroot = None;
453 let build_compiler = match mode {
454 Mode::ToolBootstrap => builder.compiler(0, host),
455 Mode::ToolTarget => get_tool_target_compiler(builder, ToolTargetBuildMode::Build(target)),
459 Mode::ToolStd => {
460 if builder.config.compile_time_deps {
461 builder.compiler(0, host)
465 } else {
466 let build_compiler = builder.compiler(builder.top_stage, host);
468 std_rmeta_sysroot = prepare_std(builder, build_compiler, target);
469 build_compiler
470 }
471 }
472 Mode::ToolRustcPrivate | Mode::Codegen => {
473 let compiler_for_rustc = prepare_compiler_for_check(builder, target, Mode::Rustc);
478 rustc_rmeta_sysroot = Some(
479 builder.ensure(PrepareRustcRmetaSysroot::new(compiler_for_rustc.clone(), target)),
480 );
481 let build_compiler = compiler_for_rustc.build_compiler();
482
483 std_rmeta_sysroot = prepare_std(builder, build_compiler, target);
485 build_compiler
486 }
487 Mode::Rustc => {
488 let stage = if host == target { builder.top_stage - 1 } else { builder.top_stage };
496 let build_compiler = builder.compiler(stage, host);
497
498 std_rmeta_sysroot = prepare_std(builder, build_compiler, target);
500 build_compiler
501 }
502 Mode::Std => {
503 builder.compiler(builder.top_stage, host)
507 }
508 };
509 CompilerForCheck { build_compiler, rustc_rmeta_sysroot, std_rmeta_sysroot }
510}
511
512#[derive(Debug, Clone, PartialEq, Eq, Hash)]
514pub struct CraneliftCodegenBackend {
515 build_compiler: CompilerForCheck,
516 target: TargetSelection,
517}
518
519impl Step for CraneliftCodegenBackend {
520 type Output = ();
521
522 const IS_HOST: bool = true;
523 const DEFAULT: bool = true;
524
525 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
526 run.alias("rustc_codegen_cranelift").alias("cg_clif")
527 }
528
529 fn make_run(run: RunConfig<'_>) {
530 run.builder.ensure(CraneliftCodegenBackend {
531 build_compiler: prepare_compiler_for_check(run.builder, run.target, Mode::Codegen),
532 target: run.target,
533 });
534 }
535
536 fn run(self, builder: &Builder<'_>) {
537 let build_compiler = self.build_compiler.build_compiler();
538 let target = self.target;
539
540 let mut cargo = builder::Cargo::new(
541 builder,
542 build_compiler,
543 Mode::Codegen,
544 SourceType::InTree,
545 target,
546 builder.kind,
547 );
548
549 cargo
550 .arg("--manifest-path")
551 .arg(builder.src.join("compiler/rustc_codegen_cranelift/Cargo.toml"));
552 rustc_cargo_env(builder, &mut cargo, target);
553 self.build_compiler.configure_cargo(&mut cargo);
554
555 let _guard = builder.msg(
556 Kind::Check,
557 "rustc_codegen_cranelift",
558 Mode::Codegen,
559 build_compiler,
560 target,
561 );
562
563 let stamp = build_stamp::codegen_backend_stamp(
564 builder,
565 build_compiler,
566 target,
567 &CodegenBackendKind::Cranelift,
568 )
569 .with_prefix("check");
570
571 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
572 }
573
574 fn metadata(&self) -> Option<StepMetadata> {
575 Some(
576 StepMetadata::check("rustc_codegen_cranelift", self.target)
577 .built_by(self.build_compiler.build_compiler()),
578 )
579 }
580}
581
582#[derive(Debug, Clone, PartialEq, Eq, Hash)]
584pub struct GccCodegenBackend {
585 build_compiler: CompilerForCheck,
586 target: TargetSelection,
587}
588
589impl Step for GccCodegenBackend {
590 type Output = ();
591
592 const IS_HOST: bool = true;
593 const DEFAULT: bool = true;
594
595 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
596 run.alias("rustc_codegen_gcc").alias("cg_gcc")
597 }
598
599 fn make_run(run: RunConfig<'_>) {
600 run.builder.ensure(GccCodegenBackend {
601 build_compiler: prepare_compiler_for_check(run.builder, run.target, Mode::Codegen),
602 target: run.target,
603 });
604 }
605
606 fn run(self, builder: &Builder<'_>) {
607 if builder.build.config.vendor {
609 println!("Skipping checking of `rustc_codegen_gcc` with vendoring enabled.");
610 return;
611 }
612
613 let build_compiler = self.build_compiler.build_compiler();
614 let target = self.target;
615
616 let mut cargo = builder::Cargo::new(
617 builder,
618 build_compiler,
619 Mode::Codegen,
620 SourceType::InTree,
621 target,
622 builder.kind,
623 );
624
625 cargo.arg("--manifest-path").arg(builder.src.join("compiler/rustc_codegen_gcc/Cargo.toml"));
626 rustc_cargo_env(builder, &mut cargo, target);
627 self.build_compiler.configure_cargo(&mut cargo);
628
629 let _guard =
630 builder.msg(Kind::Check, "rustc_codegen_gcc", Mode::Codegen, build_compiler, target);
631
632 let stamp = build_stamp::codegen_backend_stamp(
633 builder,
634 build_compiler,
635 target,
636 &CodegenBackendKind::Gcc,
637 )
638 .with_prefix("check");
639
640 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
641 }
642
643 fn metadata(&self) -> Option<StepMetadata> {
644 Some(
645 StepMetadata::check("rustc_codegen_gcc", self.target)
646 .built_by(self.build_compiler.build_compiler()),
647 )
648 }
649}
650
651macro_rules! tool_check_step {
652 (
653 $name:ident {
654 path: $path:literal
656 $(, alt_path: $alt_path:literal )*
657 , mode: $mode:expr
659 $(, allow_features: $allow_features:expr )?
661 $(, enable_features: [$($enable_features:expr),*] )?
663 $(, default: $default:literal )?
664 $( , )?
665 }
666 ) => {
667 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
668 pub struct $name {
669 compiler: CompilerForCheck,
670 target: TargetSelection,
671 }
672
673 impl Step for $name {
674 type Output = ();
675 const IS_HOST: bool = true;
676 const DEFAULT: bool = true $( && $default )?;
678
679 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
680 run.paths(&[ $path, $( $alt_path ),* ])
681 }
682
683 fn make_run(run: RunConfig<'_>) {
684 let target = run.target;
685 let builder = run.builder;
686 let mode = $mode(builder);
687
688 let compiler = prepare_compiler_for_check(run.builder, target, mode);
689
690 if mode == Mode::ToolBootstrap && target != run.builder.host_target {
692 println!("WARNING: not checking bootstrap tool {} for target {target} as it is a bootstrap (host-only) tool", stringify!($path));
693 return;
694 };
695
696 run.builder.ensure($name { target, compiler });
697 }
698
699 fn run(self, builder: &Builder<'_>) {
700 let Self { target, compiler } = self;
701 let allow_features = {
702 let mut _value = "";
703 $( _value = $allow_features; )?
704 _value
705 };
706 let extra_features: &[&str] = &[$($($enable_features),*)?];
707 let mode = $mode(builder);
708 run_tool_check_step(builder, compiler, target, $path, mode, allow_features, extra_features);
709 }
710
711 fn metadata(&self) -> Option<StepMetadata> {
712 Some(StepMetadata::check(stringify!($name), self.target).built_by(self.compiler.build_compiler))
713 }
714 }
715 }
716}
717
718fn run_tool_check_step(
720 builder: &Builder<'_>,
721 compiler: CompilerForCheck,
722 target: TargetSelection,
723 path: &str,
724 mode: Mode,
725 allow_features: &str,
726 extra_features: &[&str],
727) {
728 let display_name = path.rsplit('/').next().unwrap();
729
730 let build_compiler = compiler.build_compiler();
731
732 let extra_features = extra_features.iter().map(|f| f.to_string()).collect::<Vec<String>>();
733 let mut cargo = prepare_tool_cargo(
734 builder,
735 build_compiler,
736 mode,
737 target,
738 builder.kind,
739 path,
740 SourceType::InTree,
745 &extra_features,
746 );
747 cargo.allow_features(allow_features);
748 compiler.configure_cargo(&mut cargo);
749
750 if display_name == "rust-analyzer" {
753 cargo.arg("--bins");
754 cargo.arg("--tests");
755 cargo.arg("--benches");
756 } else {
757 cargo.arg("--all-targets");
758 }
759
760 let stamp = BuildStamp::new(&builder.cargo_out(build_compiler, mode, target))
761 .with_prefix(&format!("{display_name}-check"));
762
763 let _guard = builder.msg(builder.kind, display_name, mode, build_compiler, target);
764 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
765}
766
767tool_check_step!(Rustdoc {
768 path: "src/tools/rustdoc",
769 alt_path: "src/librustdoc",
770 mode: |_builder| Mode::ToolRustcPrivate
771});
772tool_check_step!(Clippy { path: "src/tools/clippy", mode: |_builder| Mode::ToolRustcPrivate });
777tool_check_step!(Miri { path: "src/tools/miri", mode: |_builder| Mode::ToolRustcPrivate });
778tool_check_step!(CargoMiri {
779 path: "src/tools/miri/cargo-miri",
780 mode: |_builder| Mode::ToolRustcPrivate
781});
782tool_check_step!(Rustfmt { path: "src/tools/rustfmt", mode: |_builder| Mode::ToolRustcPrivate });
783tool_check_step!(RustAnalyzer {
784 path: "src/tools/rust-analyzer",
785 mode: |_builder| Mode::ToolRustcPrivate,
786 allow_features: tool::RustAnalyzer::ALLOW_FEATURES,
787 enable_features: ["in-rust-tree"],
788});
789tool_check_step!(MiroptTestTools {
790 path: "src/tools/miropt-test-tools",
791 mode: |_builder| Mode::ToolBootstrap
792});
793tool_check_step!(TestFloatParse {
795 path: "src/tools/test-float-parse",
796 mode: |_builder| Mode::ToolStd,
797 allow_features: TEST_FLOAT_PARSE_ALLOW_FEATURES
798});
799tool_check_step!(FeaturesStatusDump {
800 path: "src/tools/features-status-dump",
801 mode: |_builder| Mode::ToolBootstrap
802});
803
804tool_check_step!(Bootstrap {
805 path: "src/bootstrap",
806 mode: |_builder| Mode::ToolBootstrap,
807 default: false
808});
809
810tool_check_step!(RunMakeSupport {
813 path: "src/tools/run-make-support",
814 mode: |_builder| Mode::ToolBootstrap,
815 default: false
816});
817
818tool_check_step!(CoverageDump {
819 path: "src/tools/coverage-dump",
820 mode: |_builder| Mode::ToolBootstrap,
821 default: false
822});
823
824tool_check_step!(Compiletest {
827 path: "src/tools/compiletest",
828 mode: |builder: &Builder<'_>| if builder.config.compiletest_use_stage0_libtest {
829 Mode::ToolBootstrap
830 } else {
831 Mode::ToolStd
832 },
833 allow_features: COMPILETEST_ALLOW_FEATURES,
834 default: false,
835});
836
837tool_check_step!(Linkchecker {
838 path: "src/tools/linkchecker",
839 mode: |_builder| Mode::ToolBootstrap,
840 default: false
841});
842
843tool_check_step!(BumpStage0 {
844 path: "src/tools/bump-stage0",
845 mode: |_builder| Mode::ToolBootstrap,
846 default: false
847});