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