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 SourceType, TEST_FLOAT_PARSE_ALLOW_FEATURES, ToolTargetBuildMode, get_tool_target_compiler,
12 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
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 is_default_step(_builder: &Builder<'_>) -> bool {
51 true
52 }
53
54 fn make_run(run: RunConfig<'_>) {
55 if !run.builder.download_rustc() && run.builder.config.skip_std_check_if_no_download_rustc {
56 eprintln!(
57 "WARNING: `--skip-std-check-if-no-download-rustc` flag was passed and `rust.download-rustc` is not available. Skipping."
58 );
59 return;
60 }
61
62 if run.builder.config.compile_time_deps {
63 return;
65 }
66
67 let crates = std_crates_for_run_make(&run);
71 run.builder.ensure(Std {
72 build_compiler: prepare_compiler_for_check(run.builder, run.target, Mode::Std)
73 .build_compiler(),
74 target: run.target,
75 crates,
76 });
77 }
78
79 fn run(self, builder: &Builder<'_>) -> Self::Output {
80 let build_compiler = self.build_compiler;
81 let target = self.target;
82
83 let mut cargo = builder::Cargo::new(
84 builder,
85 build_compiler,
86 Mode::Std,
87 SourceType::InTree,
88 target,
89 Kind::Check,
90 );
91
92 std_cargo(builder, target, &mut cargo, &self.crates);
93 if matches!(builder.config.cmd, Subcommand::Fix) {
94 cargo.arg("--lib");
96 }
97
98 let _guard = builder.msg(
99 Kind::Check,
100 format_args!("library artifacts{}", crate_description(&self.crates)),
101 Mode::Std,
102 build_compiler,
103 target,
104 );
105
106 let check_stamp =
107 build_stamp::libstd_stamp(builder, build_compiler, target).with_prefix("check");
108 run_cargo(
109 builder,
110 cargo,
111 builder.config.free_args.clone(),
112 &check_stamp,
113 vec![],
114 true,
115 false,
116 );
117
118 drop(_guard);
119
120 if !self.crates.iter().any(|krate| krate == "test") {
122 return check_stamp;
123 }
124
125 let mut cargo = builder::Cargo::new(
132 builder,
133 build_compiler,
134 Mode::Std,
135 SourceType::InTree,
136 target,
137 Kind::Check,
138 );
139
140 std_cargo(builder, target, &mut cargo, &self.crates);
141
142 let stamp =
143 build_stamp::libstd_stamp(builder, build_compiler, target).with_prefix("check-test");
144 let _guard = builder.msg(
145 Kind::Check,
146 "library test/bench/example targets",
147 Mode::Std,
148 build_compiler,
149 target,
150 );
151 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
152 check_stamp
153 }
154
155 fn metadata(&self) -> Option<StepMetadata> {
156 Some(StepMetadata::check("std", self.target).built_by(self.build_compiler))
157 }
158}
159
160#[derive(Debug, Clone, PartialEq, Eq, Hash)]
164struct RmetaSysroot {
165 host_dir: PathBuf,
166 target_dir: PathBuf,
167}
168
169impl RmetaSysroot {
170 fn from_stamp(
172 builder: &Builder<'_>,
173 stamp: BuildStamp,
174 target: TargetSelection,
175 directory: &Path,
176 ) -> Self {
177 let host_dir = directory.join("host");
178 let target_dir = directory.join(target);
179 let _ = fs::remove_dir_all(directory);
180 t!(fs::create_dir_all(directory));
181 add_to_sysroot(builder, &target_dir, &host_dir, &stamp);
182
183 Self { host_dir, target_dir }
184 }
185
186 fn configure_cargo(&self, cargo: &mut Cargo) {
189 cargo.append_to_env(
190 "RUSTC_ADDITIONAL_SYSROOT_PATHS",
191 format!("{},{}", self.host_dir.to_str().unwrap(), self.target_dir.to_str().unwrap()),
192 ",",
193 );
194 }
195}
196
197#[derive(Debug, Clone, PartialEq, Eq, Hash)]
204struct PrepareRustcRmetaSysroot {
205 build_compiler: CompilerForCheck,
206 target: TargetSelection,
207}
208
209impl PrepareRustcRmetaSysroot {
210 fn new(build_compiler: CompilerForCheck, target: TargetSelection) -> Self {
211 Self { build_compiler, target }
212 }
213}
214
215impl Step for PrepareRustcRmetaSysroot {
216 type Output = RmetaSysroot;
217
218 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
219 run.never()
220 }
221
222 fn run(self, builder: &Builder<'_>) -> Self::Output {
223 let stamp = builder.ensure(Rustc::from_build_compiler(
225 self.build_compiler.clone(),
226 self.target,
227 vec![],
228 ));
229
230 let build_compiler = self.build_compiler.build_compiler();
231
232 let dir = builder
234 .out
235 .join(build_compiler.host)
236 .join(format!("stage{}-rustc-rmeta-artifacts", build_compiler.stage + 1));
237 RmetaSysroot::from_stamp(builder, stamp, self.target, &dir)
238 }
239}
240
241#[derive(Debug, Clone, PartialEq, Eq, Hash)]
248struct PrepareStdRmetaSysroot {
249 build_compiler: Compiler,
250 target: TargetSelection,
251}
252
253impl PrepareStdRmetaSysroot {
254 fn new(build_compiler: Compiler, target: TargetSelection) -> Self {
255 Self { build_compiler, target }
256 }
257}
258
259impl Step for PrepareStdRmetaSysroot {
260 type Output = RmetaSysroot;
261
262 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
263 run.never()
264 }
265
266 fn run(self, builder: &Builder<'_>) -> Self::Output {
267 let stamp = builder.ensure(Std {
269 build_compiler: self.build_compiler,
270 target: self.target,
271 crates: vec![],
272 });
273
274 let dir = builder
276 .out
277 .join(self.build_compiler.host)
278 .join(format!("stage{}-std-rmeta-artifacts", self.build_compiler.stage));
279
280 RmetaSysroot::from_stamp(builder, stamp, self.target, &dir)
281 }
282}
283
284#[derive(Debug, Clone, PartialEq, Eq, Hash)]
286pub struct Rustc {
287 pub build_compiler: CompilerForCheck,
289 pub target: TargetSelection,
290 crates: Vec<String>,
296}
297
298impl Rustc {
299 pub fn new(builder: &Builder<'_>, target: TargetSelection, crates: Vec<String>) -> Self {
300 let build_compiler = prepare_compiler_for_check(builder, target, Mode::Rustc);
301 Self::from_build_compiler(build_compiler, target, crates)
302 }
303
304 fn from_build_compiler(
305 build_compiler: CompilerForCheck,
306 target: TargetSelection,
307 crates: Vec<String>,
308 ) -> Self {
309 Self { build_compiler, target, crates }
310 }
311}
312
313impl Step for Rustc {
314 type Output = BuildStamp;
315 const IS_HOST: bool = true;
316
317 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
318 run.crate_or_deps("rustc-main").path("compiler")
319 }
320
321 fn is_default_step(_builder: &Builder<'_>) -> bool {
322 true
323 }
324
325 fn make_run(run: RunConfig<'_>) {
326 let crates = run.make_run_crates(Alias::Compiler);
327 run.builder.ensure(Rustc::new(run.builder, run.target, crates));
328 }
329
330 fn run(self, builder: &Builder<'_>) -> Self::Output {
338 let build_compiler = self.build_compiler.build_compiler;
339 let target = self.target;
340
341 let mut cargo = builder::Cargo::new(
342 builder,
343 build_compiler,
344 Mode::Rustc,
345 SourceType::InTree,
346 target,
347 Kind::Check,
348 );
349
350 rustc_cargo(builder, &mut cargo, target, &build_compiler, &self.crates);
351 self.build_compiler.configure_cargo(&mut cargo);
352
353 for krate in &*self.crates {
357 cargo.arg("-p").arg(krate);
358 }
359
360 let _guard = builder.msg(
361 Kind::Check,
362 format_args!("compiler artifacts{}", crate_description(&self.crates)),
363 Mode::Rustc,
364 self.build_compiler.build_compiler(),
365 target,
366 );
367
368 let stamp =
369 build_stamp::librustc_stamp(builder, build_compiler, target).with_prefix("check");
370
371 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
372
373 stamp
374 }
375
376 fn metadata(&self) -> Option<StepMetadata> {
377 let metadata = StepMetadata::check("rustc", self.target)
378 .built_by(self.build_compiler.build_compiler());
379 let metadata = if self.crates.is_empty() {
380 metadata
381 } else {
382 metadata.with_metadata(format!("({} crates)", self.crates.len()))
383 };
384 Some(metadata)
385 }
386}
387
388#[derive(Debug, Clone, PartialEq, Eq, Hash)]
397pub struct CompilerForCheck {
398 build_compiler: Compiler,
399 rustc_rmeta_sysroot: Option<RmetaSysroot>,
400 std_rmeta_sysroot: Option<RmetaSysroot>,
401}
402
403impl CompilerForCheck {
404 pub fn build_compiler(&self) -> Compiler {
405 self.build_compiler
406 }
407
408 pub fn configure_cargo(&self, cargo: &mut Cargo) {
411 if let Some(sysroot) = &self.rustc_rmeta_sysroot {
412 sysroot.configure_cargo(cargo);
413 }
414 if let Some(sysroot) = &self.std_rmeta_sysroot {
415 sysroot.configure_cargo(cargo);
416 }
417 }
418}
419
420fn prepare_std(
423 builder: &Builder<'_>,
424 build_compiler: Compiler,
425 target: TargetSelection,
426) -> Option<RmetaSysroot> {
427 builder.std(build_compiler, builder.host_target);
430
431 if builder.host_target != target {
435 Some(builder.ensure(PrepareStdRmetaSysroot::new(build_compiler, target)))
436 } else {
437 None
438 }
439}
440
441pub fn prepare_compiler_for_check(
443 builder: &Builder<'_>,
444 target: TargetSelection,
445 mode: Mode,
446) -> CompilerForCheck {
447 let host = builder.host_target;
448
449 let mut rustc_rmeta_sysroot = None;
450 let mut std_rmeta_sysroot = None;
451 let build_compiler = match mode {
452 Mode::ToolBootstrap => builder.compiler(0, host),
453 Mode::ToolTarget => get_tool_target_compiler(builder, ToolTargetBuildMode::Build(target)),
457 Mode::ToolStd => {
458 if builder.config.compile_time_deps {
459 builder.compiler(0, host)
463 } else {
464 let build_compiler = builder.compiler(builder.top_stage, host);
466 std_rmeta_sysroot = prepare_std(builder, build_compiler, target);
467 build_compiler
468 }
469 }
470 Mode::ToolRustcPrivate | Mode::Codegen => {
471 let compiler_for_rustc = prepare_compiler_for_check(builder, target, Mode::Rustc);
476 rustc_rmeta_sysroot = Some(
477 builder.ensure(PrepareRustcRmetaSysroot::new(compiler_for_rustc.clone(), target)),
478 );
479 let build_compiler = compiler_for_rustc.build_compiler();
480
481 std_rmeta_sysroot = prepare_std(builder, build_compiler, target);
483 build_compiler
484 }
485 Mode::Rustc => {
486 let stage = if host == target { builder.top_stage - 1 } else { builder.top_stage };
494 let build_compiler = builder.compiler(stage, host);
495
496 std_rmeta_sysroot = prepare_std(builder, build_compiler, target);
498 build_compiler
499 }
500 Mode::Std => {
501 builder.compiler(builder.top_stage, host)
505 }
506 };
507 CompilerForCheck { build_compiler, rustc_rmeta_sysroot, std_rmeta_sysroot }
508}
509
510#[derive(Debug, Clone, PartialEq, Eq, Hash)]
512pub struct CraneliftCodegenBackend {
513 build_compiler: CompilerForCheck,
514 target: TargetSelection,
515}
516
517impl Step for CraneliftCodegenBackend {
518 type Output = ();
519 const IS_HOST: bool = true;
520
521 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
522 run.alias("rustc_codegen_cranelift").alias("cg_clif")
523 }
524
525 fn is_default_step(_builder: &Builder<'_>) -> bool {
526 true
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 const IS_HOST: bool = true;
592
593 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
594 run.alias("rustc_codegen_gcc").alias("cg_gcc")
595 }
596
597 fn is_default_step(_builder: &Builder<'_>) -> bool {
598 true
599 }
600
601 fn make_run(run: RunConfig<'_>) {
602 run.builder.ensure(GccCodegenBackend {
603 build_compiler: prepare_compiler_for_check(run.builder, run.target, Mode::Codegen),
604 target: run.target,
605 });
606 }
607
608 fn run(self, builder: &Builder<'_>) {
609 if builder.build.config.vendor {
611 println!("Skipping checking of `rustc_codegen_gcc` with vendoring enabled.");
612 return;
613 }
614
615 let build_compiler = self.build_compiler.build_compiler();
616 let target = self.target;
617
618 let mut cargo = builder::Cargo::new(
619 builder,
620 build_compiler,
621 Mode::Codegen,
622 SourceType::InTree,
623 target,
624 builder.kind,
625 );
626
627 cargo.arg("--manifest-path").arg(builder.src.join("compiler/rustc_codegen_gcc/Cargo.toml"));
628 rustc_cargo_env(builder, &mut cargo, target);
629 self.build_compiler.configure_cargo(&mut cargo);
630
631 let _guard =
632 builder.msg(Kind::Check, "rustc_codegen_gcc", Mode::Codegen, build_compiler, target);
633
634 let stamp = build_stamp::codegen_backend_stamp(
635 builder,
636 build_compiler,
637 target,
638 &CodegenBackendKind::Gcc,
639 )
640 .with_prefix("check");
641
642 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
643 }
644
645 fn metadata(&self) -> Option<StepMetadata> {
646 Some(
647 StepMetadata::check("rustc_codegen_gcc", self.target)
648 .built_by(self.build_compiler.build_compiler()),
649 )
650 }
651}
652
653macro_rules! tool_check_step {
654 (
655 $name:ident {
656 path: $path:literal
658 $(, alt_path: $alt_path:literal )*
659 , mode: $mode:expr
661 $(, allow_features: $allow_features:expr )?
663 $(, enable_features: [$($enable_features:expr),*] )?
665 $(, default_features: $default_features:expr )?
666 $(, default: $default:literal )?
667 $( , )?
668 }
669 ) => {
670 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
671 pub struct $name {
672 compiler: CompilerForCheck,
673 target: TargetSelection,
674 }
675
676 impl Step for $name {
677 type Output = ();
678 const IS_HOST: bool = true;
679
680 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
681 run.paths(&[ $path, $( $alt_path ),* ])
682 }
683
684 fn is_default_step(_builder: &Builder<'_>) -> bool {
685 true $( && const { $default } )?
687 }
688
689 fn make_run(run: RunConfig<'_>) {
690 let target = run.target;
691 let mode: Mode = $mode;
692
693 let compiler = prepare_compiler_for_check(run.builder, target, mode);
694
695 if mode == Mode::ToolBootstrap && target != run.builder.host_target {
697 println!("WARNING: not checking bootstrap tool {} for target {target} as it is a bootstrap (host-only) tool", stringify!($path));
698 return;
699 };
700
701 run.builder.ensure($name { target, compiler });
702 }
703
704 fn run(self, builder: &Builder<'_>) {
705 let Self { target, compiler } = self;
706 let allow_features = {
707 let mut _value = "";
708 $( _value = $allow_features; )?
709 _value
710 };
711 let extra_features: &[&str] = &[$($($enable_features),*)?];
712 let default_features = {
713 let mut _value = true;
714 $( _value = $default_features; )?
715 _value
716 };
717 let mode: Mode = $mode;
718 run_tool_check_step(builder, compiler, target, $path, mode, allow_features, extra_features, default_features);
719 }
720
721 fn metadata(&self) -> Option<StepMetadata> {
722 Some(StepMetadata::check(stringify!($name), self.target).built_by(self.compiler.build_compiler))
723 }
724 }
725 }
726}
727
728#[allow(clippy::too_many_arguments)]
730fn run_tool_check_step(
731 builder: &Builder<'_>,
732 compiler: CompilerForCheck,
733 target: TargetSelection,
734 path: &str,
735 mode: Mode,
736 allow_features: &str,
737 extra_features: &[&str],
738 default_features: bool,
739) {
740 let display_name = path.rsplit('/').next().unwrap();
741
742 let build_compiler = compiler.build_compiler();
743
744 let extra_features = extra_features.iter().map(|f| f.to_string()).collect::<Vec<String>>();
745 let mut cargo = prepare_tool_cargo(
746 builder,
747 build_compiler,
748 mode,
749 target,
750 builder.kind,
751 path,
752 SourceType::InTree,
757 &extra_features,
758 );
759 cargo.allow_features(allow_features);
760 compiler.configure_cargo(&mut cargo);
761
762 if display_name == "rust-analyzer" {
765 cargo.arg("--bins");
766 cargo.arg("--tests");
767 cargo.arg("--benches");
768 } else {
769 cargo.arg("--all-targets");
770 }
771
772 if !default_features {
773 cargo.arg("--no-default-features");
774 }
775
776 let stamp = BuildStamp::new(&builder.cargo_out(build_compiler, mode, target))
777 .with_prefix(&format!("{display_name}-check"));
778
779 let _guard = builder.msg(builder.kind, display_name, mode, build_compiler, target);
780 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
781}
782
783tool_check_step!(Rustdoc {
784 path: "src/tools/rustdoc",
785 alt_path: "src/librustdoc",
786 mode: Mode::ToolRustcPrivate
787});
788tool_check_step!(Clippy { path: "src/tools/clippy", mode: Mode::ToolRustcPrivate });
793tool_check_step!(Miri {
794 path: "src/tools/miri",
795 mode: Mode::ToolRustcPrivate,
796 enable_features: ["stack-cache"],
797 default_features: false,
798});
799tool_check_step!(CargoMiri { path: "src/tools/miri/cargo-miri", mode: Mode::ToolRustcPrivate });
800tool_check_step!(Rustfmt { path: "src/tools/rustfmt", mode: Mode::ToolRustcPrivate });
801tool_check_step!(RustAnalyzer {
802 path: "src/tools/rust-analyzer",
803 mode: Mode::ToolRustcPrivate,
804 allow_features: tool::RustAnalyzer::ALLOW_FEATURES,
805 enable_features: ["in-rust-tree"],
806});
807tool_check_step!(MiroptTestTools {
808 path: "src/tools/miropt-test-tools",
809 mode: Mode::ToolBootstrap
810});
811tool_check_step!(TestFloatParse {
813 path: "src/tools/test-float-parse",
814 mode: Mode::ToolStd,
815 allow_features: TEST_FLOAT_PARSE_ALLOW_FEATURES
816});
817tool_check_step!(FeaturesStatusDump {
818 path: "src/tools/features-status-dump",
819 mode: Mode::ToolBootstrap
820});
821
822tool_check_step!(Bootstrap { path: "src/bootstrap", mode: Mode::ToolBootstrap, default: false });
823
824tool_check_step!(RunMakeSupport {
827 path: "src/tools/run-make-support",
828 mode: Mode::ToolBootstrap,
829 default: false
830});
831
832tool_check_step!(CoverageDump {
833 path: "src/tools/coverage-dump",
834 mode: Mode::ToolBootstrap,
835 default: false
836});
837
838tool_check_step!(Compiletest {
841 path: "src/tools/compiletest",
842 mode: Mode::ToolBootstrap,
843 default: false,
844});
845
846tool_check_step!(RustdocGuiTest {
850 path: "src/tools/rustdoc-gui-test",
851 mode: Mode::ToolBootstrap,
852 default: false,
853});
854
855tool_check_step!(Linkchecker {
856 path: "src/tools/linkchecker",
857 mode: Mode::ToolBootstrap,
858 default: false
859});
860
861tool_check_step!(BumpStage0 {
862 path: "src/tools/bump-stage0",
863 mode: Mode::ToolBootstrap,
864 default: false
865});
866
867tool_check_step!(Tidy { path: "src/tools/tidy", mode: Mode::ToolBootstrap, default: false });