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