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 let mut skip_tests = vec![];
513
514 skip_tests.extend_from_slice(&[
522 "tests::smoke_test_real_sysroot_cargo",
525 "check_code_formatting",
528 ]);
529
530 let skip_tests = skip_tests.iter().map(|name| format!("--skip={name}")).collect::<Vec<_>>();
531 let skip_tests = skip_tests.iter().map(|s| s.as_str()).collect::<Vec<_>>();
532
533 cargo.add_rustc_lib_path(builder);
534 run_cargo_test(cargo, skip_tests.as_slice(), &[], "rust-analyzer", target, builder);
535 }
536
537 fn metadata(&self) -> Option<StepMetadata> {
538 Some(
539 StepMetadata::test("rust-analyzer", self.compilers.target())
540 .built_by(self.compilers.build_compiler()),
541 )
542 }
543}
544
545#[derive(Debug, Clone, PartialEq, Eq, Hash)]
547pub struct Rustfmt {
548 compilers: RustcPrivateCompilers,
549}
550
551impl Step for Rustfmt {
552 type Output = ();
553 const IS_HOST: bool = true;
554
555 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
556 run.path("src/tools/rustfmt")
557 }
558
559 fn make_run(run: RunConfig<'_>) {
560 run.builder.ensure(Rustfmt {
561 compilers: RustcPrivateCompilers::new(
562 run.builder,
563 run.builder.top_stage,
564 run.builder.host_target,
565 ),
566 });
567 }
568
569 fn run(self, builder: &Builder<'_>) {
571 let build_compiler = self.compilers.build_compiler();
572 let target = self.compilers.target();
573
574 let mut cargo = tool::prepare_tool_cargo(
575 builder,
576 build_compiler,
577 Mode::ToolRustcPrivate,
578 target,
579 Kind::Test,
580 "src/tools/rustfmt",
581 SourceType::InTree,
582 &[],
583 );
584
585 let dir = testdir(builder, target);
586 t!(fs::create_dir_all(&dir));
587 cargo.env("RUSTFMT_TEST_DIR", dir);
588
589 cargo.add_rustc_lib_path(builder);
590
591 run_cargo_test(cargo, &[], &[], "rustfmt", target, builder);
592 }
593
594 fn metadata(&self) -> Option<StepMetadata> {
595 Some(
596 StepMetadata::test("rustfmt", self.compilers.target())
597 .built_by(self.compilers.build_compiler()),
598 )
599 }
600}
601
602#[derive(Debug, Clone, PartialEq, Eq, Hash)]
603pub struct Miri {
604 target: TargetSelection,
605}
606
607impl Miri {
608 pub fn build_miri_sysroot(
610 builder: &Builder<'_>,
611 compiler: Compiler,
612 target: TargetSelection,
613 ) -> PathBuf {
614 let miri_sysroot = builder.out.join(compiler.host).join("miri-sysroot");
615 let mut cargo = builder::Cargo::new(
616 builder,
617 compiler,
618 Mode::Std,
619 SourceType::Submodule,
620 target,
621 Kind::MiriSetup,
622 );
623
624 cargo.env("MIRI_LIB_SRC", builder.src.join("library"));
626 cargo.env("MIRI_SYSROOT", &miri_sysroot);
628
629 let mut cargo = BootstrapCommand::from(cargo);
630 let _guard =
631 builder.msg(Kind::Build, "miri sysroot", Mode::ToolRustcPrivate, compiler, target);
632 cargo.run(builder);
633
634 cargo.arg("--print-sysroot");
640
641 builder.do_if_verbose(|| println!("running: {cargo:?}"));
642 let stdout = cargo.run_capture_stdout(builder).stdout();
643 let sysroot = stdout.trim_end();
645 builder.do_if_verbose(|| println!("`cargo miri setup --print-sysroot` said: {sysroot:?}"));
646 PathBuf::from(sysroot)
647 }
648}
649
650impl Step for Miri {
651 type Output = ();
652
653 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
654 run.path("src/tools/miri")
655 }
656
657 fn make_run(run: RunConfig<'_>) {
658 run.builder.ensure(Miri { target: run.target });
659 }
660
661 fn run(self, builder: &Builder<'_>) {
663 let host = builder.build.host_target;
664 let target = self.target;
665 let stage = builder.top_stage;
666 if stage == 0 {
667 eprintln!("miri cannot be tested at stage 0");
668 std::process::exit(1);
669 }
670
671 let compilers = RustcPrivateCompilers::new(builder, stage, host);
673
674 let miri = builder.ensure(tool::Miri::from_compilers(compilers));
676 builder.ensure(tool::CargoMiri::from_compilers(compilers));
678
679 let target_compiler = compilers.target_compiler();
680
681 let miri_sysroot = Miri::build_miri_sysroot(builder, target_compiler, target);
684 builder.std(target_compiler, host);
685 let host_sysroot = builder.sysroot(target_compiler);
686
687 if !builder.config.dry_run() {
690 let ui_test_dep_dir = builder
693 .stage_out(miri.build_compiler, Mode::ToolStd)
694 .join(host)
695 .join("tmp")
696 .join("miri_ui");
697 build_stamp::clear_if_dirty(builder, &ui_test_dep_dir, &miri_sysroot);
701 }
702
703 let mut cargo = tool::prepare_tool_cargo(
706 builder,
707 miri.build_compiler,
708 Mode::ToolRustcPrivate,
709 host,
710 Kind::Test,
711 "src/tools/miri",
712 SourceType::InTree,
713 &[],
714 );
715
716 cargo.add_rustc_lib_path(builder);
717
718 let mut cargo = prepare_cargo_test(cargo, &[], &[], host, builder);
721
722 cargo.env("MIRI_SYSROOT", &miri_sysroot);
724 cargo.env("MIRI_HOST_SYSROOT", &host_sysroot);
725
726 cargo.env("MIRI_TEST_TARGET", target.rustc_target_arg());
728
729 {
730 let _guard = builder.msg_test("miri", target, target_compiler.stage);
731 let _time = helpers::timeit(builder);
732 cargo.run(builder);
733 }
734
735 if builder.config.test_args().is_empty() {
737 cargo.env("MIRIFLAGS", "-O -Zmir-opt-level=4 -Cdebug-assertions=yes");
738 cargo.env("MIRI_SKIP_UI_CHECKS", "1");
740 cargo.env_remove("RUSTC_BLESS");
742 cargo.args(["tests/pass", "tests/panic"]);
744
745 {
746 let _guard =
747 builder.msg_test("miri (mir-opt-level 4)", target, target_compiler.stage);
748 let _time = helpers::timeit(builder);
749 cargo.run(builder);
750 }
751 }
752 }
753}
754
755#[derive(Debug, Clone, PartialEq, Eq, Hash)]
758pub struct CargoMiri {
759 target: TargetSelection,
760}
761
762impl Step for CargoMiri {
763 type Output = ();
764
765 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
766 run.path("src/tools/miri/cargo-miri")
767 }
768
769 fn make_run(run: RunConfig<'_>) {
770 run.builder.ensure(CargoMiri { target: run.target });
771 }
772
773 fn run(self, builder: &Builder<'_>) {
775 let host = builder.build.host_target;
776 let target = self.target;
777 let stage = builder.top_stage;
778 if stage == 0 {
779 eprintln!("cargo-miri cannot be tested at stage 0");
780 std::process::exit(1);
781 }
782
783 let build_compiler = builder.compiler(stage, host);
785
786 let mut cargo = tool::prepare_tool_cargo(
791 builder,
792 build_compiler,
793 Mode::ToolStd, target,
795 Kind::MiriTest,
796 "src/tools/miri/test-cargo-miri",
797 SourceType::Submodule,
798 &[],
799 );
800
801 match builder.doc_tests {
804 DocTests::Yes => {}
805 DocTests::No => {
806 cargo.args(["--lib", "--bins", "--examples", "--tests", "--benches"]);
807 }
808 DocTests::Only => {
809 cargo.arg("--doc");
810 }
811 }
812 cargo.arg("--").args(builder.config.test_args());
813
814 let mut cargo = BootstrapCommand::from(cargo);
816 {
817 let _guard = builder.msg_test("cargo-miri", target, stage);
818 let _time = helpers::timeit(builder);
819 cargo.run(builder);
820 }
821 }
822}
823
824#[derive(Debug, Clone, PartialEq, Eq, Hash)]
825pub struct CompiletestTest {
826 host: TargetSelection,
827}
828
829impl Step for CompiletestTest {
830 type Output = ();
831
832 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
833 run.path("src/tools/compiletest")
834 }
835
836 fn make_run(run: RunConfig<'_>) {
837 run.builder.ensure(CompiletestTest { host: run.target });
838 }
839
840 fn run(self, builder: &Builder<'_>) {
842 let host = self.host;
843
844 if builder.top_stage == 0 && !builder.config.compiletest_allow_stage0 {
850 eprintln!("\
851ERROR: `--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
852NOTE: 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`."
853 );
854 crate::exit!(1);
855 }
856
857 let bootstrap_compiler = builder.compiler(0, host);
858 let staged_compiler = builder.compiler(builder.top_stage, host);
859
860 let mut cargo = tool::prepare_tool_cargo(
861 builder,
862 bootstrap_compiler,
863 Mode::ToolBootstrap,
864 host,
865 Kind::Test,
866 "src/tools/compiletest",
867 SourceType::InTree,
868 &[],
869 );
870
871 cargo.env("TEST_RUSTC", builder.rustc(staged_compiler));
875
876 run_cargo_test(cargo, &[], &[], "compiletest self test", host, builder);
877 }
878}
879
880#[derive(Debug, Clone, PartialEq, Eq, Hash)]
881pub struct Clippy {
882 compilers: RustcPrivateCompilers,
883}
884
885impl Step for Clippy {
886 type Output = ();
887 const IS_HOST: bool = true;
888
889 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
890 run.suite_path("src/tools/clippy/tests").path("src/tools/clippy")
891 }
892
893 fn is_default_step(_builder: &Builder<'_>) -> bool {
894 false
895 }
896
897 fn make_run(run: RunConfig<'_>) {
898 run.builder.ensure(Clippy {
899 compilers: RustcPrivateCompilers::new(
900 run.builder,
901 run.builder.top_stage,
902 run.builder.host_target,
903 ),
904 });
905 }
906
907 fn run(self, builder: &Builder<'_>) {
909 let target = self.compilers.target();
910
911 let target_compiler = self.compilers.target_compiler();
915 let build_compiler = self.compilers.build_compiler();
916
917 let mut cargo = tool::prepare_tool_cargo(
918 builder,
919 build_compiler,
920 Mode::ToolRustcPrivate,
921 target,
922 Kind::Test,
923 "src/tools/clippy",
924 SourceType::InTree,
925 &[],
926 );
927
928 cargo.env("RUSTC_TEST_SUITE", builder.rustc(build_compiler));
929 cargo.env("RUSTC_LIB_PATH", builder.rustc_libdir(build_compiler));
930 let host_libs =
931 builder.stage_out(build_compiler, Mode::ToolRustcPrivate).join(builder.cargo_dir());
932 cargo.env("HOST_LIBS", host_libs);
933
934 builder.std(target_compiler, target);
936 cargo.env("TEST_SYSROOT", builder.sysroot(target_compiler));
937 cargo.env("TEST_RUSTC", builder.rustc(target_compiler));
938 cargo.env("TEST_RUSTC_LIB", builder.rustc_libdir(target_compiler));
939
940 'partially_test: {
942 let paths = &builder.config.paths[..];
943 let mut test_names = Vec::new();
944 for path in paths {
945 if let Some(path) =
946 helpers::is_valid_test_suite_arg(path, "src/tools/clippy/tests", builder)
947 {
948 test_names.push(path);
949 } else if path.ends_with("src/tools/clippy") {
950 break 'partially_test;
952 }
953 }
954 cargo.env("TESTNAME", test_names.join(","));
955 }
956
957 cargo.add_rustc_lib_path(builder);
958 let cargo = prepare_cargo_test(cargo, &[], &[], target, builder);
959
960 let _guard = builder.msg_test("clippy", target, target_compiler.stage);
961
962 if cargo.allow_failure().run(builder) {
964 return;
966 }
967
968 if !builder.config.cmd.bless() {
969 crate::exit!(1);
970 }
971 }
972
973 fn metadata(&self) -> Option<StepMetadata> {
974 Some(
975 StepMetadata::test("clippy", self.compilers.target())
976 .built_by(self.compilers.build_compiler()),
977 )
978 }
979}
980
981fn bin_path_for_cargo(builder: &Builder<'_>, compiler: Compiler) -> OsString {
982 let path = builder.sysroot(compiler).join("bin");
983 let old_path = env::var_os("PATH").unwrap_or_default();
984 env::join_paths(iter::once(path).chain(env::split_paths(&old_path))).expect("")
985}
986
987#[derive(Debug, Clone, Hash, PartialEq, Eq)]
989pub struct RustdocTheme {
990 test_compiler: Compiler,
992}
993
994impl Step for RustdocTheme {
995 type Output = ();
996 const IS_HOST: bool = true;
997
998 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
999 run.path("src/tools/rustdoc-themes")
1000 }
1001
1002 fn is_default_step(_builder: &Builder<'_>) -> bool {
1003 true
1004 }
1005
1006 fn make_run(run: RunConfig<'_>) {
1007 let test_compiler = run.builder.compiler(run.builder.top_stage, run.target);
1008
1009 run.builder.ensure(RustdocTheme { test_compiler });
1010 }
1011
1012 fn run(self, builder: &Builder<'_>) {
1013 let rustdoc = builder.bootstrap_out.join("rustdoc");
1014 let mut cmd = builder.tool_cmd(Tool::RustdocTheme);
1015 cmd.arg(rustdoc.to_str().unwrap())
1016 .arg(builder.src.join("src/librustdoc/html/static/css/rustdoc.css").to_str().unwrap())
1017 .env("RUSTC_STAGE", self.test_compiler.stage.to_string())
1018 .env("RUSTC_SYSROOT", builder.sysroot(self.test_compiler))
1019 .env(
1020 "RUSTDOC_LIBDIR",
1021 builder.sysroot_target_libdir(self.test_compiler, self.test_compiler.host),
1022 )
1023 .env("CFG_RELEASE_CHANNEL", &builder.config.channel)
1024 .env("RUSTDOC_REAL", builder.rustdoc_for_compiler(self.test_compiler))
1025 .env("RUSTC_BOOTSTRAP", "1");
1026 cmd.args(linker_args(builder, self.test_compiler.host, LldThreads::No));
1027
1028 cmd.delay_failure().run(builder);
1029 }
1030
1031 fn metadata(&self) -> Option<StepMetadata> {
1032 Some(
1033 StepMetadata::test("rustdoc-theme", self.test_compiler.host)
1034 .stage(self.test_compiler.stage),
1035 )
1036 }
1037}
1038
1039#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1041pub struct RustdocJSStd {
1042 build_compiler: Compiler,
1044 target: TargetSelection,
1045}
1046
1047impl Step for RustdocJSStd {
1048 type Output = ();
1049 const IS_HOST: bool = true;
1050
1051 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1052 run.suite_path("tests/rustdoc-js-std")
1053 }
1054
1055 fn is_default_step(builder: &Builder<'_>) -> bool {
1056 builder.config.nodejs.is_some()
1057 }
1058
1059 fn make_run(run: RunConfig<'_>) {
1060 run.builder.ensure(RustdocJSStd {
1061 build_compiler: run.builder.compiler(run.builder.top_stage, run.builder.host_target),
1062 target: run.target,
1063 });
1064 }
1065
1066 fn run(self, builder: &Builder<'_>) {
1067 let nodejs =
1068 builder.config.nodejs.as_ref().expect("need nodejs to run rustdoc-js-std tests");
1069 let mut command = command(nodejs);
1070 command
1071 .arg(builder.src.join("src/tools/rustdoc-js/tester.js"))
1072 .arg("--crate-name")
1073 .arg("std")
1074 .arg("--resource-suffix")
1075 .arg(&builder.version)
1076 .arg("--doc-folder")
1077 .arg(builder.doc_out(self.target))
1078 .arg("--test-folder")
1079 .arg(builder.src.join("tests/rustdoc-js-std"));
1080 for path in &builder.paths {
1081 if let Some(p) = helpers::is_valid_test_suite_arg(path, "tests/rustdoc-js-std", builder)
1082 {
1083 if !p.ends_with(".js") {
1084 eprintln!("A non-js file was given: `{}`", path.display());
1085 panic!("Cannot run rustdoc-js-std tests");
1086 }
1087 command.arg("--test-file").arg(path);
1088 }
1089 }
1090 builder.ensure(crate::core::build_steps::doc::Std::from_build_compiler(
1091 self.build_compiler,
1092 self.target,
1093 DocumentationFormat::Html,
1094 ));
1095 let _guard = builder.msg_test("rustdoc-js-std", self.target, self.build_compiler.stage);
1096 command.run(builder);
1097 }
1098
1099 fn metadata(&self) -> Option<StepMetadata> {
1100 Some(StepMetadata::test("rustdoc-js-std", self.target).stage(self.build_compiler.stage))
1101 }
1102}
1103
1104#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1105pub struct RustdocJSNotStd {
1106 pub target: TargetSelection,
1107 pub compiler: Compiler,
1108}
1109
1110impl Step for RustdocJSNotStd {
1111 type Output = ();
1112 const IS_HOST: bool = true;
1113
1114 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1115 run.suite_path("tests/rustdoc-js")
1116 }
1117
1118 fn is_default_step(builder: &Builder<'_>) -> bool {
1119 builder.config.nodejs.is_some()
1120 }
1121
1122 fn make_run(run: RunConfig<'_>) {
1123 let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1124 run.builder.ensure(RustdocJSNotStd { target: run.target, compiler });
1125 }
1126
1127 fn run(self, builder: &Builder<'_>) {
1128 builder.ensure(Compiletest {
1129 test_compiler: self.compiler,
1130 target: self.target,
1131 mode: CompiletestMode::RustdocJs,
1132 suite: "rustdoc-js",
1133 path: "tests/rustdoc-js",
1134 compare_mode: None,
1135 });
1136 }
1137}
1138
1139fn get_browser_ui_test_version_inner(
1140 builder: &Builder<'_>,
1141 yarn: &Path,
1142 global: bool,
1143) -> Option<String> {
1144 let mut command = command(yarn);
1145 command
1146 .arg("--cwd")
1147 .arg(&builder.build.out)
1148 .arg("list")
1149 .arg("--parseable")
1150 .arg("--long")
1151 .arg("--depth=0");
1152 if global {
1153 command.arg("--global");
1154 }
1155 let lines = command.allow_failure().cached().run_capture(builder).stdout();
1158 lines
1159 .lines()
1160 .find_map(|l| l.split(':').nth(1)?.strip_prefix("browser-ui-test@"))
1161 .map(|v| v.to_owned())
1162}
1163
1164fn get_browser_ui_test_version(builder: &Builder<'_>) -> Option<String> {
1165 let yarn = builder.config.yarn.as_deref()?;
1166 get_browser_ui_test_version_inner(builder, yarn, false)
1167 .or_else(|| get_browser_ui_test_version_inner(builder, yarn, true))
1168}
1169
1170#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1172pub struct RustdocGUI {
1173 test_compiler: Compiler,
1175 target: TargetSelection,
1176}
1177
1178impl Step for RustdocGUI {
1179 type Output = ();
1180 const IS_HOST: bool = true;
1181
1182 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1183 run.suite_path("tests/rustdoc-gui")
1184 }
1185
1186 fn is_default_step(builder: &Builder<'_>) -> bool {
1187 builder.config.nodejs.is_some()
1188 && builder.doc_tests != DocTests::Only
1189 && get_browser_ui_test_version(builder).is_some()
1190 }
1191
1192 fn make_run(run: RunConfig<'_>) {
1193 let test_compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1194 run.builder.ensure(RustdocGUI { test_compiler, target: run.target });
1195 }
1196
1197 fn run(self, builder: &Builder<'_>) {
1198 builder.std(self.test_compiler, self.target);
1199
1200 let mut cmd = builder.tool_cmd(Tool::RustdocGUITest);
1201
1202 let out_dir = builder.test_out(self.target).join("rustdoc-gui");
1203 build_stamp::clear_if_dirty(
1204 builder,
1205 &out_dir,
1206 &builder.rustdoc_for_compiler(self.test_compiler),
1207 );
1208
1209 if let Some(src) = builder.config.src.to_str() {
1210 cmd.arg("--rust-src").arg(src);
1211 }
1212
1213 if let Some(out_dir) = out_dir.to_str() {
1214 cmd.arg("--out-dir").arg(out_dir);
1215 }
1216
1217 if let Some(initial_cargo) = builder.config.initial_cargo.to_str() {
1218 cmd.arg("--initial-cargo").arg(initial_cargo);
1219 }
1220
1221 cmd.arg("--jobs").arg(builder.jobs().to_string());
1222
1223 cmd.env("RUSTDOC", builder.rustdoc_for_compiler(self.test_compiler))
1224 .env("RUSTC", builder.rustc(self.test_compiler));
1225
1226 add_rustdoc_cargo_linker_args(&mut cmd, builder, self.test_compiler.host, LldThreads::No);
1227
1228 for path in &builder.paths {
1229 if let Some(p) = helpers::is_valid_test_suite_arg(path, "tests/rustdoc-gui", builder) {
1230 if !p.ends_with(".goml") {
1231 eprintln!("A non-goml file was given: `{}`", path.display());
1232 panic!("Cannot run rustdoc-gui tests");
1233 }
1234 if let Some(name) = path.file_name().and_then(|f| f.to_str()) {
1235 cmd.arg("--goml-file").arg(name);
1236 }
1237 }
1238 }
1239
1240 for test_arg in builder.config.test_args() {
1241 cmd.arg("--test-arg").arg(test_arg);
1242 }
1243
1244 if let Some(ref nodejs) = builder.config.nodejs {
1245 cmd.arg("--nodejs").arg(nodejs);
1246 }
1247
1248 if let Some(ref yarn) = builder.config.yarn {
1249 cmd.arg("--yarn").arg(yarn);
1250 }
1251
1252 let _time = helpers::timeit(builder);
1253 let _guard = builder.msg_test("rustdoc-gui", self.target, self.test_compiler.stage);
1254 try_run_tests(builder, &mut cmd, true);
1255 }
1256
1257 fn metadata(&self) -> Option<StepMetadata> {
1258 Some(StepMetadata::test("rustdoc-gui", self.target).stage(self.test_compiler.stage))
1259 }
1260}
1261
1262#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1267pub struct Tidy;
1268
1269impl Step for Tidy {
1270 type Output = ();
1271 const IS_HOST: bool = true;
1272
1273 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1274 run.path("src/tools/tidy")
1275 }
1276
1277 fn is_default_step(builder: &Builder<'_>) -> bool {
1278 builder.doc_tests != DocTests::Only
1279 }
1280
1281 fn make_run(run: RunConfig<'_>) {
1282 run.builder.ensure(Tidy);
1283 }
1284
1285 fn run(self, builder: &Builder<'_>) {
1294 let mut cmd = builder.tool_cmd(Tool::Tidy);
1295 cmd.arg(&builder.src);
1296 cmd.arg(&builder.initial_cargo);
1297 cmd.arg(&builder.out);
1298 let jobs = builder.config.jobs.unwrap_or_else(|| {
1300 8 * std::thread::available_parallelism().map_or(1, std::num::NonZeroUsize::get) as u32
1301 });
1302 cmd.arg(jobs.to_string());
1303 if let Some(yarn) = &builder.config.yarn {
1305 cmd.arg(yarn);
1306 } else {
1307 cmd.arg("yarn");
1308 }
1309 if builder.is_verbose() {
1310 cmd.arg("--verbose");
1311 }
1312 if builder.config.cmd.bless() {
1313 cmd.arg("--bless");
1314 }
1315 if let Some(s) =
1316 builder.config.cmd.extra_checks().or(builder.config.tidy_extra_checks.as_deref())
1317 {
1318 cmd.arg(format!("--extra-checks={s}"));
1319 }
1320 let mut args = std::env::args_os();
1321 if args.any(|arg| arg == OsStr::new("--")) {
1322 cmd.arg("--");
1323 cmd.args(args);
1324 }
1325
1326 if builder.config.channel == "dev" || builder.config.channel == "nightly" {
1327 if !builder.config.json_output {
1328 builder.info("fmt check");
1329 if builder.config.initial_rustfmt.is_none() {
1330 let inferred_rustfmt_dir = builder.initial_sysroot.join("bin");
1331 eprintln!(
1332 "\
1333ERROR: no `rustfmt` binary found in {PATH}
1334INFO: `rust.channel` is currently set to \"{CHAN}\"
1335HELP: if you are testing a beta branch, set `rust.channel` to \"beta\" in the `bootstrap.toml` file
1336HELP: to skip test's attempt to check tidiness, pass `--skip src/tools/tidy` to `x.py test`",
1337 PATH = inferred_rustfmt_dir.display(),
1338 CHAN = builder.config.channel,
1339 );
1340 crate::exit!(1);
1341 }
1342 let all = false;
1343 crate::core::build_steps::format::format(
1344 builder,
1345 !builder.config.cmd.bless(),
1346 all,
1347 &[],
1348 );
1349 } else {
1350 eprintln!(
1351 "WARNING: `--json-output` is not supported on rustfmt, formatting will be skipped"
1352 );
1353 }
1354 }
1355
1356 builder.info("tidy check");
1357 cmd.delay_failure().run(builder);
1358
1359 builder.info("x.py completions check");
1360 let completion_paths = get_completion_paths(builder);
1361 if builder.config.cmd.bless() {
1362 builder.ensure(crate::core::build_steps::run::GenerateCompletions);
1363 } else if completion_paths
1364 .into_iter()
1365 .any(|(shell, path)| get_completion(shell, &path).is_some())
1366 {
1367 eprintln!(
1368 "x.py completions were changed; run `x.py run generate-completions` to update them"
1369 );
1370 crate::exit!(1);
1371 }
1372
1373 builder.info("x.py help check");
1374 if builder.config.cmd.bless() {
1375 builder.ensure(crate::core::build_steps::run::GenerateHelp);
1376 } else {
1377 let help_path = get_help_path(builder);
1378 let cur_help = std::fs::read_to_string(&help_path).unwrap_or_else(|err| {
1379 eprintln!("couldn't read {}: {}", help_path.display(), err);
1380 crate::exit!(1);
1381 });
1382 let new_help = top_level_help();
1383
1384 if new_help != cur_help {
1385 eprintln!("x.py help was changed; run `x.py run generate-help` to update it");
1386 crate::exit!(1);
1387 }
1388 }
1389 }
1390
1391 fn metadata(&self) -> Option<StepMetadata> {
1392 Some(StepMetadata::test("tidy", TargetSelection::default()))
1393 }
1394}
1395
1396#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1399pub struct CrateRunMakeSupport {
1400 host: TargetSelection,
1401}
1402
1403impl Step for CrateRunMakeSupport {
1404 type Output = ();
1405 const IS_HOST: bool = true;
1406
1407 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1408 run.path("src/tools/run-make-support")
1409 }
1410
1411 fn make_run(run: RunConfig<'_>) {
1412 run.builder.ensure(CrateRunMakeSupport { host: run.target });
1413 }
1414
1415 fn run(self, builder: &Builder<'_>) {
1417 let host = self.host;
1418 let compiler = builder.compiler(0, host);
1419
1420 let mut cargo = tool::prepare_tool_cargo(
1421 builder,
1422 compiler,
1423 Mode::ToolBootstrap,
1424 host,
1425 Kind::Test,
1426 "src/tools/run-make-support",
1427 SourceType::InTree,
1428 &[],
1429 );
1430 cargo.allow_features("test");
1431 run_cargo_test(cargo, &[], &[], "run-make-support self test", host, builder);
1432 }
1433}
1434
1435#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1436pub struct CrateBuildHelper {
1437 host: TargetSelection,
1438}
1439
1440impl Step for CrateBuildHelper {
1441 type Output = ();
1442 const IS_HOST: bool = true;
1443
1444 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1445 run.path("src/build_helper")
1446 }
1447
1448 fn make_run(run: RunConfig<'_>) {
1449 run.builder.ensure(CrateBuildHelper { host: run.target });
1450 }
1451
1452 fn run(self, builder: &Builder<'_>) {
1454 let host = self.host;
1455 let compiler = builder.compiler(0, host);
1456
1457 let mut cargo = tool::prepare_tool_cargo(
1458 builder,
1459 compiler,
1460 Mode::ToolBootstrap,
1461 host,
1462 Kind::Test,
1463 "src/build_helper",
1464 SourceType::InTree,
1465 &[],
1466 );
1467 cargo.allow_features("test");
1468 run_cargo_test(cargo, &[], &[], "build_helper self test", host, builder);
1469 }
1470}
1471
1472fn testdir(builder: &Builder<'_>, host: TargetSelection) -> PathBuf {
1473 builder.out.join(host).join("test")
1474}
1475
1476macro_rules! test {
1478 (
1479 $( #[$attr:meta] )* $name:ident {
1481 path: $path:expr,
1482 mode: $mode:expr,
1483 suite: $suite:expr,
1484 default: $default:expr
1485 $( , IS_HOST: $IS_HOST:expr )? $( , compare_mode: $compare_mode:expr )? $( , )? }
1489 ) => {
1490 $( #[$attr] )*
1491 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
1492 pub struct $name {
1493 test_compiler: Compiler,
1494 target: TargetSelection,
1495 }
1496
1497 impl Step for $name {
1498 type Output = ();
1499 const IS_HOST: bool = (const {
1500 #[allow(unused_assignments, unused_mut)]
1501 let mut value = false;
1502 $( value = $IS_HOST; )?
1503 value
1504 });
1505
1506 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1507 run.suite_path($path)
1508 }
1509
1510 fn is_default_step(_builder: &Builder<'_>) -> bool {
1511 const { $default }
1512 }
1513
1514 fn make_run(run: RunConfig<'_>) {
1515 let test_compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1516
1517 run.builder.ensure($name { test_compiler, target: run.target });
1518 }
1519
1520 fn run(self, builder: &Builder<'_>) {
1521 builder.ensure(Compiletest {
1522 test_compiler: self.test_compiler,
1523 target: self.target,
1524 mode: const { $mode },
1525 suite: $suite,
1526 path: $path,
1527 compare_mode: (const {
1528 #[allow(unused_assignments, unused_mut)]
1529 let mut value = None;
1530 $( value = $compare_mode; )?
1531 value
1532 }),
1533 })
1534 }
1535 }
1536 };
1537}
1538
1539test!(Ui { path: "tests/ui", mode: CompiletestMode::Ui, suite: "ui", default: true });
1540
1541test!(Crashes {
1542 path: "tests/crashes",
1543 mode: CompiletestMode::Crashes,
1544 suite: "crashes",
1545 default: true,
1546});
1547
1548test!(CodegenLlvm {
1549 path: "tests/codegen-llvm",
1550 mode: CompiletestMode::Codegen,
1551 suite: "codegen-llvm",
1552 default: true
1553});
1554
1555test!(CodegenUnits {
1556 path: "tests/codegen-units",
1557 mode: CompiletestMode::CodegenUnits,
1558 suite: "codegen-units",
1559 default: true,
1560});
1561
1562test!(Incremental {
1563 path: "tests/incremental",
1564 mode: CompiletestMode::Incremental,
1565 suite: "incremental",
1566 default: true,
1567});
1568
1569test!(Debuginfo {
1570 path: "tests/debuginfo",
1571 mode: CompiletestMode::Debuginfo,
1572 suite: "debuginfo",
1573 default: true,
1574 compare_mode: Some("split-dwarf"),
1575});
1576
1577test!(UiFullDeps {
1578 path: "tests/ui-fulldeps",
1579 mode: CompiletestMode::Ui,
1580 suite: "ui-fulldeps",
1581 default: true,
1582 IS_HOST: true,
1583});
1584
1585test!(RustdocHtml {
1586 path: "tests/rustdoc-html",
1587 mode: CompiletestMode::RustdocHtml,
1588 suite: "rustdoc-html",
1589 default: true,
1590 IS_HOST: true,
1591});
1592test!(RustdocUi {
1593 path: "tests/rustdoc-ui",
1594 mode: CompiletestMode::Ui,
1595 suite: "rustdoc-ui",
1596 default: true,
1597 IS_HOST: true,
1598});
1599
1600test!(RustdocJson {
1601 path: "tests/rustdoc-json",
1602 mode: CompiletestMode::RustdocJson,
1603 suite: "rustdoc-json",
1604 default: true,
1605 IS_HOST: true,
1606});
1607
1608test!(Pretty {
1609 path: "tests/pretty",
1610 mode: CompiletestMode::Pretty,
1611 suite: "pretty",
1612 default: true,
1613 IS_HOST: true,
1614});
1615
1616test!(RunMake {
1617 path: "tests/run-make",
1618 mode: CompiletestMode::RunMake,
1619 suite: "run-make",
1620 default: true,
1621});
1622test!(RunMakeCargo {
1623 path: "tests/run-make-cargo",
1624 mode: CompiletestMode::RunMake,
1625 suite: "run-make-cargo",
1626 default: true
1627});
1628
1629test!(AssemblyLlvm {
1630 path: "tests/assembly-llvm",
1631 mode: CompiletestMode::Assembly,
1632 suite: "assembly-llvm",
1633 default: true
1634});
1635
1636#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1639pub struct Coverage {
1640 pub compiler: Compiler,
1641 pub target: TargetSelection,
1642 pub(crate) mode: CompiletestMode,
1643}
1644
1645impl Coverage {
1646 const PATH: &'static str = "tests/coverage";
1647 const SUITE: &'static str = "coverage";
1648 const ALL_MODES: &[CompiletestMode] =
1649 &[CompiletestMode::CoverageMap, CompiletestMode::CoverageRun];
1650}
1651
1652impl Step for Coverage {
1653 type Output = ();
1654 const IS_HOST: bool = false;
1656
1657 fn should_run(mut run: ShouldRun<'_>) -> ShouldRun<'_> {
1658 run = run.suite_path(Self::PATH);
1664 for mode in Self::ALL_MODES {
1665 run = run.alias(mode.as_str());
1666 }
1667 run
1668 }
1669
1670 fn is_default_step(_builder: &Builder<'_>) -> bool {
1671 true
1672 }
1673
1674 fn make_run(run: RunConfig<'_>) {
1675 let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1676 let target = run.target;
1677
1678 let mut modes = vec![];
1682
1683 for path in &run.paths {
1686 match path {
1687 PathSet::Set(_) => {
1688 for &mode in Self::ALL_MODES {
1689 if path.assert_single_path().path == Path::new(mode.as_str()) {
1690 modes.push(mode);
1691 break;
1692 }
1693 }
1694 }
1695 PathSet::Suite(_) => {
1696 modes.extend_from_slice(Self::ALL_MODES);
1697 break;
1698 }
1699 }
1700 }
1701
1702 modes.retain(|mode| {
1705 !run.builder.config.skip.iter().any(|skip| skip == Path::new(mode.as_str()))
1706 });
1707
1708 for mode in modes {
1716 run.builder.ensure(Coverage { compiler, target, mode });
1717 }
1718 }
1719
1720 fn run(self, builder: &Builder<'_>) {
1721 let Self { compiler, target, mode } = self;
1722 builder.ensure(Compiletest {
1725 test_compiler: compiler,
1726 target,
1727 mode,
1728 suite: Self::SUITE,
1729 path: Self::PATH,
1730 compare_mode: None,
1731 });
1732 }
1733}
1734
1735test!(CoverageRunRustdoc {
1736 path: "tests/coverage-run-rustdoc",
1737 mode: CompiletestMode::CoverageRun,
1738 suite: "coverage-run-rustdoc",
1739 default: true,
1740 IS_HOST: true,
1741});
1742
1743#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1745pub struct MirOpt {
1746 pub compiler: Compiler,
1747 pub target: TargetSelection,
1748}
1749
1750impl Step for MirOpt {
1751 type Output = ();
1752
1753 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1754 run.suite_path("tests/mir-opt")
1755 }
1756
1757 fn is_default_step(_builder: &Builder<'_>) -> bool {
1758 true
1759 }
1760
1761 fn make_run(run: RunConfig<'_>) {
1762 let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1763 run.builder.ensure(MirOpt { compiler, target: run.target });
1764 }
1765
1766 fn run(self, builder: &Builder<'_>) {
1767 let run = |target| {
1768 builder.ensure(Compiletest {
1769 test_compiler: self.compiler,
1770 target,
1771 mode: CompiletestMode::MirOpt,
1772 suite: "mir-opt",
1773 path: "tests/mir-opt",
1774 compare_mode: None,
1775 })
1776 };
1777
1778 run(self.target);
1779
1780 if builder.config.cmd.bless() {
1783 for target in ["aarch64-unknown-linux-gnu", "i686-pc-windows-msvc"] {
1789 run(TargetSelection::from_user(target));
1790 }
1791
1792 for target in ["x86_64-apple-darwin", "i686-unknown-linux-musl"] {
1793 let target = TargetSelection::from_user(target);
1794 let panic_abort_target = builder.ensure(MirOptPanicAbortSyntheticTarget {
1795 compiler: self.compiler,
1796 base: target,
1797 });
1798 run(panic_abort_target);
1799 }
1800 }
1801 }
1802}
1803
1804#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1810struct Compiletest {
1811 test_compiler: Compiler,
1813 target: TargetSelection,
1814 mode: CompiletestMode,
1815 suite: &'static str,
1816 path: &'static str,
1817 compare_mode: Option<&'static str>,
1818}
1819
1820impl Step for Compiletest {
1821 type Output = ();
1822
1823 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1824 run.never()
1825 }
1826
1827 fn run(self, builder: &Builder<'_>) {
1828 if builder.doc_tests == DocTests::Only {
1829 return;
1830 }
1831
1832 if builder.top_stage == 0 && !builder.config.compiletest_allow_stage0 {
1833 eprintln!("\
1834ERROR: `--stage 0` runs compiletest on the stage0 (precompiled) compiler, not your local changes, and will almost always cause tests to fail
1835HELP: to test the compiler or standard library, omit the stage or explicitly use `--stage 1` instead
1836NOTE: 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`."
1837 );
1838 crate::exit!(1);
1839 }
1840
1841 let mut test_compiler = self.test_compiler;
1842 let target = self.target;
1843 let mode = self.mode;
1844 let suite = self.suite;
1845
1846 let suite_path = self.path;
1848
1849 if !builder.config.codegen_tests && mode == CompiletestMode::Codegen {
1851 return;
1852 }
1853
1854 let query_compiler;
1861 let (stage, stage_id) = if suite == "ui-fulldeps" && test_compiler.stage == 1 {
1862 query_compiler = Some(test_compiler);
1865 let build = builder.build.host_target;
1869 test_compiler = builder.compiler(test_compiler.stage - 1, build);
1870 let test_stage = test_compiler.stage + 1;
1871 (test_stage, format!("stage{test_stage}-{build}"))
1872 } else {
1873 query_compiler = None;
1874 let stage = test_compiler.stage;
1875 (stage, format!("stage{stage}-{target}"))
1876 };
1877
1878 if suite.ends_with("fulldeps") {
1879 builder.ensure(compile::Rustc::new(test_compiler, target));
1880 }
1881
1882 if suite == "debuginfo" {
1883 builder.ensure(dist::DebuggerScripts {
1884 sysroot: builder.sysroot(test_compiler).to_path_buf(),
1885 target,
1886 });
1887 }
1888 if mode == CompiletestMode::RunMake {
1889 builder.tool_exe(Tool::RunMakeSupport);
1890 }
1891
1892 if suite == "mir-opt" {
1894 builder.ensure(
1895 compile::Std::new(test_compiler, test_compiler.host).is_for_mir_opt_tests(true),
1896 );
1897 } else {
1898 builder.std(test_compiler, test_compiler.host);
1899 }
1900
1901 let mut cmd = builder.tool_cmd(Tool::Compiletest);
1902
1903 if suite == "mir-opt" {
1904 builder.ensure(compile::Std::new(test_compiler, target).is_for_mir_opt_tests(true));
1905 } else {
1906 builder.std(test_compiler, target);
1907 }
1908
1909 builder.ensure(RemoteCopyLibs { build_compiler: test_compiler, target });
1910
1911 cmd.arg("--stage").arg(stage.to_string());
1915 cmd.arg("--stage-id").arg(stage_id);
1916
1917 cmd.arg("--compile-lib-path").arg(builder.rustc_libdir(test_compiler));
1918 cmd.arg("--run-lib-path").arg(builder.sysroot_target_libdir(test_compiler, target));
1919 cmd.arg("--rustc-path").arg(builder.rustc(test_compiler));
1920 if let Some(query_compiler) = query_compiler {
1921 cmd.arg("--query-rustc-path").arg(builder.rustc(query_compiler));
1922 }
1923
1924 cmd.arg("--minicore-path")
1927 .arg(builder.src.join("tests").join("auxiliary").join("minicore.rs"));
1928
1929 let is_rustdoc = suite == "rustdoc-ui" || suite == "rustdoc-js";
1930
1931 if mode == CompiletestMode::RunMake {
1946 let stage0_rustc_path = builder.compiler(0, test_compiler.host);
1949 cmd.arg("--stage0-rustc-path").arg(builder.rustc(stage0_rustc_path));
1950
1951 if suite == "run-make-cargo" {
1952 let cargo_path = if test_compiler.stage == 0 {
1953 builder.initial_cargo.clone()
1955 } else {
1956 builder
1957 .ensure(tool::Cargo::from_build_compiler(
1958 builder.compiler(test_compiler.stage - 1, test_compiler.host),
1959 test_compiler.host,
1960 ))
1961 .tool_path
1962 };
1963
1964 cmd.arg("--cargo-path").arg(cargo_path);
1965 }
1966 }
1967
1968 if matches!(
1970 mode,
1971 CompiletestMode::RunMake
1972 | CompiletestMode::RustdocHtml
1973 | CompiletestMode::RustdocJs
1974 | CompiletestMode::RustdocJson
1975 ) || matches!(suite, "rustdoc-ui" | "coverage-run-rustdoc")
1976 {
1977 cmd.arg("--rustdoc-path").arg(builder.rustdoc_for_compiler(test_compiler));
1978 }
1979
1980 if mode == CompiletestMode::RustdocJson {
1981 let json_compiler = builder.compiler(0, builder.host_target);
1983 cmd.arg("--jsondocck-path")
1984 .arg(builder.ensure(tool::JsonDocCk { compiler: json_compiler, target }).tool_path);
1985 cmd.arg("--jsondoclint-path").arg(
1986 builder.ensure(tool::JsonDocLint { compiler: json_compiler, target }).tool_path,
1987 );
1988 }
1989
1990 if matches!(mode, CompiletestMode::CoverageMap | CompiletestMode::CoverageRun) {
1991 let coverage_dump = builder.tool_exe(Tool::CoverageDump);
1992 cmd.arg("--coverage-dump-path").arg(coverage_dump);
1993 }
1994
1995 cmd.arg("--src-root").arg(&builder.src);
1996 cmd.arg("--src-test-suite-root").arg(builder.src.join("tests").join(suite));
1997
1998 cmd.arg("--build-root").arg(&builder.out);
2002 cmd.arg("--build-test-suite-root").arg(testdir(builder, test_compiler.host).join(suite));
2003
2004 let sysroot = if builder.top_stage == 0 {
2009 builder.initial_sysroot.clone()
2010 } else {
2011 builder.sysroot(test_compiler)
2012 };
2013
2014 cmd.arg("--sysroot-base").arg(sysroot);
2015
2016 cmd.arg("--suite").arg(suite);
2017 cmd.arg("--mode").arg(mode.as_str());
2018 cmd.arg("--target").arg(target.rustc_target_arg());
2019 cmd.arg("--host").arg(&*test_compiler.host.triple);
2020 cmd.arg("--llvm-filecheck").arg(builder.llvm_filecheck(builder.config.host_target));
2021
2022 if let Some(codegen_backend) = builder.config.cmd.test_codegen_backend() {
2023 if !builder
2024 .config
2025 .enabled_codegen_backends(test_compiler.host)
2026 .contains(codegen_backend)
2027 {
2028 eprintln!(
2029 "\
2030ERROR: No configured backend named `{name}`
2031HELP: You can add it into `bootstrap.toml` in `rust.codegen-backends = [{name:?}]`",
2032 name = codegen_backend.name(),
2033 );
2034 crate::exit!(1);
2035 }
2036
2037 if let CodegenBackendKind::Gcc = codegen_backend
2038 && builder.config.rustc_debug_assertions
2039 {
2040 eprintln!(
2041 r#"WARNING: Running tests with the GCC codegen backend while rustc debug assertions are enabled. This might lead to test failures.
2042Please disable assertions with `rust.debug-assertions = false`.
2043 "#
2044 );
2045 }
2046
2047 cmd.arg("--override-codegen-backend").arg(codegen_backend.name());
2050 cmd.arg("--default-codegen-backend").arg(codegen_backend.name());
2053 } else {
2054 cmd.arg("--default-codegen-backend")
2057 .arg(builder.config.default_codegen_backend(test_compiler.host).name());
2058 }
2059 if builder.config.cmd.bypass_ignore_backends() {
2060 cmd.arg("--bypass-ignore-backends");
2061 }
2062
2063 if builder.build.config.llvm_enzyme {
2064 cmd.arg("--has-enzyme");
2065 }
2066
2067 if builder.build.config.llvm_offload {
2068 cmd.arg("--has-offload");
2069 }
2070
2071 if builder.config.cmd.bless() {
2072 cmd.arg("--bless");
2073 }
2074
2075 if builder.config.cmd.force_rerun() {
2076 cmd.arg("--force-rerun");
2077 }
2078
2079 if builder.config.cmd.no_capture() {
2080 cmd.arg("--no-capture");
2081 }
2082
2083 let compare_mode =
2084 builder.config.cmd.compare_mode().or_else(|| {
2085 if builder.config.test_compare_mode { self.compare_mode } else { None }
2086 });
2087
2088 if let Some(ref pass) = builder.config.cmd.pass() {
2089 cmd.arg("--pass");
2090 cmd.arg(pass);
2091 }
2092
2093 if let Some(ref run) = builder.config.cmd.run() {
2094 cmd.arg("--run");
2095 cmd.arg(run);
2096 }
2097
2098 if let Some(ref nodejs) = builder.config.nodejs {
2099 cmd.arg("--nodejs").arg(nodejs);
2100 } else if mode == CompiletestMode::RustdocJs {
2101 panic!("need nodejs to run rustdoc-js suite");
2102 }
2103 if builder.config.rust_optimize_tests {
2104 cmd.arg("--optimize-tests");
2105 }
2106 if builder.config.rust_randomize_layout {
2107 cmd.arg("--rust-randomized-layout");
2108 }
2109 if builder.config.cmd.only_modified() {
2110 cmd.arg("--only-modified");
2111 }
2112 if let Some(compiletest_diff_tool) = &builder.config.compiletest_diff_tool {
2113 cmd.arg("--compiletest-diff-tool").arg(compiletest_diff_tool);
2114 }
2115
2116 let mut flags = if is_rustdoc { Vec::new() } else { vec!["-Crpath".to_string()] };
2117 flags.push(format!(
2118 "-Cdebuginfo={}",
2119 if mode == CompiletestMode::Codegen {
2120 if builder.config.rust_debuginfo_level_tests
2123 != crate::core::config::DebuginfoLevel::None
2124 {
2125 println!(
2126 "NOTE: ignoring `rust.debuginfo-level-tests={}` for codegen tests",
2127 builder.config.rust_debuginfo_level_tests
2128 );
2129 }
2130 crate::core::config::DebuginfoLevel::None
2131 } else {
2132 builder.config.rust_debuginfo_level_tests
2133 }
2134 ));
2135 flags.extend(builder.config.cmd.compiletest_rustc_args().iter().map(|s| s.to_string()));
2136
2137 if suite != "mir-opt" {
2138 if let Some(linker) = builder.linker(target) {
2139 cmd.arg("--target-linker").arg(linker);
2140 }
2141 if let Some(linker) = builder.linker(test_compiler.host) {
2142 cmd.arg("--host-linker").arg(linker);
2143 }
2144 }
2145
2146 if suite == "ui-fulldeps" && target.ends_with("darwin") {
2148 flags.push("-Alinker_messages".into());
2149 }
2150
2151 let mut hostflags = flags.clone();
2152 hostflags.extend(linker_flags(builder, test_compiler.host, LldThreads::No));
2153
2154 let mut targetflags = flags;
2155
2156 if suite == "ui" || suite == "incremental" {
2158 builder.ensure(TestHelpers { target: test_compiler.host });
2159 builder.ensure(TestHelpers { target });
2160 hostflags.push(format!(
2161 "-Lnative={}",
2162 builder.test_helpers_out(test_compiler.host).display()
2163 ));
2164 targetflags.push(format!("-Lnative={}", builder.test_helpers_out(target).display()));
2165 }
2166
2167 for flag in hostflags {
2168 cmd.arg("--host-rustcflags").arg(flag);
2169 }
2170 for flag in targetflags {
2171 cmd.arg("--target-rustcflags").arg(flag);
2172 }
2173
2174 cmd.arg("--python").arg(
2175 builder.config.python.as_ref().expect("python is required for running rustdoc tests"),
2176 );
2177
2178 let android = android::discover_android(builder, target);
2180 if let Some(android::Android { adb_path, adb_test_dir, android_cross_path }) = &android {
2181 cmd.arg("--adb-path").arg(adb_path);
2182 cmd.arg("--adb-test-dir").arg(adb_test_dir);
2183 cmd.arg("--android-cross-path").arg(android_cross_path);
2184 }
2185
2186 if mode == CompiletestMode::Debuginfo {
2187 if let Some(debuggers::Cdb { cdb }) = debuggers::discover_cdb(target) {
2188 cmd.arg("--cdb").arg(cdb);
2189 }
2190
2191 if let Some(debuggers::Gdb { gdb }) = debuggers::discover_gdb(builder, android.as_ref())
2192 {
2193 cmd.arg("--gdb").arg(gdb.as_ref());
2194 }
2195
2196 if let Some(debuggers::Lldb { lldb_exe, lldb_version }) =
2197 debuggers::discover_lldb(builder)
2198 {
2199 cmd.arg("--lldb").arg(lldb_exe);
2200 cmd.arg("--lldb-version").arg(lldb_version);
2201 }
2202 }
2203
2204 if helpers::forcing_clang_based_tests() {
2205 let clang_exe = builder.llvm_out(target).join("bin").join("clang");
2206 cmd.arg("--run-clang-based-tests-with").arg(clang_exe);
2207 }
2208
2209 for exclude in &builder.config.skip {
2210 cmd.arg("--skip");
2211 cmd.arg(exclude);
2212 }
2213
2214 let mut paths = match &builder.config.cmd {
2216 Subcommand::Test { .. } => &builder.config.paths[..],
2217 _ => &[],
2218 };
2219
2220 let mut paths_v;
2223 if mode == CompiletestMode::RustdocJs {
2224 paths_v = paths.to_vec();
2225 for p in &mut paths_v {
2226 if let Some(ext) = p.extension()
2227 && ext == "js"
2228 {
2229 p.set_extension("rs");
2230 }
2231 }
2232 paths = &paths_v;
2233 }
2234 let mut test_args: Vec<&str> = paths
2236 .iter()
2237 .filter_map(|p| helpers::is_valid_test_suite_arg(p, suite_path, builder))
2238 .collect();
2239
2240 test_args.append(&mut builder.config.test_args());
2241
2242 if cfg!(windows) {
2245 let test_args_win: Vec<String> =
2246 test_args.iter().map(|s| s.replace('/', "\\")).collect();
2247 cmd.args(&test_args_win);
2248 } else {
2249 cmd.args(&test_args);
2250 }
2251
2252 if builder.is_verbose() {
2253 cmd.arg("--verbose");
2254 }
2255
2256 if builder.config.rustc_debug_assertions {
2257 cmd.arg("--with-rustc-debug-assertions");
2258 }
2259
2260 if builder.config.std_debug_assertions {
2261 cmd.arg("--with-std-debug-assertions");
2262 }
2263
2264 if builder.config.rust_remap_debuginfo {
2265 cmd.arg("--with-std-remap-debuginfo");
2266 }
2267
2268 cmd.arg("--jobs").arg(builder.jobs().to_string());
2269
2270 let mut llvm_components_passed = false;
2271 let mut copts_passed = false;
2272 if builder.config.llvm_enabled(test_compiler.host) {
2273 let llvm::LlvmResult { host_llvm_config, .. } =
2274 builder.ensure(llvm::Llvm { target: builder.config.host_target });
2275 if !builder.config.dry_run() {
2276 let llvm_version = get_llvm_version(builder, &host_llvm_config);
2277 let llvm_components = command(&host_llvm_config)
2278 .cached()
2279 .arg("--components")
2280 .run_capture_stdout(builder)
2281 .stdout();
2282 cmd.arg("--llvm-version")
2284 .arg(llvm_version.trim())
2285 .arg("--llvm-components")
2286 .arg(llvm_components.trim());
2287 llvm_components_passed = true;
2288 }
2289 if !builder.config.is_rust_llvm(target) {
2290 cmd.arg("--system-llvm");
2291 }
2292
2293 if !builder.config.dry_run() && suite.ends_with("fulldeps") {
2298 let llvm_libdir = command(&host_llvm_config)
2299 .cached()
2300 .arg("--libdir")
2301 .run_capture_stdout(builder)
2302 .stdout();
2303 let link_llvm = if target.is_msvc() {
2304 format!("-Clink-arg=-LIBPATH:{llvm_libdir}")
2305 } else {
2306 format!("-Clink-arg=-L{llvm_libdir}")
2307 };
2308 cmd.arg("--host-rustcflags").arg(link_llvm);
2309 }
2310
2311 if !builder.config.dry_run()
2312 && matches!(mode, CompiletestMode::RunMake | CompiletestMode::CoverageRun)
2313 {
2314 let llvm_bin_path = host_llvm_config
2319 .parent()
2320 .expect("Expected llvm-config to be contained in directory");
2321 assert!(llvm_bin_path.is_dir());
2322 cmd.arg("--llvm-bin-dir").arg(llvm_bin_path);
2323 }
2324
2325 if !builder.config.dry_run() && mode == CompiletestMode::RunMake {
2326 if builder.config.lld_enabled {
2328 let lld_install_root =
2329 builder.ensure(llvm::Lld { target: builder.config.host_target });
2330
2331 let lld_bin_path = lld_install_root.join("bin");
2332
2333 let old_path = env::var_os("PATH").unwrap_or_default();
2334 let new_path = env::join_paths(
2335 std::iter::once(lld_bin_path).chain(env::split_paths(&old_path)),
2336 )
2337 .expect("Could not add LLD bin path to PATH");
2338 cmd.env("PATH", new_path);
2339 }
2340 }
2341 }
2342
2343 if !builder.config.dry_run() && mode == CompiletestMode::RunMake {
2346 let mut cflags = builder.cc_handled_clags(target, CLang::C);
2347 cflags.extend(builder.cc_unhandled_cflags(target, GitRepo::Rustc, CLang::C));
2348 let mut cxxflags = builder.cc_handled_clags(target, CLang::Cxx);
2349 cxxflags.extend(builder.cc_unhandled_cflags(target, GitRepo::Rustc, CLang::Cxx));
2350 cmd.arg("--cc")
2351 .arg(builder.cc(target))
2352 .arg("--cxx")
2353 .arg(builder.cxx(target).unwrap())
2354 .arg("--cflags")
2355 .arg(cflags.join(" "))
2356 .arg("--cxxflags")
2357 .arg(cxxflags.join(" "));
2358 copts_passed = true;
2359 if let Some(ar) = builder.ar(target) {
2360 cmd.arg("--ar").arg(ar);
2361 }
2362 }
2363
2364 if !llvm_components_passed {
2365 cmd.arg("--llvm-components").arg("");
2366 }
2367 if !copts_passed {
2368 cmd.arg("--cc")
2369 .arg("")
2370 .arg("--cxx")
2371 .arg("")
2372 .arg("--cflags")
2373 .arg("")
2374 .arg("--cxxflags")
2375 .arg("");
2376 }
2377
2378 if builder.remote_tested(target) {
2379 cmd.arg("--remote-test-client").arg(builder.tool_exe(Tool::RemoteTestClient));
2380 } else if let Some(tool) = builder.runner(target) {
2381 cmd.arg("--runner").arg(tool);
2382 }
2383
2384 if suite != "mir-opt" {
2385 if !builder.config.dry_run() && target.is_msvc() {
2391 for (k, v) in builder.cc[&target].env() {
2392 if k != "PATH" {
2393 cmd.env(k, v);
2394 }
2395 }
2396 }
2397 }
2398
2399 if !builder.config.dry_run()
2401 && target.contains("msvc")
2402 && builder.config.sanitizers_enabled(target)
2403 {
2404 cmd.env("ASAN_WIN_CONTINUE_ON_INTERCEPTION_FAILURE", "1");
2407 let asan_runtime_path = builder.cc[&target].path().parent().unwrap().to_path_buf();
2409 let old_path = cmd
2410 .get_envs()
2411 .find_map(|(k, v)| (k == "PATH").then_some(v))
2412 .flatten()
2413 .map_or_else(|| env::var_os("PATH").unwrap_or_default(), |v| v.to_owned());
2414 let new_path = env::join_paths(
2415 env::split_paths(&old_path).chain(std::iter::once(asan_runtime_path)),
2416 )
2417 .expect("Could not add ASAN runtime path to PATH");
2418 cmd.env("PATH", new_path);
2419 }
2420
2421 cmd.env_remove("CARGO");
2424
2425 cmd.env("RUSTC_BOOTSTRAP", "1");
2426 cmd.env("RUSTC_FORCE_RUSTC_VERSION", "compiletest");
2429 cmd.env("DOC_RUST_LANG_ORG_CHANNEL", builder.doc_rust_lang_org_channel());
2430 builder.add_rust_test_threads(&mut cmd);
2431
2432 if builder.config.sanitizers_enabled(target) {
2433 cmd.env("RUSTC_SANITIZER_SUPPORT", "1");
2434 }
2435
2436 if builder.config.profiler_enabled(target) {
2437 cmd.arg("--profiler-runtime");
2438 }
2439
2440 cmd.env("RUST_TEST_TMPDIR", builder.tempdir());
2441
2442 if builder.config.cmd.rustfix_coverage() {
2443 cmd.arg("--rustfix-coverage");
2444 }
2445
2446 cmd.arg("--channel").arg(&builder.config.channel);
2447
2448 if !builder.config.omit_git_hash {
2449 cmd.arg("--git-hash");
2450 }
2451
2452 let git_config = builder.config.git_config();
2453 cmd.arg("--nightly-branch").arg(git_config.nightly_branch);
2454 cmd.arg("--git-merge-commit-email").arg(git_config.git_merge_commit_email);
2455
2456 #[cfg(feature = "build-metrics")]
2457 builder.metrics.begin_test_suite(
2458 build_helper::metrics::TestSuiteMetadata::Compiletest {
2459 suite: suite.into(),
2460 mode: mode.to_string(),
2461 compare_mode: None,
2462 target: self.target.triple.to_string(),
2463 host: self.test_compiler.host.triple.to_string(),
2464 stage: self.test_compiler.stage,
2465 },
2466 builder,
2467 );
2468
2469 let _group = builder.msg_test(
2470 format!("with compiletest suite={suite} mode={mode}"),
2471 target,
2472 test_compiler.stage,
2473 );
2474 try_run_tests(builder, &mut cmd, false);
2475
2476 if let Some(compare_mode) = compare_mode {
2477 cmd.arg("--compare-mode").arg(compare_mode);
2478
2479 #[cfg(feature = "build-metrics")]
2480 builder.metrics.begin_test_suite(
2481 build_helper::metrics::TestSuiteMetadata::Compiletest {
2482 suite: suite.into(),
2483 mode: mode.to_string(),
2484 compare_mode: Some(compare_mode.into()),
2485 target: self.target.triple.to_string(),
2486 host: self.test_compiler.host.triple.to_string(),
2487 stage: self.test_compiler.stage,
2488 },
2489 builder,
2490 );
2491
2492 builder.info(&format!(
2493 "Check compiletest suite={} mode={} compare_mode={} ({} -> {})",
2494 suite, mode, compare_mode, &test_compiler.host, target
2495 ));
2496 let _time = helpers::timeit(builder);
2497 try_run_tests(builder, &mut cmd, false);
2498 }
2499 }
2500
2501 fn metadata(&self) -> Option<StepMetadata> {
2502 Some(
2503 StepMetadata::test(&format!("compiletest-{}", self.suite), self.target)
2504 .stage(self.test_compiler.stage),
2505 )
2506 }
2507}
2508
2509#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2511struct BookTest {
2512 test_compiler: Compiler,
2513 path: PathBuf,
2514 name: &'static str,
2515 is_ext_doc: bool,
2516 dependencies: Vec<&'static str>,
2517}
2518
2519impl Step for BookTest {
2520 type Output = ();
2521 const IS_HOST: bool = true;
2522
2523 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2524 run.never()
2525 }
2526
2527 fn run(self, builder: &Builder<'_>) {
2528 if self.is_ext_doc {
2538 self.run_ext_doc(builder);
2539 } else {
2540 self.run_local_doc(builder);
2541 }
2542 }
2543}
2544
2545impl BookTest {
2546 fn run_ext_doc(self, builder: &Builder<'_>) {
2549 let test_compiler = self.test_compiler;
2550
2551 builder.std(test_compiler, test_compiler.host);
2552
2553 let mut rustdoc_path = builder.rustdoc_for_compiler(test_compiler);
2556 rustdoc_path.pop();
2557 let old_path = env::var_os("PATH").unwrap_or_default();
2558 let new_path = env::join_paths(iter::once(rustdoc_path).chain(env::split_paths(&old_path)))
2559 .expect("could not add rustdoc to PATH");
2560
2561 let mut rustbook_cmd = builder.tool_cmd(Tool::Rustbook);
2562 let path = builder.src.join(&self.path);
2563 rustbook_cmd.env("RUSTC_BOOTSTRAP", "1");
2565 rustbook_cmd.env("PATH", new_path).arg("test").arg(path);
2566
2567 let libs = if !self.dependencies.is_empty() {
2572 let mut lib_paths = vec![];
2573 for dep in self.dependencies {
2574 let mode = Mode::ToolRustcPrivate;
2575 let target = builder.config.host_target;
2576 let cargo = tool::prepare_tool_cargo(
2577 builder,
2578 test_compiler,
2579 mode,
2580 target,
2581 Kind::Build,
2582 dep,
2583 SourceType::Submodule,
2584 &[],
2585 );
2586
2587 let stamp = BuildStamp::new(&builder.cargo_out(test_compiler, mode, target))
2588 .with_prefix(PathBuf::from(dep).file_name().and_then(|v| v.to_str()).unwrap());
2589
2590 let output_paths =
2591 run_cargo(builder, cargo, vec![], &stamp, vec![], ArtifactKeepMode::OnlyRlib);
2592 let directories = output_paths
2593 .into_iter()
2594 .filter_map(|p| p.parent().map(ToOwned::to_owned))
2595 .fold(HashSet::new(), |mut set, dir| {
2596 set.insert(dir);
2597 set
2598 });
2599
2600 lib_paths.extend(directories);
2601 }
2602 lib_paths
2603 } else {
2604 vec![]
2605 };
2606
2607 if !libs.is_empty() {
2608 let paths = libs
2609 .into_iter()
2610 .map(|path| path.into_os_string())
2611 .collect::<Vec<OsString>>()
2612 .join(OsStr::new(","));
2613 rustbook_cmd.args([OsString::from("--library-path"), paths]);
2614 }
2615
2616 builder.add_rust_test_threads(&mut rustbook_cmd);
2617 let _guard = builder.msg_test(
2618 format_args!("mdbook {}", self.path.display()),
2619 test_compiler.host,
2620 test_compiler.stage,
2621 );
2622 let _time = helpers::timeit(builder);
2623 let toolstate = if rustbook_cmd.delay_failure().run(builder) {
2624 ToolState::TestPass
2625 } else {
2626 ToolState::TestFail
2627 };
2628 builder.save_toolstate(self.name, toolstate);
2629 }
2630
2631 fn run_local_doc(self, builder: &Builder<'_>) {
2633 let test_compiler = self.test_compiler;
2634 let host = self.test_compiler.host;
2635
2636 builder.std(test_compiler, host);
2637
2638 let _guard = builder.msg_test(
2639 format!("book {}", self.name),
2640 test_compiler.host,
2641 test_compiler.stage,
2642 );
2643
2644 let mut stack = vec![builder.src.join(self.path)];
2647 let _time = helpers::timeit(builder);
2648 let mut files = Vec::new();
2649 while let Some(p) = stack.pop() {
2650 if p.is_dir() {
2651 stack.extend(t!(p.read_dir()).map(|p| t!(p).path()));
2652 continue;
2653 }
2654
2655 if p.extension().and_then(|s| s.to_str()) != Some("md") {
2656 continue;
2657 }
2658
2659 files.push(p);
2660 }
2661
2662 files.sort();
2663
2664 for file in files {
2665 markdown_test(builder, test_compiler, &file);
2666 }
2667 }
2668}
2669
2670macro_rules! test_book {
2671 ($(
2672 $name:ident, $path:expr, $book_name:expr,
2673 default=$default:expr
2674 $(,submodules = $submodules:expr)?
2675 $(,dependencies=$dependencies:expr)?
2676 ;
2677 )+) => {
2678 $(
2679 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
2680 pub struct $name {
2681 test_compiler: Compiler,
2682 }
2683
2684 impl Step for $name {
2685 type Output = ();
2686 const IS_HOST: bool = true;
2687
2688 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2689 run.path($path)
2690 }
2691
2692 fn is_default_step(_builder: &Builder<'_>) -> bool {
2693 const { $default }
2694 }
2695
2696 fn make_run(run: RunConfig<'_>) {
2697 run.builder.ensure($name {
2698 test_compiler: run.builder.compiler(run.builder.top_stage, run.target),
2699 });
2700 }
2701
2702 fn run(self, builder: &Builder<'_>) {
2703 $(
2704 for submodule in $submodules {
2705 builder.require_submodule(submodule, None);
2706 }
2707 )*
2708
2709 let dependencies = vec![];
2710 $(
2711 let mut dependencies = dependencies;
2712 for dep in $dependencies {
2713 dependencies.push(dep);
2714 }
2715 )?
2716
2717 builder.ensure(BookTest {
2718 test_compiler: self.test_compiler,
2719 path: PathBuf::from($path),
2720 name: $book_name,
2721 is_ext_doc: !$default,
2722 dependencies,
2723 });
2724 }
2725 }
2726 )+
2727 }
2728}
2729
2730test_book!(
2731 Nomicon, "src/doc/nomicon", "nomicon", default=false, submodules=["src/doc/nomicon"];
2732 Reference, "src/doc/reference", "reference", default=false, submodules=["src/doc/reference"];
2733 RustdocBook, "src/doc/rustdoc", "rustdoc", default=true;
2734 RustcBook, "src/doc/rustc", "rustc", default=true;
2735 RustByExample, "src/doc/rust-by-example", "rust-by-example", default=false, submodules=["src/doc/rust-by-example"];
2736 EmbeddedBook, "src/doc/embedded-book", "embedded-book", default=false, submodules=["src/doc/embedded-book"];
2737 TheBook, "src/doc/book", "book", default=false, submodules=["src/doc/book"], dependencies=["src/doc/book/packages/trpl"];
2738 UnstableBook, "src/doc/unstable-book", "unstable-book", default=true;
2739 EditionGuide, "src/doc/edition-guide", "edition-guide", default=false, submodules=["src/doc/edition-guide"];
2740);
2741
2742#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2743pub struct ErrorIndex {
2744 compilers: RustcPrivateCompilers,
2745}
2746
2747impl Step for ErrorIndex {
2748 type Output = ();
2749 const IS_HOST: bool = true;
2750
2751 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2752 run.path("src/tools/error_index_generator").alias("error-index")
2755 }
2756
2757 fn is_default_step(_builder: &Builder<'_>) -> bool {
2758 true
2759 }
2760
2761 fn make_run(run: RunConfig<'_>) {
2762 let compilers = RustcPrivateCompilers::new(
2766 run.builder,
2767 run.builder.top_stage,
2768 run.builder.config.host_target,
2769 );
2770 run.builder.ensure(ErrorIndex { compilers });
2771 }
2772
2773 fn run(self, builder: &Builder<'_>) {
2780 let target_compiler = self.compilers.target_compiler();
2782
2783 let dir = testdir(builder, target_compiler.host);
2784 t!(fs::create_dir_all(&dir));
2785 let output = dir.join("error-index.md");
2786
2787 let mut tool = tool::ErrorIndex::command(builder, self.compilers);
2788 tool.arg("markdown").arg(&output);
2789
2790 let guard = builder.msg_test("error-index", target_compiler.host, target_compiler.stage);
2791 let _time = helpers::timeit(builder);
2792 tool.run_capture(builder);
2793 drop(guard);
2794 builder.std(target_compiler, target_compiler.host);
2797 markdown_test(builder, target_compiler, &output);
2798 }
2799}
2800
2801fn markdown_test(builder: &Builder<'_>, compiler: Compiler, markdown: &Path) -> bool {
2802 if let Ok(contents) = fs::read_to_string(markdown)
2803 && !contents.contains("```")
2804 {
2805 return true;
2806 }
2807
2808 builder.do_if_verbose(|| println!("doc tests for: {}", markdown.display()));
2809 let mut cmd = builder.rustdoc_cmd(compiler);
2810 builder.add_rust_test_threads(&mut cmd);
2811 cmd.arg("-Z");
2813 cmd.arg("unstable-options");
2814 cmd.arg("--test");
2815 cmd.arg(markdown);
2816 cmd.env("RUSTC_BOOTSTRAP", "1");
2817
2818 let test_args = builder.config.test_args().join(" ");
2819 cmd.arg("--test-args").arg(test_args);
2820
2821 cmd = cmd.delay_failure();
2822 if !builder.config.verbose_tests {
2823 cmd.run_capture(builder).is_success()
2824 } else {
2825 cmd.run(builder)
2826 }
2827}
2828
2829#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2834pub struct CrateLibrustc {
2835 build_compiler: Compiler,
2837 target: TargetSelection,
2838 crates: Vec<String>,
2839}
2840
2841impl Step for CrateLibrustc {
2842 type Output = ();
2843 const IS_HOST: bool = true;
2844
2845 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2846 run.crate_or_deps("rustc-main").path("compiler")
2847 }
2848
2849 fn is_default_step(_builder: &Builder<'_>) -> bool {
2850 true
2851 }
2852
2853 fn make_run(run: RunConfig<'_>) {
2854 let builder = run.builder;
2855 let host = run.build_triple();
2856 let build_compiler = builder.compiler(builder.top_stage - 1, host);
2857 let crates = run.make_run_crates(Alias::Compiler);
2858
2859 builder.ensure(CrateLibrustc { build_compiler, target: run.target, crates });
2860 }
2861
2862 fn run(self, builder: &Builder<'_>) {
2863 builder.std(self.build_compiler, self.target);
2864
2865 builder.ensure(Crate {
2867 build_compiler: self.build_compiler,
2868 target: self.target,
2869 mode: Mode::Rustc,
2870 crates: self.crates,
2871 });
2872 }
2873
2874 fn metadata(&self) -> Option<StepMetadata> {
2875 Some(StepMetadata::test("CrateLibrustc", self.target).built_by(self.build_compiler))
2876 }
2877}
2878
2879fn run_cargo_test<'a>(
2883 cargo: builder::Cargo,
2884 libtest_args: &[&str],
2885 crates: &[String],
2886 description: impl Into<Option<&'a str>>,
2887 target: TargetSelection,
2888 builder: &Builder<'_>,
2889) -> bool {
2890 let compiler = cargo.compiler();
2891 let stage = match cargo.mode() {
2892 Mode::Std => compiler.stage,
2893 _ => compiler.stage + 1,
2894 };
2895
2896 let mut cargo = prepare_cargo_test(cargo, libtest_args, crates, target, builder);
2897 let _time = helpers::timeit(builder);
2898
2899 let _group = description.into().and_then(|what| builder.msg_test(what, target, stage));
2900
2901 #[cfg(feature = "build-metrics")]
2902 builder.metrics.begin_test_suite(
2903 build_helper::metrics::TestSuiteMetadata::CargoPackage {
2904 crates: crates.iter().map(|c| c.to_string()).collect(),
2905 target: target.triple.to_string(),
2906 host: compiler.host.triple.to_string(),
2907 stage: compiler.stage,
2908 },
2909 builder,
2910 );
2911 add_flags_and_try_run_tests(builder, &mut cargo)
2912}
2913
2914fn prepare_cargo_test(
2916 cargo: builder::Cargo,
2917 libtest_args: &[&str],
2918 crates: &[String],
2919 target: TargetSelection,
2920 builder: &Builder<'_>,
2921) -> BootstrapCommand {
2922 let compiler = cargo.compiler();
2923 let mut cargo: BootstrapCommand = cargo.into();
2924
2925 if builder.config.cmd.bless() && !cargo.get_envs().any(|v| v.0 == "RUSTC_BLESS") {
2929 cargo.env("RUSTC_BLESS", "Gesundheit");
2930 }
2931
2932 if builder.kind == Kind::Test && !builder.fail_fast {
2936 cargo.arg("--no-fail-fast");
2937 }
2938
2939 if builder.config.json_output {
2940 cargo.arg("--message-format=json");
2941 }
2942
2943 match builder.doc_tests {
2944 DocTests::Only => {
2945 cargo.arg("--doc");
2946 }
2947 DocTests::No => {
2948 cargo.args(["--bins", "--examples", "--tests", "--benches"]);
2949 }
2950 DocTests::Yes => {}
2951 }
2952
2953 for krate in crates {
2954 cargo.arg("-p").arg(krate);
2955 }
2956
2957 cargo.arg("--").args(builder.config.test_args()).args(libtest_args);
2958 if !builder.config.verbose_tests {
2959 cargo.arg("--quiet");
2960 }
2961
2962 if builder.kind != Kind::Miri {
2971 let mut dylib_paths = builder.rustc_lib_paths(compiler);
2972 dylib_paths.push(builder.sysroot_target_libdir(compiler, target));
2973 helpers::add_dylib_path(dylib_paths, &mut cargo);
2974 }
2975
2976 if builder.remote_tested(target) {
2977 cargo.env(
2978 format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)),
2979 format!("{} run 0", builder.tool_exe(Tool::RemoteTestClient).display()),
2980 );
2981 } else if let Some(tool) = builder.runner(target) {
2982 cargo.env(format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)), tool);
2983 }
2984
2985 cargo
2986}
2987
2988#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2996pub struct Crate {
2997 build_compiler: Compiler,
2999 target: TargetSelection,
3000 mode: Mode,
3001 crates: Vec<String>,
3002}
3003
3004impl Step for Crate {
3005 type Output = ();
3006
3007 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3008 run.crate_or_deps("sysroot").crate_or_deps("coretests").crate_or_deps("alloctests")
3009 }
3010
3011 fn is_default_step(_builder: &Builder<'_>) -> bool {
3012 true
3013 }
3014
3015 fn make_run(run: RunConfig<'_>) {
3016 let builder = run.builder;
3017 let host = run.build_triple();
3018 let build_compiler = builder.compiler(builder.top_stage, host);
3019 let crates = run
3020 .paths
3021 .iter()
3022 .map(|p| builder.crate_paths[&p.assert_single_path().path].clone())
3023 .collect();
3024
3025 builder.ensure(Crate { build_compiler, target: run.target, mode: Mode::Std, crates });
3026 }
3027
3028 fn run(self, builder: &Builder<'_>) {
3037 let build_compiler = self.build_compiler;
3038 let target = self.target;
3039 let mode = self.mode;
3040
3041 builder.ensure(Std::new(build_compiler, build_compiler.host).force_recompile(true));
3044
3045 let mut cargo = if builder.kind == Kind::Miri {
3046 if builder.top_stage == 0 {
3047 eprintln!("ERROR: `x.py miri` requires stage 1 or higher");
3048 std::process::exit(1);
3049 }
3050
3051 let mut cargo = builder::Cargo::new(
3054 builder,
3055 build_compiler,
3056 mode,
3057 SourceType::InTree,
3058 target,
3059 Kind::MiriTest,
3060 );
3061 cargo.env("MIRI_REPLACE_LIBRS_IF_NOT_TEST", "1");
3073 cargo.rustflag("-Zforce-unstable-if-unmarked");
3077 cargo
3078 } else {
3079 if !builder.config.is_host_target(target) {
3081 builder.ensure(compile::Std::new(build_compiler, target).force_recompile(true));
3082 builder.ensure(RemoteCopyLibs { build_compiler, target });
3083 }
3084
3085 builder::Cargo::new(
3087 builder,
3088 build_compiler,
3089 mode,
3090 SourceType::InTree,
3091 target,
3092 builder.kind,
3093 )
3094 };
3095
3096 match mode {
3097 Mode::Std => {
3098 if builder.kind == Kind::Miri {
3099 cargo
3105 .arg("--manifest-path")
3106 .arg(builder.src.join("library/sysroot/Cargo.toml"));
3107 } else {
3108 compile::std_cargo(builder, target, &mut cargo, &[]);
3109 }
3110 }
3111 Mode::Rustc => {
3112 compile::rustc_cargo(builder, &mut cargo, target, &build_compiler, &self.crates);
3113 }
3114 _ => panic!("can only test libraries"),
3115 };
3116
3117 let mut crates = self.crates.clone();
3118 if crates.iter().any(|crate_| crate_ == "core") {
3123 crates.push("coretests".to_owned());
3124 }
3125 if crates.iter().any(|crate_| crate_ == "alloc") {
3126 crates.push("alloctests".to_owned());
3127 }
3128
3129 run_cargo_test(cargo, &[], &crates, &*crate_description(&self.crates), target, builder);
3130 }
3131}
3132
3133#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3136pub struct CrateRustdoc {
3137 host: TargetSelection,
3138}
3139
3140impl Step for CrateRustdoc {
3141 type Output = ();
3142 const IS_HOST: bool = true;
3143
3144 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3145 run.paths(&["src/librustdoc", "src/tools/rustdoc"])
3146 }
3147
3148 fn is_default_step(_builder: &Builder<'_>) -> bool {
3149 true
3150 }
3151
3152 fn make_run(run: RunConfig<'_>) {
3153 let builder = run.builder;
3154
3155 builder.ensure(CrateRustdoc { host: run.target });
3156 }
3157
3158 fn run(self, builder: &Builder<'_>) {
3159 let target = self.host;
3160
3161 let compiler = if builder.download_rustc() {
3162 builder.compiler(builder.top_stage, target)
3163 } else {
3164 builder.compiler_for(builder.top_stage, target, target)
3169 };
3170 builder.std(compiler, target);
3175 builder.ensure(compile::Rustc::new(compiler, target));
3176
3177 let mut cargo = tool::prepare_tool_cargo(
3178 builder,
3179 compiler,
3180 Mode::ToolRustcPrivate,
3181 target,
3182 builder.kind,
3183 "src/tools/rustdoc",
3184 SourceType::InTree,
3185 &[],
3186 );
3187 if self.host.contains("musl") {
3188 cargo.arg("'-Ctarget-feature=-crt-static'");
3189 }
3190
3191 let libdir = if builder.download_rustc() {
3218 builder.rustc_libdir(compiler)
3219 } else {
3220 builder.sysroot_target_libdir(compiler, target).to_path_buf()
3221 };
3222 let mut dylib_path = dylib_path();
3223 dylib_path.insert(0, PathBuf::from(&*libdir));
3224 cargo.env(dylib_path_var(), env::join_paths(&dylib_path).unwrap());
3225
3226 run_cargo_test(cargo, &[], &["rustdoc:0.0.0".to_string()], "rustdoc", target, builder);
3227 }
3228}
3229
3230#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3231pub struct CrateRustdocJsonTypes {
3232 build_compiler: Compiler,
3233 target: TargetSelection,
3234}
3235
3236impl Step for CrateRustdocJsonTypes {
3237 type Output = ();
3238 const IS_HOST: bool = true;
3239
3240 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3241 run.path("src/rustdoc-json-types")
3242 }
3243
3244 fn is_default_step(_builder: &Builder<'_>) -> bool {
3245 true
3246 }
3247
3248 fn make_run(run: RunConfig<'_>) {
3249 let builder = run.builder;
3250
3251 builder.ensure(CrateRustdocJsonTypes {
3252 build_compiler: get_tool_target_compiler(
3253 builder,
3254 ToolTargetBuildMode::Build(run.target),
3255 ),
3256 target: run.target,
3257 });
3258 }
3259
3260 fn run(self, builder: &Builder<'_>) {
3261 let target = self.target;
3262
3263 let cargo = tool::prepare_tool_cargo(
3264 builder,
3265 self.build_compiler,
3266 Mode::ToolTarget,
3267 target,
3268 builder.kind,
3269 "src/rustdoc-json-types",
3270 SourceType::InTree,
3271 &[],
3272 );
3273
3274 let libtest_args = if target.contains("musl") {
3276 ["'-Ctarget-feature=-crt-static'"].as_slice()
3277 } else {
3278 &[]
3279 };
3280
3281 run_cargo_test(
3282 cargo,
3283 libtest_args,
3284 &["rustdoc-json-types".to_string()],
3285 "rustdoc-json-types",
3286 target,
3287 builder,
3288 );
3289 }
3290}
3291
3292#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3302pub struct RemoteCopyLibs {
3303 build_compiler: Compiler,
3304 target: TargetSelection,
3305}
3306
3307impl Step for RemoteCopyLibs {
3308 type Output = ();
3309
3310 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3311 run.never()
3312 }
3313
3314 fn run(self, builder: &Builder<'_>) {
3315 let build_compiler = self.build_compiler;
3316 let target = self.target;
3317 if !builder.remote_tested(target) {
3318 return;
3319 }
3320
3321 builder.std(build_compiler, target);
3322
3323 builder.info(&format!("REMOTE copy libs to emulator ({target})"));
3324
3325 let remote_test_server = builder.ensure(tool::RemoteTestServer { build_compiler, target });
3326
3327 let tool = builder.tool_exe(Tool::RemoteTestClient);
3329 let mut cmd = command(&tool);
3330 cmd.arg("spawn-emulator")
3331 .arg(target.triple)
3332 .arg(&remote_test_server.tool_path)
3333 .arg(builder.tempdir());
3334 if let Some(rootfs) = builder.qemu_rootfs(target) {
3335 cmd.arg(rootfs);
3336 }
3337 cmd.run(builder);
3338
3339 for f in t!(builder.sysroot_target_libdir(build_compiler, target).read_dir()) {
3341 let f = t!(f);
3342 if helpers::is_dylib(&f.path()) {
3343 command(&tool).arg("push").arg(f.path()).run(builder);
3344 }
3345 }
3346 }
3347}
3348
3349#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3350pub struct Distcheck;
3351
3352impl Step for Distcheck {
3353 type Output = ();
3354
3355 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3356 run.alias("distcheck")
3357 }
3358
3359 fn make_run(run: RunConfig<'_>) {
3360 run.builder.ensure(Distcheck);
3361 }
3362
3363 fn run(self, builder: &Builder<'_>) {
3373 let root_dir = std::env::temp_dir().join("distcheck");
3376
3377 distcheck_plain_source_tarball(builder, &root_dir.join("distcheck-rustc-src"));
3378 distcheck_rust_src(builder, &root_dir.join("distcheck-rust-src"));
3379 distcheck_rustc_dev(builder, &root_dir.join("distcheck-rustc-dev"));
3380 }
3381}
3382
3383fn distcheck_plain_source_tarball(builder: &Builder<'_>, plain_src_dir: &Path) {
3385 builder.info("Distcheck plain source tarball");
3386 let plain_src_tarball = builder.ensure(dist::PlainSourceTarball);
3387 builder.clear_dir(plain_src_dir);
3388
3389 let configure_args: Vec<String> = std::env::var("DISTCHECK_CONFIGURE_ARGS")
3390 .map(|args| args.split(" ").map(|s| s.to_string()).collect::<Vec<String>>())
3391 .unwrap_or_default();
3392
3393 command("tar")
3394 .arg("-xf")
3395 .arg(plain_src_tarball.tarball())
3396 .arg("--strip-components=1")
3397 .current_dir(plain_src_dir)
3398 .run(builder);
3399 command("./configure")
3400 .arg("--set")
3401 .arg("rust.omit-git-hash=false")
3402 .args(&configure_args)
3403 .arg("--enable-vendor")
3404 .current_dir(plain_src_dir)
3405 .run(builder);
3406 command(helpers::make(&builder.config.host_target.triple))
3407 .arg("check")
3408 .env("GITHUB_ACTIONS", "0")
3411 .current_dir(plain_src_dir)
3412 .run(builder);
3413 builder.remove_dir(plain_src_dir);
3415}
3416
3417fn distcheck_rust_src(builder: &Builder<'_>, src_dir: &Path) {
3419 builder.info("Distcheck rust-src");
3420 let src_tarball = builder.ensure(dist::Src);
3421 builder.clear_dir(src_dir);
3422
3423 command("tar")
3424 .arg("-xf")
3425 .arg(src_tarball.tarball())
3426 .arg("--strip-components=1")
3427 .current_dir(src_dir)
3428 .run(builder);
3429
3430 let toml = src_dir.join("rust-src/lib/rustlib/src/rust/library/std/Cargo.toml");
3431 command(&builder.initial_cargo)
3432 .env("RUSTC_BOOTSTRAP", "1")
3435 .arg("generate-lockfile")
3436 .arg("--manifest-path")
3437 .arg(&toml)
3438 .current_dir(src_dir)
3439 .run(builder);
3440 builder.remove_dir(src_dir);
3442}
3443
3444fn distcheck_rustc_dev(builder: &Builder<'_>, dir: &Path) {
3446 builder.info("Distcheck rustc-dev");
3447 let tarball = builder.ensure(dist::RustcDev::new(builder, builder.host_target)).unwrap();
3448 builder.clear_dir(dir);
3449
3450 command("tar")
3451 .arg("-xf")
3452 .arg(tarball.tarball())
3453 .arg("--strip-components=1")
3454 .current_dir(dir)
3455 .run(builder);
3456
3457 command(&builder.initial_cargo)
3458 .arg("metadata")
3459 .arg("--manifest-path")
3460 .arg("rustc-dev/lib/rustlib/rustc-src/rust/compiler/rustc/Cargo.toml")
3461 .env("RUSTC_BOOTSTRAP", "1")
3462 .env("RUSTC", &builder.initial_rustc)
3464 .current_dir(dir)
3465 .run(builder);
3466 builder.remove_dir(dir);
3468}
3469
3470#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3472pub(crate) struct BootstrapPy;
3473
3474impl Step for BootstrapPy {
3475 type Output = ();
3476 const IS_HOST: bool = true;
3477
3478 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3479 run.alias("bootstrap-py")
3480 }
3481
3482 fn is_default_step(builder: &Builder<'_>) -> bool {
3483 builder.config.is_running_on_ci
3487 }
3488
3489 fn make_run(run: RunConfig<'_>) {
3490 run.builder.ensure(BootstrapPy)
3491 }
3492
3493 fn run(self, builder: &Builder<'_>) -> Self::Output {
3494 let mut check_bootstrap = command(
3495 builder.config.python.as_ref().expect("python is required for running bootstrap tests"),
3496 );
3497 check_bootstrap
3498 .args(["-m", "unittest", "bootstrap_test.py"])
3499 .args(builder.config.test_args())
3501 .env("BUILD_DIR", &builder.out)
3502 .env("BUILD_PLATFORM", builder.build.host_target.triple)
3503 .env("BOOTSTRAP_TEST_RUSTC_BIN", &builder.initial_rustc)
3504 .env("BOOTSTRAP_TEST_CARGO_BIN", &builder.initial_cargo)
3505 .current_dir(builder.src.join("src/bootstrap/"));
3506 check_bootstrap.delay_failure().run(builder);
3507 }
3508}
3509
3510#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3511pub struct Bootstrap;
3512
3513impl Step for Bootstrap {
3514 type Output = ();
3515 const IS_HOST: bool = true;
3516
3517 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3518 run.path("src/bootstrap")
3519 }
3520
3521 fn is_default_step(builder: &Builder<'_>) -> bool {
3522 builder.config.is_running_on_ci
3526 }
3527
3528 fn run(self, builder: &Builder<'_>) {
3530 let host = builder.config.host_target;
3531 let build_compiler = builder.compiler(0, host);
3532
3533 builder.build.require_submodule("src/tools/cargo", None);
3535
3536 let mut cargo = tool::prepare_tool_cargo(
3537 builder,
3538 build_compiler,
3539 Mode::ToolBootstrap,
3540 host,
3541 Kind::Test,
3542 "src/bootstrap",
3543 SourceType::InTree,
3544 &[],
3545 );
3546
3547 cargo.release_build(false);
3548
3549 cargo
3550 .rustflag("-Cdebuginfo=2")
3551 .env("CARGO_TARGET_DIR", builder.out.join("bootstrap"))
3552 .env("INSTA_WORKSPACE_ROOT", &builder.src)
3554 .env("RUSTC_BOOTSTRAP", "1");
3555
3556 if builder.config.cmd.bless() {
3557 cargo.env("INSTA_UPDATE", "always");
3561 }
3562
3563 run_cargo_test(cargo, &[], &[], None, host, builder);
3564 }
3565
3566 fn make_run(run: RunConfig<'_>) {
3567 run.builder.ensure(Bootstrap);
3568 }
3569}
3570
3571fn get_compiler_to_test(builder: &Builder<'_>, target: TargetSelection) -> Compiler {
3572 builder.compiler(builder.top_stage, target)
3573}
3574
3575#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3578pub struct TierCheck {
3579 test_compiler: Compiler,
3580}
3581
3582impl Step for TierCheck {
3583 type Output = ();
3584 const IS_HOST: bool = true;
3585
3586 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3587 run.path("src/tools/tier-check")
3588 }
3589
3590 fn is_default_step(_builder: &Builder<'_>) -> bool {
3591 true
3592 }
3593
3594 fn make_run(run: RunConfig<'_>) {
3595 run.builder
3596 .ensure(TierCheck { test_compiler: get_compiler_to_test(run.builder, run.target) });
3597 }
3598
3599 fn run(self, builder: &Builder<'_>) {
3600 let tool_build_compiler = builder.compiler(0, builder.host_target);
3601
3602 let mut cargo = tool::prepare_tool_cargo(
3603 builder,
3604 tool_build_compiler,
3605 Mode::ToolBootstrap,
3606 tool_build_compiler.host,
3607 Kind::Run,
3608 "src/tools/tier-check",
3609 SourceType::InTree,
3610 &[],
3611 );
3612 cargo.arg(builder.src.join("src/doc/rustc/src/platform-support.md"));
3613 cargo.arg(builder.rustc(self.test_compiler));
3614
3615 let _guard = builder.msg_test(
3616 "platform support check",
3617 self.test_compiler.host,
3618 self.test_compiler.stage,
3619 );
3620 BootstrapCommand::from(cargo).delay_failure().run(builder);
3621 }
3622
3623 fn metadata(&self) -> Option<StepMetadata> {
3624 Some(StepMetadata::test("tier-check", self.test_compiler.host))
3625 }
3626}
3627
3628#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3629pub struct LintDocs {
3630 build_compiler: Compiler,
3631 target: TargetSelection,
3632}
3633
3634impl Step for LintDocs {
3635 type Output = ();
3636 const IS_HOST: bool = true;
3637
3638 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3639 run.path("src/tools/lint-docs")
3640 }
3641
3642 fn is_default_step(builder: &Builder<'_>) -> bool {
3643 builder.top_stage >= 2
3646 }
3647
3648 fn make_run(run: RunConfig<'_>) {
3649 if run.builder.top_stage < 2 {
3650 eprintln!("WARNING: lint-docs tests might not work below stage 2");
3651 }
3652
3653 run.builder.ensure(LintDocs {
3654 build_compiler: prepare_doc_compiler(
3655 run.builder,
3656 run.builder.config.host_target,
3657 run.builder.top_stage,
3658 ),
3659 target: run.target,
3660 });
3661 }
3662
3663 fn run(self, builder: &Builder<'_>) {
3666 builder.ensure(crate::core::build_steps::doc::RustcBook::validate(
3667 self.build_compiler,
3668 self.target,
3669 ));
3670 }
3671
3672 fn metadata(&self) -> Option<StepMetadata> {
3673 Some(StepMetadata::test("lint-docs", self.target).built_by(self.build_compiler))
3674 }
3675}
3676
3677#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3678pub struct RustInstaller;
3679
3680impl Step for RustInstaller {
3681 type Output = ();
3682 const IS_HOST: bool = true;
3683
3684 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3685 run.path("src/tools/rust-installer")
3686 }
3687
3688 fn is_default_step(_builder: &Builder<'_>) -> bool {
3689 true
3690 }
3691
3692 fn make_run(run: RunConfig<'_>) {
3693 run.builder.ensure(Self);
3694 }
3695
3696 fn run(self, builder: &Builder<'_>) {
3698 let bootstrap_host = builder.config.host_target;
3699 let build_compiler = builder.compiler(0, bootstrap_host);
3700 let cargo = tool::prepare_tool_cargo(
3701 builder,
3702 build_compiler,
3703 Mode::ToolBootstrap,
3704 bootstrap_host,
3705 Kind::Test,
3706 "src/tools/rust-installer",
3707 SourceType::InTree,
3708 &[],
3709 );
3710
3711 let _guard = builder.msg_test("rust-installer", bootstrap_host, 1);
3712 run_cargo_test(cargo, &[], &[], None, bootstrap_host, builder);
3713
3714 if bootstrap_host != "x86_64-unknown-linux-gnu" {
3718 return;
3719 }
3720
3721 let mut cmd = command(builder.src.join("src/tools/rust-installer/test.sh"));
3722 let tmpdir = testdir(builder, build_compiler.host).join("rust-installer");
3723 let _ = std::fs::remove_dir_all(&tmpdir);
3724 let _ = std::fs::create_dir_all(&tmpdir);
3725 cmd.current_dir(&tmpdir);
3726 cmd.env("CARGO_TARGET_DIR", tmpdir.join("cargo-target"));
3727 cmd.env("CARGO", &builder.initial_cargo);
3728 cmd.env("RUSTC", &builder.initial_rustc);
3729 cmd.env("TMP_DIR", &tmpdir);
3730 cmd.delay_failure().run(builder);
3731 }
3732}
3733
3734#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3735pub struct TestHelpers {
3736 pub target: TargetSelection,
3737}
3738
3739impl Step for TestHelpers {
3740 type Output = ();
3741
3742 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3743 run.path("tests/auxiliary/rust_test_helpers.c")
3744 }
3745
3746 fn make_run(run: RunConfig<'_>) {
3747 run.builder.ensure(TestHelpers { target: run.target })
3748 }
3749
3750 fn run(self, builder: &Builder<'_>) {
3753 if builder.config.dry_run() {
3754 return;
3755 }
3756 let target = if self.target == "x86_64-fortanix-unknown-sgx" {
3760 TargetSelection::from_user("x86_64-unknown-linux-gnu")
3761 } else {
3762 self.target
3763 };
3764 let dst = builder.test_helpers_out(target);
3765 let src = builder.src.join("tests/auxiliary/rust_test_helpers.c");
3766 if up_to_date(&src, &dst.join("librust_test_helpers.a")) {
3767 return;
3768 }
3769
3770 let _guard = builder.msg_unstaged(Kind::Build, "test helpers", target);
3771 t!(fs::create_dir_all(&dst));
3772 let mut cfg = cc::Build::new();
3773
3774 if !target.is_msvc() {
3778 if let Some(ar) = builder.ar(target) {
3779 cfg.archiver(ar);
3780 }
3781 cfg.compiler(builder.cc(target));
3782 }
3783 cfg.cargo_metadata(false)
3784 .out_dir(&dst)
3785 .target(&target.triple)
3786 .host(&builder.config.host_target.triple)
3787 .opt_level(0)
3788 .warnings(false)
3789 .debug(false)
3790 .file(builder.src.join("tests/auxiliary/rust_test_helpers.c"))
3791 .compile("rust_test_helpers");
3792 }
3793}
3794
3795#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3796pub struct CodegenCranelift {
3797 compilers: RustcPrivateCompilers,
3798 target: TargetSelection,
3799}
3800
3801impl Step for CodegenCranelift {
3802 type Output = ();
3803 const IS_HOST: bool = true;
3804
3805 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3806 run.paths(&["compiler/rustc_codegen_cranelift"])
3807 }
3808
3809 fn is_default_step(_builder: &Builder<'_>) -> bool {
3810 true
3811 }
3812
3813 fn make_run(run: RunConfig<'_>) {
3814 let builder = run.builder;
3815 let host = run.build_triple();
3816 let compilers = RustcPrivateCompilers::new(run.builder, run.builder.top_stage, host);
3817
3818 if builder.doc_tests == DocTests::Only {
3819 return;
3820 }
3821
3822 if builder.download_rustc() {
3823 builder.info("CI rustc uses the default codegen backend. skipping");
3824 return;
3825 }
3826
3827 if !target_supports_cranelift_backend(run.target) {
3828 builder.info("target not supported by rustc_codegen_cranelift. skipping");
3829 return;
3830 }
3831
3832 if builder.remote_tested(run.target) {
3833 builder.info("remote testing is not supported by rustc_codegen_cranelift. skipping");
3834 return;
3835 }
3836
3837 if !builder
3838 .config
3839 .enabled_codegen_backends(run.target)
3840 .contains(&CodegenBackendKind::Cranelift)
3841 {
3842 builder.info("cranelift not in rust.codegen-backends. skipping");
3843 return;
3844 }
3845
3846 builder.ensure(CodegenCranelift { compilers, target: run.target });
3847 }
3848
3849 fn run(self, builder: &Builder<'_>) {
3850 let compilers = self.compilers;
3851 let build_compiler = compilers.build_compiler();
3852
3853 let target_compiler = compilers.target_compiler();
3856 let target = self.target;
3857
3858 builder.std(target_compiler, target);
3859
3860 let mut cargo = builder::Cargo::new(
3861 builder,
3862 target_compiler,
3863 Mode::Codegen, SourceType::InTree,
3865 target,
3866 Kind::Run,
3867 );
3868
3869 cargo.current_dir(&builder.src.join("compiler/rustc_codegen_cranelift"));
3870 cargo
3871 .arg("--manifest-path")
3872 .arg(builder.src.join("compiler/rustc_codegen_cranelift/build_system/Cargo.toml"));
3873 compile::rustc_cargo_env(builder, &mut cargo, target);
3874
3875 cargo.env("CARGO_BUILD_INCREMENTAL", "false");
3877
3878 let _guard = builder.msg_test(
3879 "rustc_codegen_cranelift",
3880 target_compiler.host,
3881 target_compiler.stage,
3882 );
3883
3884 let download_dir = builder.out.join("cg_clif_download");
3886
3887 cargo
3888 .arg("--")
3889 .arg("test")
3890 .arg("--download-dir")
3891 .arg(&download_dir)
3892 .arg("--out-dir")
3893 .arg(builder.stage_out(build_compiler, Mode::Codegen).join("cg_clif"))
3894 .arg("--no-unstable-features")
3895 .arg("--use-backend")
3896 .arg("cranelift")
3897 .arg("--sysroot")
3899 .arg("llvm")
3900 .arg("--skip-test")
3903 .arg("testsuite.extended_sysroot");
3904
3905 cargo.into_cmd().run(builder);
3906 }
3907
3908 fn metadata(&self) -> Option<StepMetadata> {
3909 Some(
3910 StepMetadata::test("rustc_codegen_cranelift", self.target)
3911 .built_by(self.compilers.build_compiler()),
3912 )
3913 }
3914}
3915
3916#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3917pub struct CodegenGCC {
3918 compilers: RustcPrivateCompilers,
3919 target: TargetSelection,
3920}
3921
3922impl Step for CodegenGCC {
3923 type Output = ();
3924 const IS_HOST: bool = true;
3925
3926 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3927 run.paths(&["compiler/rustc_codegen_gcc"])
3928 }
3929
3930 fn is_default_step(_builder: &Builder<'_>) -> bool {
3931 true
3932 }
3933
3934 fn make_run(run: RunConfig<'_>) {
3935 let builder = run.builder;
3936 let host = run.build_triple();
3937 let compilers = RustcPrivateCompilers::new(run.builder, run.builder.top_stage, host);
3938
3939 if builder.doc_tests == DocTests::Only {
3940 return;
3941 }
3942
3943 if builder.download_rustc() {
3944 builder.info("CI rustc uses the default codegen backend. skipping");
3945 return;
3946 }
3947
3948 let triple = run.target.triple;
3949 let target_supported =
3950 if triple.contains("linux") { triple.contains("x86_64") } else { false };
3951 if !target_supported {
3952 builder.info("target not supported by rustc_codegen_gcc. skipping");
3953 return;
3954 }
3955
3956 if builder.remote_tested(run.target) {
3957 builder.info("remote testing is not supported by rustc_codegen_gcc. skipping");
3958 return;
3959 }
3960
3961 if !builder.config.enabled_codegen_backends(run.target).contains(&CodegenBackendKind::Gcc) {
3962 builder.info("gcc not in rust.codegen-backends. skipping");
3963 return;
3964 }
3965
3966 builder.ensure(CodegenGCC { compilers, target: run.target });
3967 }
3968
3969 fn run(self, builder: &Builder<'_>) {
3970 let compilers = self.compilers;
3971 let target = self.target;
3972
3973 let gcc = builder.ensure(Gcc { target_pair: GccTargetPair::for_native_build(target) });
3974
3975 builder.ensure(
3976 compile::Std::new(compilers.build_compiler(), target)
3977 .extra_rust_args(&["-Csymbol-mangling-version=v0", "-Cpanic=abort"]),
3978 );
3979
3980 let _guard = builder.msg_test(
3981 "rustc_codegen_gcc",
3982 compilers.target(),
3983 compilers.target_compiler().stage,
3984 );
3985
3986 let mut cargo = builder::Cargo::new(
3987 builder,
3988 compilers.build_compiler(),
3989 Mode::Codegen, SourceType::InTree,
3991 target,
3992 Kind::Run,
3993 );
3994
3995 cargo.current_dir(&builder.src.join("compiler/rustc_codegen_gcc"));
3996 cargo
3997 .arg("--manifest-path")
3998 .arg(builder.src.join("compiler/rustc_codegen_gcc/build_system/Cargo.toml"));
3999 compile::rustc_cargo_env(builder, &mut cargo, target);
4000 add_cg_gcc_cargo_flags(&mut cargo, &gcc);
4001
4002 cargo.env("CARGO_BUILD_INCREMENTAL", "false");
4004 cargo.rustflag("-Cpanic=abort");
4005
4006 cargo
4007 .env("CG_RUSTFLAGS", "-Alinker-messages")
4009 .arg("--")
4010 .arg("test")
4011 .arg("--use-backend")
4012 .arg("gcc")
4013 .arg("--gcc-path")
4014 .arg(gcc.libgccjit().parent().unwrap())
4015 .arg("--out-dir")
4016 .arg(builder.stage_out(compilers.build_compiler(), Mode::Codegen).join("cg_gcc"))
4017 .arg("--release")
4018 .arg("--mini-tests")
4019 .arg("--std-tests");
4020
4021 cargo.args(builder.config.test_args());
4022
4023 cargo.into_cmd().run(builder);
4024 }
4025
4026 fn metadata(&self) -> Option<StepMetadata> {
4027 Some(
4028 StepMetadata::test("rustc_codegen_gcc", self.target)
4029 .built_by(self.compilers.build_compiler()),
4030 )
4031 }
4032}
4033
4034#[derive(Debug, Clone, PartialEq, Eq, Hash)]
4039pub struct TestFloatParse {
4040 build_compiler: Compiler,
4049 target: TargetSelection,
4051}
4052
4053impl Step for TestFloatParse {
4054 type Output = ();
4055 const IS_HOST: bool = true;
4056
4057 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
4058 run.path("src/tools/test-float-parse")
4059 }
4060
4061 fn is_default_step(_builder: &Builder<'_>) -> bool {
4062 true
4063 }
4064
4065 fn make_run(run: RunConfig<'_>) {
4066 run.builder.ensure(Self {
4067 build_compiler: get_compiler_to_test(run.builder, run.target),
4068 target: run.target,
4069 });
4070 }
4071
4072 fn run(self, builder: &Builder<'_>) {
4073 let build_compiler = self.build_compiler;
4074 let target = self.target;
4075
4076 builder.std(build_compiler, target);
4078 builder.std(build_compiler, builder.host_target);
4079
4080 let mut cargo_test = tool::prepare_tool_cargo(
4082 builder,
4083 build_compiler,
4084 Mode::ToolStd,
4085 target,
4086 Kind::Test,
4087 "src/tools/test-float-parse",
4088 SourceType::InTree,
4089 &[],
4090 );
4091 cargo_test.allow_features(TEST_FLOAT_PARSE_ALLOW_FEATURES);
4092
4093 run_cargo_test(cargo_test, &[], &[], "test-float-parse", target, builder);
4094
4095 let mut cargo_run = tool::prepare_tool_cargo(
4097 builder,
4098 build_compiler,
4099 Mode::ToolStd,
4100 target,
4101 Kind::Run,
4102 "src/tools/test-float-parse",
4103 SourceType::InTree,
4104 &[],
4105 );
4106 cargo_run.allow_features(TEST_FLOAT_PARSE_ALLOW_FEATURES);
4107
4108 if !matches!(env::var("FLOAT_PARSE_TESTS_NO_SKIP_HUGE").as_deref(), Ok("1") | Ok("true")) {
4109 cargo_run.args(["--", "--skip-huge"]);
4110 }
4111
4112 cargo_run.into_cmd().run(builder);
4113 }
4114}
4115
4116#[derive(Debug, Clone, Hash, PartialEq, Eq)]
4120pub struct CollectLicenseMetadata;
4121
4122impl Step for CollectLicenseMetadata {
4123 type Output = PathBuf;
4124 const IS_HOST: bool = true;
4125
4126 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
4127 run.path("src/tools/collect-license-metadata")
4128 }
4129
4130 fn make_run(run: RunConfig<'_>) {
4131 run.builder.ensure(CollectLicenseMetadata);
4132 }
4133
4134 fn run(self, builder: &Builder<'_>) -> Self::Output {
4135 let Some(reuse) = &builder.config.reuse else {
4136 panic!("REUSE is required to collect the license metadata");
4137 };
4138
4139 let dest = builder.src.join("license-metadata.json");
4140
4141 let mut cmd = builder.tool_cmd(Tool::CollectLicenseMetadata);
4142 cmd.env("REUSE_EXE", reuse);
4143 cmd.env("DEST", &dest);
4144 cmd.env("ONLY_CHECK", "1");
4145 cmd.run(builder);
4146
4147 dest
4148 }
4149}
4150
4151#[derive(Debug, Clone, PartialEq, Eq, Hash)]
4152pub struct RemoteTestClientTests {
4153 host: TargetSelection,
4154}
4155
4156impl Step for RemoteTestClientTests {
4157 type Output = ();
4158 const IS_HOST: bool = true;
4159
4160 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
4161 run.path("src/tools/remote-test-client")
4162 }
4163
4164 fn is_default_step(_builder: &Builder<'_>) -> bool {
4165 true
4166 }
4167
4168 fn make_run(run: RunConfig<'_>) {
4169 run.builder.ensure(Self { host: run.target });
4170 }
4171
4172 fn run(self, builder: &Builder<'_>) {
4173 let bootstrap_host = builder.config.host_target;
4174 let compiler = builder.compiler(0, bootstrap_host);
4175
4176 let cargo = tool::prepare_tool_cargo(
4177 builder,
4178 compiler,
4179 Mode::ToolBootstrap,
4180 bootstrap_host,
4181 Kind::Test,
4182 "src/tools/remote-test-client",
4183 SourceType::InTree,
4184 &[],
4185 );
4186
4187 run_cargo_test(cargo, &[], &[], "remote-test-client", bootstrap_host, builder);
4188 }
4189}