1use std::fs;
4use std::path::{Path, PathBuf};
5
6use crate::core::build_steps::compile::{
7 ArtifactKeepMode, add_to_sysroot, run_cargo, rustc_cargo, rustc_cargo_env, std_cargo,
8 std_crates_for_run_make,
9};
10use crate::core::build_steps::tool;
11use crate::core::build_steps::tool::{
12 SourceType, TEST_FLOAT_PARSE_ALLOW_FEATURES, ToolTargetBuildMode, get_tool_target_compiler,
13 prepare_tool_cargo,
14};
15use crate::core::builder::{
16 self, Alias, Builder, Cargo, Kind, RunConfig, ShouldRun, Step, StepMetadata, crate_description,
17};
18use crate::core::config::TargetSelection;
19use crate::utils::build_stamp::{self, BuildStamp};
20use crate::{CodegenBackendKind, Compiler, Mode, Subcommand, t};
21
22#[derive(Debug, Clone, PartialEq, Eq, Hash)]
23pub struct Std {
24 pub build_compiler: Compiler,
26 pub target: TargetSelection,
27 crates: Vec<String>,
33}
34
35impl Std {
36 const CRATE_OR_DEPS: &[&str] = &["sysroot", "coretests", "alloctests"];
37}
38
39impl Step for Std {
40 type Output = BuildStamp;
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 is_default_step(_builder: &Builder<'_>) -> bool {
52 true
53 }
54
55 fn make_run(run: RunConfig<'_>) {
56 if !run.builder.download_rustc() && run.builder.config.skip_std_check_if_no_download_rustc {
57 eprintln!(
58 "WARNING: `--skip-std-check-if-no-download-rustc` flag was passed and `rust.download-rustc` is not available. Skipping."
59 );
60 return;
61 }
62
63 if run.builder.config.compile_time_deps {
64 return;
66 }
67
68 let crates = std_crates_for_run_make(&run);
72 run.builder.ensure(Std {
73 build_compiler: prepare_compiler_for_check(run.builder, run.target, Mode::Std)
74 .build_compiler(),
75 target: run.target,
76 crates,
77 });
78 }
79
80 fn run(self, builder: &Builder<'_>) -> Self::Output {
81 let build_compiler = self.build_compiler;
82 let target = self.target;
83
84 let mut cargo = builder::Cargo::new(
85 builder,
86 build_compiler,
87 Mode::Std,
88 SourceType::InTree,
89 target,
90 builder.config.cmd.kind(),
91 );
92
93 std_cargo(builder, target, &mut cargo, &self.crates);
94 if matches!(builder.config.cmd, Subcommand::Fix) {
95 cargo.arg("--lib");
97 }
98
99 let _guard = builder.msg(
100 builder.config.cmd.kind(),
101 format_args!("library artifacts{}", crate_description(&self.crates)),
102 Mode::Std,
103 build_compiler,
104 target,
105 );
106
107 let check_stamp =
108 build_stamp::libstd_stamp(builder, build_compiler, target).with_prefix("check");
109 run_cargo(
110 builder,
111 cargo,
112 builder.config.free_args.clone(),
113 &check_stamp,
114 vec![],
115 ArtifactKeepMode::OnlyRmeta,
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(
152 builder,
153 cargo,
154 builder.config.free_args.clone(),
155 &stamp,
156 vec![],
157 ArtifactKeepMode::OnlyRmeta,
158 );
159 check_stamp
160 }
161
162 fn metadata(&self) -> Option<StepMetadata> {
163 Some(StepMetadata::check("std", self.target).built_by(self.build_compiler))
164 }
165}
166
167#[derive(Debug, Clone, PartialEq, Eq, Hash)]
171struct RmetaSysroot {
172 host_dir: PathBuf,
173 target_dir: PathBuf,
174}
175
176impl RmetaSysroot {
177 fn from_stamp(
179 builder: &Builder<'_>,
180 stamp: BuildStamp,
181 target: TargetSelection,
182 directory: &Path,
183 ) -> Self {
184 let host_dir = directory.join("host");
185 let target_dir = directory.join(target);
186 let _ = fs::remove_dir_all(directory);
187 t!(fs::create_dir_all(directory));
188 add_to_sysroot(builder, &target_dir, &host_dir, &stamp);
189
190 Self { host_dir, target_dir }
191 }
192
193 fn configure_cargo(&self, cargo: &mut Cargo) {
196 cargo.append_to_env(
197 "RUSTC_ADDITIONAL_SYSROOT_PATHS",
198 format!("{},{}", self.host_dir.to_str().unwrap(), self.target_dir.to_str().unwrap()),
199 ",",
200 );
201 }
202}
203
204#[derive(Debug, Clone, PartialEq, Eq, Hash)]
211struct PrepareRustcRmetaSysroot {
212 build_compiler: CompilerForCheck,
213 target: TargetSelection,
214}
215
216impl PrepareRustcRmetaSysroot {
217 fn new(build_compiler: CompilerForCheck, target: TargetSelection) -> Self {
218 Self { build_compiler, target }
219 }
220}
221
222impl Step for PrepareRustcRmetaSysroot {
223 type Output = RmetaSysroot;
224
225 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
226 run.never()
227 }
228
229 fn run(self, builder: &Builder<'_>) -> Self::Output {
230 let stamp = builder.ensure(Rustc::from_build_compiler(
232 self.build_compiler.clone(),
233 self.target,
234 vec![],
235 ));
236
237 let build_compiler = self.build_compiler.build_compiler();
238
239 let dir = builder
241 .out
242 .join(build_compiler.host)
243 .join(format!("stage{}-rustc-rmeta-artifacts", build_compiler.stage + 1));
244 RmetaSysroot::from_stamp(builder, stamp, self.target, &dir)
245 }
246}
247
248#[derive(Debug, Clone, PartialEq, Eq, Hash)]
255struct PrepareStdRmetaSysroot {
256 build_compiler: Compiler,
257 target: TargetSelection,
258}
259
260impl PrepareStdRmetaSysroot {
261 fn new(build_compiler: Compiler, target: TargetSelection) -> Self {
262 Self { build_compiler, target }
263 }
264}
265
266impl Step for PrepareStdRmetaSysroot {
267 type Output = RmetaSysroot;
268
269 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
270 run.never()
271 }
272
273 fn run(self, builder: &Builder<'_>) -> Self::Output {
274 let stamp = builder.ensure(Std {
276 build_compiler: self.build_compiler,
277 target: self.target,
278 crates: vec![],
279 });
280
281 let dir = builder
283 .out
284 .join(self.build_compiler.host)
285 .join(format!("stage{}-std-rmeta-artifacts", self.build_compiler.stage));
286
287 RmetaSysroot::from_stamp(builder, stamp, self.target, &dir)
288 }
289}
290
291#[derive(Debug, Clone, PartialEq, Eq, Hash)]
293pub struct Rustc {
294 pub build_compiler: CompilerForCheck,
296 pub target: TargetSelection,
297 crates: Vec<String>,
303}
304
305impl Rustc {
306 pub fn new(builder: &Builder<'_>, target: TargetSelection, crates: Vec<String>) -> Self {
307 let build_compiler = prepare_compiler_for_check(builder, target, Mode::Rustc);
308 Self::from_build_compiler(build_compiler, target, crates)
309 }
310
311 fn from_build_compiler(
312 build_compiler: CompilerForCheck,
313 target: TargetSelection,
314 crates: Vec<String>,
315 ) -> Self {
316 Self { build_compiler, target, crates }
317 }
318}
319
320impl Step for Rustc {
321 type Output = BuildStamp;
322 const IS_HOST: bool = true;
323
324 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
325 run.crate_or_deps("rustc-main").path("compiler")
326 }
327
328 fn is_default_step(_builder: &Builder<'_>) -> bool {
329 true
330 }
331
332 fn make_run(run: RunConfig<'_>) {
333 let crates = run.make_run_crates(Alias::Compiler);
334 run.builder.ensure(Rustc::new(run.builder, run.target, crates));
335 }
336
337 fn run(self, builder: &Builder<'_>) -> Self::Output {
345 let build_compiler = self.build_compiler.build_compiler;
346 let target = self.target;
347
348 let mut cargo = builder::Cargo::new(
349 builder,
350 build_compiler,
351 Mode::Rustc,
352 SourceType::InTree,
353 target,
354 Kind::Check,
355 );
356
357 rustc_cargo(builder, &mut cargo, target, &build_compiler, &self.crates);
358 self.build_compiler.configure_cargo(&mut cargo);
359
360 for krate in &*self.crates {
364 cargo.arg("-p").arg(krate);
365 }
366
367 let _guard = builder.msg(
368 Kind::Check,
369 format_args!("compiler artifacts{}", crate_description(&self.crates)),
370 Mode::Rustc,
371 self.build_compiler.build_compiler(),
372 target,
373 );
374
375 let stamp =
376 build_stamp::librustc_stamp(builder, build_compiler, target).with_prefix("check");
377
378 run_cargo(
379 builder,
380 cargo,
381 builder.config.free_args.clone(),
382 &stamp,
383 vec![],
384 ArtifactKeepMode::OnlyRmeta,
385 );
386
387 stamp
388 }
389
390 fn metadata(&self) -> Option<StepMetadata> {
391 let metadata = StepMetadata::check("rustc", self.target)
392 .built_by(self.build_compiler.build_compiler());
393 let metadata = if self.crates.is_empty() {
394 metadata
395 } else {
396 metadata.with_metadata(format!("({} crates)", self.crates.len()))
397 };
398 Some(metadata)
399 }
400}
401
402#[derive(Debug, Clone, PartialEq, Eq, Hash)]
411pub struct CompilerForCheck {
412 build_compiler: Compiler,
413 rustc_rmeta_sysroot: Option<RmetaSysroot>,
414 std_rmeta_sysroot: Option<RmetaSysroot>,
415}
416
417impl CompilerForCheck {
418 pub fn build_compiler(&self) -> Compiler {
419 self.build_compiler
420 }
421
422 pub fn configure_cargo(&self, cargo: &mut Cargo) {
425 if let Some(sysroot) = &self.rustc_rmeta_sysroot {
426 sysroot.configure_cargo(cargo);
427 }
428 if let Some(sysroot) = &self.std_rmeta_sysroot {
429 sysroot.configure_cargo(cargo);
430 }
431 }
432}
433
434fn prepare_std(
437 builder: &Builder<'_>,
438 build_compiler: Compiler,
439 target: TargetSelection,
440) -> Option<RmetaSysroot> {
441 builder.std(build_compiler, builder.host_target);
444
445 if builder.host_target != target {
449 Some(builder.ensure(PrepareStdRmetaSysroot::new(build_compiler, target)))
450 } else {
451 None
452 }
453}
454
455pub fn prepare_compiler_for_check(
457 builder: &Builder<'_>,
458 target: TargetSelection,
459 mode: Mode,
460) -> CompilerForCheck {
461 let host = builder.host_target;
462
463 let mut rustc_rmeta_sysroot = None;
464 let mut std_rmeta_sysroot = None;
465 let build_compiler = match mode {
466 Mode::ToolBootstrap => builder.compiler(0, host),
467 Mode::ToolTarget => get_tool_target_compiler(builder, ToolTargetBuildMode::Build(target)),
471 Mode::ToolStd => {
472 if builder.config.compile_time_deps {
473 builder.compiler(0, host)
477 } else {
478 let build_compiler = builder.compiler(builder.top_stage, host);
480 std_rmeta_sysroot = prepare_std(builder, build_compiler, target);
481 build_compiler
482 }
483 }
484 Mode::ToolRustcPrivate | Mode::Codegen => {
485 let compiler_for_rustc = prepare_compiler_for_check(builder, target, Mode::Rustc);
490 rustc_rmeta_sysroot = Some(
491 builder.ensure(PrepareRustcRmetaSysroot::new(compiler_for_rustc.clone(), target)),
492 );
493 let build_compiler = compiler_for_rustc.build_compiler();
494
495 std_rmeta_sysroot = prepare_std(builder, build_compiler, target);
497 build_compiler
498 }
499 Mode::Rustc => {
500 let stage = if host == target { builder.top_stage - 1 } else { builder.top_stage };
508 let build_compiler = builder.compiler(stage, host);
509
510 std_rmeta_sysroot = prepare_std(builder, build_compiler, target);
512 build_compiler
513 }
514 Mode::Std => {
515 builder.compiler(builder.top_stage, host)
519 }
520 };
521 CompilerForCheck { build_compiler, rustc_rmeta_sysroot, std_rmeta_sysroot }
522}
523
524#[derive(Debug, Clone, PartialEq, Eq, Hash)]
526pub struct CraneliftCodegenBackend {
527 build_compiler: CompilerForCheck,
528 target: TargetSelection,
529}
530
531impl Step for CraneliftCodegenBackend {
532 type Output = ();
533 const IS_HOST: bool = true;
534
535 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
536 run.alias("rustc_codegen_cranelift").alias("cg_clif")
537 }
538
539 fn is_default_step(_builder: &Builder<'_>) -> bool {
540 true
541 }
542
543 fn make_run(run: RunConfig<'_>) {
544 run.builder.ensure(CraneliftCodegenBackend {
545 build_compiler: prepare_compiler_for_check(run.builder, run.target, Mode::Codegen),
546 target: run.target,
547 });
548 }
549
550 fn run(self, builder: &Builder<'_>) {
551 let build_compiler = self.build_compiler.build_compiler();
552 let target = self.target;
553
554 let mut cargo = builder::Cargo::new(
555 builder,
556 build_compiler,
557 Mode::Codegen,
558 SourceType::InTree,
559 target,
560 builder.kind,
561 );
562
563 cargo
564 .arg("--manifest-path")
565 .arg(builder.src.join("compiler/rustc_codegen_cranelift/Cargo.toml"));
566 rustc_cargo_env(builder, &mut cargo, target);
567 self.build_compiler.configure_cargo(&mut cargo);
568
569 let _guard = builder.msg(
570 Kind::Check,
571 "rustc_codegen_cranelift",
572 Mode::Codegen,
573 build_compiler,
574 target,
575 );
576
577 let stamp = build_stamp::codegen_backend_stamp(
578 builder,
579 build_compiler,
580 target,
581 &CodegenBackendKind::Cranelift,
582 )
583 .with_prefix("check");
584
585 run_cargo(
586 builder,
587 cargo,
588 builder.config.free_args.clone(),
589 &stamp,
590 vec![],
591 ArtifactKeepMode::OnlyRmeta,
592 );
593 }
594
595 fn metadata(&self) -> Option<StepMetadata> {
596 Some(
597 StepMetadata::check("rustc_codegen_cranelift", self.target)
598 .built_by(self.build_compiler.build_compiler()),
599 )
600 }
601}
602
603#[derive(Debug, Clone, PartialEq, Eq, Hash)]
605pub struct GccCodegenBackend {
606 build_compiler: CompilerForCheck,
607 target: TargetSelection,
608}
609
610impl Step for GccCodegenBackend {
611 type Output = ();
612 const IS_HOST: bool = true;
613
614 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
615 run.alias("rustc_codegen_gcc").alias("cg_gcc")
616 }
617
618 fn is_default_step(_builder: &Builder<'_>) -> bool {
619 true
620 }
621
622 fn make_run(run: RunConfig<'_>) {
623 run.builder.ensure(GccCodegenBackend {
624 build_compiler: prepare_compiler_for_check(run.builder, run.target, Mode::Codegen),
625 target: run.target,
626 });
627 }
628
629 fn run(self, builder: &Builder<'_>) {
630 if builder.build.config.vendor {
632 println!("Skipping checking of `rustc_codegen_gcc` with vendoring enabled.");
633 return;
634 }
635
636 let build_compiler = self.build_compiler.build_compiler();
637 let target = self.target;
638
639 let mut cargo = builder::Cargo::new(
640 builder,
641 build_compiler,
642 Mode::Codegen,
643 SourceType::InTree,
644 target,
645 builder.kind,
646 );
647
648 cargo.arg("--manifest-path").arg(builder.src.join("compiler/rustc_codegen_gcc/Cargo.toml"));
649 rustc_cargo_env(builder, &mut cargo, target);
650 self.build_compiler.configure_cargo(&mut cargo);
651
652 let _guard =
653 builder.msg(Kind::Check, "rustc_codegen_gcc", Mode::Codegen, build_compiler, target);
654
655 let stamp = build_stamp::codegen_backend_stamp(
656 builder,
657 build_compiler,
658 target,
659 &CodegenBackendKind::Gcc,
660 )
661 .with_prefix("check");
662
663 run_cargo(
664 builder,
665 cargo,
666 builder.config.free_args.clone(),
667 &stamp,
668 vec![],
669 ArtifactKeepMode::OnlyRmeta,
670 );
671 }
672
673 fn metadata(&self) -> Option<StepMetadata> {
674 Some(
675 StepMetadata::check("rustc_codegen_gcc", self.target)
676 .built_by(self.build_compiler.build_compiler()),
677 )
678 }
679}
680
681macro_rules! tool_check_step {
682 (
683 $name:ident {
684 path: $path:literal
686 $(, alt_path: $alt_path:literal )*
687 , mode: $mode:expr
689 $(, allow_features: $allow_features:expr )?
691 $(, enable_features: [$($enable_features:expr),*] )?
693 $(, default_features: $default_features:expr )?
694 $(, default: $default:literal )?
695 $( , )?
696 }
697 ) => {
698 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
699 pub struct $name {
700 compiler: CompilerForCheck,
701 target: TargetSelection,
702 }
703
704 impl Step for $name {
705 type Output = ();
706 const IS_HOST: bool = true;
707
708 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
709 run.paths(&[ $path, $( $alt_path ),* ])
710 }
711
712 fn is_default_step(_builder: &Builder<'_>) -> bool {
713 true $( && const { $default } )?
715 }
716
717 fn make_run(run: RunConfig<'_>) {
718 let target = run.target;
719 let mode: Mode = $mode;
720
721 let compiler = prepare_compiler_for_check(run.builder, target, mode);
722
723 if mode == Mode::ToolBootstrap && target != run.builder.host_target {
725 println!("WARNING: not checking bootstrap tool {} for target {target} as it is a bootstrap (host-only) tool", stringify!($path));
726 return;
727 };
728
729 run.builder.ensure($name { target, compiler });
730 }
731
732 fn run(self, builder: &Builder<'_>) {
733 let Self { target, compiler } = self;
734 let allow_features = {
735 let mut _value = "";
736 $( _value = $allow_features; )?
737 _value
738 };
739 let extra_features: &[&str] = &[$($($enable_features),*)?];
740 let default_features = {
741 let mut _value = true;
742 $( _value = $default_features; )?
743 _value
744 };
745 let mode: Mode = $mode;
746 run_tool_check_step(builder, compiler, target, $path, mode, allow_features, extra_features, default_features);
747 }
748
749 fn metadata(&self) -> Option<StepMetadata> {
750 Some(StepMetadata::check(stringify!($name), self.target).built_by(self.compiler.build_compiler))
751 }
752 }
753 }
754}
755
756#[allow(clippy::too_many_arguments)]
758fn run_tool_check_step(
759 builder: &Builder<'_>,
760 compiler: CompilerForCheck,
761 target: TargetSelection,
762 path: &str,
763 mode: Mode,
764 allow_features: &str,
765 extra_features: &[&str],
766 default_features: bool,
767) {
768 let display_name = path.rsplit('/').next().unwrap();
769
770 let build_compiler = compiler.build_compiler();
771
772 let extra_features = extra_features.iter().map(|f| f.to_string()).collect::<Vec<String>>();
773 let mut cargo = prepare_tool_cargo(
774 builder,
775 build_compiler,
776 mode,
777 target,
778 builder.kind,
779 path,
780 SourceType::InTree,
785 &extra_features,
786 );
787 cargo.allow_features(allow_features);
788 compiler.configure_cargo(&mut cargo);
789
790 if display_name == "rust-analyzer" {
793 cargo.arg("--bins");
794 cargo.arg("--tests");
795 cargo.arg("--benches");
796 } else {
797 cargo.arg("--all-targets");
798 }
799
800 if !default_features {
801 cargo.arg("--no-default-features");
802 }
803
804 let stamp = BuildStamp::new(&builder.cargo_out(build_compiler, mode, target))
805 .with_prefix(&format!("{display_name}-check"));
806
807 let _guard = builder.msg(builder.kind, display_name, mode, build_compiler, target);
808 run_cargo(
809 builder,
810 cargo,
811 builder.config.free_args.clone(),
812 &stamp,
813 vec![],
814 ArtifactKeepMode::OnlyRmeta,
815 );
816}
817
818tool_check_step!(Rustdoc {
819 path: "src/tools/rustdoc",
820 alt_path: "src/librustdoc",
821 mode: Mode::ToolRustcPrivate
822});
823tool_check_step!(Clippy { path: "src/tools/clippy", mode: Mode::ToolRustcPrivate });
828tool_check_step!(Miri {
829 path: "src/tools/miri",
830 mode: Mode::ToolRustcPrivate,
831 enable_features: ["check_only"],
832});
833tool_check_step!(CargoMiri { path: "src/tools/miri/cargo-miri", mode: Mode::ToolRustcPrivate });
834tool_check_step!(Rustfmt { path: "src/tools/rustfmt", mode: Mode::ToolRustcPrivate });
835tool_check_step!(RustAnalyzer {
836 path: "src/tools/rust-analyzer",
837 mode: Mode::ToolRustcPrivate,
838 allow_features: tool::RustAnalyzer::ALLOW_FEATURES,
839 enable_features: ["in-rust-tree"],
840});
841tool_check_step!(MiroptTestTools {
842 path: "src/tools/miropt-test-tools",
843 mode: Mode::ToolBootstrap
844});
845tool_check_step!(TestFloatParse {
847 path: "src/tools/test-float-parse",
848 mode: Mode::ToolStd,
849 allow_features: TEST_FLOAT_PARSE_ALLOW_FEATURES
850});
851tool_check_step!(FeaturesStatusDump {
852 path: "src/tools/features-status-dump",
853 mode: Mode::ToolBootstrap
854});
855
856tool_check_step!(Bootstrap { path: "src/bootstrap", mode: Mode::ToolBootstrap, default: false });
857
858tool_check_step!(RunMakeSupport {
861 path: "src/tools/run-make-support",
862 mode: Mode::ToolBootstrap,
863 default: false
864});
865
866tool_check_step!(CoverageDump {
867 path: "src/tools/coverage-dump",
868 mode: Mode::ToolBootstrap,
869 default: false
870});
871
872tool_check_step!(Compiletest {
875 path: "src/tools/compiletest",
876 mode: Mode::ToolBootstrap,
877 default: false,
878});
879
880tool_check_step!(RustdocGuiTest {
884 path: "src/tools/rustdoc-gui-test",
885 mode: Mode::ToolBootstrap,
886 default: false,
887});
888
889tool_check_step!(Linkchecker {
890 path: "src/tools/linkchecker",
891 mode: Mode::ToolBootstrap,
892 default: false
893});
894
895tool_check_step!(BumpStage0 {
896 path: "src/tools/bump-stage0",
897 mode: Mode::ToolBootstrap,
898 default: false
899});
900
901tool_check_step!(Tidy { path: "src/tools/tidy", mode: Mode::ToolBootstrap, default: false });