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