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 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);
68 run.builder.ensure(Std {
69 build_compiler: prepare_compiler_for_check(run.builder, run.target, Mode::Std)
70 .build_compiler(),
71 target: run.target,
72 crates,
73 });
74 }
75
76 fn run(self, builder: &Builder<'_>) -> Self::Output {
77 let build_compiler = self.build_compiler;
78 let target = self.target;
79
80 let mut cargo = builder::Cargo::new(
81 builder,
82 build_compiler,
83 Mode::Std,
84 SourceType::InTree,
85 target,
86 Kind::Check,
87 );
88
89 std_cargo(builder, target, &mut cargo, &self.crates);
90 if matches!(builder.config.cmd, Subcommand::Fix) {
91 cargo.arg("--lib");
93 }
94
95 let _guard = builder.msg(
96 Kind::Check,
97 format_args!("library artifacts{}", crate_description(&self.crates)),
98 Mode::Std,
99 build_compiler,
100 target,
101 );
102
103 let check_stamp =
104 build_stamp::libstd_stamp(builder, build_compiler, target).with_prefix("check");
105 run_cargo(
106 builder,
107 cargo,
108 builder.config.free_args.clone(),
109 &check_stamp,
110 vec![],
111 true,
112 false,
113 );
114
115 drop(_guard);
116
117 if !self.crates.iter().any(|krate| krate == "test") {
119 return check_stamp;
120 }
121
122 let mut cargo = builder::Cargo::new(
129 builder,
130 build_compiler,
131 Mode::Std,
132 SourceType::InTree,
133 target,
134 Kind::Check,
135 );
136
137 std_cargo(builder, target, &mut cargo, &self.crates);
138
139 let stamp =
140 build_stamp::libstd_stamp(builder, build_compiler, target).with_prefix("check-test");
141 let _guard = builder.msg(
142 Kind::Check,
143 "library test/bench/example targets",
144 Mode::Std,
145 build_compiler,
146 target,
147 );
148 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
149 check_stamp
150 }
151
152 fn metadata(&self) -> Option<StepMetadata> {
153 Some(StepMetadata::check("std", self.target).built_by(self.build_compiler))
154 }
155}
156
157#[derive(Debug, Clone, PartialEq, Eq, Hash)]
161struct RmetaSysroot {
162 host_dir: PathBuf,
163 target_dir: PathBuf,
164}
165
166impl RmetaSysroot {
167 fn from_stamp(
169 builder: &Builder<'_>,
170 stamp: BuildStamp,
171 target: TargetSelection,
172 directory: &Path,
173 ) -> Self {
174 let host_dir = directory.join("host");
175 let target_dir = directory.join(target);
176 let _ = fs::remove_dir_all(directory);
177 t!(fs::create_dir_all(directory));
178 add_to_sysroot(builder, &target_dir, &host_dir, &stamp);
179
180 Self { host_dir, target_dir }
181 }
182
183 fn configure_cargo(&self, cargo: &mut Cargo) {
186 cargo.append_to_env(
187 "RUSTC_ADDITIONAL_SYSROOT_PATHS",
188 format!("{},{}", self.host_dir.to_str().unwrap(), self.target_dir.to_str().unwrap()),
189 ",",
190 );
191 }
192}
193
194#[derive(Debug, Clone, PartialEq, Eq, Hash)]
201struct PrepareRustcRmetaSysroot {
202 build_compiler: CompilerForCheck,
203 target: TargetSelection,
204}
205
206impl PrepareRustcRmetaSysroot {
207 fn new(build_compiler: CompilerForCheck, target: TargetSelection) -> Self {
208 Self { build_compiler, target }
209 }
210}
211
212impl Step for PrepareRustcRmetaSysroot {
213 type Output = RmetaSysroot;
214
215 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
216 run.never()
217 }
218
219 fn run(self, builder: &Builder<'_>) -> Self::Output {
220 let stamp = builder.ensure(Rustc::from_build_compiler(
222 self.build_compiler.clone(),
223 self.target,
224 vec![],
225 ));
226
227 let build_compiler = self.build_compiler.build_compiler();
228
229 let dir = builder
231 .out
232 .join(build_compiler.host)
233 .join(format!("stage{}-rustc-rmeta-artifacts", build_compiler.stage + 1));
234 RmetaSysroot::from_stamp(builder, stamp, self.target, &dir)
235 }
236}
237
238#[derive(Debug, Clone, PartialEq, Eq, Hash)]
245struct PrepareStdRmetaSysroot {
246 build_compiler: Compiler,
247 target: TargetSelection,
248}
249
250impl PrepareStdRmetaSysroot {
251 fn new(build_compiler: Compiler, target: TargetSelection) -> Self {
252 Self { build_compiler, target }
253 }
254}
255
256impl Step for PrepareStdRmetaSysroot {
257 type Output = RmetaSysroot;
258
259 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
260 run.never()
261 }
262
263 fn run(self, builder: &Builder<'_>) -> Self::Output {
264 let stamp = builder.ensure(Std {
266 build_compiler: self.build_compiler,
267 target: self.target,
268 crates: vec![],
269 });
270
271 let dir = builder
273 .out
274 .join(self.build_compiler.host)
275 .join(format!("stage{}-std-rmeta-artifacts", self.build_compiler.stage));
276
277 RmetaSysroot::from_stamp(builder, stamp, self.target, &dir)
278 }
279}
280
281#[derive(Debug, Clone, PartialEq, Eq, Hash)]
283pub struct Rustc {
284 pub build_compiler: CompilerForCheck,
286 pub target: TargetSelection,
287 crates: Vec<String>,
293}
294
295impl Rustc {
296 pub fn new(builder: &Builder<'_>, target: TargetSelection, crates: Vec<String>) -> Self {
297 let build_compiler = prepare_compiler_for_check(builder, target, Mode::Rustc);
298 Self::from_build_compiler(build_compiler, target, crates)
299 }
300
301 fn from_build_compiler(
302 build_compiler: CompilerForCheck,
303 target: TargetSelection,
304 crates: Vec<String>,
305 ) -> Self {
306 Self { build_compiler, target, crates }
307 }
308}
309
310impl Step for Rustc {
311 type Output = BuildStamp;
312 const IS_HOST: bool = true;
313 const DEFAULT: bool = true;
314
315 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
316 run.crate_or_deps("rustc-main").path("compiler")
317 }
318
319 fn make_run(run: RunConfig<'_>) {
320 let crates = run.make_run_crates(Alias::Compiler);
321 run.builder.ensure(Rustc::new(run.builder, run.target, crates));
322 }
323
324 fn run(self, builder: &Builder<'_>) -> Self::Output {
332 let build_compiler = self.build_compiler.build_compiler;
333 let target = self.target;
334
335 let mut cargo = builder::Cargo::new(
336 builder,
337 build_compiler,
338 Mode::Rustc,
339 SourceType::InTree,
340 target,
341 Kind::Check,
342 );
343
344 rustc_cargo(builder, &mut cargo, target, &build_compiler, &self.crates);
345 self.build_compiler.configure_cargo(&mut cargo);
346
347 for krate in &*self.crates {
351 cargo.arg("-p").arg(krate);
352 }
353
354 let _guard = builder.msg(
355 Kind::Check,
356 format_args!("compiler artifacts{}", crate_description(&self.crates)),
357 Mode::Rustc,
358 self.build_compiler.build_compiler(),
359 target,
360 );
361
362 let stamp =
363 build_stamp::librustc_stamp(builder, build_compiler, target).with_prefix("check");
364
365 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
366
367 stamp
368 }
369
370 fn metadata(&self) -> Option<StepMetadata> {
371 let metadata = StepMetadata::check("rustc", self.target)
372 .built_by(self.build_compiler.build_compiler());
373 let metadata = if self.crates.is_empty() {
374 metadata
375 } else {
376 metadata.with_metadata(format!("({} crates)", self.crates.len()))
377 };
378 Some(metadata)
379 }
380}
381
382#[derive(Debug, Clone, PartialEq, Eq, Hash)]
391pub struct CompilerForCheck {
392 build_compiler: Compiler,
393 rustc_rmeta_sysroot: Option<RmetaSysroot>,
394 std_rmeta_sysroot: Option<RmetaSysroot>,
395}
396
397impl CompilerForCheck {
398 pub fn build_compiler(&self) -> Compiler {
399 self.build_compiler
400 }
401
402 pub fn configure_cargo(&self, cargo: &mut Cargo) {
405 if let Some(sysroot) = &self.rustc_rmeta_sysroot {
406 sysroot.configure_cargo(cargo);
407 }
408 if let Some(sysroot) = &self.std_rmeta_sysroot {
409 sysroot.configure_cargo(cargo);
410 }
411 }
412}
413
414fn prepare_std(
417 builder: &Builder<'_>,
418 build_compiler: Compiler,
419 target: TargetSelection,
420) -> Option<RmetaSysroot> {
421 builder.std(build_compiler, builder.host_target);
424
425 if builder.host_target != target {
429 Some(builder.ensure(PrepareStdRmetaSysroot::new(build_compiler, target)))
430 } else {
431 None
432 }
433}
434
435pub fn prepare_compiler_for_check(
437 builder: &Builder<'_>,
438 target: TargetSelection,
439 mode: Mode,
440) -> CompilerForCheck {
441 let host = builder.host_target;
442
443 let mut rustc_rmeta_sysroot = None;
444 let mut std_rmeta_sysroot = None;
445 let build_compiler = match mode {
446 Mode::ToolBootstrap => builder.compiler(0, host),
447 Mode::ToolTarget => get_tool_target_compiler(builder, ToolTargetBuildMode::Build(target)),
451 Mode::ToolStd => {
452 if builder.config.compile_time_deps {
453 builder.compiler(0, host)
457 } else {
458 let build_compiler = builder.compiler(builder.top_stage, host);
460 std_rmeta_sysroot = prepare_std(builder, build_compiler, target);
461 build_compiler
462 }
463 }
464 Mode::ToolRustcPrivate | Mode::Codegen => {
465 let compiler_for_rustc = prepare_compiler_for_check(builder, target, Mode::Rustc);
470 rustc_rmeta_sysroot = Some(
471 builder.ensure(PrepareRustcRmetaSysroot::new(compiler_for_rustc.clone(), target)),
472 );
473 let build_compiler = compiler_for_rustc.build_compiler();
474
475 std_rmeta_sysroot = prepare_std(builder, build_compiler, target);
477 build_compiler
478 }
479 Mode::Rustc => {
480 let stage = if host == target { builder.top_stage - 1 } else { builder.top_stage };
488 let build_compiler = builder.compiler(stage, host);
489
490 std_rmeta_sysroot = prepare_std(builder, build_compiler, target);
492 build_compiler
493 }
494 Mode::Std => {
495 builder.compiler(builder.top_stage, host)
499 }
500 };
501 CompilerForCheck { build_compiler, rustc_rmeta_sysroot, std_rmeta_sysroot }
502}
503
504#[derive(Debug, Clone, PartialEq, Eq, Hash)]
506pub struct CraneliftCodegenBackend {
507 build_compiler: CompilerForCheck,
508 target: TargetSelection,
509}
510
511impl Step for CraneliftCodegenBackend {
512 type Output = ();
513
514 const IS_HOST: bool = true;
515 const DEFAULT: bool = true;
516
517 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
518 run.alias("rustc_codegen_cranelift").alias("cg_clif")
519 }
520
521 fn make_run(run: RunConfig<'_>) {
522 run.builder.ensure(CraneliftCodegenBackend {
523 build_compiler: prepare_compiler_for_check(run.builder, run.target, Mode::Codegen),
524 target: run.target,
525 });
526 }
527
528 fn run(self, builder: &Builder<'_>) {
529 let build_compiler = self.build_compiler.build_compiler();
530 let target = self.target;
531
532 let mut cargo = builder::Cargo::new(
533 builder,
534 build_compiler,
535 Mode::Codegen,
536 SourceType::InTree,
537 target,
538 builder.kind,
539 );
540
541 cargo
542 .arg("--manifest-path")
543 .arg(builder.src.join("compiler/rustc_codegen_cranelift/Cargo.toml"));
544 rustc_cargo_env(builder, &mut cargo, target);
545 self.build_compiler.configure_cargo(&mut cargo);
546
547 let _guard = builder.msg(
548 Kind::Check,
549 "rustc_codegen_cranelift",
550 Mode::Codegen,
551 build_compiler,
552 target,
553 );
554
555 let stamp = build_stamp::codegen_backend_stamp(
556 builder,
557 build_compiler,
558 target,
559 &CodegenBackendKind::Cranelift,
560 )
561 .with_prefix("check");
562
563 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
564 }
565
566 fn metadata(&self) -> Option<StepMetadata> {
567 Some(
568 StepMetadata::check("rustc_codegen_cranelift", self.target)
569 .built_by(self.build_compiler.build_compiler()),
570 )
571 }
572}
573
574#[derive(Debug, Clone, PartialEq, Eq, Hash)]
576pub struct GccCodegenBackend {
577 build_compiler: CompilerForCheck,
578 target: TargetSelection,
579}
580
581impl Step for GccCodegenBackend {
582 type Output = ();
583
584 const IS_HOST: bool = true;
585 const DEFAULT: bool = true;
586
587 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
588 run.alias("rustc_codegen_gcc").alias("cg_gcc")
589 }
590
591 fn make_run(run: RunConfig<'_>) {
592 run.builder.ensure(GccCodegenBackend {
593 build_compiler: prepare_compiler_for_check(run.builder, run.target, Mode::Codegen),
594 target: run.target,
595 });
596 }
597
598 fn run(self, builder: &Builder<'_>) {
599 if builder.build.config.vendor {
601 println!("Skipping checking of `rustc_codegen_gcc` with vendoring enabled.");
602 return;
603 }
604
605 let build_compiler = self.build_compiler.build_compiler();
606 let target = self.target;
607
608 let mut cargo = builder::Cargo::new(
609 builder,
610 build_compiler,
611 Mode::Codegen,
612 SourceType::InTree,
613 target,
614 builder.kind,
615 );
616
617 cargo.arg("--manifest-path").arg(builder.src.join("compiler/rustc_codegen_gcc/Cargo.toml"));
618 rustc_cargo_env(builder, &mut cargo, target);
619 self.build_compiler.configure_cargo(&mut cargo);
620
621 let _guard =
622 builder.msg(Kind::Check, "rustc_codegen_gcc", Mode::Codegen, build_compiler, target);
623
624 let stamp = build_stamp::codegen_backend_stamp(
625 builder,
626 build_compiler,
627 target,
628 &CodegenBackendKind::Gcc,
629 )
630 .with_prefix("check");
631
632 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
633 }
634
635 fn metadata(&self) -> Option<StepMetadata> {
636 Some(
637 StepMetadata::check("rustc_codegen_gcc", self.target)
638 .built_by(self.build_compiler.build_compiler()),
639 )
640 }
641}
642
643macro_rules! tool_check_step {
644 (
645 $name:ident {
646 path: $path:literal
648 $(, alt_path: $alt_path:literal )*
649 , mode: $mode:expr
651 $(, allow_features: $allow_features:expr )?
653 $(, enable_features: [$($enable_features:expr),*] )?
655 $(, default: $default:literal )?
656 $( , )?
657 }
658 ) => {
659 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
660 pub struct $name {
661 compiler: CompilerForCheck,
662 target: TargetSelection,
663 }
664
665 impl Step for $name {
666 type Output = ();
667 const IS_HOST: bool = true;
668 const DEFAULT: bool = true $( && $default )?;
670
671 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
672 run.paths(&[ $path, $( $alt_path ),* ])
673 }
674
675 fn make_run(run: RunConfig<'_>) {
676 let target = run.target;
677 let mode: Mode = $mode;
678
679 let compiler = prepare_compiler_for_check(run.builder, target, mode);
680
681 if mode == Mode::ToolBootstrap && target != run.builder.host_target {
683 println!("WARNING: not checking bootstrap tool {} for target {target} as it is a bootstrap (host-only) tool", stringify!($path));
684 return;
685 };
686
687 run.builder.ensure($name { target, compiler });
688 }
689
690 fn run(self, builder: &Builder<'_>) {
691 let Self { target, compiler } = self;
692 let allow_features = {
693 let mut _value = "";
694 $( _value = $allow_features; )?
695 _value
696 };
697 let extra_features: &[&str] = &[$($($enable_features),*)?];
698 let mode: Mode = $mode;
699 run_tool_check_step(builder, compiler, target, $path, mode, allow_features, extra_features);
700 }
701
702 fn metadata(&self) -> Option<StepMetadata> {
703 Some(StepMetadata::check(stringify!($name), self.target).built_by(self.compiler.build_compiler))
704 }
705 }
706 }
707}
708
709fn run_tool_check_step(
711 builder: &Builder<'_>,
712 compiler: CompilerForCheck,
713 target: TargetSelection,
714 path: &str,
715 mode: Mode,
716 allow_features: &str,
717 extra_features: &[&str],
718) {
719 let display_name = path.rsplit('/').next().unwrap();
720
721 let build_compiler = compiler.build_compiler();
722
723 let extra_features = extra_features.iter().map(|f| f.to_string()).collect::<Vec<String>>();
724 let mut cargo = prepare_tool_cargo(
725 builder,
726 build_compiler,
727 mode,
728 target,
729 builder.kind,
730 path,
731 SourceType::InTree,
736 &extra_features,
737 );
738 cargo.allow_features(allow_features);
739 compiler.configure_cargo(&mut cargo);
740
741 if display_name == "rust-analyzer" {
744 cargo.arg("--bins");
745 cargo.arg("--tests");
746 cargo.arg("--benches");
747 } else {
748 cargo.arg("--all-targets");
749 }
750
751 let stamp = BuildStamp::new(&builder.cargo_out(build_compiler, mode, target))
752 .with_prefix(&format!("{display_name}-check"));
753
754 let _guard = builder.msg(builder.kind, display_name, mode, build_compiler, target);
755 run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false);
756}
757
758tool_check_step!(Rustdoc {
759 path: "src/tools/rustdoc",
760 alt_path: "src/librustdoc",
761 mode: Mode::ToolRustcPrivate
762});
763tool_check_step!(Clippy { path: "src/tools/clippy", mode: Mode::ToolRustcPrivate });
768tool_check_step!(Miri { path: "src/tools/miri", mode: Mode::ToolRustcPrivate });
769tool_check_step!(CargoMiri { path: "src/tools/miri/cargo-miri", mode: Mode::ToolRustcPrivate });
770tool_check_step!(Rustfmt { path: "src/tools/rustfmt", mode: Mode::ToolRustcPrivate });
771tool_check_step!(RustAnalyzer {
772 path: "src/tools/rust-analyzer",
773 mode: Mode::ToolRustcPrivate,
774 allow_features: tool::RustAnalyzer::ALLOW_FEATURES,
775 enable_features: ["in-rust-tree"],
776});
777tool_check_step!(MiroptTestTools {
778 path: "src/tools/miropt-test-tools",
779 mode: Mode::ToolBootstrap
780});
781tool_check_step!(TestFloatParse {
783 path: "src/tools/test-float-parse",
784 mode: Mode::ToolStd,
785 allow_features: TEST_FLOAT_PARSE_ALLOW_FEATURES
786});
787tool_check_step!(FeaturesStatusDump {
788 path: "src/tools/features-status-dump",
789 mode: Mode::ToolBootstrap
790});
791
792tool_check_step!(Bootstrap { path: "src/bootstrap", mode: Mode::ToolBootstrap, default: false });
793
794tool_check_step!(RunMakeSupport {
797 path: "src/tools/run-make-support",
798 mode: Mode::ToolBootstrap,
799 default: false
800});
801
802tool_check_step!(CoverageDump {
803 path: "src/tools/coverage-dump",
804 mode: Mode::ToolBootstrap,
805 default: false
806});
807
808tool_check_step!(Compiletest {
811 path: "src/tools/compiletest",
812 mode: Mode::ToolBootstrap,
813 default: false,
814});
815
816tool_check_step!(RustdocGuiTest {
820 path: "src/tools/rustdoc-gui-test",
821 mode: Mode::ToolBootstrap,
822 default: false,
823});
824
825tool_check_step!(Linkchecker {
826 path: "src/tools/linkchecker",
827 mode: Mode::ToolBootstrap,
828 default: false
829});
830
831tool_check_step!(BumpStage0 {
832 path: "src/tools/bump-stage0",
833 mode: Mode::ToolBootstrap,
834 default: false
835});
836
837tool_check_step!(Tidy { path: "src/tools/tidy", mode: Mode::ToolBootstrap, default: false });