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