1use std::collections::HashSet;
10use std::env::split_paths;
11use std::ffi::{OsStr, OsString};
12use std::path::{Path, PathBuf};
13use std::{env, fs, iter};
14
15use build_helper::exit;
16
17use crate::core::build_steps::compile::{ArtifactKeepMode, Std, run_cargo};
18use crate::core::build_steps::doc::{DocumentationFormat, prepare_doc_compiler};
19use crate::core::build_steps::gcc::{Gcc, GccTargetPair, add_cg_gcc_cargo_flags};
20use crate::core::build_steps::llvm::get_llvm_version;
21use crate::core::build_steps::run::{get_completion_paths, get_help_path};
22use crate::core::build_steps::synthetic_targets::MirOptPanicAbortSyntheticTarget;
23use crate::core::build_steps::test::compiletest::CompiletestMode;
24use crate::core::build_steps::tool::{
25 self, RustcPrivateCompilers, SourceType, TEST_FLOAT_PARSE_ALLOW_FEATURES, Tool,
26 ToolTargetBuildMode, get_tool_target_compiler,
27};
28use crate::core::build_steps::toolstate::ToolState;
29use crate::core::build_steps::{compile, dist, llvm};
30use crate::core::builder::{
31 self, Alias, Builder, Compiler, Kind, RunConfig, ShouldRun, Step, StepMetadata,
32 crate_description,
33};
34use crate::core::config::TargetSelection;
35use crate::core::config::flags::{Subcommand, get_completion, top_level_help};
36use crate::core::{android, debuggers};
37use crate::utils::build_stamp::{self, BuildStamp};
38use crate::utils::exec::{BootstrapCommand, command};
39use crate::utils::helpers::{
40 self, LldThreads, add_dylib_path, add_rustdoc_cargo_linker_args, dylib_path, dylib_path_var,
41 linker_args, linker_flags, t, target_supports_cranelift_backend, up_to_date,
42};
43use crate::utils::render_tests::{add_flags_and_try_run_tests, try_run_tests};
44use crate::{CLang, CodegenBackendKind, DocTests, GitRepo, Mode, PathSet, envify};
45
46mod compiletest;
47
48#[derive(Debug, Clone, PartialEq, Eq, Hash)]
50pub struct CrateBootstrap {
51 path: PathBuf,
52 host: TargetSelection,
53}
54
55impl Step for CrateBootstrap {
56 type Output = ();
57 const IS_HOST: bool = true;
58
59 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
60 run.path("src/tools/jsondoclint")
65 .path("src/tools/replace-version-placeholder")
66 .path("src/tools/coverage-dump")
67 .alias("tidyselftest")
70 }
71
72 fn is_default_step(_builder: &Builder<'_>) -> bool {
73 true
74 }
75
76 fn make_run(run: RunConfig<'_>) {
77 for path in run.paths {
80 let path = path.assert_single_path().path.clone();
81 run.builder.ensure(CrateBootstrap { host: run.target, path });
82 }
83 }
84
85 fn run(self, builder: &Builder<'_>) {
86 let bootstrap_host = builder.config.host_target;
87 let compiler = builder.compiler(0, bootstrap_host);
88 let mut path = self.path.to_str().unwrap();
89
90 if path == "tidyselftest" {
92 path = "src/tools/tidy";
93 }
94
95 let cargo = tool::prepare_tool_cargo(
96 builder,
97 compiler,
98 Mode::ToolBootstrap,
99 bootstrap_host,
100 Kind::Test,
101 path,
102 SourceType::InTree,
103 &[],
104 );
105
106 let crate_name = path.rsplit_once('/').unwrap().1;
107 run_cargo_test(cargo, &[], &[], crate_name, bootstrap_host, builder);
108 }
109
110 fn metadata(&self) -> Option<StepMetadata> {
111 Some(
112 StepMetadata::test("crate-bootstrap", self.host)
113 .with_metadata(self.path.as_path().to_string_lossy().to_string()),
114 )
115 }
116}
117
118#[derive(Debug, Clone, PartialEq, Eq, Hash)]
119pub struct Linkcheck {
120 host: TargetSelection,
121}
122
123impl Step for Linkcheck {
124 type Output = ();
125 const IS_HOST: bool = true;
126
127 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
128 run.path("src/tools/linkchecker")
129 }
130
131 fn is_default_step(builder: &Builder<'_>) -> bool {
132 builder.config.docs
133 }
134
135 fn make_run(run: RunConfig<'_>) {
136 run.builder.ensure(Linkcheck { host: run.target });
137 }
138
139 fn run(self, builder: &Builder<'_>) {
144 let host = self.host;
145 let hosts = &builder.hosts;
146 let targets = &builder.targets;
147
148 if (hosts != targets) && !hosts.is_empty() && !targets.is_empty() {
153 panic!(
154 "Linkcheck currently does not support builds with different hosts and targets.
155You can skip linkcheck with --skip src/tools/linkchecker"
156 );
157 }
158
159 builder.info(&format!("Linkcheck ({host})"));
160
161 let bootstrap_host = builder.config.host_target;
163 let compiler = builder.compiler(0, bootstrap_host);
164
165 let cargo = tool::prepare_tool_cargo(
166 builder,
167 compiler,
168 Mode::ToolBootstrap,
169 bootstrap_host,
170 Kind::Test,
171 "src/tools/linkchecker",
172 SourceType::InTree,
173 &[],
174 );
175 run_cargo_test(cargo, &[], &[], "linkchecker self tests", bootstrap_host, builder);
176
177 if builder.doc_tests == DocTests::No {
178 return;
179 }
180
181 builder.run_default_doc_steps();
183
184 let linkchecker = builder.tool_cmd(Tool::Linkchecker);
186
187 let _guard = builder.msg_test("Linkcheck", bootstrap_host, 1);
189 let _time = helpers::timeit(builder);
190 linkchecker.delay_failure().arg(builder.out.join(host).join("doc")).run(builder);
191 }
192
193 fn metadata(&self) -> Option<StepMetadata> {
194 Some(StepMetadata::test("link-check", self.host))
195 }
196}
197
198fn check_if_tidy_is_installed(builder: &Builder<'_>) -> bool {
199 command("tidy")
200 .allow_failure()
201 .arg("--version")
202 .cached()
204 .run_capture_stdout(builder)
205 .is_success()
206}
207
208#[derive(Debug, Clone, PartialEq, Eq, Hash)]
209pub struct HtmlCheck {
210 target: TargetSelection,
211}
212
213impl Step for HtmlCheck {
214 type Output = ();
215 const IS_HOST: bool = true;
216
217 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
218 run.path("src/tools/html-checker")
219 }
220
221 fn is_default_step(builder: &Builder<'_>) -> bool {
222 check_if_tidy_is_installed(builder)
223 }
224
225 fn make_run(run: RunConfig<'_>) {
226 run.builder.ensure(HtmlCheck { target: run.target });
227 }
228
229 fn run(self, builder: &Builder<'_>) {
230 if !check_if_tidy_is_installed(builder) {
231 eprintln!("not running HTML-check tool because `tidy` is missing");
232 eprintln!(
233 "You need the HTML tidy tool https://www.html-tidy.org/, this tool is *not* part of the rust project and needs to be installed separately, for example via your package manager."
234 );
235 panic!("Cannot run html-check tests");
236 }
237 builder.run_default_doc_steps();
239 builder.ensure(crate::core::build_steps::doc::Rustc::for_stage(
240 builder,
241 builder.top_stage,
242 self.target,
243 ));
244
245 builder
246 .tool_cmd(Tool::HtmlChecker)
247 .delay_failure()
248 .arg(builder.doc_out(self.target))
249 .run(builder);
250 }
251
252 fn metadata(&self) -> Option<StepMetadata> {
253 Some(StepMetadata::test("html-check", self.target))
254 }
255}
256
257#[derive(Debug, Clone, PartialEq, Eq, Hash)]
261pub struct Cargotest {
262 build_compiler: Compiler,
263 host: TargetSelection,
264}
265
266impl Step for Cargotest {
267 type Output = ();
268 const IS_HOST: bool = true;
269
270 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
271 run.path("src/tools/cargotest")
272 }
273
274 fn make_run(run: RunConfig<'_>) {
275 if run.builder.top_stage == 0 {
276 eprintln!(
277 "ERROR: running cargotest with stage 0 is currently unsupported. Use at least stage 1."
278 );
279 exit!(1);
280 }
281 run.builder.ensure(Cargotest {
285 build_compiler: run.builder.compiler(run.builder.top_stage - 1, run.target),
286 host: run.target,
287 });
288 }
289
290 fn run(self, builder: &Builder<'_>) {
295 let cargo =
305 builder.ensure(tool::Cargo::from_build_compiler(self.build_compiler, self.host));
306 let tested_compiler = builder.compiler(self.build_compiler.stage + 1, self.host);
307 builder.std(tested_compiler, self.host);
308
309 let out_dir = builder.out.join("ct");
313 t!(fs::create_dir_all(&out_dir));
314
315 let _time = helpers::timeit(builder);
316 let mut cmd = builder.tool_cmd(Tool::CargoTest);
317 cmd.arg(&cargo.tool_path)
318 .arg(&out_dir)
319 .args(builder.config.test_args())
320 .env("RUSTC", builder.rustc(tested_compiler))
321 .env("RUSTDOC", builder.rustdoc_for_compiler(tested_compiler));
322 add_rustdoc_cargo_linker_args(&mut cmd, builder, tested_compiler.host, LldThreads::No);
323 cmd.delay_failure().run(builder);
324 }
325
326 fn metadata(&self) -> Option<StepMetadata> {
327 Some(StepMetadata::test("cargotest", self.host).stage(self.build_compiler.stage + 1))
328 }
329}
330
331#[derive(Debug, Clone, PartialEq, Eq, Hash)]
334pub struct Cargo {
335 build_compiler: Compiler,
336 host: TargetSelection,
337}
338
339impl Cargo {
340 const CRATE_PATH: &str = "src/tools/cargo";
341}
342
343impl Step for Cargo {
344 type Output = ();
345 const IS_HOST: bool = true;
346
347 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
348 run.path(Self::CRATE_PATH)
349 }
350
351 fn make_run(run: RunConfig<'_>) {
352 run.builder.ensure(Cargo {
353 build_compiler: get_tool_target_compiler(
354 run.builder,
355 ToolTargetBuildMode::Build(run.target),
356 ),
357 host: run.target,
358 });
359 }
360
361 fn run(self, builder: &Builder<'_>) {
363 builder.ensure(tool::Cargo::from_build_compiler(self.build_compiler, self.host));
367
368 let tested_compiler = builder.compiler(self.build_compiler.stage + 1, self.host);
369 builder.std(tested_compiler, self.host);
370 builder.rustdoc_for_compiler(tested_compiler);
374
375 let cargo = tool::prepare_tool_cargo(
376 builder,
377 self.build_compiler,
378 Mode::ToolTarget,
379 self.host,
380 Kind::Test,
381 Self::CRATE_PATH,
382 SourceType::Submodule,
383 &[],
384 );
385
386 let mut cargo = prepare_cargo_test(cargo, &[], &[], self.host, builder);
388
389 cargo.env("CFG_DISABLE_CROSS_TESTS", "1");
392 cargo.env("CARGO_TEST_DISABLE_NIGHTLY", "1");
395
396 cargo.env("PATH", bin_path_for_cargo(builder, tested_compiler));
400
401 let mut existing_dylib_paths = cargo
406 .get_envs()
407 .find(|(k, _)| *k == OsStr::new(dylib_path_var()))
408 .and_then(|(_, v)| v)
409 .map(|value| split_paths(value).collect::<Vec<PathBuf>>())
410 .unwrap_or_default();
411 existing_dylib_paths.insert(0, builder.rustc_libdir(tested_compiler));
412 add_dylib_path(existing_dylib_paths, &mut cargo);
413
414 cargo.env("CARGO_RUSTC_CURRENT_DIR", builder.src.display().to_string());
418
419 #[cfg(feature = "build-metrics")]
420 builder.metrics.begin_test_suite(
421 build_helper::metrics::TestSuiteMetadata::CargoPackage {
422 crates: vec!["cargo".into()],
423 target: self.host.triple.to_string(),
424 host: self.host.triple.to_string(),
425 stage: self.build_compiler.stage + 1,
426 },
427 builder,
428 );
429
430 let _time = helpers::timeit(builder);
431 add_flags_and_try_run_tests(builder, &mut cargo);
432 }
433
434 fn metadata(&self) -> Option<StepMetadata> {
435 Some(StepMetadata::test("cargo", self.host).built_by(self.build_compiler))
436 }
437}
438
439#[derive(Debug, Clone, PartialEq, Eq, Hash)]
440pub struct RustAnalyzer {
441 compilers: RustcPrivateCompilers,
442}
443
444impl Step for RustAnalyzer {
445 type Output = ();
446 const IS_HOST: bool = true;
447
448 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
449 run.path("src/tools/rust-analyzer")
450 }
451
452 fn is_default_step(_builder: &Builder<'_>) -> bool {
453 true
454 }
455
456 fn make_run(run: RunConfig<'_>) {
457 run.builder.ensure(Self {
458 compilers: RustcPrivateCompilers::new(
459 run.builder,
460 run.builder.top_stage,
461 run.builder.host_target,
462 ),
463 });
464 }
465
466 fn run(self, builder: &Builder<'_>) {
468 let build_compiler = self.compilers.build_compiler();
469 let target = self.compilers.target();
470
471 if target.starts_with("i686") {
481 return;
482 }
483
484 let mut cargo = tool::prepare_tool_cargo(
485 builder,
486 build_compiler,
487 Mode::ToolRustcPrivate,
488 target,
489 Kind::Test,
490 "src/tools/rust-analyzer",
491 SourceType::InTree,
492 &["in-rust-tree".to_owned()],
493 );
494 cargo.allow_features(tool::RustAnalyzer::ALLOW_FEATURES);
495
496 cargo.env("SKIP_SLOW_TESTS", "1");
503
504 cargo.arg("--workspace");
510 cargo.arg("--exclude=xtask");
511
512 if build_compiler.stage == 0 {
513 cargo.arg("--exclude=proc-macro-srv");
516 cargo.arg("--exclude=proc-macro-srv-cli");
517 }
518
519 let mut skip_tests = vec![];
520
521 skip_tests.extend_from_slice(&[
529 "tests::smoke_test_real_sysroot_cargo",
532 "check_code_formatting",
535 ]);
536
537 let skip_tests = skip_tests.iter().map(|name| format!("--skip={name}")).collect::<Vec<_>>();
538 let skip_tests = skip_tests.iter().map(|s| s.as_str()).collect::<Vec<_>>();
539
540 cargo.add_rustc_lib_path(builder);
541 run_cargo_test(cargo, skip_tests.as_slice(), &[], "rust-analyzer", target, builder);
542 }
543
544 fn metadata(&self) -> Option<StepMetadata> {
545 Some(
546 StepMetadata::test("rust-analyzer", self.compilers.target())
547 .built_by(self.compilers.build_compiler()),
548 )
549 }
550}
551
552#[derive(Debug, Clone, PartialEq, Eq, Hash)]
554pub struct Rustfmt {
555 compilers: RustcPrivateCompilers,
556}
557
558impl Step for Rustfmt {
559 type Output = ();
560 const IS_HOST: bool = true;
561
562 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
563 run.path("src/tools/rustfmt")
564 }
565
566 fn make_run(run: RunConfig<'_>) {
567 run.builder.ensure(Rustfmt {
568 compilers: RustcPrivateCompilers::new(
569 run.builder,
570 run.builder.top_stage,
571 run.builder.host_target,
572 ),
573 });
574 }
575
576 fn run(self, builder: &Builder<'_>) {
578 let build_compiler = self.compilers.build_compiler();
579 let target = self.compilers.target();
580
581 let mut cargo = tool::prepare_tool_cargo(
582 builder,
583 build_compiler,
584 Mode::ToolRustcPrivate,
585 target,
586 Kind::Test,
587 "src/tools/rustfmt",
588 SourceType::InTree,
589 &[],
590 );
591
592 let dir = testdir(builder, target);
593 t!(fs::create_dir_all(&dir));
594 cargo.env("RUSTFMT_TEST_DIR", dir);
595
596 cargo.add_rustc_lib_path(builder);
597
598 run_cargo_test(cargo, &[], &[], "rustfmt", target, builder);
599 }
600
601 fn metadata(&self) -> Option<StepMetadata> {
602 Some(
603 StepMetadata::test("rustfmt", self.compilers.target())
604 .built_by(self.compilers.build_compiler()),
605 )
606 }
607}
608
609#[derive(Debug, Clone, PartialEq, Eq, Hash)]
610pub struct Miri {
611 target: TargetSelection,
612}
613
614impl Miri {
615 pub fn build_miri_sysroot(
617 builder: &Builder<'_>,
618 compiler: Compiler,
619 target: TargetSelection,
620 ) -> PathBuf {
621 let miri_sysroot = builder.out.join(compiler.host).join("miri-sysroot");
622 let mut cargo = builder::Cargo::new(
623 builder,
624 compiler,
625 Mode::Std,
626 SourceType::Submodule,
627 target,
628 Kind::MiriSetup,
629 );
630
631 cargo.env("MIRI_LIB_SRC", builder.src.join("library"));
633 cargo.env("MIRI_SYSROOT", &miri_sysroot);
635
636 let mut cargo = BootstrapCommand::from(cargo);
637 let _guard =
638 builder.msg(Kind::Build, "miri sysroot", Mode::ToolRustcPrivate, compiler, target);
639 cargo.run(builder);
640
641 cargo.arg("--print-sysroot");
647
648 builder.do_if_verbose(|| println!("running: {cargo:?}"));
649 let stdout = cargo.run_capture_stdout(builder).stdout();
650 let sysroot = stdout.trim_end();
652 builder.do_if_verbose(|| println!("`cargo miri setup --print-sysroot` said: {sysroot:?}"));
653 PathBuf::from(sysroot)
654 }
655}
656
657impl Step for Miri {
658 type Output = ();
659
660 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
661 run.path("src/tools/miri")
662 }
663
664 fn make_run(run: RunConfig<'_>) {
665 run.builder.ensure(Miri { target: run.target });
666 }
667
668 fn run(self, builder: &Builder<'_>) {
670 let host = builder.build.host_target;
671 let target = self.target;
672 let stage = builder.top_stage;
673 if stage == 0 {
674 eprintln!("miri cannot be tested at stage 0");
675 std::process::exit(1);
676 }
677
678 let compilers = RustcPrivateCompilers::new(builder, stage, host);
680
681 let miri = builder.ensure(tool::Miri::from_compilers(compilers));
683 builder.ensure(tool::CargoMiri::from_compilers(compilers));
685
686 let target_compiler = compilers.target_compiler();
687
688 let miri_sysroot = Miri::build_miri_sysroot(builder, target_compiler, target);
691 builder.std(target_compiler, host);
692 let host_sysroot = builder.sysroot(target_compiler);
693
694 if !builder.config.dry_run() {
697 let ui_test_dep_dir = builder
700 .stage_out(miri.build_compiler, Mode::ToolStd)
701 .join(host)
702 .join("tmp")
703 .join("miri_ui");
704 build_stamp::clear_if_dirty(builder, &ui_test_dep_dir, &miri_sysroot);
708 }
709
710 let mut cargo = tool::prepare_tool_cargo(
713 builder,
714 miri.build_compiler,
715 Mode::ToolRustcPrivate,
716 host,
717 Kind::Test,
718 "src/tools/miri",
719 SourceType::InTree,
720 &[],
721 );
722
723 cargo.add_rustc_lib_path(builder);
724
725 let mut cargo = prepare_cargo_test(cargo, &[], &[], host, builder);
728
729 cargo.env("MIRI_SYSROOT", &miri_sysroot);
731 cargo.env("MIRI_HOST_SYSROOT", &host_sysroot);
732
733 cargo.env("MIRI_TEST_TARGET", target.rustc_target_arg());
735
736 {
737 let _guard = builder.msg_test("miri", target, target_compiler.stage);
738 let _time = helpers::timeit(builder);
739 cargo.run(builder);
740 }
741
742 if builder.config.test_args().is_empty() {
744 cargo.env("MIRIFLAGS", "-O -Zmir-opt-level=4 -Cdebug-assertions=yes");
745 cargo.env("MIRI_SKIP_UI_CHECKS", "1");
747 cargo.env_remove("RUSTC_BLESS");
749 cargo.args(["tests/pass", "tests/panic"]);
751
752 {
753 let _guard =
754 builder.msg_test("miri (mir-opt-level 4)", target, target_compiler.stage);
755 let _time = helpers::timeit(builder);
756 cargo.run(builder);
757 }
758 }
759 }
760}
761
762#[derive(Debug, Clone, PartialEq, Eq, Hash)]
765pub struct CargoMiri {
766 target: TargetSelection,
767}
768
769impl Step for CargoMiri {
770 type Output = ();
771
772 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
773 run.path("src/tools/miri/cargo-miri")
774 }
775
776 fn make_run(run: RunConfig<'_>) {
777 run.builder.ensure(CargoMiri { target: run.target });
778 }
779
780 fn run(self, builder: &Builder<'_>) {
782 let host = builder.build.host_target;
783 let target = self.target;
784 let stage = builder.top_stage;
785 if stage == 0 {
786 eprintln!("cargo-miri cannot be tested at stage 0");
787 std::process::exit(1);
788 }
789
790 let build_compiler = builder.compiler(stage, host);
792
793 let mut cargo = tool::prepare_tool_cargo(
798 builder,
799 build_compiler,
800 Mode::ToolStd, target,
802 Kind::MiriTest,
803 "src/tools/miri/test-cargo-miri",
804 SourceType::Submodule,
805 &[],
806 );
807
808 if stage >= 2 {
811 let built_cargo = builder
812 .ensure(tool::Cargo::from_build_compiler(
813 builder.compiler(0, builder.host_target),
816 builder.host_target,
817 ))
818 .tool_path;
819 cargo.env("CARGO", built_cargo);
820 }
821
822 match builder.doc_tests {
825 DocTests::Yes => {}
826 DocTests::No => {
827 cargo.args(["--lib", "--bins", "--examples", "--tests", "--benches"]);
828 }
829 DocTests::Only => {
830 cargo.arg("--doc");
831 }
832 }
833 cargo.arg("--").args(builder.config.test_args());
834
835 let mut cargo = BootstrapCommand::from(cargo);
837 {
838 let _guard = builder.msg_test("cargo-miri", target, stage);
839 let _time = helpers::timeit(builder);
840 cargo.run(builder);
841 }
842 }
843}
844
845#[derive(Debug, Clone, PartialEq, Eq, Hash)]
846pub struct CompiletestTest {
847 host: TargetSelection,
848}
849
850impl Step for CompiletestTest {
851 type Output = ();
852
853 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
854 run.path("src/tools/compiletest")
855 }
856
857 fn make_run(run: RunConfig<'_>) {
858 run.builder.ensure(CompiletestTest { host: run.target });
859 }
860
861 fn run(self, builder: &Builder<'_>) {
863 let host = self.host;
864
865 if builder.top_stage == 0 && !builder.config.compiletest_allow_stage0 {
871 eprintln!("\
872ERROR: `--stage 0` causes compiletest to query information from the stage0 (precompiled) compiler, instead of the in-tree compiler, which can cause some tests to fail inappropriately
873NOTE: if you're sure you want to do this, please open an issue as to why. In the meantime, you can override this with `--set build.compiletest-allow-stage0=true`."
874 );
875 crate::exit!(1);
876 }
877
878 let bootstrap_compiler = builder.compiler(0, host);
879 let staged_compiler = builder.compiler(builder.top_stage, host);
880
881 let mut cargo = tool::prepare_tool_cargo(
882 builder,
883 bootstrap_compiler,
884 Mode::ToolBootstrap,
885 host,
886 Kind::Test,
887 "src/tools/compiletest",
888 SourceType::InTree,
889 &[],
890 );
891
892 cargo.env("TEST_RUSTC", builder.rustc(staged_compiler));
896
897 run_cargo_test(cargo, &[], &[], "compiletest self test", host, builder);
898 }
899}
900
901#[derive(Debug, Clone, PartialEq, Eq, Hash)]
902pub struct Clippy {
903 compilers: RustcPrivateCompilers,
904}
905
906impl Step for Clippy {
907 type Output = ();
908 const IS_HOST: bool = true;
909
910 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
911 run.suite_path("src/tools/clippy/tests").path("src/tools/clippy")
912 }
913
914 fn is_default_step(_builder: &Builder<'_>) -> bool {
915 false
916 }
917
918 fn make_run(run: RunConfig<'_>) {
919 run.builder.ensure(Clippy {
920 compilers: RustcPrivateCompilers::new(
921 run.builder,
922 run.builder.top_stage,
923 run.builder.host_target,
924 ),
925 });
926 }
927
928 fn run(self, builder: &Builder<'_>) {
930 let target = self.compilers.target();
931
932 let target_compiler = self.compilers.target_compiler();
936 let build_compiler = self.compilers.build_compiler();
937
938 let mut cargo = tool::prepare_tool_cargo(
939 builder,
940 build_compiler,
941 Mode::ToolRustcPrivate,
942 target,
943 Kind::Test,
944 "src/tools/clippy",
945 SourceType::InTree,
946 &[],
947 );
948
949 cargo.env("RUSTC_TEST_SUITE", builder.rustc(build_compiler));
950 cargo.env("RUSTC_LIB_PATH", builder.rustc_libdir(build_compiler));
951 let host_libs = builder
952 .stage_out(build_compiler, Mode::ToolRustcPrivate)
953 .join(builder.cargo_dir(Mode::ToolRustcPrivate));
954 cargo.env("HOST_LIBS", host_libs);
955
956 builder.std(target_compiler, target);
958 cargo.env("TEST_SYSROOT", builder.sysroot(target_compiler));
959 cargo.env("TEST_RUSTC", builder.rustc(target_compiler));
960 cargo.env("TEST_RUSTC_LIB", builder.rustc_libdir(target_compiler));
961
962 'partially_test: {
964 let paths = &builder.config.paths[..];
965 let mut test_names = Vec::new();
966 for path in paths {
967 if let Some(path) =
968 helpers::is_valid_test_suite_arg(path, "src/tools/clippy/tests", builder)
969 {
970 test_names.push(path);
971 } else if path.ends_with("src/tools/clippy") {
972 break 'partially_test;
974 }
975 }
976 cargo.env("TESTNAME", test_names.join(","));
977 }
978
979 cargo.add_rustc_lib_path(builder);
980 let cargo = prepare_cargo_test(cargo, &[], &[], target, builder);
981
982 let _guard = builder.msg_test("clippy", target, target_compiler.stage);
983
984 if cargo.allow_failure().run(builder) {
986 return;
988 }
989
990 if !builder.config.cmd.bless() {
991 crate::exit!(1);
992 }
993 }
994
995 fn metadata(&self) -> Option<StepMetadata> {
996 Some(
997 StepMetadata::test("clippy", self.compilers.target())
998 .built_by(self.compilers.build_compiler()),
999 )
1000 }
1001}
1002
1003fn bin_path_for_cargo(builder: &Builder<'_>, compiler: Compiler) -> OsString {
1004 let path = builder.sysroot(compiler).join("bin");
1005 let old_path = env::var_os("PATH").unwrap_or_default();
1006 env::join_paths(iter::once(path).chain(env::split_paths(&old_path))).expect("")
1007}
1008
1009#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1011pub struct RustdocTheme {
1012 test_compiler: Compiler,
1014}
1015
1016impl Step for RustdocTheme {
1017 type Output = ();
1018 const IS_HOST: bool = true;
1019
1020 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1021 run.path("src/tools/rustdoc-themes")
1022 }
1023
1024 fn is_default_step(_builder: &Builder<'_>) -> bool {
1025 true
1026 }
1027
1028 fn make_run(run: RunConfig<'_>) {
1029 let test_compiler = run.builder.compiler(run.builder.top_stage, run.target);
1030
1031 run.builder.ensure(RustdocTheme { test_compiler });
1032 }
1033
1034 fn run(self, builder: &Builder<'_>) {
1035 let rustdoc = builder.bootstrap_out.join("rustdoc");
1036 let mut cmd = builder.tool_cmd(Tool::RustdocTheme);
1037 cmd.arg(rustdoc.to_str().unwrap())
1038 .arg(builder.src.join("src/librustdoc/html/static/css/rustdoc.css").to_str().unwrap())
1039 .env("RUSTC_STAGE", self.test_compiler.stage.to_string())
1040 .env("RUSTC_SYSROOT", builder.sysroot(self.test_compiler))
1041 .env(
1042 "RUSTDOC_LIBDIR",
1043 builder.sysroot_target_libdir(self.test_compiler, self.test_compiler.host),
1044 )
1045 .env("CFG_RELEASE_CHANNEL", &builder.config.channel)
1046 .env("RUSTDOC_REAL", builder.rustdoc_for_compiler(self.test_compiler))
1047 .env("RUSTC_BOOTSTRAP", "1");
1048 cmd.args(linker_args(builder, self.test_compiler.host, LldThreads::No));
1049
1050 cmd.delay_failure().run(builder);
1051 }
1052
1053 fn metadata(&self) -> Option<StepMetadata> {
1054 Some(
1055 StepMetadata::test("rustdoc-theme", self.test_compiler.host)
1056 .stage(self.test_compiler.stage),
1057 )
1058 }
1059}
1060
1061#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1063pub struct RustdocJSStd {
1064 build_compiler: Compiler,
1066 target: TargetSelection,
1067}
1068
1069impl Step for RustdocJSStd {
1070 type Output = ();
1071 const IS_HOST: bool = true;
1072
1073 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1074 run.suite_path("tests/rustdoc-js-std")
1075 }
1076
1077 fn is_default_step(builder: &Builder<'_>) -> bool {
1078 builder.config.nodejs.is_some()
1079 }
1080
1081 fn make_run(run: RunConfig<'_>) {
1082 run.builder.ensure(RustdocJSStd {
1083 build_compiler: run.builder.compiler(run.builder.top_stage, run.builder.host_target),
1084 target: run.target,
1085 });
1086 }
1087
1088 fn run(self, builder: &Builder<'_>) {
1089 let nodejs =
1090 builder.config.nodejs.as_ref().expect("need nodejs to run rustdoc-js-std tests");
1091 let mut command = command(nodejs);
1092 command
1093 .arg(builder.src.join("src/tools/rustdoc-js/tester.js"))
1094 .arg("--crate-name")
1095 .arg("std")
1096 .arg("--resource-suffix")
1097 .arg(&builder.version)
1098 .arg("--doc-folder")
1099 .arg(builder.doc_out(self.target))
1100 .arg("--test-folder")
1101 .arg(builder.src.join("tests/rustdoc-js-std"));
1102 for path in &builder.paths {
1103 if let Some(p) = helpers::is_valid_test_suite_arg(path, "tests/rustdoc-js-std", builder)
1104 {
1105 if !p.ends_with(".js") {
1106 eprintln!("A non-js file was given: `{}`", path.display());
1107 panic!("Cannot run rustdoc-js-std tests");
1108 }
1109 command.arg("--test-file").arg(path);
1110 }
1111 }
1112 builder.ensure(crate::core::build_steps::doc::Std::from_build_compiler(
1113 self.build_compiler,
1114 self.target,
1115 DocumentationFormat::Html,
1116 ));
1117 let _guard = builder.msg_test("rustdoc-js-std", self.target, self.build_compiler.stage);
1118 command.run(builder);
1119 }
1120
1121 fn metadata(&self) -> Option<StepMetadata> {
1122 Some(StepMetadata::test("rustdoc-js-std", self.target).stage(self.build_compiler.stage))
1123 }
1124}
1125
1126#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1127pub struct RustdocJSNotStd {
1128 pub target: TargetSelection,
1129 pub compiler: Compiler,
1130}
1131
1132impl Step for RustdocJSNotStd {
1133 type Output = ();
1134 const IS_HOST: bool = true;
1135
1136 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1137 run.suite_path("tests/rustdoc-js")
1138 }
1139
1140 fn is_default_step(builder: &Builder<'_>) -> bool {
1141 builder.config.nodejs.is_some()
1142 }
1143
1144 fn make_run(run: RunConfig<'_>) {
1145 let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1146 run.builder.ensure(RustdocJSNotStd { target: run.target, compiler });
1147 }
1148
1149 fn run(self, builder: &Builder<'_>) {
1150 builder.ensure(Compiletest {
1151 test_compiler: self.compiler,
1152 target: self.target,
1153 mode: CompiletestMode::RustdocJs,
1154 suite: "rustdoc-js",
1155 path: "tests/rustdoc-js",
1156 compare_mode: None,
1157 });
1158 }
1159}
1160
1161fn get_browser_ui_test_version_inner(
1162 builder: &Builder<'_>,
1163 yarn: &Path,
1164 global: bool,
1165) -> Option<String> {
1166 let mut command = command(yarn);
1167 command
1168 .arg("--cwd")
1169 .arg(&builder.build.out)
1170 .arg("list")
1171 .arg("--parseable")
1172 .arg("--long")
1173 .arg("--depth=0");
1174 if global {
1175 command.arg("--global");
1176 }
1177 let lines = command.allow_failure().cached().run_capture(builder).stdout();
1180 lines
1181 .lines()
1182 .find_map(|l| l.split(':').nth(1)?.strip_prefix("browser-ui-test@"))
1183 .map(|v| v.to_owned())
1184}
1185
1186fn get_browser_ui_test_version(builder: &Builder<'_>) -> Option<String> {
1187 let yarn = builder.config.yarn.as_deref()?;
1188 get_browser_ui_test_version_inner(builder, yarn, false)
1189 .or_else(|| get_browser_ui_test_version_inner(builder, yarn, true))
1190}
1191
1192#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1194pub struct RustdocGUI {
1195 test_compiler: Compiler,
1197 target: TargetSelection,
1198}
1199
1200impl Step for RustdocGUI {
1201 type Output = ();
1202 const IS_HOST: bool = true;
1203
1204 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1205 run.suite_path("tests/rustdoc-gui")
1206 }
1207
1208 fn is_default_step(builder: &Builder<'_>) -> bool {
1209 builder.config.nodejs.is_some()
1210 && builder.doc_tests != DocTests::Only
1211 && get_browser_ui_test_version(builder).is_some()
1212 }
1213
1214 fn make_run(run: RunConfig<'_>) {
1215 let test_compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1216 run.builder.ensure(RustdocGUI { test_compiler, target: run.target });
1217 }
1218
1219 fn run(self, builder: &Builder<'_>) {
1220 builder.std(self.test_compiler, self.target);
1221
1222 let mut cmd = builder.tool_cmd(Tool::RustdocGUITest);
1223
1224 let out_dir = builder.test_out(self.target).join("rustdoc-gui");
1225 build_stamp::clear_if_dirty(
1226 builder,
1227 &out_dir,
1228 &builder.rustdoc_for_compiler(self.test_compiler),
1229 );
1230
1231 if let Some(src) = builder.config.src.to_str() {
1232 cmd.arg("--rust-src").arg(src);
1233 }
1234
1235 if let Some(out_dir) = out_dir.to_str() {
1236 cmd.arg("--out-dir").arg(out_dir);
1237 }
1238
1239 if let Some(initial_cargo) = builder.config.initial_cargo.to_str() {
1240 cmd.arg("--initial-cargo").arg(initial_cargo);
1241 }
1242
1243 cmd.arg("--jobs").arg(builder.jobs().to_string());
1244
1245 cmd.env("RUSTDOC", builder.rustdoc_for_compiler(self.test_compiler))
1246 .env("RUSTC", builder.rustc(self.test_compiler));
1247
1248 add_rustdoc_cargo_linker_args(&mut cmd, builder, self.test_compiler.host, LldThreads::No);
1249
1250 for path in &builder.paths {
1251 if let Some(p) = helpers::is_valid_test_suite_arg(path, "tests/rustdoc-gui", builder) {
1252 if !p.ends_with(".goml") {
1253 eprintln!("A non-goml file was given: `{}`", path.display());
1254 panic!("Cannot run rustdoc-gui tests");
1255 }
1256 if let Some(name) = path.file_name().and_then(|f| f.to_str()) {
1257 cmd.arg("--goml-file").arg(name);
1258 }
1259 }
1260 }
1261
1262 for test_arg in builder.config.test_args() {
1263 cmd.arg("--test-arg").arg(test_arg);
1264 }
1265
1266 if let Some(ref nodejs) = builder.config.nodejs {
1267 cmd.arg("--nodejs").arg(nodejs);
1268 }
1269
1270 if let Some(ref yarn) = builder.config.yarn {
1271 cmd.arg("--yarn").arg(yarn);
1272 }
1273
1274 let _time = helpers::timeit(builder);
1275 let _guard = builder.msg_test("rustdoc-gui", self.target, self.test_compiler.stage);
1276 try_run_tests(builder, &mut cmd, true);
1277 }
1278
1279 fn metadata(&self) -> Option<StepMetadata> {
1280 Some(StepMetadata::test("rustdoc-gui", self.target).stage(self.test_compiler.stage))
1281 }
1282}
1283
1284#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1289pub struct Tidy;
1290
1291impl Step for Tidy {
1292 type Output = ();
1293 const IS_HOST: bool = true;
1294
1295 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1296 run.path("src/tools/tidy")
1297 }
1298
1299 fn is_default_step(builder: &Builder<'_>) -> bool {
1300 builder.doc_tests != DocTests::Only
1301 }
1302
1303 fn make_run(run: RunConfig<'_>) {
1304 run.builder.ensure(Tidy);
1305 }
1306
1307 fn run(self, builder: &Builder<'_>) {
1316 let mut cmd = builder.tool_cmd(Tool::Tidy);
1317 cmd.arg(format!("--root-path={}", &builder.src.display()));
1318 cmd.arg(format!("--cargo-path={}", &builder.initial_cargo.display()));
1319 cmd.arg(format!("--output-dir={}", &builder.out.display()));
1320 let jobs = builder.config.jobs.unwrap_or_else(|| {
1322 8 * std::thread::available_parallelism().map_or(1, std::num::NonZeroUsize::get) as u32
1323 });
1324 cmd.arg(format!("--concurrency={jobs}"));
1325 if let Some(yarn) = &builder.config.yarn {
1327 cmd.arg(format!("--npm-path={}", yarn.display()));
1328 } else {
1329 cmd.arg("--npm-path=yarn");
1330 }
1331 if builder.is_verbose() {
1332 cmd.arg("--verbose");
1333 }
1334 if builder.config.cmd.bless() {
1335 cmd.arg("--bless");
1336 }
1337 if builder.config.is_running_on_ci() {
1338 cmd.arg("--ci=true");
1339 }
1340 if let Some(s) =
1341 builder.config.cmd.extra_checks().or(builder.config.tidy_extra_checks.as_deref())
1342 {
1343 cmd.arg(format!("--extra-checks={s}"));
1344 }
1345 let mut args = std::env::args_os();
1346 if args.any(|arg| arg == OsStr::new("--")) {
1347 cmd.arg("--");
1348 cmd.args(args);
1349 }
1350
1351 if builder.config.channel == "dev" || builder.config.channel == "nightly" {
1352 if !builder.config.json_output {
1353 builder.info("fmt check");
1354 if builder.config.initial_rustfmt.is_none() {
1355 let inferred_rustfmt_dir = builder.initial_sysroot.join("bin");
1356 eprintln!(
1357 "\
1358ERROR: no `rustfmt` binary found in {PATH}
1359INFO: `rust.channel` is currently set to \"{CHAN}\"
1360HELP: if you are testing a beta branch, set `rust.channel` to \"beta\" in the `bootstrap.toml` file
1361HELP: to skip test's attempt to check tidiness, pass `--skip src/tools/tidy` to `x.py test`",
1362 PATH = inferred_rustfmt_dir.display(),
1363 CHAN = builder.config.channel,
1364 );
1365 crate::exit!(1);
1366 }
1367 let all = false;
1368 crate::core::build_steps::format::format(
1369 builder,
1370 !builder.config.cmd.bless(),
1371 all,
1372 &[],
1373 );
1374 } else {
1375 eprintln!(
1376 "WARNING: `--json-output` is not supported on rustfmt, formatting will be skipped"
1377 );
1378 }
1379 }
1380
1381 builder.info("tidy check");
1382 cmd.delay_failure().run(builder);
1383
1384 builder.info("x.py completions check");
1385 let completion_paths = get_completion_paths(builder);
1386 if builder.config.cmd.bless() {
1387 builder.ensure(crate::core::build_steps::run::GenerateCompletions);
1388 } else if completion_paths
1389 .into_iter()
1390 .any(|(shell, path)| get_completion(shell, &path).is_some())
1391 {
1392 eprintln!(
1393 "x.py completions were changed; run `x.py run generate-completions` to update them"
1394 );
1395 crate::exit!(1);
1396 }
1397
1398 builder.info("x.py help check");
1399 if builder.config.cmd.bless() {
1400 builder.ensure(crate::core::build_steps::run::GenerateHelp);
1401 } else {
1402 let help_path = get_help_path(builder);
1403 let cur_help = std::fs::read_to_string(&help_path).unwrap_or_else(|err| {
1404 eprintln!("couldn't read {}: {}", help_path.display(), err);
1405 crate::exit!(1);
1406 });
1407 let new_help = top_level_help();
1408
1409 if new_help != cur_help {
1410 eprintln!("x.py help was changed; run `x.py run generate-help` to update it");
1411 crate::exit!(1);
1412 }
1413 }
1414 }
1415
1416 fn metadata(&self) -> Option<StepMetadata> {
1417 Some(StepMetadata::test("tidy", TargetSelection::default()))
1418 }
1419}
1420
1421#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1424pub struct CrateRunMakeSupport {
1425 host: TargetSelection,
1426}
1427
1428impl Step for CrateRunMakeSupport {
1429 type Output = ();
1430 const IS_HOST: bool = true;
1431
1432 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1433 run.path("src/tools/run-make-support")
1434 }
1435
1436 fn make_run(run: RunConfig<'_>) {
1437 run.builder.ensure(CrateRunMakeSupport { host: run.target });
1438 }
1439
1440 fn run(self, builder: &Builder<'_>) {
1442 let host = self.host;
1443 let compiler = builder.compiler(0, host);
1444
1445 let mut cargo = tool::prepare_tool_cargo(
1446 builder,
1447 compiler,
1448 Mode::ToolBootstrap,
1449 host,
1450 Kind::Test,
1451 "src/tools/run-make-support",
1452 SourceType::InTree,
1453 &[],
1454 );
1455 cargo.allow_features("test");
1456 run_cargo_test(cargo, &[], &[], "run-make-support self test", host, builder);
1457 }
1458}
1459
1460#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1461pub struct CrateBuildHelper {
1462 host: TargetSelection,
1463}
1464
1465impl Step for CrateBuildHelper {
1466 type Output = ();
1467 const IS_HOST: bool = true;
1468
1469 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1470 run.path("src/build_helper")
1471 }
1472
1473 fn make_run(run: RunConfig<'_>) {
1474 run.builder.ensure(CrateBuildHelper { host: run.target });
1475 }
1476
1477 fn run(self, builder: &Builder<'_>) {
1479 let host = self.host;
1480 let compiler = builder.compiler(0, host);
1481
1482 let mut cargo = tool::prepare_tool_cargo(
1483 builder,
1484 compiler,
1485 Mode::ToolBootstrap,
1486 host,
1487 Kind::Test,
1488 "src/build_helper",
1489 SourceType::InTree,
1490 &[],
1491 );
1492 cargo.allow_features("test");
1493 run_cargo_test(cargo, &[], &[], "build_helper self test", host, builder);
1494 }
1495}
1496
1497fn testdir(builder: &Builder<'_>, host: TargetSelection) -> PathBuf {
1498 builder.out.join(host).join("test")
1499}
1500
1501macro_rules! test {
1503 (
1504 $( #[$attr:meta] )* $name:ident {
1506 path: $path:expr,
1507 mode: $mode:expr,
1508 suite: $suite:expr,
1509 default: $default:expr
1510 $( , IS_HOST: $IS_HOST:expr )? $( , compare_mode: $compare_mode:expr )? $( , )? }
1514 ) => {
1515 $( #[$attr] )*
1516 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
1517 pub struct $name {
1518 test_compiler: Compiler,
1519 target: TargetSelection,
1520 }
1521
1522 impl Step for $name {
1523 type Output = ();
1524 const IS_HOST: bool = (const {
1525 #[allow(unused_assignments, unused_mut)]
1526 let mut value = false;
1527 $( value = $IS_HOST; )?
1528 value
1529 });
1530
1531 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1532 run.suite_path($path)
1533 }
1534
1535 fn is_default_step(_builder: &Builder<'_>) -> bool {
1536 const { $default }
1537 }
1538
1539 fn make_run(run: RunConfig<'_>) {
1540 let test_compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1541
1542 run.builder.ensure($name { test_compiler, target: run.target });
1543 }
1544
1545 fn run(self, builder: &Builder<'_>) {
1546 builder.ensure(Compiletest {
1547 test_compiler: self.test_compiler,
1548 target: self.target,
1549 mode: const { $mode },
1550 suite: $suite,
1551 path: $path,
1552 compare_mode: (const {
1553 #[allow(unused_assignments, unused_mut)]
1554 let mut value = None;
1555 $( value = $compare_mode; )?
1556 value
1557 }),
1558 })
1559 }
1560 }
1561 };
1562}
1563
1564test!(Ui { path: "tests/ui", mode: CompiletestMode::Ui, suite: "ui", default: true });
1565
1566test!(Crashes {
1567 path: "tests/crashes",
1568 mode: CompiletestMode::Crashes,
1569 suite: "crashes",
1570 default: true,
1571});
1572
1573test!(CodegenLlvm {
1574 path: "tests/codegen-llvm",
1575 mode: CompiletestMode::Codegen,
1576 suite: "codegen-llvm",
1577 default: true
1578});
1579
1580test!(CodegenUnits {
1581 path: "tests/codegen-units",
1582 mode: CompiletestMode::CodegenUnits,
1583 suite: "codegen-units",
1584 default: true,
1585});
1586
1587test!(Incremental {
1588 path: "tests/incremental",
1589 mode: CompiletestMode::Incremental,
1590 suite: "incremental",
1591 default: true,
1592});
1593
1594test!(Debuginfo {
1595 path: "tests/debuginfo",
1596 mode: CompiletestMode::Debuginfo,
1597 suite: "debuginfo",
1598 default: true,
1599 compare_mode: Some("split-dwarf"),
1600});
1601
1602test!(UiFullDeps {
1603 path: "tests/ui-fulldeps",
1604 mode: CompiletestMode::Ui,
1605 suite: "ui-fulldeps",
1606 default: true,
1607 IS_HOST: true,
1608});
1609
1610test!(RustdocHtml {
1611 path: "tests/rustdoc-html",
1612 mode: CompiletestMode::RustdocHtml,
1613 suite: "rustdoc-html",
1614 default: true,
1615 IS_HOST: true,
1616});
1617test!(RustdocUi {
1618 path: "tests/rustdoc-ui",
1619 mode: CompiletestMode::Ui,
1620 suite: "rustdoc-ui",
1621 default: true,
1622 IS_HOST: true,
1623});
1624
1625test!(RustdocJson {
1626 path: "tests/rustdoc-json",
1627 mode: CompiletestMode::RustdocJson,
1628 suite: "rustdoc-json",
1629 default: true,
1630 IS_HOST: true,
1631});
1632
1633test!(Pretty {
1634 path: "tests/pretty",
1635 mode: CompiletestMode::Pretty,
1636 suite: "pretty",
1637 default: true,
1638 IS_HOST: true,
1639});
1640
1641test!(RunMake {
1642 path: "tests/run-make",
1643 mode: CompiletestMode::RunMake,
1644 suite: "run-make",
1645 default: true,
1646});
1647test!(RunMakeCargo {
1648 path: "tests/run-make-cargo",
1649 mode: CompiletestMode::RunMake,
1650 suite: "run-make-cargo",
1651 default: true
1652});
1653test!(BuildStd {
1654 path: "tests/build-std",
1655 mode: CompiletestMode::RunMake,
1656 suite: "build-std",
1657 default: false
1658});
1659
1660test!(AssemblyLlvm {
1661 path: "tests/assembly-llvm",
1662 mode: CompiletestMode::Assembly,
1663 suite: "assembly-llvm",
1664 default: true
1665});
1666
1667#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1670pub struct Coverage {
1671 pub compiler: Compiler,
1672 pub target: TargetSelection,
1673 pub(crate) mode: CompiletestMode,
1674}
1675
1676impl Coverage {
1677 const PATH: &'static str = "tests/coverage";
1678 const SUITE: &'static str = "coverage";
1679 const ALL_MODES: &[CompiletestMode] =
1680 &[CompiletestMode::CoverageMap, CompiletestMode::CoverageRun];
1681}
1682
1683impl Step for Coverage {
1684 type Output = ();
1685 const IS_HOST: bool = false;
1687
1688 fn should_run(mut run: ShouldRun<'_>) -> ShouldRun<'_> {
1689 run = run.suite_path(Self::PATH);
1695 for mode in Self::ALL_MODES {
1696 run = run.alias(mode.as_str());
1697 }
1698 run
1699 }
1700
1701 fn is_default_step(_builder: &Builder<'_>) -> bool {
1702 true
1703 }
1704
1705 fn make_run(run: RunConfig<'_>) {
1706 let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1707 let target = run.target;
1708
1709 let mut modes = vec![];
1713
1714 for path in &run.paths {
1717 match path {
1718 PathSet::Set(_) => {
1719 for &mode in Self::ALL_MODES {
1720 if path.assert_single_path().path == Path::new(mode.as_str()) {
1721 modes.push(mode);
1722 break;
1723 }
1724 }
1725 }
1726 PathSet::Suite(_) => {
1727 modes.extend_from_slice(Self::ALL_MODES);
1728 break;
1729 }
1730 }
1731 }
1732
1733 modes.retain(|mode| {
1736 !run.builder.config.skip.iter().any(|skip| skip == Path::new(mode.as_str()))
1737 });
1738
1739 for mode in modes {
1747 run.builder.ensure(Coverage { compiler, target, mode });
1748 }
1749 }
1750
1751 fn run(self, builder: &Builder<'_>) {
1752 let Self { compiler, target, mode } = self;
1753 builder.ensure(Compiletest {
1756 test_compiler: compiler,
1757 target,
1758 mode,
1759 suite: Self::SUITE,
1760 path: Self::PATH,
1761 compare_mode: None,
1762 });
1763 }
1764}
1765
1766test!(CoverageRunRustdoc {
1767 path: "tests/coverage-run-rustdoc",
1768 mode: CompiletestMode::CoverageRun,
1769 suite: "coverage-run-rustdoc",
1770 default: true,
1771 IS_HOST: true,
1772});
1773
1774#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1776pub struct MirOpt {
1777 pub compiler: Compiler,
1778 pub target: TargetSelection,
1779}
1780
1781impl Step for MirOpt {
1782 type Output = ();
1783
1784 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1785 run.suite_path("tests/mir-opt")
1786 }
1787
1788 fn is_default_step(_builder: &Builder<'_>) -> bool {
1789 true
1790 }
1791
1792 fn make_run(run: RunConfig<'_>) {
1793 let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1794 run.builder.ensure(MirOpt { compiler, target: run.target });
1795 }
1796
1797 fn run(self, builder: &Builder<'_>) {
1798 let run = |target| {
1799 builder.ensure(Compiletest {
1800 test_compiler: self.compiler,
1801 target,
1802 mode: CompiletestMode::MirOpt,
1803 suite: "mir-opt",
1804 path: "tests/mir-opt",
1805 compare_mode: None,
1806 })
1807 };
1808
1809 run(self.target);
1810
1811 if builder.config.cmd.bless() {
1814 for target in ["aarch64-unknown-linux-gnu", "i686-pc-windows-msvc"] {
1820 run(TargetSelection::from_user(target));
1821 }
1822
1823 for target in ["x86_64-apple-darwin", "i686-unknown-linux-musl"] {
1824 let target = TargetSelection::from_user(target);
1825 let panic_abort_target = builder.ensure(MirOptPanicAbortSyntheticTarget {
1826 compiler: self.compiler,
1827 base: target,
1828 });
1829 run(panic_abort_target);
1830 }
1831 }
1832 }
1833}
1834
1835#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1841struct Compiletest {
1842 test_compiler: Compiler,
1844 target: TargetSelection,
1845 mode: CompiletestMode,
1846 suite: &'static str,
1847 path: &'static str,
1848 compare_mode: Option<&'static str>,
1849}
1850
1851impl Step for Compiletest {
1852 type Output = ();
1853
1854 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1855 run.never()
1856 }
1857
1858 fn run(self, builder: &Builder<'_>) {
1859 if builder.doc_tests == DocTests::Only {
1860 return;
1861 }
1862
1863 if builder.top_stage == 0 && !builder.config.compiletest_allow_stage0 {
1864 eprintln!("\
1865ERROR: `--stage 0` runs compiletest on the stage0 (precompiled) compiler, not your local changes, and will almost always cause tests to fail
1866HELP: to test the compiler or standard library, omit the stage or explicitly use `--stage 1` instead
1867NOTE: if you're sure you want to do this, please open an issue as to why. In the meantime, you can override this with `--set build.compiletest-allow-stage0=true`."
1868 );
1869 crate::exit!(1);
1870 }
1871
1872 let mut test_compiler = self.test_compiler;
1873 let target = self.target;
1874 let mode = self.mode;
1875 let suite = self.suite;
1876
1877 let suite_path = self.path;
1879
1880 if !builder.config.codegen_tests && mode == CompiletestMode::Codegen {
1882 return;
1883 }
1884
1885 let query_compiler;
1892 let (stage, stage_id) = if suite == "ui-fulldeps" && test_compiler.stage == 1 {
1893 query_compiler = Some(test_compiler);
1896 let build = builder.build.host_target;
1900 test_compiler = builder.compiler(test_compiler.stage - 1, build);
1901 let test_stage = test_compiler.stage + 1;
1902 (test_stage, format!("stage{test_stage}-{build}"))
1903 } else {
1904 query_compiler = None;
1905 let stage = test_compiler.stage;
1906 (stage, format!("stage{stage}-{target}"))
1907 };
1908
1909 if suite.ends_with("fulldeps") {
1910 builder.ensure(compile::Rustc::new(test_compiler, target));
1911 }
1912
1913 if suite == "debuginfo" {
1914 builder.ensure(dist::DebuggerScripts {
1915 sysroot: builder.sysroot(test_compiler).to_path_buf(),
1916 target,
1917 });
1918 }
1919 if mode == CompiletestMode::RunMake {
1920 builder.tool_exe(Tool::RunMakeSupport);
1921 }
1922
1923 if suite == "mir-opt" {
1925 builder.ensure(
1926 compile::Std::new(test_compiler, test_compiler.host).is_for_mir_opt_tests(true),
1927 );
1928 } else {
1929 builder.std(test_compiler, test_compiler.host);
1930 }
1931
1932 let mut cmd = builder.tool_cmd(Tool::Compiletest);
1933
1934 if suite == "mir-opt" {
1935 builder.ensure(compile::Std::new(test_compiler, target).is_for_mir_opt_tests(true));
1936 } else {
1937 builder.std(test_compiler, target);
1938 }
1939
1940 builder.ensure(RemoteCopyLibs { build_compiler: test_compiler, target });
1941
1942 cmd.arg("--stage").arg(stage.to_string());
1946 cmd.arg("--stage-id").arg(stage_id);
1947
1948 cmd.arg("--compile-lib-path").arg(builder.rustc_libdir(test_compiler));
1949 cmd.arg("--run-lib-path").arg(builder.sysroot_target_libdir(test_compiler, target));
1950 cmd.arg("--rustc-path").arg(builder.rustc(test_compiler));
1951 if let Some(query_compiler) = query_compiler {
1952 cmd.arg("--query-rustc-path").arg(builder.rustc(query_compiler));
1953 }
1954
1955 cmd.arg("--minicore-path")
1958 .arg(builder.src.join("tests").join("auxiliary").join("minicore.rs"));
1959
1960 let is_rustdoc = suite == "rustdoc-ui" || suite == "rustdoc-js";
1961
1962 if mode == CompiletestMode::RunMake {
1977 let stage0_rustc_path = builder.compiler(0, test_compiler.host);
1980 cmd.arg("--stage0-rustc-path").arg(builder.rustc(stage0_rustc_path));
1981
1982 if matches!(suite, "run-make-cargo" | "build-std") {
1983 let cargo_path = if test_compiler.stage == 0 {
1984 builder.initial_cargo.clone()
1986 } else {
1987 builder
1988 .ensure(tool::Cargo::from_build_compiler(
1989 builder.compiler(test_compiler.stage - 1, test_compiler.host),
1990 test_compiler.host,
1991 ))
1992 .tool_path
1993 };
1994
1995 cmd.arg("--cargo-path").arg(cargo_path);
1996 }
1997 }
1998
1999 if matches!(
2001 mode,
2002 CompiletestMode::RunMake
2003 | CompiletestMode::RustdocHtml
2004 | CompiletestMode::RustdocJs
2005 | CompiletestMode::RustdocJson
2006 ) || matches!(suite, "rustdoc-ui" | "coverage-run-rustdoc")
2007 {
2008 cmd.arg("--rustdoc-path").arg(builder.rustdoc_for_compiler(test_compiler));
2009 }
2010
2011 if mode == CompiletestMode::RustdocJson {
2012 let json_compiler = builder.compiler(0, builder.host_target);
2014 cmd.arg("--jsondocck-path")
2015 .arg(builder.ensure(tool::JsonDocCk { compiler: json_compiler, target }).tool_path);
2016 cmd.arg("--jsondoclint-path").arg(
2017 builder.ensure(tool::JsonDocLint { compiler: json_compiler, target }).tool_path,
2018 );
2019 }
2020
2021 if matches!(mode, CompiletestMode::CoverageMap | CompiletestMode::CoverageRun) {
2022 let coverage_dump = builder.tool_exe(Tool::CoverageDump);
2023 cmd.arg("--coverage-dump-path").arg(coverage_dump);
2024 }
2025
2026 cmd.arg("--src-root").arg(&builder.src);
2027 cmd.arg("--src-test-suite-root").arg(builder.src.join("tests").join(suite));
2028
2029 cmd.arg("--build-root").arg(&builder.out);
2033 cmd.arg("--build-test-suite-root").arg(testdir(builder, test_compiler.host).join(suite));
2034
2035 let sysroot = if builder.top_stage == 0 {
2040 builder.initial_sysroot.clone()
2041 } else {
2042 builder.sysroot(test_compiler)
2043 };
2044
2045 cmd.arg("--sysroot-base").arg(sysroot);
2046
2047 cmd.arg("--suite").arg(suite);
2048 cmd.arg("--mode").arg(mode.as_str());
2049 cmd.arg("--target").arg(target.rustc_target_arg());
2050 cmd.arg("--host").arg(&*test_compiler.host.triple);
2051 cmd.arg("--llvm-filecheck").arg(builder.llvm_filecheck(builder.config.host_target));
2052
2053 if let Some(codegen_backend) = builder.config.cmd.test_codegen_backend() {
2054 if !builder
2055 .config
2056 .enabled_codegen_backends(test_compiler.host)
2057 .contains(codegen_backend)
2058 {
2059 eprintln!(
2060 "\
2061ERROR: No configured backend named `{name}`
2062HELP: You can add it into `bootstrap.toml` in `rust.codegen-backends = [{name:?}]`",
2063 name = codegen_backend.name(),
2064 );
2065 crate::exit!(1);
2066 }
2067
2068 if let CodegenBackendKind::Gcc = codegen_backend
2069 && builder.config.rustc_debug_assertions
2070 {
2071 eprintln!(
2072 r#"WARNING: Running tests with the GCC codegen backend while rustc debug assertions are enabled. This might lead to test failures.
2073Please disable assertions with `rust.debug-assertions = false`.
2074 "#
2075 );
2076 }
2077
2078 cmd.arg("--override-codegen-backend").arg(codegen_backend.name());
2081 cmd.arg("--default-codegen-backend").arg(codegen_backend.name());
2084 } else {
2085 cmd.arg("--default-codegen-backend")
2088 .arg(builder.config.default_codegen_backend(test_compiler.host).name());
2089 }
2090 if builder.config.cmd.bypass_ignore_backends() {
2091 cmd.arg("--bypass-ignore-backends");
2092 }
2093
2094 if builder.build.config.llvm_enzyme {
2095 cmd.arg("--has-enzyme");
2096 }
2097
2098 if builder.build.config.llvm_offload {
2099 cmd.arg("--has-offload");
2100 }
2101
2102 if builder.config.cmd.bless() {
2103 cmd.arg("--bless");
2104 }
2105
2106 if builder.config.cmd.force_rerun() {
2107 cmd.arg("--force-rerun");
2108 }
2109
2110 if builder.config.cmd.no_capture() {
2111 cmd.arg("--no-capture");
2112 }
2113
2114 let compare_mode =
2115 builder.config.cmd.compare_mode().or_else(|| {
2116 if builder.config.test_compare_mode { self.compare_mode } else { None }
2117 });
2118
2119 if let Some(ref pass) = builder.config.cmd.pass() {
2120 cmd.arg("--pass");
2121 cmd.arg(pass);
2122 }
2123
2124 if let Some(ref run) = builder.config.cmd.run() {
2125 cmd.arg("--run");
2126 cmd.arg(run);
2127 }
2128
2129 if let Some(ref nodejs) = builder.config.nodejs {
2130 cmd.arg("--nodejs").arg(nodejs);
2131 } else if mode == CompiletestMode::RustdocJs {
2132 panic!("need nodejs to run rustdoc-js suite");
2133 }
2134 if builder.config.rust_optimize_tests {
2135 cmd.arg("--optimize-tests");
2136 }
2137 if builder.config.rust_randomize_layout {
2138 cmd.arg("--rust-randomized-layout");
2139 }
2140 if builder.config.cmd.only_modified() {
2141 cmd.arg("--only-modified");
2142 }
2143 if let Some(compiletest_diff_tool) = &builder.config.compiletest_diff_tool {
2144 cmd.arg("--compiletest-diff-tool").arg(compiletest_diff_tool);
2145 }
2146
2147 let mut flags = if is_rustdoc { Vec::new() } else { vec!["-Crpath".to_string()] };
2148 flags.push(format!(
2149 "-Cdebuginfo={}",
2150 if mode == CompiletestMode::Codegen {
2151 if builder.config.rust_debuginfo_level_tests
2154 != crate::core::config::DebuginfoLevel::None
2155 {
2156 println!(
2157 "NOTE: ignoring `rust.debuginfo-level-tests={}` for codegen tests",
2158 builder.config.rust_debuginfo_level_tests
2159 );
2160 }
2161 crate::core::config::DebuginfoLevel::None
2162 } else {
2163 builder.config.rust_debuginfo_level_tests
2164 }
2165 ));
2166 flags.extend(builder.config.cmd.compiletest_rustc_args().iter().map(|s| s.to_string()));
2167
2168 if suite != "mir-opt" {
2169 if let Some(linker) = builder.linker(target) {
2170 cmd.arg("--target-linker").arg(linker);
2171 }
2172 if let Some(linker) = builder.linker(test_compiler.host) {
2173 cmd.arg("--host-linker").arg(linker);
2174 }
2175 }
2176
2177 if suite == "ui-fulldeps" && target.ends_with("darwin") {
2179 flags.push("-Alinker_messages".into());
2180 }
2181
2182 let mut hostflags = flags.clone();
2183 hostflags.extend(linker_flags(builder, test_compiler.host, LldThreads::No));
2184
2185 let mut targetflags = flags;
2186
2187 if suite == "ui" || suite == "incremental" {
2189 builder.ensure(TestHelpers { target: test_compiler.host });
2190 builder.ensure(TestHelpers { target });
2191 hostflags.push(format!(
2192 "-Lnative={}",
2193 builder.test_helpers_out(test_compiler.host).display()
2194 ));
2195 targetflags.push(format!("-Lnative={}", builder.test_helpers_out(target).display()));
2196 }
2197
2198 for flag in hostflags {
2199 cmd.arg("--host-rustcflags").arg(flag);
2200 }
2201 for flag in targetflags {
2202 cmd.arg("--target-rustcflags").arg(flag);
2203 }
2204 if target.is_synthetic() {
2205 cmd.arg("--target-rustcflags").arg("-Zunstable-options");
2206 }
2207
2208 cmd.arg("--python").arg(
2209 builder.config.python.as_ref().expect("python is required for running rustdoc tests"),
2210 );
2211
2212 let android = android::discover_android(builder, target);
2214 if let Some(android::Android { adb_path, adb_test_dir, android_cross_path }) = &android {
2215 cmd.arg("--adb-path").arg(adb_path);
2216 cmd.arg("--adb-test-dir").arg(adb_test_dir);
2217 cmd.arg("--android-cross-path").arg(android_cross_path);
2218 }
2219
2220 if mode == CompiletestMode::Debuginfo {
2221 if let Some(debuggers::Cdb { cdb }) = debuggers::discover_cdb(target) {
2222 cmd.arg("--cdb").arg(cdb);
2223 }
2224
2225 if let Some(debuggers::Gdb { gdb }) = debuggers::discover_gdb(builder, android.as_ref())
2226 {
2227 cmd.arg("--gdb").arg(gdb.as_ref());
2228 }
2229
2230 if let Some(debuggers::Lldb { lldb_exe, lldb_version }) =
2231 debuggers::discover_lldb(builder)
2232 {
2233 cmd.arg("--lldb").arg(lldb_exe);
2234 cmd.arg("--lldb-version").arg(lldb_version);
2235 }
2236 }
2237
2238 if helpers::forcing_clang_based_tests() {
2239 let clang_exe = builder.llvm_out(target).join("bin").join("clang");
2240 cmd.arg("--run-clang-based-tests-with").arg(clang_exe);
2241 }
2242
2243 for exclude in &builder.config.skip {
2244 cmd.arg("--skip");
2245 cmd.arg(exclude);
2246 }
2247
2248 let mut paths = match &builder.config.cmd {
2250 Subcommand::Test { .. } => &builder.config.paths[..],
2251 _ => &[],
2252 };
2253
2254 let mut paths_v;
2257 if mode == CompiletestMode::RustdocJs {
2258 paths_v = paths.to_vec();
2259 for p in &mut paths_v {
2260 if let Some(ext) = p.extension()
2261 && ext == "js"
2262 {
2263 p.set_extension("rs");
2264 }
2265 }
2266 paths = &paths_v;
2267 }
2268 let mut test_args: Vec<&str> = paths
2270 .iter()
2271 .filter_map(|p| helpers::is_valid_test_suite_arg(p, suite_path, builder))
2272 .collect();
2273
2274 test_args.append(&mut builder.config.test_args());
2275
2276 if cfg!(windows) {
2279 let test_args_win: Vec<String> =
2280 test_args.iter().map(|s| s.replace('/', "\\")).collect();
2281 cmd.args(&test_args_win);
2282 } else {
2283 cmd.args(&test_args);
2284 }
2285
2286 if builder.is_verbose() {
2287 cmd.arg("--verbose");
2288 }
2289
2290 if builder.config.rustc_debug_assertions {
2291 cmd.arg("--with-rustc-debug-assertions");
2292 }
2293
2294 if builder.config.std_debug_assertions {
2295 cmd.arg("--with-std-debug-assertions");
2296 }
2297
2298 if builder.config.rust_remap_debuginfo {
2299 cmd.arg("--with-std-remap-debuginfo");
2300 }
2301
2302 cmd.arg("--jobs").arg(builder.jobs().to_string());
2303
2304 let mut llvm_components_passed = false;
2305 let mut copts_passed = false;
2306 if builder.config.llvm_enabled(test_compiler.host) {
2307 let llvm::LlvmResult { host_llvm_config, .. } =
2308 builder.ensure(llvm::Llvm { target: builder.config.host_target });
2309 if !builder.config.dry_run() {
2310 let llvm_version = get_llvm_version(builder, &host_llvm_config);
2311 let llvm_components = command(&host_llvm_config)
2312 .cached()
2313 .arg("--components")
2314 .run_capture_stdout(builder)
2315 .stdout();
2316 cmd.arg("--llvm-version")
2318 .arg(llvm_version.trim())
2319 .arg("--llvm-components")
2320 .arg(llvm_components.trim());
2321 llvm_components_passed = true;
2322 }
2323 if !builder.config.is_rust_llvm(target) {
2324 cmd.arg("--system-llvm");
2325 }
2326
2327 if !builder.config.dry_run() && suite.ends_with("fulldeps") {
2332 let llvm_libdir = command(&host_llvm_config)
2333 .cached()
2334 .arg("--libdir")
2335 .run_capture_stdout(builder)
2336 .stdout();
2337 let link_llvm = if target.is_msvc() {
2338 format!("-Clink-arg=-LIBPATH:{llvm_libdir}")
2339 } else {
2340 format!("-Clink-arg=-L{llvm_libdir}")
2341 };
2342 cmd.arg("--host-rustcflags").arg(link_llvm);
2343 }
2344
2345 if !builder.config.dry_run()
2346 && matches!(mode, CompiletestMode::RunMake | CompiletestMode::CoverageRun)
2347 {
2348 let llvm_bin_path = host_llvm_config
2353 .parent()
2354 .expect("Expected llvm-config to be contained in directory");
2355 assert!(llvm_bin_path.is_dir());
2356 cmd.arg("--llvm-bin-dir").arg(llvm_bin_path);
2357 }
2358
2359 if !builder.config.dry_run() && mode == CompiletestMode::RunMake {
2360 if builder.config.lld_enabled {
2362 let lld_install_root =
2363 builder.ensure(llvm::Lld { target: builder.config.host_target });
2364
2365 let lld_bin_path = lld_install_root.join("bin");
2366
2367 let old_path = env::var_os("PATH").unwrap_or_default();
2368 let new_path = env::join_paths(
2369 std::iter::once(lld_bin_path).chain(env::split_paths(&old_path)),
2370 )
2371 .expect("Could not add LLD bin path to PATH");
2372 cmd.env("PATH", new_path);
2373 }
2374 }
2375 }
2376
2377 if !builder.config.dry_run() && mode == CompiletestMode::RunMake {
2380 let mut cflags = builder.cc_handled_clags(target, CLang::C);
2381 cflags.extend(builder.cc_unhandled_cflags(target, GitRepo::Rustc, CLang::C));
2382 let mut cxxflags = builder.cc_handled_clags(target, CLang::Cxx);
2383 cxxflags.extend(builder.cc_unhandled_cflags(target, GitRepo::Rustc, CLang::Cxx));
2384 cmd.arg("--cc")
2385 .arg(builder.cc(target))
2386 .arg("--cxx")
2387 .arg(builder.cxx(target).unwrap())
2388 .arg("--cflags")
2389 .arg(cflags.join(" "))
2390 .arg("--cxxflags")
2391 .arg(cxxflags.join(" "));
2392 copts_passed = true;
2393 if let Some(ar) = builder.ar(target) {
2394 cmd.arg("--ar").arg(ar);
2395 }
2396 }
2397
2398 if !llvm_components_passed {
2399 cmd.arg("--llvm-components").arg("");
2400 }
2401 if !copts_passed {
2402 cmd.arg("--cc")
2403 .arg("")
2404 .arg("--cxx")
2405 .arg("")
2406 .arg("--cflags")
2407 .arg("")
2408 .arg("--cxxflags")
2409 .arg("");
2410 }
2411
2412 if builder.remote_tested(target) {
2413 cmd.arg("--remote-test-client").arg(builder.tool_exe(Tool::RemoteTestClient));
2414 } else if let Some(tool) = builder.runner(target) {
2415 cmd.arg("--runner").arg(tool);
2416 }
2417
2418 if suite != "mir-opt" {
2419 if !builder.config.dry_run() && target.is_msvc() {
2425 for (k, v) in builder.cc[&target].env() {
2426 if k != "PATH" {
2427 cmd.env(k, v);
2428 }
2429 }
2430 }
2431 }
2432
2433 if !builder.config.dry_run()
2435 && target.contains("msvc")
2436 && builder.config.sanitizers_enabled(target)
2437 {
2438 cmd.env("ASAN_WIN_CONTINUE_ON_INTERCEPTION_FAILURE", "1");
2441 let asan_runtime_path = builder.cc[&target].path().parent().unwrap().to_path_buf();
2443 let old_path = cmd
2444 .get_envs()
2445 .find_map(|(k, v)| (k == "PATH").then_some(v))
2446 .flatten()
2447 .map_or_else(|| env::var_os("PATH").unwrap_or_default(), |v| v.to_owned());
2448 let new_path = env::join_paths(
2449 env::split_paths(&old_path).chain(std::iter::once(asan_runtime_path)),
2450 )
2451 .expect("Could not add ASAN runtime path to PATH");
2452 cmd.env("PATH", new_path);
2453 }
2454
2455 cmd.env_remove("CARGO");
2458
2459 cmd.env("RUSTC_BOOTSTRAP", "1");
2460 cmd.env("RUSTC_FORCE_RUSTC_VERSION", "compiletest");
2463 cmd.env("DOC_RUST_LANG_ORG_CHANNEL", builder.doc_rust_lang_org_channel());
2464 builder.add_rust_test_threads(&mut cmd);
2465
2466 if builder.config.sanitizers_enabled(target) {
2467 cmd.env("RUSTC_SANITIZER_SUPPORT", "1");
2468 }
2469
2470 if builder.config.profiler_enabled(target) {
2471 cmd.arg("--profiler-runtime");
2472 }
2473
2474 cmd.env("RUST_TEST_TMPDIR", builder.tempdir());
2475
2476 if builder.config.cmd.rustfix_coverage() {
2477 cmd.arg("--rustfix-coverage");
2478 }
2479
2480 cmd.arg("--channel").arg(&builder.config.channel);
2481
2482 if !builder.config.omit_git_hash {
2483 cmd.arg("--git-hash");
2484 }
2485
2486 let git_config = builder.config.git_config();
2487 cmd.arg("--nightly-branch").arg(git_config.nightly_branch);
2488 cmd.arg("--git-merge-commit-email").arg(git_config.git_merge_commit_email);
2489
2490 #[cfg(feature = "build-metrics")]
2491 builder.metrics.begin_test_suite(
2492 build_helper::metrics::TestSuiteMetadata::Compiletest {
2493 suite: suite.into(),
2494 mode: mode.to_string(),
2495 compare_mode: None,
2496 target: self.target.triple.to_string(),
2497 host: self.test_compiler.host.triple.to_string(),
2498 stage: self.test_compiler.stage,
2499 },
2500 builder,
2501 );
2502
2503 let _group = builder.msg_test(
2504 format!("with compiletest suite={suite} mode={mode}"),
2505 target,
2506 test_compiler.stage,
2507 );
2508 try_run_tests(builder, &mut cmd, false);
2509
2510 if let Some(compare_mode) = compare_mode {
2511 cmd.arg("--compare-mode").arg(compare_mode);
2512
2513 #[cfg(feature = "build-metrics")]
2514 builder.metrics.begin_test_suite(
2515 build_helper::metrics::TestSuiteMetadata::Compiletest {
2516 suite: suite.into(),
2517 mode: mode.to_string(),
2518 compare_mode: Some(compare_mode.into()),
2519 target: self.target.triple.to_string(),
2520 host: self.test_compiler.host.triple.to_string(),
2521 stage: self.test_compiler.stage,
2522 },
2523 builder,
2524 );
2525
2526 builder.info(&format!(
2527 "Check compiletest suite={} mode={} compare_mode={} ({} -> {})",
2528 suite, mode, compare_mode, &test_compiler.host, target
2529 ));
2530 let _time = helpers::timeit(builder);
2531 try_run_tests(builder, &mut cmd, false);
2532 }
2533 }
2534
2535 fn metadata(&self) -> Option<StepMetadata> {
2536 Some(
2537 StepMetadata::test(&format!("compiletest-{}", self.suite), self.target)
2538 .stage(self.test_compiler.stage),
2539 )
2540 }
2541}
2542
2543#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2545struct BookTest {
2546 test_compiler: Compiler,
2547 path: PathBuf,
2548 name: &'static str,
2549 is_ext_doc: bool,
2550 dependencies: Vec<&'static str>,
2551}
2552
2553impl Step for BookTest {
2554 type Output = ();
2555 const IS_HOST: bool = true;
2556
2557 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2558 run.never()
2559 }
2560
2561 fn run(self, builder: &Builder<'_>) {
2562 if self.is_ext_doc {
2572 self.run_ext_doc(builder);
2573 } else {
2574 self.run_local_doc(builder);
2575 }
2576 }
2577}
2578
2579impl BookTest {
2580 fn run_ext_doc(self, builder: &Builder<'_>) {
2583 let test_compiler = self.test_compiler;
2584
2585 builder.std(test_compiler, test_compiler.host);
2586
2587 let mut rustdoc_path = builder.rustdoc_for_compiler(test_compiler);
2590 rustdoc_path.pop();
2591 let old_path = env::var_os("PATH").unwrap_or_default();
2592 let new_path = env::join_paths(iter::once(rustdoc_path).chain(env::split_paths(&old_path)))
2593 .expect("could not add rustdoc to PATH");
2594
2595 let mut rustbook_cmd = builder.tool_cmd(Tool::Rustbook);
2596 let path = builder.src.join(&self.path);
2597 rustbook_cmd.env("RUSTC_BOOTSTRAP", "1");
2599 rustbook_cmd.env("PATH", new_path).arg("test").arg(path);
2600
2601 let libs = if !self.dependencies.is_empty() {
2606 let mut lib_paths = vec![];
2607 for dep in self.dependencies {
2608 let mode = Mode::ToolRustcPrivate;
2609 let target = builder.config.host_target;
2610 let cargo = tool::prepare_tool_cargo(
2611 builder,
2612 test_compiler,
2613 mode,
2614 target,
2615 Kind::Build,
2616 dep,
2617 SourceType::Submodule,
2618 &[],
2619 );
2620
2621 let stamp = BuildStamp::new(&builder.cargo_out(test_compiler, mode, target))
2622 .with_prefix(PathBuf::from(dep).file_name().and_then(|v| v.to_str()).unwrap());
2623
2624 let output_paths =
2625 run_cargo(builder, cargo, vec![], &stamp, vec![], ArtifactKeepMode::OnlyRlib);
2626 let directories = output_paths
2627 .into_iter()
2628 .filter_map(|p| p.parent().map(ToOwned::to_owned))
2629 .fold(HashSet::new(), |mut set, dir| {
2630 set.insert(dir);
2631 set
2632 });
2633
2634 lib_paths.extend(directories);
2635 }
2636 lib_paths
2637 } else {
2638 vec![]
2639 };
2640
2641 if !libs.is_empty() {
2642 let paths = libs
2643 .into_iter()
2644 .map(|path| path.into_os_string())
2645 .collect::<Vec<OsString>>()
2646 .join(OsStr::new(","));
2647 rustbook_cmd.args([OsString::from("--library-path"), paths]);
2648 }
2649
2650 builder.add_rust_test_threads(&mut rustbook_cmd);
2651 let _guard = builder.msg_test(
2652 format_args!("mdbook {}", self.path.display()),
2653 test_compiler.host,
2654 test_compiler.stage,
2655 );
2656 let _time = helpers::timeit(builder);
2657 let toolstate = if rustbook_cmd.delay_failure().run(builder) {
2658 ToolState::TestPass
2659 } else {
2660 ToolState::TestFail
2661 };
2662 builder.save_toolstate(self.name, toolstate);
2663 }
2664
2665 fn run_local_doc(self, builder: &Builder<'_>) {
2667 let test_compiler = self.test_compiler;
2668 let host = self.test_compiler.host;
2669
2670 builder.std(test_compiler, host);
2671
2672 let _guard = builder.msg_test(
2673 format!("book {}", self.name),
2674 test_compiler.host,
2675 test_compiler.stage,
2676 );
2677
2678 let mut stack = vec![builder.src.join(self.path)];
2681 let _time = helpers::timeit(builder);
2682 let mut files = Vec::new();
2683 while let Some(p) = stack.pop() {
2684 if p.is_dir() {
2685 stack.extend(t!(p.read_dir()).map(|p| t!(p).path()));
2686 continue;
2687 }
2688
2689 if p.extension().and_then(|s| s.to_str()) != Some("md") {
2690 continue;
2691 }
2692
2693 files.push(p);
2694 }
2695
2696 files.sort();
2697
2698 for file in files {
2699 markdown_test(builder, test_compiler, &file);
2700 }
2701 }
2702}
2703
2704macro_rules! test_book {
2705 ($(
2706 $name:ident, $path:expr, $book_name:expr,
2707 default=$default:expr
2708 $(,submodules = $submodules:expr)?
2709 $(,dependencies=$dependencies:expr)?
2710 ;
2711 )+) => {
2712 $(
2713 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
2714 pub struct $name {
2715 test_compiler: Compiler,
2716 }
2717
2718 impl Step for $name {
2719 type Output = ();
2720 const IS_HOST: bool = true;
2721
2722 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2723 run.path($path)
2724 }
2725
2726 fn is_default_step(_builder: &Builder<'_>) -> bool {
2727 const { $default }
2728 }
2729
2730 fn make_run(run: RunConfig<'_>) {
2731 run.builder.ensure($name {
2732 test_compiler: run.builder.compiler(run.builder.top_stage, run.target),
2733 });
2734 }
2735
2736 fn run(self, builder: &Builder<'_>) {
2737 $(
2738 for submodule in $submodules {
2739 builder.require_submodule(submodule, None);
2740 }
2741 )*
2742
2743 let dependencies = vec![];
2744 $(
2745 let mut dependencies = dependencies;
2746 for dep in $dependencies {
2747 dependencies.push(dep);
2748 }
2749 )?
2750
2751 builder.ensure(BookTest {
2752 test_compiler: self.test_compiler,
2753 path: PathBuf::from($path),
2754 name: $book_name,
2755 is_ext_doc: !$default,
2756 dependencies,
2757 });
2758 }
2759 }
2760 )+
2761 }
2762}
2763
2764test_book!(
2765 Nomicon, "src/doc/nomicon", "nomicon", default=false, submodules=["src/doc/nomicon"];
2766 Reference, "src/doc/reference", "reference", default=false, submodules=["src/doc/reference"];
2767 RustdocBook, "src/doc/rustdoc", "rustdoc", default=true;
2768 RustcBook, "src/doc/rustc", "rustc", default=true;
2769 RustByExample, "src/doc/rust-by-example", "rust-by-example", default=false, submodules=["src/doc/rust-by-example"];
2770 EmbeddedBook, "src/doc/embedded-book", "embedded-book", default=false, submodules=["src/doc/embedded-book"];
2771 TheBook, "src/doc/book", "book", default=false, submodules=["src/doc/book"], dependencies=["src/doc/book/packages/trpl"];
2772 UnstableBook, "src/doc/unstable-book", "unstable-book", default=true;
2773 EditionGuide, "src/doc/edition-guide", "edition-guide", default=false, submodules=["src/doc/edition-guide"];
2774);
2775
2776#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2777pub struct ErrorIndex {
2778 compilers: RustcPrivateCompilers,
2779}
2780
2781impl Step for ErrorIndex {
2782 type Output = ();
2783 const IS_HOST: bool = true;
2784
2785 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2786 run.path("src/tools/error_index_generator").alias("error-index")
2789 }
2790
2791 fn is_default_step(_builder: &Builder<'_>) -> bool {
2792 true
2793 }
2794
2795 fn make_run(run: RunConfig<'_>) {
2796 let compilers = RustcPrivateCompilers::new(
2800 run.builder,
2801 run.builder.top_stage,
2802 run.builder.config.host_target,
2803 );
2804 run.builder.ensure(ErrorIndex { compilers });
2805 }
2806
2807 fn run(self, builder: &Builder<'_>) {
2814 let target_compiler = self.compilers.target_compiler();
2816
2817 let dir = testdir(builder, target_compiler.host);
2818 t!(fs::create_dir_all(&dir));
2819 let output = dir.join("error-index.md");
2820
2821 let mut tool = tool::ErrorIndex::command(builder, self.compilers);
2822 tool.arg("markdown").arg(&output);
2823
2824 let guard = builder.msg_test("error-index", target_compiler.host, target_compiler.stage);
2825 let _time = helpers::timeit(builder);
2826 tool.run_capture(builder);
2827 drop(guard);
2828 builder.std(target_compiler, target_compiler.host);
2831 markdown_test(builder, target_compiler, &output);
2832 }
2833}
2834
2835fn markdown_test(builder: &Builder<'_>, compiler: Compiler, markdown: &Path) -> bool {
2836 if let Ok(contents) = fs::read_to_string(markdown)
2837 && !contents.contains("```")
2838 {
2839 return true;
2840 }
2841
2842 builder.do_if_verbose(|| println!("doc tests for: {}", markdown.display()));
2843 let mut cmd = builder.rustdoc_cmd(compiler);
2844 builder.add_rust_test_threads(&mut cmd);
2845 cmd.arg("-Z");
2847 cmd.arg("unstable-options");
2848 cmd.arg("--test");
2849 cmd.arg(markdown);
2850 cmd.env("RUSTC_BOOTSTRAP", "1");
2851
2852 let test_args = builder.config.test_args().join(" ");
2853 cmd.arg("--test-args").arg(test_args);
2854
2855 cmd = cmd.delay_failure();
2856 if !builder.config.verbose_tests {
2857 cmd.run_capture(builder).is_success()
2858 } else {
2859 cmd.run(builder)
2860 }
2861}
2862
2863#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2868pub struct CrateLibrustc {
2869 build_compiler: Compiler,
2871 target: TargetSelection,
2872 crates: Vec<String>,
2873}
2874
2875impl Step for CrateLibrustc {
2876 type Output = ();
2877 const IS_HOST: bool = true;
2878
2879 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2880 run.crate_or_deps("rustc-main").path("compiler")
2881 }
2882
2883 fn is_default_step(_builder: &Builder<'_>) -> bool {
2884 true
2885 }
2886
2887 fn make_run(run: RunConfig<'_>) {
2888 let builder = run.builder;
2889 let host = run.build_triple();
2890 let build_compiler = builder.compiler(builder.top_stage - 1, host);
2891 let crates = run.make_run_crates(Alias::Compiler);
2892
2893 builder.ensure(CrateLibrustc { build_compiler, target: run.target, crates });
2894 }
2895
2896 fn run(self, builder: &Builder<'_>) {
2897 builder.std(self.build_compiler, self.target);
2898
2899 builder.ensure(Crate {
2901 build_compiler: self.build_compiler,
2902 target: self.target,
2903 mode: Mode::Rustc,
2904 crates: self.crates,
2905 });
2906 }
2907
2908 fn metadata(&self) -> Option<StepMetadata> {
2909 Some(StepMetadata::test("CrateLibrustc", self.target).built_by(self.build_compiler))
2910 }
2911}
2912
2913fn run_cargo_test<'a>(
2917 cargo: builder::Cargo,
2918 libtest_args: &[&str],
2919 crates: &[String],
2920 description: impl Into<Option<&'a str>>,
2921 target: TargetSelection,
2922 builder: &Builder<'_>,
2923) -> bool {
2924 let compiler = cargo.compiler();
2925 let stage = match cargo.mode() {
2926 Mode::Std => compiler.stage,
2927 _ => compiler.stage + 1,
2928 };
2929
2930 let mut cargo = prepare_cargo_test(cargo, libtest_args, crates, target, builder);
2931 let _time = helpers::timeit(builder);
2932
2933 let _group = description.into().and_then(|what| builder.msg_test(what, target, stage));
2934
2935 #[cfg(feature = "build-metrics")]
2936 builder.metrics.begin_test_suite(
2937 build_helper::metrics::TestSuiteMetadata::CargoPackage {
2938 crates: crates.iter().map(|c| c.to_string()).collect(),
2939 target: target.triple.to_string(),
2940 host: compiler.host.triple.to_string(),
2941 stage: compiler.stage,
2942 },
2943 builder,
2944 );
2945 add_flags_and_try_run_tests(builder, &mut cargo)
2946}
2947
2948fn prepare_cargo_test(
2950 cargo: builder::Cargo,
2951 libtest_args: &[&str],
2952 crates: &[String],
2953 target: TargetSelection,
2954 builder: &Builder<'_>,
2955) -> BootstrapCommand {
2956 let compiler = cargo.compiler();
2957 let mut cargo: BootstrapCommand = cargo.into();
2958
2959 if builder.config.cmd.bless() && !cargo.get_envs().any(|v| v.0 == "RUSTC_BLESS") {
2963 cargo.env("RUSTC_BLESS", "Gesundheit");
2964 }
2965
2966 if builder.kind == Kind::Test && !builder.fail_fast {
2970 cargo.arg("--no-fail-fast");
2971 }
2972
2973 if builder.config.json_output {
2974 cargo.arg("--message-format=json");
2975 }
2976
2977 match builder.doc_tests {
2978 DocTests::Only => {
2979 cargo.arg("--doc");
2980 }
2981 DocTests::No => {
2982 cargo.args(["--bins", "--examples", "--tests", "--benches"]);
2983 }
2984 DocTests::Yes => {}
2985 }
2986
2987 for krate in crates {
2988 cargo.arg("-p").arg(krate);
2989 }
2990
2991 cargo.arg("--").args(builder.config.test_args()).args(libtest_args);
2992 if !builder.config.verbose_tests {
2993 cargo.arg("--quiet");
2994 }
2995
2996 if builder.kind != Kind::Miri {
3005 let mut dylib_paths = builder.rustc_lib_paths(compiler);
3006 dylib_paths.push(builder.sysroot_target_libdir(compiler, target));
3007 helpers::add_dylib_path(dylib_paths, &mut cargo);
3008 }
3009
3010 if builder.remote_tested(target) {
3011 cargo.env(
3012 format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)),
3013 format!("{} run 0", builder.tool_exe(Tool::RemoteTestClient).display()),
3014 );
3015 } else if let Some(tool) = builder.runner(target) {
3016 cargo.env(format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)), tool);
3017 }
3018
3019 cargo
3020}
3021
3022#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3030pub struct Crate {
3031 build_compiler: Compiler,
3033 target: TargetSelection,
3034 mode: Mode,
3035 crates: Vec<String>,
3036}
3037
3038impl Step for Crate {
3039 type Output = ();
3040
3041 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3042 run.crate_or_deps("sysroot").crate_or_deps("coretests").crate_or_deps("alloctests")
3043 }
3044
3045 fn is_default_step(_builder: &Builder<'_>) -> bool {
3046 true
3047 }
3048
3049 fn make_run(run: RunConfig<'_>) {
3050 let builder = run.builder;
3051 let host = run.build_triple();
3052 let build_compiler = builder.compiler(builder.top_stage, host);
3053 let crates = run
3054 .paths
3055 .iter()
3056 .map(|p| builder.crate_paths[&p.assert_single_path().path].clone())
3057 .collect();
3058
3059 builder.ensure(Crate { build_compiler, target: run.target, mode: Mode::Std, crates });
3060 }
3061
3062 fn run(self, builder: &Builder<'_>) {
3071 let build_compiler = self.build_compiler;
3072 let target = self.target;
3073 let mode = self.mode;
3074
3075 builder.ensure(Std::new(build_compiler, build_compiler.host).force_recompile(true));
3078
3079 let mut cargo = if builder.kind == Kind::Miri {
3080 if builder.top_stage == 0 {
3081 eprintln!("ERROR: `x.py miri` requires stage 1 or higher");
3082 std::process::exit(1);
3083 }
3084
3085 let mut cargo = builder::Cargo::new(
3088 builder,
3089 build_compiler,
3090 mode,
3091 SourceType::InTree,
3092 target,
3093 Kind::MiriTest,
3094 );
3095 cargo.env("MIRI_REPLACE_LIBRS_IF_NOT_TEST", "1");
3107 cargo.rustflag("-Zforce-unstable-if-unmarked");
3111 cargo
3112 } else {
3113 if !builder.config.is_host_target(target) {
3115 builder.ensure(compile::Std::new(build_compiler, target).force_recompile(true));
3116 builder.ensure(RemoteCopyLibs { build_compiler, target });
3117 }
3118
3119 builder::Cargo::new(
3121 builder,
3122 build_compiler,
3123 mode,
3124 SourceType::InTree,
3125 target,
3126 builder.kind,
3127 )
3128 };
3129
3130 match mode {
3131 Mode::Std => {
3132 if builder.kind == Kind::Miri {
3133 cargo
3139 .arg("--manifest-path")
3140 .arg(builder.src.join("library/sysroot/Cargo.toml"));
3141 } else {
3142 compile::std_cargo(builder, target, &mut cargo, &[]);
3143 }
3144 }
3145 Mode::Rustc => {
3146 compile::rustc_cargo(builder, &mut cargo, target, &build_compiler, &self.crates);
3147 }
3148 _ => panic!("can only test libraries"),
3149 };
3150
3151 let mut crates = self.crates.clone();
3152 if crates.iter().any(|crate_| crate_ == "core") {
3157 crates.push("coretests".to_owned());
3158 }
3159 if crates.iter().any(|crate_| crate_ == "alloc") {
3160 crates.push("alloctests".to_owned());
3161 }
3162
3163 run_cargo_test(cargo, &[], &crates, &*crate_description(&self.crates), target, builder);
3164 }
3165}
3166
3167#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3170pub struct CrateRustdoc {
3171 host: TargetSelection,
3172}
3173
3174impl Step for CrateRustdoc {
3175 type Output = ();
3176 const IS_HOST: bool = true;
3177
3178 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3179 run.path("src/librustdoc").path("src/tools/rustdoc")
3180 }
3181
3182 fn is_default_step(_builder: &Builder<'_>) -> bool {
3183 true
3184 }
3185
3186 fn make_run(run: RunConfig<'_>) {
3187 let builder = run.builder;
3188
3189 builder.ensure(CrateRustdoc { host: run.target });
3190 }
3191
3192 fn run(self, builder: &Builder<'_>) {
3193 let target = self.host;
3194
3195 let compiler = if builder.download_rustc() {
3196 builder.compiler(builder.top_stage, target)
3197 } else {
3198 builder.compiler_for(builder.top_stage, target, target)
3203 };
3204 builder.std(compiler, target);
3209 builder.ensure(compile::Rustc::new(compiler, target));
3210
3211 let mut cargo = tool::prepare_tool_cargo(
3212 builder,
3213 compiler,
3214 Mode::ToolRustcPrivate,
3215 target,
3216 builder.kind,
3217 "src/tools/rustdoc",
3218 SourceType::InTree,
3219 &[],
3220 );
3221 if self.host.contains("musl") {
3222 cargo.arg("'-Ctarget-feature=-crt-static'");
3223 }
3224
3225 let libdir = if builder.download_rustc() {
3252 builder.rustc_libdir(compiler)
3253 } else {
3254 builder.sysroot_target_libdir(compiler, target).to_path_buf()
3255 };
3256 let mut dylib_path = dylib_path();
3257 dylib_path.insert(0, PathBuf::from(&*libdir));
3258 cargo.env(dylib_path_var(), env::join_paths(&dylib_path).unwrap());
3259
3260 run_cargo_test(cargo, &[], &["rustdoc:0.0.0".to_string()], "rustdoc", target, builder);
3261 }
3262}
3263
3264#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3265pub struct CrateRustdocJsonTypes {
3266 build_compiler: Compiler,
3267 target: TargetSelection,
3268}
3269
3270impl Step for CrateRustdocJsonTypes {
3271 type Output = ();
3272 const IS_HOST: bool = true;
3273
3274 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3275 run.path("src/rustdoc-json-types")
3276 }
3277
3278 fn is_default_step(_builder: &Builder<'_>) -> bool {
3279 true
3280 }
3281
3282 fn make_run(run: RunConfig<'_>) {
3283 let builder = run.builder;
3284
3285 builder.ensure(CrateRustdocJsonTypes {
3286 build_compiler: get_tool_target_compiler(
3287 builder,
3288 ToolTargetBuildMode::Build(run.target),
3289 ),
3290 target: run.target,
3291 });
3292 }
3293
3294 fn run(self, builder: &Builder<'_>) {
3295 let target = self.target;
3296
3297 let cargo = tool::prepare_tool_cargo(
3298 builder,
3299 self.build_compiler,
3300 Mode::ToolTarget,
3301 target,
3302 builder.kind,
3303 "src/rustdoc-json-types",
3304 SourceType::InTree,
3305 &[],
3306 );
3307
3308 let libtest_args = if target.contains("musl") {
3310 ["'-Ctarget-feature=-crt-static'"].as_slice()
3311 } else {
3312 &[]
3313 };
3314
3315 run_cargo_test(
3316 cargo,
3317 libtest_args,
3318 &["rustdoc-json-types".to_string()],
3319 "rustdoc-json-types",
3320 target,
3321 builder,
3322 );
3323 }
3324}
3325
3326#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3336pub struct RemoteCopyLibs {
3337 build_compiler: Compiler,
3338 target: TargetSelection,
3339}
3340
3341impl Step for RemoteCopyLibs {
3342 type Output = ();
3343
3344 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3345 run.never()
3346 }
3347
3348 fn run(self, builder: &Builder<'_>) {
3349 let build_compiler = self.build_compiler;
3350 let target = self.target;
3351 if !builder.remote_tested(target) {
3352 return;
3353 }
3354
3355 builder.std(build_compiler, target);
3356
3357 builder.info(&format!("REMOTE copy libs to emulator ({target})"));
3358
3359 let remote_test_server = builder.ensure(tool::RemoteTestServer { build_compiler, target });
3360
3361 let tool = builder.tool_exe(Tool::RemoteTestClient);
3363 let mut cmd = command(&tool);
3364 cmd.arg("spawn-emulator")
3365 .arg(target.triple)
3366 .arg(&remote_test_server.tool_path)
3367 .arg(builder.tempdir());
3368 if let Some(rootfs) = builder.qemu_rootfs(target) {
3369 cmd.arg(rootfs);
3370 }
3371 cmd.run(builder);
3372
3373 for f in t!(builder.sysroot_target_libdir(build_compiler, target).read_dir()) {
3375 let f = t!(f);
3376 if helpers::is_dylib(&f.path()) {
3377 command(&tool).arg("push").arg(f.path()).run(builder);
3378 }
3379 }
3380 }
3381}
3382
3383#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3384pub struct Distcheck;
3385
3386impl Step for Distcheck {
3387 type Output = ();
3388
3389 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3390 run.alias("distcheck")
3391 }
3392
3393 fn make_run(run: RunConfig<'_>) {
3394 run.builder.ensure(Distcheck);
3395 }
3396
3397 fn run(self, builder: &Builder<'_>) {
3407 let root_dir = std::env::temp_dir().join("distcheck");
3410
3411 distcheck_plain_source_tarball(builder, &root_dir.join("distcheck-rustc-src"));
3412 distcheck_rust_src(builder, &root_dir.join("distcheck-rust-src"));
3413 distcheck_rustc_dev(builder, &root_dir.join("distcheck-rustc-dev"));
3414 }
3415}
3416
3417fn distcheck_plain_source_tarball(builder: &Builder<'_>, plain_src_dir: &Path) {
3419 builder.info("Distcheck plain source tarball");
3420 let plain_src_tarball = builder.ensure(dist::PlainSourceTarball);
3421 builder.clear_dir(plain_src_dir);
3422
3423 let configure_args: Vec<String> = std::env::var("DISTCHECK_CONFIGURE_ARGS")
3424 .map(|args| args.split(" ").map(|s| s.to_string()).collect::<Vec<String>>())
3425 .unwrap_or_default();
3426
3427 command("tar")
3428 .arg("-xf")
3429 .arg(plain_src_tarball.tarball())
3430 .arg("--strip-components=1")
3431 .current_dir(plain_src_dir)
3432 .run(builder);
3433 command("./configure")
3434 .arg("--set")
3435 .arg("rust.omit-git-hash=false")
3436 .arg("--set")
3437 .arg("rust.remap-debuginfo=false")
3438 .args(&configure_args)
3439 .arg("--enable-vendor")
3440 .current_dir(plain_src_dir)
3441 .run(builder);
3442 command(helpers::make(&builder.config.host_target.triple))
3443 .arg("check")
3444 .env("GITHUB_ACTIONS", "0")
3447 .current_dir(plain_src_dir)
3448 .run(builder);
3449 builder.remove_dir(plain_src_dir);
3451}
3452
3453fn distcheck_rust_src(builder: &Builder<'_>, src_dir: &Path) {
3455 builder.info("Distcheck rust-src");
3456 let src_tarball = builder.ensure(dist::Src);
3457 builder.clear_dir(src_dir);
3458
3459 command("tar")
3460 .arg("-xf")
3461 .arg(src_tarball.tarball())
3462 .arg("--strip-components=1")
3463 .current_dir(src_dir)
3464 .run(builder);
3465
3466 let toml = src_dir.join("rust-src/lib/rustlib/src/rust/library/std/Cargo.toml");
3467 command(&builder.initial_cargo)
3468 .env("RUSTC_BOOTSTRAP", "1")
3471 .arg("generate-lockfile")
3472 .arg("--manifest-path")
3473 .arg(&toml)
3474 .current_dir(src_dir)
3475 .run(builder);
3476 builder.remove_dir(src_dir);
3478}
3479
3480fn distcheck_rustc_dev(builder: &Builder<'_>, dir: &Path) {
3482 builder.info("Distcheck rustc-dev");
3483 let tarball = builder.ensure(dist::RustcDev::new(builder, builder.host_target)).unwrap();
3484 builder.clear_dir(dir);
3485
3486 command("tar")
3487 .arg("-xf")
3488 .arg(tarball.tarball())
3489 .arg("--strip-components=1")
3490 .current_dir(dir)
3491 .run(builder);
3492
3493 command(&builder.initial_cargo)
3494 .arg("metadata")
3495 .arg("--manifest-path")
3496 .arg("rustc-dev/lib/rustlib/rustc-src/rust/compiler/rustc/Cargo.toml")
3497 .env("RUSTC_BOOTSTRAP", "1")
3498 .env("RUSTC", &builder.initial_rustc)
3500 .current_dir(dir)
3501 .run(builder);
3502 builder.remove_dir(dir);
3504}
3505
3506#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3508pub(crate) struct BootstrapPy;
3509
3510impl Step for BootstrapPy {
3511 type Output = ();
3512 const IS_HOST: bool = true;
3513
3514 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3515 run.alias("bootstrap-py")
3516 }
3517
3518 fn is_default_step(builder: &Builder<'_>) -> bool {
3519 builder.config.is_running_on_ci()
3523 }
3524
3525 fn make_run(run: RunConfig<'_>) {
3526 run.builder.ensure(BootstrapPy)
3527 }
3528
3529 fn run(self, builder: &Builder<'_>) -> Self::Output {
3530 let mut check_bootstrap = command(
3531 builder.config.python.as_ref().expect("python is required for running bootstrap tests"),
3532 );
3533 check_bootstrap
3534 .args(["-m", "unittest", "bootstrap_test.py"])
3535 .args(builder.config.test_args())
3537 .env("BUILD_DIR", &builder.out)
3538 .env("BUILD_PLATFORM", builder.build.host_target.triple)
3539 .env("BOOTSTRAP_TEST_RUSTC_BIN", &builder.initial_rustc)
3540 .env("BOOTSTRAP_TEST_CARGO_BIN", &builder.initial_cargo)
3541 .current_dir(builder.src.join("src/bootstrap/"));
3542 check_bootstrap.delay_failure().run(builder);
3543 }
3544}
3545
3546#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3547pub struct Bootstrap;
3548
3549impl Step for Bootstrap {
3550 type Output = ();
3551 const IS_HOST: bool = true;
3552
3553 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3554 run.path("src/bootstrap")
3555 }
3556
3557 fn is_default_step(builder: &Builder<'_>) -> bool {
3558 builder.config.is_running_on_ci()
3562 }
3563
3564 fn run(self, builder: &Builder<'_>) {
3566 let host = builder.config.host_target;
3567 let build_compiler = builder.compiler(0, host);
3568
3569 builder.build.require_submodule("src/tools/cargo", None);
3571
3572 let mut cargo = tool::prepare_tool_cargo(
3573 builder,
3574 build_compiler,
3575 Mode::ToolBootstrap,
3576 host,
3577 Kind::Test,
3578 "src/bootstrap",
3579 SourceType::InTree,
3580 &[],
3581 );
3582
3583 cargo.release_build(false);
3584
3585 cargo
3586 .rustflag("-Cdebuginfo=2")
3587 .env("CARGO_TARGET_DIR", builder.out.join("bootstrap"))
3588 .env("INSTA_WORKSPACE_ROOT", &builder.src)
3590 .env("RUSTC_BOOTSTRAP", "1");
3591
3592 if builder.config.cmd.bless() {
3593 cargo.env("INSTA_UPDATE", "always");
3597 }
3598
3599 run_cargo_test(cargo, &[], &[], None, host, builder);
3600 }
3601
3602 fn make_run(run: RunConfig<'_>) {
3603 run.builder.ensure(Bootstrap);
3604 }
3605}
3606
3607fn get_compiler_to_test(builder: &Builder<'_>, target: TargetSelection) -> Compiler {
3608 builder.compiler(builder.top_stage, target)
3609}
3610
3611#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3614pub struct TierCheck {
3615 test_compiler: Compiler,
3616}
3617
3618impl Step for TierCheck {
3619 type Output = ();
3620 const IS_HOST: bool = true;
3621
3622 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3623 run.path("src/tools/tier-check")
3624 }
3625
3626 fn is_default_step(_builder: &Builder<'_>) -> bool {
3627 true
3628 }
3629
3630 fn make_run(run: RunConfig<'_>) {
3631 run.builder
3632 .ensure(TierCheck { test_compiler: get_compiler_to_test(run.builder, run.target) });
3633 }
3634
3635 fn run(self, builder: &Builder<'_>) {
3636 let tool_build_compiler = builder.compiler(0, builder.host_target);
3637
3638 let mut cargo = tool::prepare_tool_cargo(
3639 builder,
3640 tool_build_compiler,
3641 Mode::ToolBootstrap,
3642 tool_build_compiler.host,
3643 Kind::Run,
3644 "src/tools/tier-check",
3645 SourceType::InTree,
3646 &[],
3647 );
3648 cargo.arg(builder.src.join("src/doc/rustc/src/platform-support.md"));
3649 cargo.arg(builder.rustc(self.test_compiler));
3650
3651 let _guard = builder.msg_test(
3652 "platform support check",
3653 self.test_compiler.host,
3654 self.test_compiler.stage,
3655 );
3656 BootstrapCommand::from(cargo).delay_failure().run(builder);
3657 }
3658
3659 fn metadata(&self) -> Option<StepMetadata> {
3660 Some(StepMetadata::test("tier-check", self.test_compiler.host))
3661 }
3662}
3663
3664#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3665pub struct LintDocs {
3666 build_compiler: Compiler,
3667 target: TargetSelection,
3668}
3669
3670impl Step for LintDocs {
3671 type Output = ();
3672 const IS_HOST: bool = true;
3673
3674 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3675 run.path("src/tools/lint-docs")
3676 }
3677
3678 fn is_default_step(builder: &Builder<'_>) -> bool {
3679 builder.top_stage >= 2
3682 }
3683
3684 fn make_run(run: RunConfig<'_>) {
3685 if run.builder.top_stage < 2 {
3686 eprintln!("WARNING: lint-docs tests might not work below stage 2");
3687 }
3688
3689 run.builder.ensure(LintDocs {
3690 build_compiler: prepare_doc_compiler(
3691 run.builder,
3692 run.builder.config.host_target,
3693 run.builder.top_stage,
3694 ),
3695 target: run.target,
3696 });
3697 }
3698
3699 fn run(self, builder: &Builder<'_>) {
3702 builder.ensure(crate::core::build_steps::doc::RustcBook::validate(
3703 self.build_compiler,
3704 self.target,
3705 ));
3706 }
3707
3708 fn metadata(&self) -> Option<StepMetadata> {
3709 Some(StepMetadata::test("lint-docs", self.target).built_by(self.build_compiler))
3710 }
3711}
3712
3713#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3714pub struct RustInstaller;
3715
3716impl Step for RustInstaller {
3717 type Output = ();
3718 const IS_HOST: bool = true;
3719
3720 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3721 run.path("src/tools/rust-installer")
3722 }
3723
3724 fn is_default_step(_builder: &Builder<'_>) -> bool {
3725 true
3726 }
3727
3728 fn make_run(run: RunConfig<'_>) {
3729 run.builder.ensure(Self);
3730 }
3731
3732 fn run(self, builder: &Builder<'_>) {
3734 let bootstrap_host = builder.config.host_target;
3735 let build_compiler = builder.compiler(0, bootstrap_host);
3736 let cargo = tool::prepare_tool_cargo(
3737 builder,
3738 build_compiler,
3739 Mode::ToolBootstrap,
3740 bootstrap_host,
3741 Kind::Test,
3742 "src/tools/rust-installer",
3743 SourceType::InTree,
3744 &[],
3745 );
3746
3747 let _guard = builder.msg_test("rust-installer", bootstrap_host, 1);
3748 run_cargo_test(cargo, &[], &[], None, bootstrap_host, builder);
3749
3750 if bootstrap_host != "x86_64-unknown-linux-gnu" {
3754 return;
3755 }
3756
3757 let mut cmd = command(builder.src.join("src/tools/rust-installer/test.sh"));
3758 let tmpdir = testdir(builder, build_compiler.host).join("rust-installer");
3759 let _ = std::fs::remove_dir_all(&tmpdir);
3760 let _ = std::fs::create_dir_all(&tmpdir);
3761 cmd.current_dir(&tmpdir);
3762 cmd.env("CARGO_TARGET_DIR", tmpdir.join("cargo-target"));
3763 cmd.env("CARGO", &builder.initial_cargo);
3764 cmd.env("RUSTC", &builder.initial_rustc);
3765 cmd.env("TMP_DIR", &tmpdir);
3766 cmd.delay_failure().run(builder);
3767 }
3768}
3769
3770#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3771pub struct TestHelpers {
3772 pub target: TargetSelection,
3773}
3774
3775impl Step for TestHelpers {
3776 type Output = ();
3777
3778 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3779 run.path("tests/auxiliary/rust_test_helpers.c")
3780 }
3781
3782 fn make_run(run: RunConfig<'_>) {
3783 run.builder.ensure(TestHelpers { target: run.target })
3784 }
3785
3786 fn run(self, builder: &Builder<'_>) {
3789 if builder.config.dry_run() {
3790 return;
3791 }
3792 let target = if self.target == "x86_64-fortanix-unknown-sgx" {
3796 TargetSelection::from_user("x86_64-unknown-linux-gnu")
3797 } else {
3798 self.target
3799 };
3800 let dst = builder.test_helpers_out(target);
3801 let src = builder.src.join("tests/auxiliary/rust_test_helpers.c");
3802 if up_to_date(&src, &dst.join("librust_test_helpers.a")) {
3803 return;
3804 }
3805
3806 let _guard = builder.msg_unstaged(Kind::Build, "test helpers", target);
3807 t!(fs::create_dir_all(&dst));
3808 let mut cfg = cc::Build::new();
3809
3810 if !target.is_msvc() {
3814 if let Some(ar) = builder.ar(target) {
3815 cfg.archiver(ar);
3816 }
3817 cfg.compiler(builder.cc(target));
3818 }
3819 cfg.cargo_metadata(false)
3820 .out_dir(&dst)
3821 .target(&target.triple)
3822 .host(&builder.config.host_target.triple)
3823 .opt_level(0)
3824 .warnings(false)
3825 .debug(false)
3826 .file(builder.src.join("tests/auxiliary/rust_test_helpers.c"))
3827 .compile("rust_test_helpers");
3828 }
3829}
3830
3831#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3832pub struct CodegenCranelift {
3833 compilers: RustcPrivateCompilers,
3834 target: TargetSelection,
3835}
3836
3837impl Step for CodegenCranelift {
3838 type Output = ();
3839 const IS_HOST: bool = true;
3840
3841 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3842 run.path("compiler/rustc_codegen_cranelift")
3843 }
3844
3845 fn is_default_step(_builder: &Builder<'_>) -> bool {
3846 true
3847 }
3848
3849 fn make_run(run: RunConfig<'_>) {
3850 let builder = run.builder;
3851 let host = run.build_triple();
3852 let compilers = RustcPrivateCompilers::new(run.builder, run.builder.top_stage, host);
3853
3854 if builder.doc_tests == DocTests::Only {
3855 return;
3856 }
3857
3858 if builder.download_rustc() {
3859 builder.info("CI rustc uses the default codegen backend. skipping");
3860 return;
3861 }
3862
3863 if !target_supports_cranelift_backend(run.target) {
3864 builder.info("target not supported by rustc_codegen_cranelift. skipping");
3865 return;
3866 }
3867
3868 if builder.remote_tested(run.target) {
3869 builder.info("remote testing is not supported by rustc_codegen_cranelift. skipping");
3870 return;
3871 }
3872
3873 if !builder
3874 .config
3875 .enabled_codegen_backends(run.target)
3876 .contains(&CodegenBackendKind::Cranelift)
3877 {
3878 builder.info("cranelift not in rust.codegen-backends. skipping");
3879 return;
3880 }
3881
3882 builder.ensure(CodegenCranelift { compilers, target: run.target });
3883 }
3884
3885 fn run(self, builder: &Builder<'_>) {
3886 let compilers = self.compilers;
3887 let build_compiler = compilers.build_compiler();
3888
3889 let target_compiler = compilers.target_compiler();
3892 let target = self.target;
3893
3894 builder.std(target_compiler, target);
3895
3896 let mut cargo = builder::Cargo::new(
3897 builder,
3898 target_compiler,
3899 Mode::Codegen, SourceType::InTree,
3901 target,
3902 Kind::Run,
3903 );
3904
3905 cargo.current_dir(&builder.src.join("compiler/rustc_codegen_cranelift"));
3906 cargo
3907 .arg("--manifest-path")
3908 .arg(builder.src.join("compiler/rustc_codegen_cranelift/build_system/Cargo.toml"));
3909 compile::rustc_cargo_env(builder, &mut cargo, target);
3910
3911 cargo.env("CARGO_BUILD_INCREMENTAL", "false");
3913
3914 let _guard = builder.msg_test(
3915 "rustc_codegen_cranelift",
3916 target_compiler.host,
3917 target_compiler.stage,
3918 );
3919
3920 let download_dir = builder.out.join("cg_clif_download");
3922
3923 cargo
3924 .arg("--")
3925 .arg("test")
3926 .arg("--download-dir")
3927 .arg(&download_dir)
3928 .arg("--out-dir")
3929 .arg(builder.stage_out(build_compiler, Mode::Codegen).join("cg_clif"))
3930 .arg("--no-unstable-features")
3931 .arg("--use-backend")
3932 .arg("cranelift")
3933 .arg("--sysroot")
3935 .arg("llvm")
3936 .arg("--skip-test")
3939 .arg("testsuite.extended_sysroot");
3940
3941 cargo.into_cmd().run(builder);
3942 }
3943
3944 fn metadata(&self) -> Option<StepMetadata> {
3945 Some(
3946 StepMetadata::test("rustc_codegen_cranelift", self.target)
3947 .built_by(self.compilers.build_compiler()),
3948 )
3949 }
3950}
3951
3952#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3953pub struct CodegenGCC {
3954 compilers: RustcPrivateCompilers,
3955 target: TargetSelection,
3956}
3957
3958impl Step for CodegenGCC {
3959 type Output = ();
3960 const IS_HOST: bool = true;
3961
3962 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3963 run.path("compiler/rustc_codegen_gcc")
3964 }
3965
3966 fn is_default_step(_builder: &Builder<'_>) -> bool {
3967 true
3968 }
3969
3970 fn make_run(run: RunConfig<'_>) {
3971 let builder = run.builder;
3972 let host = run.build_triple();
3973 let compilers = RustcPrivateCompilers::new(run.builder, run.builder.top_stage, host);
3974
3975 if builder.doc_tests == DocTests::Only {
3976 return;
3977 }
3978
3979 if builder.download_rustc() {
3980 builder.info("CI rustc uses the default codegen backend. skipping");
3981 return;
3982 }
3983
3984 let triple = run.target.triple;
3985 let target_supported =
3986 if triple.contains("linux") { triple.contains("x86_64") } else { false };
3987 if !target_supported {
3988 builder.info("target not supported by rustc_codegen_gcc. skipping");
3989 return;
3990 }
3991
3992 if builder.remote_tested(run.target) {
3993 builder.info("remote testing is not supported by rustc_codegen_gcc. skipping");
3994 return;
3995 }
3996
3997 if !builder.config.enabled_codegen_backends(run.target).contains(&CodegenBackendKind::Gcc) {
3998 builder.info("gcc not in rust.codegen-backends. skipping");
3999 return;
4000 }
4001
4002 builder.ensure(CodegenGCC { compilers, target: run.target });
4003 }
4004
4005 fn run(self, builder: &Builder<'_>) {
4006 let compilers = self.compilers;
4007 let target = self.target;
4008
4009 let gcc = builder.ensure(Gcc { target_pair: GccTargetPair::for_native_build(target) });
4010
4011 builder.ensure(
4012 compile::Std::new(compilers.build_compiler(), target)
4013 .extra_rust_args(&["-Csymbol-mangling-version=v0", "-Cpanic=abort"]),
4014 );
4015
4016 let _guard = builder.msg_test(
4017 "rustc_codegen_gcc",
4018 compilers.target(),
4019 compilers.target_compiler().stage,
4020 );
4021
4022 let mut cargo = builder::Cargo::new(
4023 builder,
4024 compilers.build_compiler(),
4025 Mode::Codegen, SourceType::InTree,
4027 target,
4028 Kind::Run,
4029 );
4030
4031 cargo.current_dir(&builder.src.join("compiler/rustc_codegen_gcc"));
4032 cargo
4033 .arg("--manifest-path")
4034 .arg(builder.src.join("compiler/rustc_codegen_gcc/build_system/Cargo.toml"));
4035 compile::rustc_cargo_env(builder, &mut cargo, target);
4036 add_cg_gcc_cargo_flags(&mut cargo, &gcc);
4037
4038 cargo.env("CARGO_BUILD_INCREMENTAL", "false");
4040 cargo.rustflag("-Cpanic=abort");
4041
4042 cargo
4043 .env("CG_RUSTFLAGS", "-Alinker-messages")
4045 .arg("--")
4046 .arg("test")
4047 .arg("--use-backend")
4048 .arg("gcc")
4049 .arg("--gcc-path")
4050 .arg(gcc.libgccjit().parent().unwrap())
4051 .arg("--out-dir")
4052 .arg(builder.stage_out(compilers.build_compiler(), Mode::Codegen).join("cg_gcc"))
4053 .arg("--release")
4054 .arg("--mini-tests")
4055 .arg("--std-tests");
4056
4057 cargo.args(builder.config.test_args());
4058
4059 cargo.into_cmd().run(builder);
4060 }
4061
4062 fn metadata(&self) -> Option<StepMetadata> {
4063 Some(
4064 StepMetadata::test("rustc_codegen_gcc", self.target)
4065 .built_by(self.compilers.build_compiler()),
4066 )
4067 }
4068}
4069
4070#[derive(Debug, Clone, PartialEq, Eq, Hash)]
4075pub struct TestFloatParse {
4076 build_compiler: Compiler,
4085 target: TargetSelection,
4087}
4088
4089impl Step for TestFloatParse {
4090 type Output = ();
4091 const IS_HOST: bool = true;
4092
4093 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
4094 run.path("src/tools/test-float-parse")
4095 }
4096
4097 fn is_default_step(_builder: &Builder<'_>) -> bool {
4098 true
4099 }
4100
4101 fn make_run(run: RunConfig<'_>) {
4102 run.builder.ensure(Self {
4103 build_compiler: get_compiler_to_test(run.builder, run.target),
4104 target: run.target,
4105 });
4106 }
4107
4108 fn run(self, builder: &Builder<'_>) {
4109 let build_compiler = self.build_compiler;
4110 let target = self.target;
4111
4112 builder.std(build_compiler, target);
4114 builder.std(build_compiler, builder.host_target);
4115
4116 let mut cargo_test = tool::prepare_tool_cargo(
4118 builder,
4119 build_compiler,
4120 Mode::ToolStd,
4121 target,
4122 Kind::Test,
4123 "src/tools/test-float-parse",
4124 SourceType::InTree,
4125 &[],
4126 );
4127 cargo_test.allow_features(TEST_FLOAT_PARSE_ALLOW_FEATURES);
4128
4129 run_cargo_test(cargo_test, &[], &[], "test-float-parse", target, builder);
4130
4131 let mut cargo_run = tool::prepare_tool_cargo(
4133 builder,
4134 build_compiler,
4135 Mode::ToolStd,
4136 target,
4137 Kind::Run,
4138 "src/tools/test-float-parse",
4139 SourceType::InTree,
4140 &[],
4141 );
4142 cargo_run.allow_features(TEST_FLOAT_PARSE_ALLOW_FEATURES);
4143
4144 if !matches!(env::var("FLOAT_PARSE_TESTS_NO_SKIP_HUGE").as_deref(), Ok("1") | Ok("true")) {
4145 cargo_run.args(["--", "--skip-huge"]);
4146 }
4147
4148 cargo_run.into_cmd().run(builder);
4149 }
4150}
4151
4152#[derive(Debug, Clone, Hash, PartialEq, Eq)]
4156pub struct CollectLicenseMetadata;
4157
4158impl Step for CollectLicenseMetadata {
4159 type Output = PathBuf;
4160 const IS_HOST: bool = true;
4161
4162 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
4163 run.path("src/tools/collect-license-metadata")
4164 }
4165
4166 fn make_run(run: RunConfig<'_>) {
4167 run.builder.ensure(CollectLicenseMetadata);
4168 }
4169
4170 fn run(self, builder: &Builder<'_>) -> Self::Output {
4171 let Some(reuse) = &builder.config.reuse else {
4172 panic!("REUSE is required to collect the license metadata");
4173 };
4174
4175 let dest = builder.src.join("license-metadata.json");
4176
4177 let mut cmd = builder.tool_cmd(Tool::CollectLicenseMetadata);
4178 cmd.env("REUSE_EXE", reuse);
4179 cmd.env("DEST", &dest);
4180 cmd.env("ONLY_CHECK", "1");
4181 cmd.run(builder);
4182
4183 dest
4184 }
4185}
4186
4187#[derive(Debug, Clone, PartialEq, Eq, Hash)]
4188pub struct RemoteTestClientTests {
4189 host: TargetSelection,
4190}
4191
4192impl Step for RemoteTestClientTests {
4193 type Output = ();
4194 const IS_HOST: bool = true;
4195
4196 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
4197 run.path("src/tools/remote-test-client")
4198 }
4199
4200 fn is_default_step(_builder: &Builder<'_>) -> bool {
4201 true
4202 }
4203
4204 fn make_run(run: RunConfig<'_>) {
4205 run.builder.ensure(Self { host: run.target });
4206 }
4207
4208 fn run(self, builder: &Builder<'_>) {
4209 let bootstrap_host = builder.config.host_target;
4210 let compiler = builder.compiler(0, bootstrap_host);
4211
4212 let cargo = tool::prepare_tool_cargo(
4213 builder,
4214 compiler,
4215 Mode::ToolBootstrap,
4216 bootstrap_host,
4217 Kind::Test,
4218 "src/tools/remote-test-client",
4219 SourceType::InTree,
4220 &[],
4221 );
4222
4223 run_cargo_test(cargo, &[], &[], "remote-test-client", bootstrap_host, builder);
4224 }
4225}