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::test::failed_tests::{RecordFailedTests, SetupFailedTestsFile};
25use crate::core::build_steps::tool::{
26 self, RustcPrivateCompilers, SourceType, TEST_FLOAT_PARSE_ALLOW_FEATURES, Tool,
27 ToolTargetBuildMode, get_tool_target_compiler,
28};
29use crate::core::build_steps::toolstate::ToolState;
30use crate::core::build_steps::{compile, dist, llvm};
31use crate::core::builder::{
32 self, Alias, Builder, Compiler, Kind, RunConfig, ShouldRun, Step, StepMetadata,
33 crate_description,
34};
35use crate::core::config::TargetSelection;
36use crate::core::config::flags::{Subcommand, get_completion, top_level_help};
37use crate::core::{android, debuggers};
38use crate::utils::build_stamp::{self, BuildStamp};
39use crate::utils::exec::{BootstrapCommand, command};
40use crate::utils::helpers::{
41 self, LldThreads, TestFilterCategory, add_dylib_path, add_rustdoc_cargo_linker_args,
42 dylib_path, dylib_path_var, linker_args, linker_flags, t, target_supports_cranelift_backend,
43 up_to_date,
44};
45use crate::utils::render_tests::{add_flags_and_try_run_tests, try_run_tests};
46use crate::{CLang, CodegenBackendKind, GitRepo, Mode, PathSet, TestTarget, envify};
47
48mod compiletest;
49pub mod failed_tests;
50
51#[derive(Debug, Clone, PartialEq, Eq, Hash)]
53pub struct CrateBootstrap {
54 path: PathBuf,
55 host: TargetSelection,
56}
57
58impl Step for CrateBootstrap {
59 type Output = ();
60 const IS_HOST: bool = true;
61
62 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
63 run.path("src/tools/jsondoclint")
68 .path("src/tools/replace-version-placeholder")
69 .path("src/tools/coverage-dump")
70 .alias("tidyselftest")
73 }
74
75 fn is_default_step(_builder: &Builder<'_>) -> bool {
76 true
77 }
78
79 fn make_run(run: RunConfig<'_>) {
80 for path in run.paths {
83 let path = path.assert_single_path().path.clone();
84 run.builder.ensure(CrateBootstrap { host: run.target, path });
85 }
86 }
87
88 fn run(self, builder: &Builder<'_>) {
89 let bootstrap_host = builder.config.host_target;
90 let compiler = builder.compiler(0, bootstrap_host);
91 let record_failed_tests = builder.ensure(SetupFailedTestsFile);
92 let mut path = self.path.to_str().unwrap();
93
94 if path == "tidyselftest" {
96 path = "src/tools/tidy";
97 }
98
99 let cargo = tool::prepare_tool_cargo(
100 builder,
101 compiler,
102 Mode::ToolBootstrap,
103 bootstrap_host,
104 Kind::Test,
105 path,
106 SourceType::InTree,
107 &[],
108 );
109
110 let crate_name = path.rsplit_once('/').unwrap().1;
111 run_cargo_test(cargo, &[], &[], crate_name, bootstrap_host, builder, record_failed_tests);
112 }
113
114 fn metadata(&self) -> Option<StepMetadata> {
115 Some(
116 StepMetadata::test("crate-bootstrap", self.host)
117 .with_metadata(self.path.as_path().to_string_lossy().to_string()),
118 )
119 }
120}
121
122#[derive(Debug, Clone, PartialEq, Eq, Hash)]
123pub struct Linkcheck {
124 host: TargetSelection,
125}
126
127impl Step for Linkcheck {
128 type Output = ();
129 const IS_HOST: bool = true;
130
131 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
132 run.path("src/tools/linkchecker")
133 }
134
135 fn is_default_step(builder: &Builder<'_>) -> bool {
136 builder.config.docs
137 }
138
139 fn make_run(run: RunConfig<'_>) {
140 run.builder.ensure(Linkcheck { host: run.target });
141 }
142
143 fn run(self, builder: &Builder<'_>) {
148 let host = self.host;
149 let hosts = &builder.hosts;
150 let targets = &builder.targets;
151
152 if (hosts != targets) && !hosts.is_empty() && !targets.is_empty() {
157 panic!(
158 "Linkcheck currently does not support builds with different hosts and targets.
159You can skip linkcheck with --skip src/tools/linkchecker"
160 );
161 }
162
163 builder.info(&format!("Linkcheck ({host})"));
164
165 let bootstrap_host = builder.config.host_target;
167 let compiler = builder.compiler(0, bootstrap_host);
168 let record_failed_tests = builder.ensure(SetupFailedTestsFile);
169
170 let cargo = tool::prepare_tool_cargo(
171 builder,
172 compiler,
173 Mode::ToolBootstrap,
174 bootstrap_host,
175 Kind::Test,
176 "src/tools/linkchecker",
177 SourceType::InTree,
178 &[],
179 );
180 run_cargo_test(
181 cargo,
182 &[],
183 &[],
184 "linkchecker self tests",
185 bootstrap_host,
186 builder,
187 record_failed_tests,
188 );
189
190 if !builder.test_target.runs_doctests() {
191 return;
192 }
193
194 builder.run_default_doc_steps();
196
197 let linkchecker = builder.tool_cmd(Tool::Linkchecker);
199
200 let _guard = builder.msg_test("Linkcheck", bootstrap_host, 1);
202 let _time = helpers::timeit(builder);
203 linkchecker.delay_failure().arg(builder.out.join(host).join("doc")).run(builder);
204 }
205
206 fn metadata(&self) -> Option<StepMetadata> {
207 Some(StepMetadata::test("link-check", self.host))
208 }
209}
210
211fn check_if_tidy_is_installed(builder: &Builder<'_>) -> bool {
212 command("tidy")
213 .allow_failure()
214 .arg("--version")
215 .cached()
217 .run_capture_stdout(builder)
218 .is_success()
219}
220
221#[derive(Debug, Clone, PartialEq, Eq, Hash)]
222pub struct HtmlCheck {
223 target: TargetSelection,
224}
225
226impl Step for HtmlCheck {
227 type Output = ();
228 const IS_HOST: bool = true;
229
230 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
231 run.path("src/tools/html-checker")
232 }
233
234 fn is_default_step(builder: &Builder<'_>) -> bool {
235 check_if_tidy_is_installed(builder)
236 }
237
238 fn make_run(run: RunConfig<'_>) {
239 run.builder.ensure(HtmlCheck { target: run.target });
240 }
241
242 fn run(self, builder: &Builder<'_>) {
243 if !check_if_tidy_is_installed(builder) {
244 eprintln!("not running HTML-check tool because `tidy` is missing");
245 eprintln!(
246 "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."
247 );
248 panic!("Cannot run html-check tests");
249 }
250 builder.run_default_doc_steps();
252 builder.ensure(crate::core::build_steps::doc::Rustc::for_stage(
253 builder,
254 builder.top_stage,
255 self.target,
256 ));
257
258 builder
259 .tool_cmd(Tool::HtmlChecker)
260 .delay_failure()
261 .arg(builder.doc_out(self.target))
262 .run(builder);
263 }
264
265 fn metadata(&self) -> Option<StepMetadata> {
266 Some(StepMetadata::test("html-check", self.target))
267 }
268}
269
270#[derive(Debug, Clone, PartialEq, Eq, Hash)]
274pub struct Cargotest {
275 build_compiler: Compiler,
276 host: TargetSelection,
277}
278
279impl Step for Cargotest {
280 type Output = ();
281 const IS_HOST: bool = true;
282
283 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
284 run.path("src/tools/cargotest")
285 }
286
287 fn make_run(run: RunConfig<'_>) {
288 if run.builder.top_stage == 0 {
289 eprintln!(
290 "ERROR: running cargotest with stage 0 is currently unsupported. Use at least stage 1."
291 );
292 exit!(1);
293 }
294 run.builder.ensure(Cargotest {
298 build_compiler: run.builder.compiler(run.builder.top_stage - 1, run.target),
299 host: run.target,
300 });
301 }
302
303 fn run(self, builder: &Builder<'_>) {
308 let cargo =
318 builder.ensure(tool::Cargo::from_build_compiler(self.build_compiler, self.host));
319 let tested_compiler = builder.compiler(self.build_compiler.stage + 1, self.host);
320 builder.std(tested_compiler, self.host);
321
322 let out_dir = builder.out.join("ct");
326 t!(fs::create_dir_all(&out_dir));
327
328 let _time = helpers::timeit(builder);
329 let mut cmd = builder.tool_cmd(Tool::CargoTest);
330 cmd.arg(&cargo.tool_path)
331 .arg(&out_dir)
332 .args(builder.config.test_args())
333 .env("RUSTC", builder.rustc(tested_compiler))
334 .env("RUSTDOC", builder.rustdoc_for_compiler(tested_compiler));
335 add_rustdoc_cargo_linker_args(&mut cmd, builder, tested_compiler.host, LldThreads::No);
336 cmd.delay_failure().run(builder);
337 }
338
339 fn metadata(&self) -> Option<StepMetadata> {
340 Some(StepMetadata::test("cargotest", self.host).stage(self.build_compiler.stage + 1))
341 }
342}
343
344#[derive(Debug, Clone, PartialEq, Eq, Hash)]
347pub struct Cargo {
348 build_compiler: Compiler,
349 host: TargetSelection,
350}
351
352impl Cargo {
353 const CRATE_PATH: &str = "src/tools/cargo";
354}
355
356impl Step for Cargo {
357 type Output = ();
358 const IS_HOST: bool = true;
359
360 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
361 run.path(Self::CRATE_PATH)
362 }
363
364 fn make_run(run: RunConfig<'_>) {
365 run.builder.ensure(Cargo {
366 build_compiler: get_tool_target_compiler(
367 run.builder,
368 ToolTargetBuildMode::Build(run.target),
369 ),
370 host: run.target,
371 });
372 }
373
374 fn run(self, builder: &Builder<'_>) {
376 builder.ensure(tool::Cargo::from_build_compiler(self.build_compiler, self.host));
380 let record_failed_tests = builder.ensure(SetupFailedTestsFile);
381
382 let tested_compiler = builder.compiler(self.build_compiler.stage + 1, self.host);
383 builder.std(tested_compiler, self.host);
384 builder.rustdoc_for_compiler(tested_compiler);
388
389 let cargo = tool::prepare_tool_cargo(
390 builder,
391 self.build_compiler,
392 Mode::ToolTarget,
393 self.host,
394 Kind::Test,
395 Self::CRATE_PATH,
396 SourceType::Submodule,
397 &[],
398 );
399
400 let mut cargo = prepare_cargo_test(cargo, &[], &[], self.host, builder);
402
403 cargo.env("CFG_DISABLE_CROSS_TESTS", "1");
406 cargo.env("CARGO_TEST_DISABLE_NIGHTLY", "1");
409
410 cargo.env("PATH", bin_path_for_cargo(builder, tested_compiler));
414
415 let mut existing_dylib_paths = cargo
420 .get_envs()
421 .find(|(k, _)| *k == OsStr::new(dylib_path_var()))
422 .and_then(|(_, v)| v)
423 .map(|value| split_paths(value).collect::<Vec<PathBuf>>())
424 .unwrap_or_default();
425 existing_dylib_paths.insert(0, builder.rustc_libdir(tested_compiler));
426 add_dylib_path(existing_dylib_paths, &mut cargo);
427
428 cargo.env("CARGO_RUSTC_CURRENT_DIR", builder.src.display().to_string());
432
433 #[cfg(feature = "build-metrics")]
434 builder.metrics.begin_test_suite(
435 build_helper::metrics::TestSuiteMetadata::CargoPackage {
436 crates: vec!["cargo".into()],
437 target: self.host.triple.to_string(),
438 host: self.host.triple.to_string(),
439 stage: self.build_compiler.stage + 1,
440 },
441 builder,
442 );
443
444 let _time = helpers::timeit(builder);
445 add_flags_and_try_run_tests(builder, &mut cargo, record_failed_tests);
446 }
447
448 fn metadata(&self) -> Option<StepMetadata> {
449 Some(StepMetadata::test("cargo", self.host).built_by(self.build_compiler))
450 }
451}
452
453#[derive(Debug, Clone, PartialEq, Eq, Hash)]
454pub struct RustAnalyzer {
455 compilers: RustcPrivateCompilers,
456}
457
458impl Step for RustAnalyzer {
459 type Output = ();
460 const IS_HOST: bool = true;
461
462 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
463 run.path("src/tools/rust-analyzer")
464 }
465
466 fn is_default_step(_builder: &Builder<'_>) -> bool {
467 true
468 }
469
470 fn make_run(run: RunConfig<'_>) {
471 run.builder.ensure(Self {
472 compilers: RustcPrivateCompilers::new(
473 run.builder,
474 run.builder.top_stage,
475 run.builder.host_target,
476 ),
477 });
478 }
479
480 fn run(self, builder: &Builder<'_>) {
482 let build_compiler = self.compilers.build_compiler();
483 let target = self.compilers.target();
484 let record_failed_tests = builder.ensure(SetupFailedTestsFile);
485
486 if target.starts_with("i686") {
496 return;
497 }
498
499 let suite = "src/tools/rust-analyzer";
500 let mut cargo = tool::prepare_tool_cargo(
501 builder,
502 build_compiler,
503 Mode::ToolRustcPrivate,
504 target,
505 Kind::Test,
506 suite,
507 SourceType::InTree,
508 &["in-rust-tree".to_owned()],
509 );
510 cargo.allow_features(tool::RustAnalyzer::ALLOW_FEATURES);
511
512 cargo.env("SKIP_SLOW_TESTS", "1");
519
520 cargo.arg("--workspace");
526 cargo.arg("--exclude=xtask");
527
528 if build_compiler.stage == 0 {
529 cargo.arg("--exclude=proc-macro-srv");
532 cargo.arg("--exclude=proc-macro-srv-cli");
533 }
534
535 let mut skip_tests = vec![];
536
537 skip_tests.extend_from_slice(&[
545 "tests::smoke_test_real_sysroot_cargo",
548 "check_code_formatting",
551 ]);
552
553 let skip_tests = skip_tests.iter().map(|name| format!("--skip={name}")).collect::<Vec<_>>();
554 let skip_tests = skip_tests.iter().map(|s| s.as_str()).collect::<Vec<_>>();
555
556 cargo.add_rustc_lib_path(builder);
557 run_cargo_test(
558 cargo,
559 skip_tests.as_slice(),
560 &[],
561 "rust-analyzer",
562 target,
563 builder,
564 record_failed_tests,
565 );
566 }
567
568 fn metadata(&self) -> Option<StepMetadata> {
569 Some(
570 StepMetadata::test("rust-analyzer", self.compilers.target())
571 .built_by(self.compilers.build_compiler()),
572 )
573 }
574}
575
576#[derive(Debug, Clone, PartialEq, Eq, Hash)]
578pub struct Rustfmt {
579 compilers: RustcPrivateCompilers,
580}
581
582impl Step for Rustfmt {
583 type Output = ();
584 const IS_HOST: bool = true;
585
586 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
587 run.path("src/tools/rustfmt")
588 }
589
590 fn make_run(run: RunConfig<'_>) {
591 run.builder.ensure(Rustfmt {
592 compilers: RustcPrivateCompilers::new(
593 run.builder,
594 run.builder.top_stage,
595 run.builder.host_target,
596 ),
597 });
598 }
599
600 fn run(self, builder: &Builder<'_>) {
602 let build_compiler = self.compilers.build_compiler();
603 let target = self.compilers.target();
604 let record_failed_tests = builder.ensure(SetupFailedTestsFile);
605
606 builder.ensure(compile::Rustc::new(build_compiler, target));
610
611 let mut cargo = tool::prepare_tool_cargo(
612 builder,
613 build_compiler,
614 Mode::ToolRustcPrivate,
615 target,
616 Kind::Test,
617 "src/tools/rustfmt",
618 SourceType::InTree,
619 &[],
620 );
621
622 let dir = testdir(builder, target);
623 t!(fs::create_dir_all(&dir));
624 cargo.env("RUSTFMT_TEST_DIR", dir);
625
626 cargo.add_rustc_lib_path(builder);
627
628 run_cargo_test(cargo, &[], &[], "rustfmt", target, builder, record_failed_tests);
629 }
630
631 fn metadata(&self) -> Option<StepMetadata> {
632 Some(
633 StepMetadata::test("rustfmt", self.compilers.target())
634 .built_by(self.compilers.build_compiler()),
635 )
636 }
637}
638
639#[derive(Debug, Clone, PartialEq, Eq, Hash)]
640pub struct Miri {
641 target: TargetSelection,
642}
643
644impl Miri {
645 pub fn build_miri_sysroot(
647 builder: &Builder<'_>,
648 compiler: Compiler,
649 target: TargetSelection,
650 ) -> PathBuf {
651 let miri_sysroot = builder.out.join(compiler.host).join("miri-sysroot");
652 let mut cargo = builder::Cargo::new(
653 builder,
654 compiler,
655 Mode::Std,
656 SourceType::Submodule,
657 target,
658 Kind::MiriSetup,
659 );
660
661 cargo.env("MIRI_LIB_SRC", builder.src.join("library"));
663 cargo.env("MIRI_SYSROOT", &miri_sysroot);
665
666 let mut cargo = BootstrapCommand::from(cargo);
667 let _guard =
668 builder.msg(Kind::Build, "miri sysroot", Mode::ToolRustcPrivate, compiler, target);
669 cargo.run(builder);
670
671 cargo.arg("--print-sysroot");
677
678 builder.do_if_verbose(|| println!("running: {cargo:?}"));
679 let stdout = cargo.run_capture_stdout(builder).stdout();
680 let sysroot = stdout.trim_end();
682 builder.do_if_verbose(|| println!("`cargo miri setup --print-sysroot` said: {sysroot:?}"));
683 PathBuf::from(sysroot)
684 }
685}
686
687impl Step for Miri {
688 type Output = ();
689
690 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
691 run.path("src/tools/miri")
692 }
693
694 fn make_run(run: RunConfig<'_>) {
695 run.builder.ensure(Miri { target: run.target });
696 }
697
698 fn run(self, builder: &Builder<'_>) {
700 let host = builder.build.host_target;
701 let target = self.target;
702 let stage = builder.top_stage;
703 if stage == 0 {
704 eprintln!("miri cannot be tested at stage 0");
705 std::process::exit(1);
706 }
707
708 let compilers = RustcPrivateCompilers::new(builder, stage, host);
710
711 let miri = builder.ensure(tool::Miri::from_compilers(compilers));
713 builder.ensure(tool::CargoMiri::from_compilers(compilers));
715
716 let target_compiler = compilers.target_compiler();
717
718 let miri_sysroot = Miri::build_miri_sysroot(builder, target_compiler, target);
721 builder.std(target_compiler, host);
722 let host_sysroot = builder.sysroot(target_compiler);
723
724 if !builder.config.dry_run() {
727 let ui_test_dep_dir = builder
730 .stage_out(miri.build_compiler, Mode::ToolStd)
731 .join(host)
732 .join("tmp")
733 .join("miri_ui");
734 build_stamp::clear_if_dirty(builder, &ui_test_dep_dir, &miri_sysroot);
738 }
739
740 let mut cargo = tool::prepare_tool_cargo(
743 builder,
744 miri.build_compiler,
745 Mode::ToolRustcPrivate,
746 host,
747 Kind::Test,
748 "src/tools/miri",
749 SourceType::InTree,
750 &[],
751 );
752
753 cargo.add_rustc_lib_path(builder);
754
755 let mut cargo = prepare_cargo_test(cargo, &[], &[], host, builder);
758
759 cargo.env("MIRI_SYSROOT", &miri_sysroot);
761 cargo.env("MIRI_HOST_SYSROOT", &host_sysroot);
762
763 cargo.env("MIRI_TEST_TARGET", target.rustc_target_arg());
765
766 {
767 let _guard = builder.msg_test("miri", target, target_compiler.stage);
768 let _time = helpers::timeit(builder);
769 cargo.run(builder);
770 }
771
772 if builder.config.test_args().is_empty() {
774 cargo.env(
775 "MIRIFLAGS",
776 format!(
777 "{} -O -Zmir-opt-level=4 -Cdebug-assertions=yes",
778 env::var("MIRIFLAGS").unwrap_or_default()
779 ),
780 );
781 cargo.env("MIRI_SKIP_UI_CHECKS", "1");
783 cargo.env_remove("RUSTC_BLESS");
785 cargo.args(["tests/pass", "tests/panic"]);
787
788 {
789 let _guard =
790 builder.msg_test("miri (mir-opt-level 4)", target, target_compiler.stage);
791 let _time = helpers::timeit(builder);
792 cargo.run(builder);
793 }
794 }
795 }
796}
797
798#[derive(Debug, Clone, PartialEq, Eq, Hash)]
801pub struct CargoMiri {
802 target: TargetSelection,
803}
804
805impl Step for CargoMiri {
806 type Output = ();
807
808 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
809 run.path("src/tools/miri/cargo-miri")
810 }
811
812 fn make_run(run: RunConfig<'_>) {
813 run.builder.ensure(CargoMiri { target: run.target });
814 }
815
816 fn run(self, builder: &Builder<'_>) {
818 let host = builder.build.host_target;
819 let target = self.target;
820 let stage = builder.top_stage;
821 if stage == 0 {
822 eprintln!("cargo-miri cannot be tested at stage 0");
823 std::process::exit(1);
824 }
825
826 let build_compiler = builder.compiler(stage, host);
828
829 let mut cargo = tool::prepare_tool_cargo(
834 builder,
835 build_compiler,
836 Mode::ToolStd, target,
838 Kind::MiriTest,
839 "src/tools/miri/test-cargo-miri",
840 SourceType::Submodule,
841 &[],
842 );
843
844 if stage >= 2 {
847 let built_cargo = builder
848 .ensure(tool::Cargo::from_build_compiler(
849 builder.compiler(0, builder.host_target),
852 builder.host_target,
853 ))
854 .tool_path;
855 cargo.env("CARGO", built_cargo);
856 }
857
858 match builder.test_target {
861 TestTarget::AllTargets => {
862 cargo.args(["--lib", "--bins", "--examples", "--tests", "--benches"])
863 }
864 TestTarget::Default => &mut cargo,
865 TestTarget::DocOnly => cargo.arg("--doc"),
866 TestTarget::Tests => cargo.arg("--tests"),
867 };
868 cargo.arg("--").args(builder.config.test_args());
869
870 let mut cargo = BootstrapCommand::from(cargo);
872 {
873 let _guard = builder.msg_test("cargo-miri", target, stage);
874 let _time = helpers::timeit(builder);
875 cargo.run(builder);
876 }
877 }
878}
879
880#[derive(Debug, Clone, PartialEq, Eq, Hash)]
881pub struct CompiletestTest {
882 host: TargetSelection,
883}
884
885impl Step for CompiletestTest {
886 type Output = ();
887
888 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
889 run.path("src/tools/compiletest")
890 }
891
892 fn make_run(run: RunConfig<'_>) {
893 run.builder.ensure(CompiletestTest { host: run.target });
894 }
895
896 fn run(self, builder: &Builder<'_>) {
898 let host = self.host;
899 let record_failed_tests = builder.ensure(SetupFailedTestsFile);
900
901 if builder.top_stage == 0 && !builder.config.compiletest_allow_stage0 {
907 eprintln!("\
908ERROR: `--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
909NOTE: 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`."
910 );
911 crate::exit!(1);
912 }
913
914 let bootstrap_compiler = builder.compiler(0, host);
915 let staged_compiler = builder.compiler(builder.top_stage, host);
916
917 let mut cargo = tool::prepare_tool_cargo(
918 builder,
919 bootstrap_compiler,
920 Mode::ToolBootstrap,
921 host,
922 Kind::Test,
923 "src/tools/compiletest",
924 SourceType::InTree,
925 &[],
926 );
927
928 cargo.env("TEST_RUSTC", builder.rustc(staged_compiler));
932
933 run_cargo_test(
934 cargo,
935 &[],
936 &[],
937 "compiletest self test",
938 host,
939 builder,
940 record_failed_tests,
941 );
942 }
943}
944
945#[derive(Debug, Clone, PartialEq, Eq, Hash)]
949pub struct StdarchVerify;
950
951impl Step for StdarchVerify {
952 type Output = ();
953 const IS_HOST: bool = true;
954
955 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
956 run.path("library/stdarch/crates/stdarch-verify")
957 }
958
959 fn is_default_step(_builder: &Builder<'_>) -> bool {
960 true
961 }
962
963 fn make_run(run: RunConfig<'_>) {
964 run.builder.ensure(StdarchVerify);
965 }
966
967 fn run(self, builder: &Builder<'_>) {
968 let host = builder.config.host_target;
969 let record_failed_tests = builder.ensure(SetupFailedTestsFile);
970 let build_compiler = builder.compiler(0, host);
971
972 let cargo = tool::prepare_tool_cargo(
973 builder,
974 build_compiler,
975 Mode::ToolBootstrap,
976 host,
977 Kind::Test,
978 "library/stdarch/crates/stdarch-verify",
979 SourceType::InTree,
980 &[],
981 );
982
983 run_cargo_test(
984 cargo,
985 &[],
986 &["stdarch-verify".to_string()],
987 Some("stdarch-verify"),
988 host,
989 builder,
990 record_failed_tests,
991 );
992 }
993}
994
995#[derive(Debug, Clone, PartialEq, Eq, Hash)]
996pub struct Clippy {
997 compilers: RustcPrivateCompilers,
998}
999
1000impl Step for Clippy {
1001 type Output = ();
1002 const IS_HOST: bool = true;
1003
1004 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1005 run.suite_path("src/tools/clippy/tests").path("src/tools/clippy")
1006 }
1007
1008 fn is_default_step(_builder: &Builder<'_>) -> bool {
1009 false
1010 }
1011
1012 fn make_run(run: RunConfig<'_>) {
1013 run.builder.ensure(Clippy {
1014 compilers: RustcPrivateCompilers::new(
1015 run.builder,
1016 run.builder.top_stage,
1017 run.builder.host_target,
1018 ),
1019 });
1020 }
1021
1022 fn run(self, builder: &Builder<'_>) {
1024 let target = self.compilers.target();
1025
1026 let target_compiler = self.compilers.target_compiler();
1030 let build_compiler = self.compilers.build_compiler();
1031
1032 builder.ensure(compile::Rustc::new(build_compiler, target));
1036
1037 let mut cargo = tool::prepare_tool_cargo(
1038 builder,
1039 build_compiler,
1040 Mode::ToolRustcPrivate,
1041 target,
1042 Kind::Test,
1043 "src/tools/clippy",
1044 SourceType::InTree,
1045 &[],
1046 );
1047
1048 cargo.env("RUSTC_TEST_SUITE", builder.rustc(build_compiler));
1049 cargo.env("RUSTC_LIB_PATH", builder.rustc_libdir(build_compiler));
1050 let host_libs = builder
1051 .stage_out(build_compiler, Mode::ToolRustcPrivate)
1052 .join(builder.cargo_dir(Mode::ToolRustcPrivate));
1053 cargo.env("HOST_LIBS", host_libs);
1054
1055 builder.std(target_compiler, target);
1057 cargo.env("TEST_SYSROOT", builder.sysroot(target_compiler));
1058 cargo.env("TEST_RUSTC", builder.rustc(target_compiler));
1059 cargo.env("TEST_RUSTC_LIB", builder.rustc_libdir(target_compiler));
1060
1061 'partially_test: {
1063 let paths = &builder.config.paths[..];
1064 let mut test_names = Vec::new();
1065 for path in paths {
1066 match helpers::is_valid_test_suite_arg(path, "src/tools/clippy/tests", builder) {
1067 TestFilterCategory::Arg(path) => {
1068 test_names.push(path);
1069 }
1070 TestFilterCategory::Fullsuite => {
1071 break 'partially_test;
1073 }
1074 TestFilterCategory::Uninteresting => {}
1075 }
1076 }
1077 cargo.env("TESTNAME", test_names.join(","));
1078 }
1079
1080 cargo.add_rustc_lib_path(builder);
1081 let cargo = prepare_cargo_test(cargo, &[], &[], target, builder);
1082
1083 let _guard = builder.msg_test("clippy", target, target_compiler.stage);
1084
1085 if cargo.allow_failure().run(builder) {
1087 return;
1089 }
1090
1091 if !builder.config.cmd.bless() {
1092 crate::exit!(1);
1093 }
1094 }
1095
1096 fn metadata(&self) -> Option<StepMetadata> {
1097 Some(
1098 StepMetadata::test("clippy", self.compilers.target())
1099 .built_by(self.compilers.build_compiler()),
1100 )
1101 }
1102}
1103
1104fn bin_path_for_cargo(builder: &Builder<'_>, compiler: Compiler) -> OsString {
1105 let path = builder.sysroot(compiler).join("bin");
1106 let old_path = env::var_os("PATH").unwrap_or_default();
1107 env::join_paths(iter::once(path).chain(env::split_paths(&old_path))).expect("")
1108}
1109
1110#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1112pub struct RustdocTheme {
1113 test_compiler: Compiler,
1115}
1116
1117impl Step for RustdocTheme {
1118 type Output = ();
1119 const IS_HOST: bool = true;
1120
1121 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1122 run.path("src/tools/rustdoc-themes")
1123 }
1124
1125 fn is_default_step(_builder: &Builder<'_>) -> bool {
1126 true
1127 }
1128
1129 fn make_run(run: RunConfig<'_>) {
1130 let test_compiler = run.builder.compiler(run.builder.top_stage, run.target);
1131
1132 run.builder.ensure(RustdocTheme { test_compiler });
1133 }
1134
1135 fn run(self, builder: &Builder<'_>) {
1136 let rustdoc = builder.bootstrap_out.join("rustdoc");
1137 let mut cmd = builder.tool_cmd(Tool::RustdocTheme);
1138 cmd.arg(rustdoc.to_str().unwrap())
1139 .arg(builder.src.join("src/librustdoc/html/static/css/rustdoc.css").to_str().unwrap())
1140 .env("RUSTC_STAGE", self.test_compiler.stage.to_string())
1141 .env("RUSTC_SYSROOT", builder.sysroot(self.test_compiler))
1142 .env(
1143 "RUSTDOC_LIBDIR",
1144 builder.sysroot_target_libdir(self.test_compiler, self.test_compiler.host),
1145 )
1146 .env("CFG_RELEASE_CHANNEL", &builder.config.channel)
1147 .env("RUSTDOC_REAL", builder.rustdoc_for_compiler(self.test_compiler))
1148 .env("RUSTC_BOOTSTRAP", "1");
1149 cmd.args(linker_args(builder, self.test_compiler.host, LldThreads::No));
1150
1151 cmd.delay_failure().run(builder);
1152 }
1153
1154 fn metadata(&self) -> Option<StepMetadata> {
1155 Some(
1156 StepMetadata::test("rustdoc-theme", self.test_compiler.host)
1157 .stage(self.test_compiler.stage),
1158 )
1159 }
1160}
1161
1162#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1164pub struct RustdocJSStd {
1165 build_compiler: Compiler,
1167 target: TargetSelection,
1168}
1169
1170impl Step for RustdocJSStd {
1171 type Output = ();
1172 const IS_HOST: bool = true;
1173
1174 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1175 run.suite_path("tests/rustdoc-js-std")
1176 }
1177
1178 fn is_default_step(builder: &Builder<'_>) -> bool {
1179 builder.config.nodejs.is_some()
1180 }
1181
1182 fn make_run(run: RunConfig<'_>) {
1183 run.builder.ensure(RustdocJSStd {
1184 build_compiler: run.builder.compiler(run.builder.top_stage, run.builder.host_target),
1185 target: run.target,
1186 });
1187 }
1188
1189 fn run(self, builder: &Builder<'_>) {
1190 let nodejs =
1191 builder.config.nodejs.as_ref().expect("need nodejs to run rustdoc-js-std tests");
1192 let mut command = command(nodejs);
1193 command
1194 .arg(builder.src.join("src/tools/rustdoc-js/tester.js"))
1195 .arg("--crate-name")
1196 .arg("std")
1197 .arg("--resource-suffix")
1198 .arg(&builder.version)
1199 .arg("--doc-folder")
1200 .arg(builder.doc_out(self.target))
1201 .arg("--test-folder")
1202 .arg(builder.src.join("tests/rustdoc-js-std"));
1203
1204 let full_suite = builder.paths.iter().any(|path| {
1205 matches!(
1206 helpers::is_valid_test_suite_arg(path, "tests/rustdoc-js-std", builder),
1207 TestFilterCategory::Fullsuite
1208 )
1209 });
1210
1211 if !full_suite {
1214 for path in &builder.paths {
1215 if let TestFilterCategory::Arg(p) =
1216 helpers::is_valid_test_suite_arg(path, "tests/rustdoc-js-std", builder)
1217 {
1218 if !p.ends_with(".js") {
1219 eprintln!("A non-js file was given: `{}`", path.display());
1220 panic!("Cannot run rustdoc-js-std tests");
1221 }
1222 command.arg("--test-file").arg(path);
1223 }
1224 }
1225 }
1226
1227 builder.ensure(crate::core::build_steps::doc::Std::from_build_compiler(
1228 self.build_compiler,
1229 self.target,
1230 DocumentationFormat::Html,
1231 ));
1232 let _guard = builder.msg_test("rustdoc-js-std", self.target, self.build_compiler.stage);
1233 command.run(builder);
1234 }
1235
1236 fn metadata(&self) -> Option<StepMetadata> {
1237 Some(StepMetadata::test("rustdoc-js-std", self.target).stage(self.build_compiler.stage))
1238 }
1239}
1240
1241#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1242pub struct RustdocJSNotStd {
1243 pub target: TargetSelection,
1244 pub compiler: Compiler,
1245}
1246
1247impl Step for RustdocJSNotStd {
1248 type Output = ();
1249 const IS_HOST: bool = true;
1250
1251 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1252 run.suite_path("tests/rustdoc-js")
1253 }
1254
1255 fn is_default_step(builder: &Builder<'_>) -> bool {
1256 builder.config.nodejs.is_some()
1257 }
1258
1259 fn make_run(run: RunConfig<'_>) {
1260 let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1261 run.builder.ensure(RustdocJSNotStd { target: run.target, compiler });
1262 }
1263
1264 fn run(self, builder: &Builder<'_>) {
1265 builder.ensure(Compiletest {
1266 test_compiler: self.compiler,
1267 target: self.target,
1268 mode: CompiletestMode::RustdocJs,
1269 suite: "rustdoc-js",
1270 path: "tests/rustdoc-js",
1271 compare_mode: None,
1272 });
1273 }
1274}
1275
1276fn get_browser_ui_test_version_inner(
1277 builder: &Builder<'_>,
1278 yarn: &Path,
1279 global: bool,
1280) -> Option<String> {
1281 let mut command = command(yarn);
1282 command
1283 .arg("--cwd")
1284 .arg(&builder.build.out)
1285 .arg("list")
1286 .arg("--parseable")
1287 .arg("--long")
1288 .arg("--depth=0");
1289 if global {
1290 command.arg("--global");
1291 }
1292 let lines = command.allow_failure().cached().run_capture(builder).stdout();
1295 lines
1296 .lines()
1297 .find_map(|l| l.split(':').nth(1)?.strip_prefix("browser-ui-test@"))
1298 .map(|v| v.to_owned())
1299}
1300
1301fn get_browser_ui_test_version(builder: &Builder<'_>) -> Option<String> {
1302 let yarn = builder.config.yarn.as_deref()?;
1303 get_browser_ui_test_version_inner(builder, yarn, false)
1304 .or_else(|| get_browser_ui_test_version_inner(builder, yarn, true))
1305}
1306
1307#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1309pub struct RustdocGUI {
1310 test_compiler: Compiler,
1312 target: TargetSelection,
1313}
1314
1315impl Step for RustdocGUI {
1316 type Output = ();
1317 const IS_HOST: bool = true;
1318
1319 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1320 run.suite_path("tests/rustdoc-gui")
1321 }
1322
1323 fn is_default_step(builder: &Builder<'_>) -> bool {
1324 builder.config.nodejs.is_some()
1325 && builder.test_target != TestTarget::DocOnly
1326 && get_browser_ui_test_version(builder).is_some()
1327 }
1328
1329 fn make_run(run: RunConfig<'_>) {
1330 let test_compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1331 run.builder.ensure(RustdocGUI { test_compiler, target: run.target });
1332 }
1333
1334 fn run(self, builder: &Builder<'_>) {
1335 builder.std(self.test_compiler, self.target);
1336 let record_failed_tests = builder.ensure(SetupFailedTestsFile);
1337
1338 let mut cmd = builder.tool_cmd(Tool::RustdocGUITest);
1339
1340 let out_dir = builder.test_out(self.target).join("rustdoc-gui");
1341 build_stamp::clear_if_dirty(
1342 builder,
1343 &out_dir,
1344 &builder.rustdoc_for_compiler(self.test_compiler),
1345 );
1346
1347 if let Some(src) = builder.config.src.to_str() {
1348 cmd.arg("--rust-src").arg(src);
1349 }
1350
1351 if let Some(out_dir) = out_dir.to_str() {
1352 cmd.arg("--out-dir").arg(out_dir);
1353 }
1354
1355 if let Some(initial_cargo) = builder.config.initial_cargo.to_str() {
1356 cmd.arg("--initial-cargo").arg(initial_cargo);
1357 }
1358
1359 cmd.arg("--jobs").arg(builder.jobs().to_string());
1360
1361 cmd.env("RUSTDOC", builder.rustdoc_for_compiler(self.test_compiler))
1362 .env("RUSTC", builder.rustc(self.test_compiler));
1363
1364 add_rustdoc_cargo_linker_args(&mut cmd, builder, self.test_compiler.host, LldThreads::No);
1365
1366 let full_suite = builder.paths.iter().any(|path| {
1367 matches!(
1368 helpers::is_valid_test_suite_arg(path, "tests/rustdoc-js-std", builder),
1369 TestFilterCategory::Fullsuite
1370 )
1371 });
1372
1373 if !full_suite {
1376 for path in &builder.paths {
1377 if let TestFilterCategory::Arg(p) =
1378 helpers::is_valid_test_suite_arg(path, "tests/rustdoc-gui", builder)
1379 {
1380 if !p.ends_with(".goml") {
1381 eprintln!("A non-goml file was given: `{}`", path.display());
1382 panic!("Cannot run rustdoc-gui tests");
1383 }
1384 if let Some(name) = path.file_name().and_then(|f| f.to_str()) {
1385 cmd.arg("--goml-file").arg(name);
1386 }
1387 }
1388 }
1389 }
1390
1391 for test_arg in builder.config.test_args() {
1392 cmd.arg("--test-arg").arg(test_arg);
1393 }
1394
1395 if let Some(ref nodejs) = builder.config.nodejs {
1396 cmd.arg("--nodejs").arg(nodejs);
1397 }
1398
1399 if let Some(ref yarn) = builder.config.yarn {
1400 cmd.arg("--yarn").arg(yarn);
1401 }
1402
1403 let _time = helpers::timeit(builder);
1404 let _guard = builder.msg_test("rustdoc-gui", self.target, self.test_compiler.stage);
1405 try_run_tests(builder, &mut cmd, true, record_failed_tests);
1406 }
1407
1408 fn metadata(&self) -> Option<StepMetadata> {
1409 Some(StepMetadata::test("rustdoc-gui", self.target).stage(self.test_compiler.stage))
1410 }
1411}
1412
1413#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1418pub struct Tidy;
1419
1420impl Step for Tidy {
1421 type Output = ();
1422 const IS_HOST: bool = true;
1423
1424 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1425 run.path("src/tools/tidy")
1426 }
1427
1428 fn is_default_step(builder: &Builder<'_>) -> bool {
1429 builder.test_target != TestTarget::DocOnly
1430 }
1431
1432 fn make_run(run: RunConfig<'_>) {
1433 run.builder.ensure(Tidy);
1434 }
1435
1436 fn run(self, builder: &Builder<'_>) {
1445 let mut cmd = builder.tool_cmd(Tool::Tidy);
1446 cmd.arg(format!("--root-path={}", builder.src.display()));
1447 cmd.arg(format!("--cargo-path={}", builder.initial_cargo.display()));
1448 cmd.arg(format!("--output-dir={}", builder.out.display()));
1449 let jobs = builder.config.jobs.unwrap_or_else(|| {
1451 8 * std::thread::available_parallelism().map_or(1, std::num::NonZeroUsize::get) as u32
1452 });
1453 cmd.arg(format!("--concurrency={jobs}"));
1454 if let Some(yarn) = &builder.config.yarn {
1456 cmd.arg(format!("--npm-path={}", yarn.display()));
1457 } else {
1458 cmd.arg("--npm-path=yarn");
1459 }
1460 if builder.is_verbose() {
1461 cmd.arg("--verbose");
1462 }
1463 if builder.config.cmd.bless() {
1464 cmd.arg("--bless");
1465 }
1466 if builder.config.is_running_on_ci() {
1467 cmd.arg("--ci=true");
1468 }
1469 if let Some(s) =
1470 builder.config.cmd.extra_checks().or(builder.config.tidy_extra_checks.as_deref())
1471 {
1472 cmd.arg(format!("--extra-checks={s}"));
1473 }
1474 let mut args = std::env::args_os();
1475 if args.any(|arg| arg == OsStr::new("--")) {
1476 cmd.arg("--");
1477 cmd.args(args);
1478 }
1479
1480 if builder.config.channel == "dev" || builder.config.channel == "nightly" {
1481 if !builder.config.json_output {
1482 builder.info("fmt check");
1483 if builder.config.initial_rustfmt.is_none() {
1484 let inferred_rustfmt_dir = builder.initial_sysroot.join("bin");
1485 eprintln!(
1486 "\
1487ERROR: no `rustfmt` binary found in {PATH}
1488INFO: `rust.channel` is currently set to \"{CHAN}\"
1489HELP: if you are testing a beta branch, set `rust.channel` to \"beta\" in the `bootstrap.toml` file
1490HELP: to skip test's attempt to check tidiness, pass `--skip src/tools/tidy` to `x.py test`",
1491 PATH = inferred_rustfmt_dir.display(),
1492 CHAN = builder.config.channel,
1493 );
1494 crate::exit!(1);
1495 }
1496 let all = false;
1497 crate::core::build_steps::format::format(
1498 builder,
1499 !builder.config.cmd.bless(),
1500 all,
1501 &[],
1502 );
1503 } else {
1504 eprintln!(
1505 "WARNING: `--json-output` is not supported on rustfmt, formatting will be skipped"
1506 );
1507 }
1508 }
1509
1510 builder.info("tidy check");
1511 cmd.delay_failure().run(builder);
1512
1513 builder.info("x.py completions check");
1514 let completion_paths = get_completion_paths(builder);
1515 if builder.config.cmd.bless() {
1516 builder.ensure(crate::core::build_steps::run::GenerateCompletions);
1517 } else if completion_paths
1518 .into_iter()
1519 .any(|(shell, path)| get_completion(shell, &path).is_some())
1520 {
1521 eprintln!(
1522 "x.py completions were changed; run `x.py run generate-completions` to update them"
1523 );
1524 crate::exit!(1);
1525 }
1526
1527 builder.info("x.py help check");
1528 if builder.config.cmd.bless() {
1529 builder.ensure(crate::core::build_steps::run::GenerateHelp);
1530 } else {
1531 let help_path = get_help_path(builder);
1532 let cur_help = std::fs::read_to_string(&help_path).unwrap_or_else(|err| {
1533 eprintln!("couldn't read {}: {}", help_path.display(), err);
1534 crate::exit!(1);
1535 });
1536 let new_help = top_level_help();
1537
1538 if new_help != cur_help {
1539 eprintln!("x.py help was changed; run `x.py run generate-help` to update it");
1540 crate::exit!(1);
1541 }
1542 }
1543 }
1544
1545 fn metadata(&self) -> Option<StepMetadata> {
1546 Some(StepMetadata::test("tidy", TargetSelection::default()))
1547 }
1548}
1549
1550#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1553pub struct CrateRunMakeSupport {
1554 host: TargetSelection,
1555}
1556
1557impl Step for CrateRunMakeSupport {
1558 type Output = ();
1559 const IS_HOST: bool = true;
1560
1561 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1562 run.path("src/tools/run-make-support")
1563 }
1564
1565 fn make_run(run: RunConfig<'_>) {
1566 run.builder.ensure(CrateRunMakeSupport { host: run.target });
1567 }
1568
1569 fn run(self, builder: &Builder<'_>) {
1571 let host = self.host;
1572 let compiler = builder.compiler(0, host);
1573 let record_failed_tests = builder.ensure(SetupFailedTestsFile);
1574
1575 let mut cargo = tool::prepare_tool_cargo(
1576 builder,
1577 compiler,
1578 Mode::ToolBootstrap,
1579 host,
1580 Kind::Test,
1581 "src/tools/run-make-support",
1582 SourceType::InTree,
1583 &[],
1584 );
1585 cargo.allow_features("test");
1586 run_cargo_test(
1587 cargo,
1588 &[],
1589 &[],
1590 "run-make-support self test",
1591 host,
1592 builder,
1593 record_failed_tests,
1594 );
1595 }
1596}
1597
1598#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1599pub struct CrateBuildHelper {
1600 host: TargetSelection,
1601}
1602
1603impl Step for CrateBuildHelper {
1604 type Output = ();
1605 const IS_HOST: bool = true;
1606
1607 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1608 run.path("src/build_helper")
1609 }
1610
1611 fn make_run(run: RunConfig<'_>) {
1612 run.builder.ensure(CrateBuildHelper { host: run.target });
1613 }
1614
1615 fn run(self, builder: &Builder<'_>) {
1617 let host = self.host;
1618 let compiler = builder.compiler(0, host);
1619 let record_failed_tests = builder.ensure(SetupFailedTestsFile);
1620
1621 let mut cargo = tool::prepare_tool_cargo(
1622 builder,
1623 compiler,
1624 Mode::ToolBootstrap,
1625 host,
1626 Kind::Test,
1627 "src/build_helper",
1628 SourceType::InTree,
1629 &[],
1630 );
1631 cargo.allow_features("test");
1632 run_cargo_test(
1633 cargo,
1634 &[],
1635 &[],
1636 "build_helper self test",
1637 host,
1638 builder,
1639 record_failed_tests,
1640 );
1641 }
1642}
1643
1644fn testdir(builder: &Builder<'_>, host: TargetSelection) -> PathBuf {
1645 builder.out.join(host).join("test")
1646}
1647
1648macro_rules! test {
1650 (
1651 $( #[$attr:meta] )* $name:ident {
1653 path: $path:expr,
1654 mode: $mode:expr,
1655 suite: $suite:expr,
1656 default: $default:expr
1657 $( , IS_HOST: $IS_HOST:expr )? $( , compare_mode: $compare_mode:expr )? $( , )? }
1661 ) => {
1662 $( #[$attr] )*
1663 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
1664 pub struct $name {
1665 test_compiler: Compiler,
1666 target: TargetSelection,
1667 }
1668
1669 impl Step for $name {
1670 type Output = ();
1671 const IS_HOST: bool = (const {
1672 #[allow(unused_assignments, unused_mut)]
1673 let mut value = false;
1674 $( value = $IS_HOST; )?
1675 value
1676 });
1677
1678 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1679 run.suite_path($path)
1680 }
1681
1682 fn is_default_step(_builder: &Builder<'_>) -> bool {
1683 const { $default }
1684 }
1685
1686 fn make_run(run: RunConfig<'_>) {
1687 let test_compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1688
1689 run.builder.ensure($name { test_compiler, target: run.target });
1690 }
1691
1692 fn run(self, builder: &Builder<'_>) {
1693 builder.ensure(Compiletest {
1694 test_compiler: self.test_compiler,
1695 target: self.target,
1696 mode: const { $mode },
1697 suite: $suite,
1698 path: $path,
1699 compare_mode: (const {
1700 #[allow(unused_assignments, unused_mut)]
1701 let mut value = None;
1702 $( value = $compare_mode; )?
1703 value
1704 }),
1705 })
1706 }
1707 }
1708 };
1709}
1710
1711test!(Ui { path: "tests/ui", mode: CompiletestMode::Ui, suite: "ui", default: true });
1712
1713test!(Crashes {
1714 path: "tests/crashes",
1715 mode: CompiletestMode::Crashes,
1716 suite: "crashes",
1717 default: true,
1718});
1719
1720test!(CodegenLlvm {
1721 path: "tests/codegen-llvm",
1722 mode: CompiletestMode::Codegen,
1723 suite: "codegen-llvm",
1724 default: true
1725});
1726
1727test!(CodegenUnits {
1728 path: "tests/codegen-units",
1729 mode: CompiletestMode::CodegenUnits,
1730 suite: "codegen-units",
1731 default: true,
1732});
1733
1734test!(Incremental {
1735 path: "tests/incremental",
1736 mode: CompiletestMode::Incremental,
1737 suite: "incremental",
1738 default: true,
1739});
1740
1741test!(Debuginfo {
1742 path: "tests/debuginfo",
1743 mode: CompiletestMode::Debuginfo,
1744 suite: "debuginfo",
1745 default: true,
1746 compare_mode: Some("split-dwarf"),
1747});
1748
1749test!(UiFullDeps {
1750 path: "tests/ui-fulldeps",
1751 mode: CompiletestMode::Ui,
1752 suite: "ui-fulldeps",
1753 default: true,
1754 IS_HOST: true,
1755});
1756
1757test!(RustdocHtml {
1758 path: "tests/rustdoc-html",
1759 mode: CompiletestMode::RustdocHtml,
1760 suite: "rustdoc-html",
1761 default: true,
1762 IS_HOST: true,
1763});
1764test!(RustdocUi {
1765 path: "tests/rustdoc-ui",
1766 mode: CompiletestMode::Ui,
1767 suite: "rustdoc-ui",
1768 default: true,
1769 IS_HOST: true,
1770});
1771
1772test!(RustdocJson {
1773 path: "tests/rustdoc-json",
1774 mode: CompiletestMode::RustdocJson,
1775 suite: "rustdoc-json",
1776 default: true,
1777 IS_HOST: true,
1778});
1779
1780test!(Pretty {
1781 path: "tests/pretty",
1782 mode: CompiletestMode::Pretty,
1783 suite: "pretty",
1784 default: true,
1785 IS_HOST: true,
1786});
1787
1788test!(RunMake {
1789 path: "tests/run-make",
1790 mode: CompiletestMode::RunMake,
1791 suite: "run-make",
1792 default: true,
1793});
1794test!(RunMakeCargo {
1795 path: "tests/run-make-cargo",
1796 mode: CompiletestMode::RunMake,
1797 suite: "run-make-cargo",
1798 default: true
1799});
1800test!(BuildStd {
1801 path: "tests/build-std",
1802 mode: CompiletestMode::RunMake,
1803 suite: "build-std",
1804 default: false
1805});
1806
1807test!(AssemblyLlvm {
1808 path: "tests/assembly-llvm",
1809 mode: CompiletestMode::Assembly,
1810 suite: "assembly-llvm",
1811 default: true
1812});
1813
1814#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1817pub struct Coverage {
1818 pub compiler: Compiler,
1819 pub target: TargetSelection,
1820 pub(crate) mode: CompiletestMode,
1821}
1822
1823impl Coverage {
1824 const PATH: &'static str = "tests/coverage";
1825 const SUITE: &'static str = "coverage";
1826 const ALL_MODES: &[CompiletestMode] =
1827 &[CompiletestMode::CoverageMap, CompiletestMode::CoverageRun];
1828}
1829
1830impl Step for Coverage {
1831 type Output = ();
1832 const IS_HOST: bool = false;
1834
1835 fn should_run(mut run: ShouldRun<'_>) -> ShouldRun<'_> {
1836 run = run.suite_path(Self::PATH);
1842 for mode in Self::ALL_MODES {
1843 run = run.alias(mode.as_str());
1844 }
1845 run
1846 }
1847
1848 fn is_default_step(_builder: &Builder<'_>) -> bool {
1849 true
1850 }
1851
1852 fn make_run(run: RunConfig<'_>) {
1853 let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1854 let target = run.target;
1855
1856 let mut modes = vec![];
1860
1861 for path in &run.paths {
1864 match path {
1865 PathSet::Set(_) => {
1866 for &mode in Self::ALL_MODES {
1867 if path.assert_single_path().path == Path::new(mode.as_str()) {
1868 modes.push(mode);
1869 break;
1870 }
1871 }
1872 }
1873 PathSet::Suite(_) => {
1874 modes.extend_from_slice(Self::ALL_MODES);
1875 break;
1876 }
1877 }
1878 }
1879
1880 modes.retain(|mode| {
1883 !run.builder.config.skip.iter().any(|skip| skip == Path::new(mode.as_str()))
1884 });
1885
1886 for mode in modes {
1894 run.builder.ensure(Coverage { compiler, target, mode });
1895 }
1896 }
1897
1898 fn run(self, builder: &Builder<'_>) {
1899 let Self { compiler, target, mode } = self;
1900 builder.ensure(Compiletest {
1903 test_compiler: compiler,
1904 target,
1905 mode,
1906 suite: Self::SUITE,
1907 path: Self::PATH,
1908 compare_mode: None,
1909 });
1910 }
1911}
1912
1913test!(CoverageRunRustdoc {
1914 path: "tests/coverage-run-rustdoc",
1915 mode: CompiletestMode::CoverageRun,
1916 suite: "coverage-run-rustdoc",
1917 default: true,
1918 IS_HOST: true,
1919});
1920
1921#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1923pub struct MirOpt {
1924 pub compiler: Compiler,
1925 pub target: TargetSelection,
1926}
1927
1928impl Step for MirOpt {
1929 type Output = ();
1930
1931 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1932 run.suite_path("tests/mir-opt")
1933 }
1934
1935 fn is_default_step(_builder: &Builder<'_>) -> bool {
1936 true
1937 }
1938
1939 fn make_run(run: RunConfig<'_>) {
1940 let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1941 run.builder.ensure(MirOpt { compiler, target: run.target });
1942 }
1943
1944 fn run(self, builder: &Builder<'_>) {
1945 let run = |target| {
1946 builder.ensure(Compiletest {
1947 test_compiler: self.compiler,
1948 target,
1949 mode: CompiletestMode::MirOpt,
1950 suite: "mir-opt",
1951 path: "tests/mir-opt",
1952 compare_mode: None,
1953 })
1954 };
1955
1956 run(self.target);
1957
1958 if builder.config.cmd.bless() {
1961 for target in ["aarch64-unknown-linux-gnu", "i686-pc-windows-msvc"] {
1967 run(TargetSelection::from_user(target));
1968 }
1969
1970 for target in ["x86_64-apple-darwin", "i686-unknown-linux-musl"] {
1971 let target = TargetSelection::from_user(target);
1972 let panic_abort_target = builder.ensure(MirOptPanicAbortSyntheticTarget {
1973 compiler: self.compiler,
1974 base: target,
1975 });
1976 run(panic_abort_target);
1977 }
1978 }
1979 }
1980}
1981
1982#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1988struct Compiletest {
1989 test_compiler: Compiler,
1991 target: TargetSelection,
1992 mode: CompiletestMode,
1993 suite: &'static str,
1994 path: &'static str,
1995 compare_mode: Option<&'static str>,
1996}
1997
1998impl Step for Compiletest {
1999 type Output = ();
2000
2001 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2002 run.never()
2003 }
2004
2005 fn run(self, builder: &Builder<'_>) {
2006 if builder.test_target == TestTarget::DocOnly {
2007 return;
2008 }
2009
2010 if builder.top_stage == 0 && !builder.config.compiletest_allow_stage0 {
2011 eprintln!("\
2012ERROR: `--stage 0` runs compiletest on the stage0 (precompiled) compiler, not your local changes, and will almost always cause tests to fail
2013HELP: to test the compiler or standard library, omit the stage or explicitly use `--stage 1` instead
2014NOTE: 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`."
2015 );
2016 crate::exit!(1);
2017 }
2018
2019 let mut test_compiler = self.test_compiler;
2020 let target = self.target;
2021 let mode = self.mode;
2022 let suite = self.suite;
2023 let record_failed_tests = builder.ensure(SetupFailedTestsFile);
2024
2025 let suite_path = self.path;
2027
2028 if !builder.config.codegen_tests && mode == CompiletestMode::Codegen {
2030 return;
2031 }
2032
2033 let query_compiler;
2040 let (stage, stage_id) = if suite == "ui-fulldeps" && test_compiler.stage == 1 {
2041 query_compiler = Some(test_compiler);
2044 let build = builder.build.host_target;
2048 test_compiler = builder.compiler(test_compiler.stage - 1, build);
2049 let test_stage = test_compiler.stage + 1;
2050 (test_stage, format!("stage{test_stage}-{build}"))
2051 } else {
2052 query_compiler = None;
2053 let stage = test_compiler.stage;
2054 (stage, format!("stage{stage}-{target}"))
2055 };
2056
2057 if suite.ends_with("fulldeps") {
2058 builder.ensure(compile::Rustc::new(test_compiler, target));
2059 }
2060
2061 if suite == "debuginfo" {
2062 builder.ensure(dist::DebuggerScripts {
2063 sysroot: builder.sysroot(test_compiler).to_path_buf(),
2064 target,
2065 });
2066 }
2067 if mode == CompiletestMode::RunMake {
2068 builder.tool_exe(Tool::RunMakeSupport);
2069 }
2070
2071 if suite == "mir-opt" {
2073 builder.ensure(
2074 compile::Std::new(test_compiler, test_compiler.host).is_for_mir_opt_tests(true),
2075 );
2076 } else {
2077 builder.std(test_compiler, test_compiler.host);
2078 }
2079
2080 let mut cmd = builder.tool_cmd(Tool::Compiletest);
2081
2082 if suite == "mir-opt" {
2083 builder.ensure(compile::Std::new(test_compiler, target).is_for_mir_opt_tests(true));
2084 } else {
2085 builder.std(test_compiler, target);
2086 }
2087
2088 builder.ensure(RemoteCopyLibs { build_compiler: test_compiler, target });
2089
2090 cmd.arg("--stage").arg(stage.to_string());
2094 cmd.arg("--stage-id").arg(stage_id);
2095
2096 cmd.arg("--compile-lib-path").arg(builder.rustc_libdir(test_compiler));
2097 cmd.arg("--run-lib-path").arg(builder.sysroot_target_libdir(test_compiler, target));
2098 cmd.arg("--rustc-path").arg(builder.rustc(test_compiler));
2099 if let Some(query_compiler) = query_compiler {
2100 cmd.arg("--query-rustc-path").arg(builder.rustc(query_compiler));
2101 }
2102
2103 cmd.arg("--minicore-path")
2106 .arg(builder.src.join("tests").join("auxiliary").join("minicore.rs"));
2107
2108 let is_rustdoc = suite == "rustdoc-ui" || suite == "rustdoc-js";
2109
2110 if mode == CompiletestMode::RunMake {
2125 let stage0_rustc_path = builder.compiler(0, test_compiler.host);
2128 cmd.arg("--stage0-rustc-path").arg(builder.rustc(stage0_rustc_path));
2129
2130 if matches!(suite, "run-make-cargo" | "build-std") {
2131 let cargo_path = if test_compiler.stage == 0 {
2132 builder.initial_cargo.clone()
2134 } else {
2135 builder
2136 .ensure(tool::Cargo::from_build_compiler(
2137 builder.compiler(test_compiler.stage - 1, test_compiler.host),
2138 test_compiler.host,
2139 ))
2140 .tool_path
2141 };
2142
2143 cmd.arg("--cargo-path").arg(cargo_path);
2144 }
2145 }
2146
2147 if matches!(
2149 mode,
2150 CompiletestMode::RunMake
2151 | CompiletestMode::RustdocHtml
2152 | CompiletestMode::RustdocJs
2153 | CompiletestMode::RustdocJson
2154 ) || matches!(suite, "rustdoc-ui" | "coverage-run-rustdoc")
2155 {
2156 cmd.arg("--rustdoc-path").arg(builder.rustdoc_for_compiler(test_compiler));
2157 }
2158
2159 if mode == CompiletestMode::RustdocJson {
2160 let json_compiler = builder.compiler(0, builder.host_target);
2162 cmd.arg("--jsondocck-path")
2163 .arg(builder.ensure(tool::JsonDocCk { compiler: json_compiler, target }).tool_path);
2164 cmd.arg("--jsondoclint-path").arg(
2165 builder.ensure(tool::JsonDocLint { compiler: json_compiler, target }).tool_path,
2166 );
2167 }
2168
2169 if matches!(mode, CompiletestMode::CoverageMap | CompiletestMode::CoverageRun) {
2170 let coverage_dump = builder.tool_exe(Tool::CoverageDump);
2171 cmd.arg("--coverage-dump-path").arg(coverage_dump);
2172 }
2173
2174 cmd.arg("--src-root").arg(&builder.src);
2175 cmd.arg("--src-test-suite-root").arg(builder.src.join("tests").join(suite));
2176
2177 cmd.arg("--build-root").arg(&builder.out);
2181 cmd.arg("--build-test-suite-root").arg(testdir(builder, test_compiler.host).join(suite));
2182
2183 let sysroot = if builder.top_stage == 0 {
2188 builder.initial_sysroot.clone()
2189 } else {
2190 builder.sysroot(test_compiler)
2191 };
2192
2193 cmd.arg("--sysroot-base").arg(sysroot);
2194
2195 cmd.arg("--suite").arg(suite);
2196 cmd.arg("--mode").arg(mode.as_str());
2197 cmd.arg("--target").arg(target.rustc_target_arg());
2198 cmd.arg("--host").arg(&*test_compiler.host.triple);
2199 cmd.arg("--llvm-filecheck").arg(builder.llvm_filecheck(builder.config.host_target));
2200
2201 if let Some(codegen_backend) = builder.config.cmd.test_codegen_backend() {
2202 if !builder
2203 .config
2204 .enabled_codegen_backends(test_compiler.host)
2205 .contains(codegen_backend)
2206 {
2207 eprintln!(
2208 "\
2209ERROR: No configured backend named `{name}`
2210HELP: You can add it into `bootstrap.toml` in `rust.codegen-backends = [{name:?}]`",
2211 name = codegen_backend.name(),
2212 );
2213 crate::exit!(1);
2214 }
2215
2216 if let CodegenBackendKind::Gcc = codegen_backend
2217 && builder.config.rustc_debug_assertions
2218 {
2219 eprintln!(
2220 r#"WARNING: Running tests with the GCC codegen backend while rustc debug assertions are enabled. This might lead to test failures.
2221Please disable assertions with `rust.debug-assertions = false`.
2222 "#
2223 );
2224 }
2225
2226 cmd.arg("--override-codegen-backend").arg(codegen_backend.name());
2229 cmd.arg("--default-codegen-backend").arg(codegen_backend.name());
2232 } else {
2233 cmd.arg("--default-codegen-backend")
2236 .arg(builder.config.default_codegen_backend(test_compiler.host).name());
2237 }
2238 if builder.config.cmd.bypass_ignore_backends() {
2239 cmd.arg("--bypass-ignore-backends");
2240 }
2241
2242 if builder.build.config.llvm_enzyme {
2243 cmd.arg("--has-enzyme");
2244 }
2245
2246 if builder.build.config.llvm_offload {
2247 cmd.arg("--has-offload");
2248 }
2249
2250 if builder.config.cmd.bless() {
2251 cmd.arg("--bless");
2252 }
2253
2254 if builder.config.cmd.force_rerun() {
2255 cmd.arg("--force-rerun");
2256 }
2257
2258 if builder.config.cmd.no_capture() {
2259 cmd.arg("--no-capture");
2260 }
2261
2262 let compare_mode =
2263 builder.config.cmd.compare_mode().or_else(|| {
2264 if builder.config.test_compare_mode { self.compare_mode } else { None }
2265 });
2266
2267 if let Some(ref pass) = builder.config.cmd.pass() {
2268 cmd.arg("--pass");
2269 cmd.arg(pass);
2270 }
2271
2272 if let Some(ref run) = builder.config.cmd.run() {
2273 cmd.arg("--run");
2274 cmd.arg(run);
2275 }
2276
2277 if let Some(ref nodejs) = builder.config.nodejs {
2278 cmd.arg("--nodejs").arg(nodejs);
2279 } else if mode == CompiletestMode::RustdocJs {
2280 panic!("need nodejs to run rustdoc-js suite");
2281 }
2282 if builder.config.rust_optimize_tests {
2283 cmd.arg("--optimize-tests");
2284 }
2285 if builder.config.rust_randomize_layout {
2286 cmd.arg("--rust-randomized-layout");
2287 }
2288 if builder.config.cmd.only_modified() {
2289 cmd.arg("--only-modified");
2290 }
2291 if let Some(compiletest_diff_tool) = &builder.config.compiletest_diff_tool {
2292 cmd.arg("--compiletest-diff-tool").arg(compiletest_diff_tool);
2293 }
2294
2295 let mut flags = if is_rustdoc { Vec::new() } else { vec!["-Crpath".to_string()] };
2296 flags.push(format!(
2297 "-Cdebuginfo={}",
2298 if mode == CompiletestMode::Codegen {
2299 if builder.config.rust_debuginfo_level_tests
2302 != crate::core::config::DebuginfoLevel::None
2303 {
2304 println!(
2305 "NOTE: ignoring `rust.debuginfo-level-tests={}` for codegen tests",
2306 builder.config.rust_debuginfo_level_tests
2307 );
2308 }
2309 crate::core::config::DebuginfoLevel::None
2310 } else {
2311 builder.config.rust_debuginfo_level_tests
2312 }
2313 ));
2314 flags.extend(builder.config.cmd.compiletest_rustc_args().iter().map(|s| s.to_string()));
2315
2316 if suite != "mir-opt" {
2317 if let Some(linker) = builder.linker(target) {
2318 cmd.arg("--target-linker").arg(linker);
2319 }
2320 if let Some(linker) = builder.linker(test_compiler.host) {
2321 cmd.arg("--host-linker").arg(linker);
2322 }
2323 }
2324
2325 if suite == "ui-fulldeps" && target.ends_with("darwin") {
2327 flags.push("-Alinker_messages".into());
2328 }
2329
2330 let mut hostflags = flags.clone();
2331 hostflags.extend(linker_flags(builder, test_compiler.host, LldThreads::No));
2332
2333 let mut targetflags = flags;
2334
2335 if suite == "ui" || suite == "incremental" {
2337 builder.ensure(TestHelpers { target: test_compiler.host });
2338 builder.ensure(TestHelpers { target });
2339 hostflags.push(format!(
2340 "-Lnative={}",
2341 builder.test_helpers_out(test_compiler.host).display()
2342 ));
2343 targetflags.push(format!("-Lnative={}", builder.test_helpers_out(target).display()));
2344 }
2345
2346 for flag in hostflags {
2347 cmd.arg("--host-rustcflags").arg(flag);
2348 }
2349 for flag in targetflags {
2350 cmd.arg("--target-rustcflags").arg(flag);
2351 }
2352 if target.is_synthetic() {
2353 cmd.arg("--target-rustcflags").arg("-Zunstable-options");
2354 }
2355
2356 cmd.arg("--python").arg(
2357 builder.config.python.as_ref().expect("python is required for running rustdoc tests"),
2358 );
2359
2360 let android = android::discover_android(builder, target);
2362 if let Some(android::Android { adb_path, adb_test_dir, android_cross_path }) = &android {
2363 cmd.arg("--adb-path").arg(adb_path);
2364 cmd.arg("--adb-test-dir").arg(adb_test_dir);
2365 cmd.arg("--android-cross-path").arg(android_cross_path);
2366 }
2367
2368 if mode == CompiletestMode::Debuginfo {
2369 if let Some(debuggers::Cdb { cdb }) = debuggers::discover_cdb(target) {
2370 cmd.arg("--cdb").arg(cdb);
2371 }
2372
2373 if let Some(debuggers::Gdb { gdb }) = debuggers::discover_gdb(builder, android.as_ref())
2374 {
2375 cmd.arg("--gdb").arg(gdb.as_ref());
2376 }
2377
2378 if let Some(debuggers::Lldb { lldb_exe, lldb_version }) =
2379 debuggers::discover_lldb(builder)
2380 {
2381 cmd.arg("--lldb").arg(lldb_exe);
2382 cmd.arg("--lldb-version").arg(lldb_version);
2383 }
2384 }
2385
2386 if helpers::forcing_clang_based_tests() {
2387 let clang_exe = builder.llvm_out(target).join("bin").join("clang");
2388 cmd.arg("--run-clang-based-tests-with").arg(clang_exe);
2389 }
2390
2391 for exclude in &builder.config.skip {
2392 cmd.arg("--skip");
2393 cmd.arg(exclude);
2394 }
2395
2396 let mut paths = match &builder.config.cmd {
2398 Subcommand::Test { .. } => &builder.config.paths[..],
2399 _ => &[],
2400 };
2401
2402 let mut paths_v;
2405 if mode == CompiletestMode::RustdocJs {
2406 paths_v = paths.to_vec();
2407 for p in &mut paths_v {
2408 if let Some(ext) = p.extension()
2409 && ext == "js"
2410 {
2411 p.set_extension("rs");
2412 }
2413 }
2414 paths = &paths_v;
2415 }
2416
2417 let mut test_args = Vec::new();
2419 for p in paths {
2420 match helpers::is_valid_test_suite_arg(p, suite_path, builder) {
2421 TestFilterCategory::Fullsuite => {
2422 test_args.clear();
2427 break;
2428 }
2429 TestFilterCategory::Arg(a) => test_args.push(a),
2430 TestFilterCategory::Uninteresting => {}
2431 }
2432 }
2433
2434 test_args.append(&mut builder.config.test_args());
2435
2436 if cfg!(windows) {
2439 let test_args_win: Vec<String> =
2440 test_args.iter().map(|s| s.replace('/', "\\")).collect();
2441 cmd.args(&test_args_win);
2442 } else {
2443 cmd.args(&test_args);
2444 }
2445
2446 if builder.is_verbose() {
2447 cmd.arg("--verbose");
2448 }
2449
2450 if builder.config.cmd.verbose_run_make_subprocess_output() {
2451 cmd.arg("--verbose-run-make-subprocess-output");
2452 }
2453
2454 if builder.config.rustc_debug_assertions {
2455 cmd.arg("--with-rustc-debug-assertions");
2456 }
2457
2458 if builder.config.std_debug_assertions {
2459 cmd.arg("--with-std-debug-assertions");
2460 }
2461
2462 if builder.config.rust_remap_debuginfo {
2463 cmd.arg("--with-std-remap-debuginfo");
2464 }
2465
2466 cmd.arg("--jobs").arg(builder.jobs().to_string());
2467
2468 let mut llvm_components_passed = false;
2469 let mut copts_passed = false;
2470 if builder.config.llvm_enabled(test_compiler.host) {
2471 let llvm::LlvmResult { host_llvm_config, .. } =
2472 builder.ensure(llvm::Llvm { target: builder.config.host_target });
2473 if !builder.config.dry_run() {
2474 let llvm_version = get_llvm_version(builder, &host_llvm_config);
2475 let llvm_components = command(&host_llvm_config)
2476 .cached()
2477 .arg("--components")
2478 .run_capture_stdout(builder)
2479 .stdout();
2480 cmd.arg("--llvm-version")
2482 .arg(llvm_version.trim())
2483 .arg("--llvm-components")
2484 .arg(llvm_components.trim());
2485 llvm_components_passed = true;
2486 }
2487 if !builder.config.is_rust_llvm(target) {
2488 cmd.arg("--system-llvm");
2489 }
2490
2491 if !builder.config.dry_run() && suite.ends_with("fulldeps") {
2496 let llvm_libdir = command(&host_llvm_config)
2497 .cached()
2498 .arg("--libdir")
2499 .run_capture_stdout(builder)
2500 .stdout();
2501 let link_llvm = if target.is_msvc() {
2502 format!("-Clink-arg=-LIBPATH:{llvm_libdir}")
2503 } else {
2504 format!("-Clink-arg=-L{llvm_libdir}")
2505 };
2506 cmd.arg("--host-rustcflags").arg(link_llvm);
2507 }
2508
2509 if !builder.config.dry_run()
2510 && matches!(mode, CompiletestMode::RunMake | CompiletestMode::CoverageRun)
2511 {
2512 let llvm_bin_path = host_llvm_config
2517 .parent()
2518 .expect("Expected llvm-config to be contained in directory");
2519 assert!(llvm_bin_path.is_dir());
2520 cmd.arg("--llvm-bin-dir").arg(llvm_bin_path);
2521 }
2522
2523 if !builder.config.dry_run() && mode == CompiletestMode::RunMake {
2524 if builder.config.lld_enabled {
2526 let lld_install_root =
2527 builder.ensure(llvm::Lld { target: builder.config.host_target });
2528
2529 let lld_bin_path = lld_install_root.join("bin");
2530
2531 let old_path = env::var_os("PATH").unwrap_or_default();
2532 let new_path = env::join_paths(
2533 std::iter::once(lld_bin_path).chain(env::split_paths(&old_path)),
2534 )
2535 .expect("Could not add LLD bin path to PATH");
2536 cmd.env("PATH", new_path);
2537 }
2538 }
2539 }
2540
2541 if !builder.config.dry_run() && mode == CompiletestMode::RunMake {
2544 let mut cflags = builder.cc_handled_clags(target, CLang::C);
2545 cflags.extend(builder.cc_unhandled_cflags(target, GitRepo::Rustc, CLang::C));
2546 let mut cxxflags = builder.cc_handled_clags(target, CLang::Cxx);
2547 cxxflags.extend(builder.cc_unhandled_cflags(target, GitRepo::Rustc, CLang::Cxx));
2548 cmd.arg("--cc")
2549 .arg(builder.cc(target))
2550 .arg("--cxx")
2551 .arg(builder.cxx(target).unwrap())
2552 .arg("--cflags")
2553 .arg(cflags.join(" "))
2554 .arg("--cxxflags")
2555 .arg(cxxflags.join(" "));
2556 copts_passed = true;
2557 if let Some(ar) = builder.ar(target) {
2558 cmd.arg("--ar").arg(ar);
2559 }
2560 }
2561
2562 if !llvm_components_passed {
2563 cmd.arg("--llvm-components").arg("");
2564 }
2565 if !copts_passed {
2566 cmd.arg("--cc")
2567 .arg("")
2568 .arg("--cxx")
2569 .arg("")
2570 .arg("--cflags")
2571 .arg("")
2572 .arg("--cxxflags")
2573 .arg("");
2574 }
2575
2576 if builder.remote_tested(target) {
2577 cmd.arg("--remote-test-client").arg(builder.tool_exe(Tool::RemoteTestClient));
2578 } else if let Some(tool) = builder.runner(target) {
2579 cmd.arg("--runner").arg(tool);
2580 }
2581
2582 if suite != "mir-opt" {
2583 if !builder.config.dry_run() && target.is_msvc() {
2589 for (k, v) in builder.cc[&target].env() {
2590 if k != "PATH" {
2591 cmd.env(k, v);
2592 }
2593 }
2594 }
2595 }
2596
2597 if !builder.config.dry_run()
2599 && target.contains("msvc")
2600 && builder.config.sanitizers_enabled(target)
2601 {
2602 cmd.env("ASAN_WIN_CONTINUE_ON_INTERCEPTION_FAILURE", "1");
2605 let asan_runtime_path = builder.cc[&target].path().parent().unwrap().to_path_buf();
2607 let old_path = cmd
2608 .get_envs()
2609 .find_map(|(k, v)| (k == "PATH").then_some(v))
2610 .flatten()
2611 .map_or_else(|| env::var_os("PATH").unwrap_or_default(), |v| v.to_owned());
2612 let new_path = env::join_paths(
2613 env::split_paths(&old_path).chain(std::iter::once(asan_runtime_path)),
2614 )
2615 .expect("Could not add ASAN runtime path to PATH");
2616 cmd.env("PATH", new_path);
2617 }
2618
2619 cmd.env_remove("CARGO");
2622
2623 cmd.env("RUSTC_BOOTSTRAP", "1");
2624 cmd.env("RUSTC_FORCE_RUSTC_VERSION", "compiletest");
2627 cmd.env("DOC_RUST_LANG_ORG_CHANNEL", builder.doc_rust_lang_org_channel());
2628 builder.add_rust_test_threads(&mut cmd);
2629
2630 if builder.config.sanitizers_enabled(target) {
2631 cmd.env("RUSTC_SANITIZER_SUPPORT", "1");
2632 }
2633
2634 if builder.config.profiler_enabled(target) {
2635 cmd.arg("--profiler-runtime");
2636 }
2637
2638 cmd.env("RUST_TEST_TMPDIR", builder.tempdir());
2639
2640 if builder.config.cmd.rustfix_coverage() {
2641 cmd.arg("--rustfix-coverage");
2642 }
2643
2644 cmd.arg("--channel").arg(&builder.config.channel);
2645
2646 if !builder.config.omit_git_hash {
2647 cmd.arg("--git-hash");
2648 }
2649
2650 let git_config = builder.config.git_config();
2651 cmd.arg("--nightly-branch").arg(git_config.nightly_branch);
2652 cmd.arg("--git-merge-commit-email").arg(git_config.git_merge_commit_email);
2653
2654 #[cfg(feature = "build-metrics")]
2655 builder.metrics.begin_test_suite(
2656 build_helper::metrics::TestSuiteMetadata::Compiletest {
2657 suite: suite.into(),
2658 mode: mode.to_string(),
2659 compare_mode: None,
2660 target: self.target.triple.to_string(),
2661 host: self.test_compiler.host.triple.to_string(),
2662 stage: self.test_compiler.stage,
2663 },
2664 builder,
2665 );
2666
2667 let _group = builder.msg_test(
2668 format!("with compiletest suite={suite} mode={mode}"),
2669 target,
2670 test_compiler.stage,
2671 );
2672 try_run_tests(builder, &mut cmd, false, record_failed_tests.clone());
2673
2674 if let Some(compare_mode) = compare_mode {
2675 cmd.arg("--compare-mode").arg(compare_mode);
2676
2677 #[cfg(feature = "build-metrics")]
2678 builder.metrics.begin_test_suite(
2679 build_helper::metrics::TestSuiteMetadata::Compiletest {
2680 suite: suite.into(),
2681 mode: mode.to_string(),
2682 compare_mode: Some(compare_mode.into()),
2683 target: self.target.triple.to_string(),
2684 host: self.test_compiler.host.triple.to_string(),
2685 stage: self.test_compiler.stage,
2686 },
2687 builder,
2688 );
2689
2690 builder.info(&format!(
2691 "Check compiletest suite={} mode={} compare_mode={} ({} -> {})",
2692 suite, mode, compare_mode, test_compiler.host, target
2693 ));
2694 let _time = helpers::timeit(builder);
2695 try_run_tests(builder, &mut cmd, false, record_failed_tests);
2696 }
2697 }
2698
2699 fn metadata(&self) -> Option<StepMetadata> {
2700 Some(
2701 StepMetadata::test(&format!("compiletest-{}", self.suite), self.target)
2702 .stage(self.test_compiler.stage),
2703 )
2704 }
2705}
2706
2707#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2709struct BookTest {
2710 test_compiler: Compiler,
2711 path: PathBuf,
2712 name: &'static str,
2713 is_ext_doc: bool,
2714 dependencies: Vec<&'static str>,
2715}
2716
2717impl Step for BookTest {
2718 type Output = ();
2719 const IS_HOST: bool = true;
2720
2721 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2722 run.never()
2723 }
2724
2725 fn run(self, builder: &Builder<'_>) {
2726 if self.is_ext_doc {
2736 self.run_ext_doc(builder);
2737 } else {
2738 self.run_local_doc(builder);
2739 }
2740 }
2741}
2742
2743impl BookTest {
2744 fn run_ext_doc(self, builder: &Builder<'_>) {
2747 let test_compiler = self.test_compiler;
2748
2749 builder.std(test_compiler, test_compiler.host);
2750
2751 let mut rustdoc_path = builder.rustdoc_for_compiler(test_compiler);
2754 rustdoc_path.pop();
2755 let old_path = env::var_os("PATH").unwrap_or_default();
2756 let new_path = env::join_paths(iter::once(rustdoc_path).chain(env::split_paths(&old_path)))
2757 .expect("could not add rustdoc to PATH");
2758
2759 let mut rustbook_cmd = builder.tool_cmd(Tool::Rustbook);
2760 let path = builder.src.join(&self.path);
2761 rustbook_cmd.env("RUSTC_BOOTSTRAP", "1");
2763 rustbook_cmd.env("PATH", new_path).arg("test").arg(path);
2764
2765 let libs = if !self.dependencies.is_empty() {
2770 let mut lib_paths = vec![];
2771 for dep in self.dependencies {
2772 let mode = Mode::ToolRustcPrivate;
2773 let target = builder.config.host_target;
2774 let cargo = tool::prepare_tool_cargo(
2775 builder,
2776 test_compiler,
2777 mode,
2778 target,
2779 Kind::Build,
2780 dep,
2781 SourceType::Submodule,
2782 &[],
2783 );
2784
2785 let stamp = BuildStamp::new(&builder.cargo_out(test_compiler, mode, target))
2786 .with_prefix(PathBuf::from(dep).file_name().and_then(|v| v.to_str()).unwrap());
2787
2788 let output_paths =
2789 run_cargo(builder, cargo, vec![], &stamp, vec![], ArtifactKeepMode::OnlyRlib);
2790 let directories = output_paths
2791 .into_iter()
2792 .filter_map(|p| p.parent().map(ToOwned::to_owned))
2793 .fold(HashSet::new(), |mut set, dir| {
2794 set.insert(dir);
2795 set
2796 });
2797
2798 lib_paths.extend(directories);
2799 }
2800 lib_paths
2801 } else {
2802 vec![]
2803 };
2804
2805 if !libs.is_empty() {
2806 let paths = libs
2807 .into_iter()
2808 .map(|path| path.into_os_string())
2809 .collect::<Vec<OsString>>()
2810 .join(OsStr::new(","));
2811 rustbook_cmd.args([OsString::from("--library-path"), paths]);
2812 }
2813
2814 builder.add_rust_test_threads(&mut rustbook_cmd);
2815 let _guard = builder.msg_test(
2816 format_args!("mdbook {}", self.path.display()),
2817 test_compiler.host,
2818 test_compiler.stage,
2819 );
2820 let _time = helpers::timeit(builder);
2821 let toolstate = if rustbook_cmd.delay_failure().run(builder) {
2822 ToolState::TestPass
2823 } else {
2824 ToolState::TestFail
2825 };
2826 builder.save_toolstate(self.name, toolstate);
2827 }
2828
2829 fn run_local_doc(self, builder: &Builder<'_>) {
2831 let test_compiler = self.test_compiler;
2832 let host = self.test_compiler.host;
2833
2834 builder.std(test_compiler, host);
2835
2836 let _guard = builder.msg_test(
2837 format!("book {}", self.name),
2838 test_compiler.host,
2839 test_compiler.stage,
2840 );
2841
2842 let mut stack = vec![builder.src.join(self.path)];
2845 let _time = helpers::timeit(builder);
2846 let mut files = Vec::new();
2847 while let Some(p) = stack.pop() {
2848 if p.is_dir() {
2849 stack.extend(t!(p.read_dir()).map(|p| t!(p).path()));
2850 continue;
2851 }
2852
2853 if p.extension().and_then(|s| s.to_str()) != Some("md") {
2854 continue;
2855 }
2856
2857 files.push(p);
2858 }
2859
2860 files.sort();
2861
2862 for file in files {
2863 markdown_test(builder, test_compiler, &file);
2864 }
2865 }
2866}
2867
2868macro_rules! test_book {
2869 ($(
2870 $name:ident, $path:expr, $book_name:expr,
2871 default=$default:expr
2872 $(,submodules = $submodules:expr)?
2873 $(,dependencies=$dependencies:expr)?
2874 ;
2875 )+) => {
2876 $(
2877 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
2878 pub struct $name {
2879 test_compiler: Compiler,
2880 }
2881
2882 impl Step for $name {
2883 type Output = ();
2884 const IS_HOST: bool = true;
2885
2886 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2887 run.path($path)
2888 }
2889
2890 fn is_default_step(_builder: &Builder<'_>) -> bool {
2891 const { $default }
2892 }
2893
2894 fn make_run(run: RunConfig<'_>) {
2895 run.builder.ensure($name {
2896 test_compiler: run.builder.compiler(run.builder.top_stage, run.target),
2897 });
2898 }
2899
2900 fn run(self, builder: &Builder<'_>) {
2901 $(
2902 for submodule in $submodules {
2903 builder.require_submodule(submodule, None);
2904 }
2905 )*
2906
2907 let dependencies = vec![];
2908 $(
2909 let mut dependencies = dependencies;
2910 for dep in $dependencies {
2911 dependencies.push(dep);
2912 }
2913 )?
2914
2915 builder.ensure(BookTest {
2916 test_compiler: self.test_compiler,
2917 path: PathBuf::from($path),
2918 name: $book_name,
2919 is_ext_doc: !$default,
2920 dependencies,
2921 });
2922 }
2923 }
2924 )+
2925 }
2926}
2927
2928test_book!(
2929 Nomicon, "src/doc/nomicon", "nomicon", default=false, submodules=["src/doc/nomicon"];
2930 Reference, "src/doc/reference", "reference", default=false, submodules=["src/doc/reference"];
2931 RustdocBook, "src/doc/rustdoc", "rustdoc", default=true;
2932 RustcBook, "src/doc/rustc", "rustc", default=true;
2933 RustByExample, "src/doc/rust-by-example", "rust-by-example", default=false, submodules=["src/doc/rust-by-example"];
2934 EmbeddedBook, "src/doc/embedded-book", "embedded-book", default=false, submodules=["src/doc/embedded-book"];
2935 TheBook, "src/doc/book", "book", default=false, submodules=["src/doc/book"], dependencies=["src/doc/book/packages/trpl"];
2936 UnstableBook, "src/doc/unstable-book", "unstable-book", default=true;
2937 EditionGuide, "src/doc/edition-guide", "edition-guide", default=false, submodules=["src/doc/edition-guide"];
2938);
2939
2940#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2941pub struct ErrorIndex {
2942 compilers: RustcPrivateCompilers,
2943}
2944
2945impl Step for ErrorIndex {
2946 type Output = ();
2947 const IS_HOST: bool = true;
2948
2949 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2950 run.path("src/tools/error_index_generator").alias("error-index")
2953 }
2954
2955 fn is_default_step(_builder: &Builder<'_>) -> bool {
2956 true
2957 }
2958
2959 fn make_run(run: RunConfig<'_>) {
2960 let compilers = RustcPrivateCompilers::new(
2964 run.builder,
2965 run.builder.top_stage,
2966 run.builder.config.host_target,
2967 );
2968 run.builder.ensure(ErrorIndex { compilers });
2969 }
2970
2971 fn run(self, builder: &Builder<'_>) {
2978 let target_compiler = self.compilers.target_compiler();
2980
2981 let dir = testdir(builder, target_compiler.host);
2982 t!(fs::create_dir_all(&dir));
2983 let output = dir.join("error-index.md");
2984
2985 let mut tool = tool::ErrorIndex::command(builder, self.compilers);
2986 tool.arg("markdown").arg(&output);
2987
2988 let guard = builder.msg_test("error-index", target_compiler.host, target_compiler.stage);
2989 let _time = helpers::timeit(builder);
2990 tool.run_capture(builder);
2991 drop(guard);
2992 builder.std(target_compiler, target_compiler.host);
2995 markdown_test(builder, target_compiler, &output);
2996 }
2997}
2998
2999fn markdown_test(builder: &Builder<'_>, compiler: Compiler, markdown: &Path) -> bool {
3000 if let Ok(contents) = fs::read_to_string(markdown)
3001 && !contents.contains("```")
3002 {
3003 return true;
3004 }
3005
3006 builder.do_if_verbose(|| println!("doc tests for: {}", markdown.display()));
3007 let mut cmd = builder.rustdoc_cmd(compiler);
3008 builder.add_rust_test_threads(&mut cmd);
3009 cmd.arg("-Z");
3011 cmd.arg("unstable-options");
3012 cmd.arg("--test");
3013 cmd.arg(markdown);
3014 cmd.env("RUSTC_BOOTSTRAP", "1");
3015
3016 let test_args = builder.config.test_args().join(" ");
3017 cmd.arg("--test-args").arg(test_args);
3018
3019 cmd = cmd.delay_failure();
3020 if !builder.config.verbose_tests {
3021 cmd.run_capture(builder).is_success()
3022 } else {
3023 cmd.run(builder)
3024 }
3025}
3026
3027#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3032pub struct CrateLibrustc {
3033 build_compiler: Compiler,
3035 target: TargetSelection,
3036 crates: Vec<String>,
3037}
3038
3039impl Step for CrateLibrustc {
3040 type Output = ();
3041 const IS_HOST: bool = true;
3042
3043 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3044 run.crate_or_deps("rustc-main").path("compiler")
3045 }
3046
3047 fn is_default_step(_builder: &Builder<'_>) -> bool {
3048 true
3049 }
3050
3051 fn make_run(run: RunConfig<'_>) {
3052 let builder = run.builder;
3053 let host = run.build_triple();
3054 let build_compiler = builder.compiler(builder.top_stage - 1, host);
3055 let crates = run.make_run_crates(Alias::Compiler);
3056
3057 builder.ensure(CrateLibrustc { build_compiler, target: run.target, crates });
3058 }
3059
3060 fn run(self, builder: &Builder<'_>) {
3061 builder.std(self.build_compiler, self.target);
3062
3063 builder.ensure(Crate {
3065 build_compiler: self.build_compiler,
3066 target: self.target,
3067 mode: Mode::Rustc,
3068 crates: self.crates,
3069 });
3070 }
3071
3072 fn metadata(&self) -> Option<StepMetadata> {
3073 Some(StepMetadata::test("CrateLibrustc", self.target).built_by(self.build_compiler))
3074 }
3075}
3076
3077fn run_cargo_test<'a>(
3081 cargo: builder::Cargo,
3082 libtest_args: &[&str],
3083 crates: &[String],
3084 description: impl Into<Option<&'a str>>,
3085 target: TargetSelection,
3086 builder: &Builder<'_>,
3087 record_failed_tests: RecordFailedTests,
3088) -> bool {
3089 let compiler = cargo.compiler();
3090 let stage = match cargo.mode() {
3091 Mode::Std => compiler.stage,
3092 _ => compiler.stage + 1,
3093 };
3094
3095 let mut cargo = prepare_cargo_test(cargo, libtest_args, crates, target, builder);
3096 let _time = helpers::timeit(builder);
3097
3098 let _group = description.into().and_then(|what| builder.msg_test(what, target, stage));
3099
3100 #[cfg(feature = "build-metrics")]
3101 builder.metrics.begin_test_suite(
3102 build_helper::metrics::TestSuiteMetadata::CargoPackage {
3103 crates: crates.iter().map(|c| c.to_string()).collect(),
3104 target: target.triple.to_string(),
3105 host: compiler.host.triple.to_string(),
3106 stage: compiler.stage,
3107 },
3108 builder,
3109 );
3110 add_flags_and_try_run_tests(builder, &mut cargo, record_failed_tests)
3111}
3112
3113fn prepare_cargo_test(
3115 cargo: builder::Cargo,
3116 libtest_args: &[&str],
3117 crates: &[String],
3118 target: TargetSelection,
3119 builder: &Builder<'_>,
3120) -> BootstrapCommand {
3121 let compiler = cargo.compiler();
3122 let mut cargo: BootstrapCommand = cargo.into();
3123
3124 if builder.config.cmd.bless() && !cargo.get_envs().any(|v| v.0 == "RUSTC_BLESS") {
3128 cargo.env("RUSTC_BLESS", "Gesundheit");
3129 }
3130
3131 if builder.kind == Kind::Test && !builder.fail_fast {
3135 cargo.arg("--no-fail-fast");
3136 }
3137
3138 if builder.config.json_output {
3139 cargo.arg("--message-format=json");
3140 }
3141
3142 match builder.test_target {
3143 TestTarget::AllTargets => cargo.args(["--bins", "--examples", "--tests", "--benches"]),
3144 TestTarget::Default => &mut cargo,
3145 TestTarget::DocOnly => cargo.arg("--doc"),
3146 TestTarget::Tests => cargo.arg("--tests"),
3147 };
3148
3149 for krate in crates {
3150 cargo.arg("-p").arg(krate);
3151 }
3152
3153 cargo.arg("--").args(builder.config.test_args()).args(libtest_args);
3154 if !builder.config.verbose_tests {
3155 cargo.arg("--quiet");
3156 }
3157
3158 if builder.kind != Kind::Miri {
3167 let mut dylib_paths = builder.rustc_lib_paths(compiler);
3168 dylib_paths.push(builder.sysroot_target_libdir(compiler, target));
3169 helpers::add_dylib_path(dylib_paths, &mut cargo);
3170 }
3171
3172 if builder.remote_tested(target) {
3173 cargo.env(
3174 format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)),
3175 format!("{} run 0", builder.tool_exe(Tool::RemoteTestClient).display()),
3176 );
3177 } else if let Some(tool) = builder.runner(target) {
3178 cargo.env(format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)), tool);
3179 }
3180
3181 cargo
3182}
3183
3184#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3192pub struct Crate {
3193 build_compiler: Compiler,
3195 target: TargetSelection,
3196 mode: Mode,
3197 crates: Vec<String>,
3198}
3199
3200impl Step for Crate {
3201 type Output = ();
3202
3203 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3204 run.crate_or_deps("sysroot").crate_or_deps("coretests").crate_or_deps("alloctests")
3205 }
3206
3207 fn is_default_step(_builder: &Builder<'_>) -> bool {
3208 true
3209 }
3210
3211 fn make_run(run: RunConfig<'_>) {
3212 let builder = run.builder;
3213 let host = run.build_triple();
3214 let build_compiler = builder.compiler(builder.top_stage, host);
3215 let crates = run
3216 .paths
3217 .iter()
3218 .map(|p| builder.crate_paths[&p.assert_single_path().path].clone())
3219 .collect();
3220
3221 builder.ensure(Crate { build_compiler, target: run.target, mode: Mode::Std, crates });
3222 }
3223
3224 fn run(self, builder: &Builder<'_>) {
3233 let build_compiler = self.build_compiler;
3234 let target = self.target;
3235 let mode = self.mode;
3236
3237 builder.ensure(Std::new(build_compiler, build_compiler.host).force_recompile(true));
3240 let record_failed_tests = builder.ensure(SetupFailedTestsFile);
3241
3242 let mut cargo = if builder.kind == Kind::Miri {
3243 if builder.top_stage == 0 {
3244 eprintln!("ERROR: `x.py miri` requires stage 1 or higher");
3245 std::process::exit(1);
3246 }
3247
3248 let mut cargo = builder::Cargo::new(
3251 builder,
3252 build_compiler,
3253 mode,
3254 SourceType::InTree,
3255 target,
3256 Kind::MiriTest,
3257 );
3258 cargo.env("MIRI_REPLACE_LIBRS_IF_NOT_TEST", "1");
3270 cargo.rustflag("-Zforce-unstable-if-unmarked");
3274 cargo.env(
3279 "MIRIFLAGS",
3280 format!(
3281 "{} -Zmiri-env-forward=RUSTC_BOOTSTRAP",
3282 env::var("MIRIFLAGS").unwrap_or_default()
3283 ),
3284 );
3285 cargo
3286 } else {
3287 if !builder.config.is_host_target(target) {
3289 builder.ensure(compile::Std::new(build_compiler, target).force_recompile(true));
3290 builder.ensure(RemoteCopyLibs { build_compiler, target });
3291 }
3292
3293 builder::Cargo::new(
3295 builder,
3296 build_compiler,
3297 mode,
3298 SourceType::InTree,
3299 target,
3300 builder.kind,
3301 )
3302 };
3303
3304 match mode {
3305 Mode::Std => {
3306 if builder.kind == Kind::Miri {
3307 cargo
3313 .arg("--manifest-path")
3314 .arg(builder.src.join("library/sysroot/Cargo.toml"));
3315 } else {
3316 compile::std_cargo(builder, target, &mut cargo, &[]);
3317 }
3318 }
3319 Mode::Rustc => {
3320 compile::rustc_cargo(builder, &mut cargo, target, &build_compiler, &self.crates);
3321 }
3322 _ => panic!("can only test libraries"),
3323 };
3324
3325 let mut crates = self.crates.clone();
3326 if crates.iter().any(|crate_| crate_ == "core") {
3331 crates.push("coretests".to_owned());
3332 }
3333 if crates.iter().any(|crate_| crate_ == "alloc") {
3334 crates.push("alloctests".to_owned());
3335 };
3336 let description = crate_description(&self.crates);
3337 run_cargo_test(cargo, &[], &crates, &*description, target, builder, record_failed_tests);
3338 }
3339}
3340
3341#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3344pub struct CrateRustdoc {
3345 host: TargetSelection,
3346}
3347
3348impl Step for CrateRustdoc {
3349 type Output = ();
3350 const IS_HOST: bool = true;
3351
3352 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3353 run.selectors(&["src/librustdoc", "src/tools/rustdoc"])
3354 }
3355
3356 fn is_default_step(_builder: &Builder<'_>) -> bool {
3357 true
3358 }
3359
3360 fn make_run(run: RunConfig<'_>) {
3361 let builder = run.builder;
3362
3363 builder.ensure(CrateRustdoc { host: run.target });
3364 }
3365
3366 fn run(self, builder: &Builder<'_>) {
3367 let target = self.host;
3368 let record_failed_tests = builder.ensure(SetupFailedTestsFile);
3369
3370 let compiler = if builder.download_rustc() {
3371 builder.compiler(builder.top_stage, target)
3372 } else {
3373 builder.compiler_for(builder.top_stage, target, target)
3378 };
3379 builder.std(compiler, target);
3384 builder.ensure(compile::Rustc::new(compiler, target));
3385
3386 let mut cargo = tool::prepare_tool_cargo(
3387 builder,
3388 compiler,
3389 Mode::ToolRustcPrivate,
3390 target,
3391 builder.kind,
3392 "src/tools/rustdoc",
3393 SourceType::InTree,
3394 &[],
3395 );
3396 if self.host.contains("musl") {
3397 cargo.arg("'-Ctarget-feature=-crt-static'");
3398 }
3399
3400 let libdir = if builder.download_rustc() {
3427 builder.rustc_libdir(compiler)
3428 } else {
3429 builder.sysroot_target_libdir(compiler, target).to_path_buf()
3430 };
3431 let mut dylib_path = dylib_path();
3432 dylib_path.insert(0, PathBuf::from(&*libdir));
3433 cargo.env(dylib_path_var(), env::join_paths(&dylib_path).unwrap());
3434
3435 run_cargo_test(
3436 cargo,
3437 &[],
3438 &["rustdoc:0.0.0".to_string()],
3439 "rustdoc",
3440 target,
3441 builder,
3442 record_failed_tests,
3443 );
3444 }
3445}
3446
3447#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3448pub struct CrateRustdocJsonTypes {
3449 build_compiler: Compiler,
3450 target: TargetSelection,
3451}
3452
3453impl Step for CrateRustdocJsonTypes {
3454 type Output = ();
3455 const IS_HOST: bool = true;
3456
3457 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3458 run.path("src/rustdoc-json-types")
3459 }
3460
3461 fn is_default_step(_builder: &Builder<'_>) -> bool {
3462 true
3463 }
3464
3465 fn make_run(run: RunConfig<'_>) {
3466 let builder = run.builder;
3467
3468 builder.ensure(CrateRustdocJsonTypes {
3469 build_compiler: get_tool_target_compiler(
3470 builder,
3471 ToolTargetBuildMode::Build(run.target),
3472 ),
3473 target: run.target,
3474 });
3475 }
3476
3477 fn run(self, builder: &Builder<'_>) {
3478 let target = self.target;
3479 let record_failed_tests = builder.ensure(SetupFailedTestsFile);
3480
3481 let cargo = tool::prepare_tool_cargo(
3482 builder,
3483 self.build_compiler,
3484 Mode::ToolTarget,
3485 target,
3486 builder.kind,
3487 "src/rustdoc-json-types",
3488 SourceType::InTree,
3489 &["rkyv_0_8".to_owned()],
3490 );
3491
3492 let libtest_args = if target.contains("musl") {
3494 ["'-Ctarget-feature=-crt-static'"].as_slice()
3495 } else {
3496 &[]
3497 };
3498
3499 run_cargo_test(
3500 cargo,
3501 libtest_args,
3502 &["rustdoc-json-types".to_string()],
3503 "rustdoc-json-types",
3504 target,
3505 builder,
3506 record_failed_tests,
3507 );
3508 }
3509}
3510
3511#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3521pub struct RemoteCopyLibs {
3522 build_compiler: Compiler,
3523 target: TargetSelection,
3524}
3525
3526impl Step for RemoteCopyLibs {
3527 type Output = ();
3528
3529 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3530 run.never()
3531 }
3532
3533 fn run(self, builder: &Builder<'_>) {
3534 let build_compiler = self.build_compiler;
3535 let target = self.target;
3536 if !builder.remote_tested(target) {
3537 return;
3538 }
3539
3540 builder.std(build_compiler, target);
3541
3542 builder.info(&format!("REMOTE copy libs to emulator ({target})"));
3543
3544 let remote_test_server = builder.ensure(tool::RemoteTestServer { build_compiler, target });
3545
3546 let tool = builder.tool_exe(Tool::RemoteTestClient);
3548 let mut cmd = command(&tool);
3549 cmd.arg("spawn-emulator")
3550 .arg(target.triple)
3551 .arg(&remote_test_server.tool_path)
3552 .arg(builder.tempdir());
3553 if let Some(rootfs) = builder.qemu_rootfs(target) {
3554 cmd.arg(rootfs);
3555 }
3556 cmd.run(builder);
3557
3558 for f in t!(builder.sysroot_target_libdir(build_compiler, target).read_dir()) {
3560 let f = t!(f);
3561 if helpers::is_dylib(&f.path()) {
3562 command(&tool).arg("push").arg(f.path()).run(builder);
3563 }
3564 }
3565 }
3566}
3567
3568#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3569pub struct Distcheck;
3570
3571impl Step for Distcheck {
3572 type Output = ();
3573
3574 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3575 run.alias("distcheck")
3576 }
3577
3578 fn make_run(run: RunConfig<'_>) {
3579 run.builder.ensure(Distcheck);
3580 }
3581
3582 fn run(self, builder: &Builder<'_>) {
3592 let root_dir = std::env::temp_dir().join("distcheck");
3595
3596 distcheck_plain_source_tarball(builder, &root_dir.join("distcheck-rustc-src"));
3597 distcheck_rust_src(builder, &root_dir.join("distcheck-rust-src"));
3598 distcheck_rustc_dev(builder, &root_dir.join("distcheck-rustc-dev"));
3599 }
3600}
3601
3602fn distcheck_plain_source_tarball(builder: &Builder<'_>, plain_src_dir: &Path) {
3604 builder.info("Distcheck plain source tarball");
3605 let plain_src_tarball = builder.ensure(dist::PlainSourceTarball);
3606 builder.clear_dir(plain_src_dir);
3607
3608 let configure_args: Vec<String> = std::env::var("DISTCHECK_CONFIGURE_ARGS")
3609 .map(|args| args.split(" ").map(|s| s.to_string()).collect::<Vec<String>>())
3610 .unwrap_or_default();
3611
3612 command("tar")
3613 .arg("-xf")
3614 .arg(plain_src_tarball.tarball())
3615 .arg("--strip-components=1")
3616 .current_dir(plain_src_dir)
3617 .run(builder);
3618 command("./configure")
3619 .arg("--set")
3620 .arg("rust.omit-git-hash=false")
3621 .arg("--set")
3622 .arg("rust.remap-debuginfo=false")
3623 .args(&configure_args)
3624 .arg("--enable-vendor")
3625 .current_dir(plain_src_dir)
3626 .run(builder);
3627 command(helpers::make(&builder.config.host_target.triple))
3628 .arg("check")
3629 .env("GITHUB_ACTIONS", "0")
3632 .current_dir(plain_src_dir)
3633 .run(builder);
3634 builder.remove_dir(plain_src_dir);
3636}
3637
3638fn distcheck_rust_src(builder: &Builder<'_>, src_dir: &Path) {
3640 builder.info("Distcheck rust-src");
3641 let src_tarball = builder.ensure(dist::Src);
3642 builder.clear_dir(src_dir);
3643
3644 command("tar")
3645 .arg("-xf")
3646 .arg(src_tarball.tarball())
3647 .arg("--strip-components=1")
3648 .current_dir(src_dir)
3649 .run(builder);
3650
3651 let toml = src_dir.join("rust-src/lib/rustlib/src/rust/library/std/Cargo.toml");
3652 command(&builder.initial_cargo)
3653 .env("RUSTC_BOOTSTRAP", "1")
3656 .arg("generate-lockfile")
3657 .arg("--manifest-path")
3658 .arg(&toml)
3659 .current_dir(src_dir)
3660 .run(builder);
3661 builder.remove_dir(src_dir);
3663}
3664
3665fn distcheck_rustc_dev(builder: &Builder<'_>, dir: &Path) {
3667 builder.info("Distcheck rustc-dev");
3668 let tarball = builder.ensure(dist::RustcDev::new(builder, builder.host_target)).unwrap();
3669 builder.clear_dir(dir);
3670
3671 command("tar")
3672 .arg("-xf")
3673 .arg(tarball.tarball())
3674 .arg("--strip-components=1")
3675 .current_dir(dir)
3676 .run(builder);
3677
3678 command(&builder.initial_cargo)
3679 .arg("metadata")
3680 .arg("--manifest-path")
3681 .arg("rustc-dev/lib/rustlib/rustc-src/rust/compiler/rustc/Cargo.toml")
3682 .env("RUSTC_BOOTSTRAP", "1")
3683 .env("RUSTC", &builder.initial_rustc)
3685 .current_dir(dir)
3686 .run(builder);
3687 builder.remove_dir(dir);
3689}
3690
3691#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3693pub(crate) struct BootstrapPy;
3694
3695impl Step for BootstrapPy {
3696 type Output = ();
3697 const IS_HOST: bool = true;
3698
3699 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3700 run.alias("bootstrap-py")
3701 }
3702
3703 fn is_default_step(builder: &Builder<'_>) -> bool {
3704 builder.config.is_running_on_ci()
3708 }
3709
3710 fn make_run(run: RunConfig<'_>) {
3711 run.builder.ensure(BootstrapPy)
3712 }
3713
3714 fn run(self, builder: &Builder<'_>) -> Self::Output {
3715 let mut check_bootstrap = command(
3716 builder.config.python.as_ref().expect("python is required for running bootstrap tests"),
3717 );
3718 check_bootstrap
3719 .args(["-m", "unittest", "bootstrap_test.py"])
3720 .args(builder.config.test_args())
3722 .env("BUILD_DIR", &builder.out)
3723 .env("BUILD_PLATFORM", builder.build.host_target.triple)
3724 .env("BOOTSTRAP_TEST_RUSTC_BIN", &builder.initial_rustc)
3725 .env("BOOTSTRAP_TEST_CARGO_BIN", &builder.initial_cargo)
3726 .current_dir(builder.src.join("src/bootstrap/"));
3727 check_bootstrap.delay_failure().run(builder);
3728 }
3729}
3730
3731#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3732pub struct Bootstrap;
3733
3734impl Step for Bootstrap {
3735 type Output = ();
3736 const IS_HOST: bool = true;
3737
3738 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3739 run.path("src/bootstrap")
3740 }
3741
3742 fn is_default_step(builder: &Builder<'_>) -> bool {
3743 builder.config.is_running_on_ci()
3747 }
3748
3749 fn run(self, builder: &Builder<'_>) {
3751 let host = builder.config.host_target;
3752 let build_compiler = builder.compiler(0, host);
3753 let record_failed_tests = builder.ensure(SetupFailedTestsFile);
3754
3755 builder.build.require_submodule("src/tools/cargo", None);
3757
3758 let mut cargo = tool::prepare_tool_cargo(
3759 builder,
3760 build_compiler,
3761 Mode::ToolBootstrap,
3762 host,
3763 Kind::Test,
3764 "src/bootstrap",
3765 SourceType::InTree,
3766 &[],
3767 );
3768
3769 cargo.release_build(false);
3770
3771 cargo
3772 .rustflag("-Cdebuginfo=2")
3773 .env("CARGO_TARGET_DIR", builder.out.join("bootstrap"))
3774 .env("INSTA_WORKSPACE_ROOT", &builder.src)
3776 .env("RUSTC_BOOTSTRAP", "1");
3777
3778 if builder.config.cmd.bless() {
3779 cargo.env("INSTA_UPDATE", "always");
3783 }
3784
3785 run_cargo_test(cargo, &[], &[], None, host, builder, record_failed_tests);
3786 }
3787
3788 fn make_run(run: RunConfig<'_>) {
3789 run.builder.ensure(Bootstrap);
3790 }
3791}
3792
3793fn get_compiler_to_test(builder: &Builder<'_>, target: TargetSelection) -> Compiler {
3794 builder.compiler(builder.top_stage, target)
3795}
3796
3797#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3800pub struct TierCheck {
3801 test_compiler: Compiler,
3802}
3803
3804impl Step for TierCheck {
3805 type Output = ();
3806 const IS_HOST: bool = true;
3807
3808 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3809 run.path("src/tools/tier-check")
3810 }
3811
3812 fn is_default_step(_builder: &Builder<'_>) -> bool {
3813 true
3814 }
3815
3816 fn make_run(run: RunConfig<'_>) {
3817 run.builder
3818 .ensure(TierCheck { test_compiler: get_compiler_to_test(run.builder, run.target) });
3819 }
3820
3821 fn run(self, builder: &Builder<'_>) {
3822 let tool_build_compiler = builder.compiler(0, builder.host_target);
3823
3824 let mut cargo = tool::prepare_tool_cargo(
3825 builder,
3826 tool_build_compiler,
3827 Mode::ToolBootstrap,
3828 tool_build_compiler.host,
3829 Kind::Run,
3830 "src/tools/tier-check",
3831 SourceType::InTree,
3832 &[],
3833 );
3834 cargo.arg(builder.src.join("src/doc/rustc/src/platform-support.md"));
3835 cargo.arg(builder.rustc(self.test_compiler));
3836
3837 let _guard = builder.msg_test(
3838 "platform support check",
3839 self.test_compiler.host,
3840 self.test_compiler.stage,
3841 );
3842 BootstrapCommand::from(cargo).delay_failure().run(builder);
3843 }
3844
3845 fn metadata(&self) -> Option<StepMetadata> {
3846 Some(StepMetadata::test("tier-check", self.test_compiler.host))
3847 }
3848}
3849
3850#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3851pub struct LintDocs {
3852 build_compiler: Compiler,
3853 target: TargetSelection,
3854}
3855
3856impl Step for LintDocs {
3857 type Output = ();
3858 const IS_HOST: bool = true;
3859
3860 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3861 run.path("src/tools/lint-docs")
3862 }
3863
3864 fn is_default_step(builder: &Builder<'_>) -> bool {
3865 builder.top_stage >= 2
3868 }
3869
3870 fn make_run(run: RunConfig<'_>) {
3871 if run.builder.top_stage < 2 {
3872 eprintln!("WARNING: lint-docs tests might not work below stage 2");
3873 }
3874
3875 run.builder.ensure(LintDocs {
3876 build_compiler: prepare_doc_compiler(
3877 run.builder,
3878 run.builder.config.host_target,
3879 run.builder.top_stage,
3880 ),
3881 target: run.target,
3882 });
3883 }
3884
3885 fn run(self, builder: &Builder<'_>) {
3888 builder.ensure(crate::core::build_steps::doc::RustcBook::validate(
3889 self.build_compiler,
3890 self.target,
3891 ));
3892 }
3893
3894 fn metadata(&self) -> Option<StepMetadata> {
3895 Some(StepMetadata::test("lint-docs", self.target).built_by(self.build_compiler))
3896 }
3897}
3898
3899#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3900pub struct RustInstaller;
3901
3902impl Step for RustInstaller {
3903 type Output = ();
3904 const IS_HOST: bool = true;
3905
3906 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3907 run.path("src/tools/rust-installer")
3908 }
3909
3910 fn is_default_step(_builder: &Builder<'_>) -> bool {
3911 true
3912 }
3913
3914 fn make_run(run: RunConfig<'_>) {
3915 run.builder.ensure(Self);
3916 }
3917
3918 fn run(self, builder: &Builder<'_>) {
3920 let bootstrap_host = builder.config.host_target;
3921 let build_compiler = builder.compiler(0, bootstrap_host);
3922 let record_failed_tests = builder.ensure(SetupFailedTestsFile);
3923 let cargo = tool::prepare_tool_cargo(
3924 builder,
3925 build_compiler,
3926 Mode::ToolBootstrap,
3927 bootstrap_host,
3928 Kind::Test,
3929 "src/tools/rust-installer",
3930 SourceType::InTree,
3931 &[],
3932 );
3933
3934 let _guard = builder.msg_test("rust-installer", bootstrap_host, 1);
3935 run_cargo_test(cargo, &[], &[], None, bootstrap_host, builder, record_failed_tests);
3936
3937 if bootstrap_host != "x86_64-unknown-linux-gnu" {
3941 return;
3942 }
3943
3944 let mut cmd = command(builder.src.join("src/tools/rust-installer/test.sh"));
3945 let tmpdir = testdir(builder, build_compiler.host).join("rust-installer");
3946 let _ = std::fs::remove_dir_all(&tmpdir);
3947 let _ = std::fs::create_dir_all(&tmpdir);
3948 cmd.current_dir(&tmpdir);
3949 cmd.env("CARGO_TARGET_DIR", tmpdir.join("cargo-target"));
3950 cmd.env("CARGO", &builder.initial_cargo);
3951 cmd.env("RUSTC", &builder.initial_rustc);
3952 cmd.env("TMP_DIR", &tmpdir);
3953 cmd.delay_failure().run(builder);
3954 }
3955}
3956
3957#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3958pub struct TestHelpers {
3959 pub target: TargetSelection,
3960}
3961
3962impl Step for TestHelpers {
3963 type Output = ();
3964
3965 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3966 run.path("tests/auxiliary/rust_test_helpers.c")
3967 }
3968
3969 fn make_run(run: RunConfig<'_>) {
3970 run.builder.ensure(TestHelpers { target: run.target })
3971 }
3972
3973 fn run(self, builder: &Builder<'_>) {
3976 if builder.config.dry_run() {
3977 return;
3978 }
3979 let target = if self.target == "x86_64-fortanix-unknown-sgx" {
3983 TargetSelection::from_user("x86_64-unknown-linux-gnu")
3984 } else {
3985 self.target
3986 };
3987 let dst = builder.test_helpers_out(target);
3988 let src = builder.src.join("tests/auxiliary/rust_test_helpers.c");
3989 if up_to_date(&src, &dst.join("librust_test_helpers.a")) {
3990 return;
3991 }
3992
3993 let _guard = builder.msg_unstaged(Kind::Build, "test helpers", target);
3994 t!(fs::create_dir_all(&dst));
3995 let mut cfg = cc::Build::new();
3996
3997 if !target.is_msvc() {
4001 if let Some(ar) = builder.ar(target) {
4002 cfg.archiver(ar);
4003 }
4004 cfg.compiler(builder.cc(target));
4005 }
4006 cfg.cargo_metadata(false)
4007 .out_dir(&dst)
4008 .target(&target.triple)
4009 .host(&builder.config.host_target.triple)
4010 .opt_level(0)
4011 .warnings(false)
4012 .debug(false)
4013 .file(builder.src.join("tests/auxiliary/rust_test_helpers.c"))
4014 .compile("rust_test_helpers");
4015 }
4016}
4017
4018#[derive(Debug, Clone, PartialEq, Eq, Hash)]
4019pub struct CodegenCranelift {
4020 compilers: RustcPrivateCompilers,
4021 target: TargetSelection,
4022}
4023
4024impl Step for CodegenCranelift {
4025 type Output = ();
4026 const IS_HOST: bool = true;
4027
4028 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
4029 run.path("compiler/rustc_codegen_cranelift")
4030 }
4031
4032 fn is_default_step(_builder: &Builder<'_>) -> bool {
4033 true
4034 }
4035
4036 fn make_run(run: RunConfig<'_>) {
4037 let builder = run.builder;
4038 let host = run.build_triple();
4039 let compilers = RustcPrivateCompilers::new(run.builder, run.builder.top_stage, host);
4040
4041 if builder.test_target == TestTarget::DocOnly {
4042 return;
4043 }
4044
4045 if builder.download_rustc() {
4046 builder.info("CI rustc uses the default codegen backend. skipping");
4047 return;
4048 }
4049
4050 if !target_supports_cranelift_backend(run.target) {
4051 builder.info("target not supported by rustc_codegen_cranelift. skipping");
4052 return;
4053 }
4054
4055 if builder.remote_tested(run.target) {
4056 builder.info("remote testing is not supported by rustc_codegen_cranelift. skipping");
4057 return;
4058 }
4059
4060 if !builder
4061 .config
4062 .enabled_codegen_backends(run.target)
4063 .contains(&CodegenBackendKind::Cranelift)
4064 {
4065 builder.info("cranelift not in rust.codegen-backends. skipping");
4066 return;
4067 }
4068
4069 builder.ensure(CodegenCranelift { compilers, target: run.target });
4070 }
4071
4072 fn run(self, builder: &Builder<'_>) {
4073 let compilers = self.compilers;
4074 let build_compiler = compilers.build_compiler();
4075
4076 let target_compiler = compilers.target_compiler();
4079 let target = self.target;
4080
4081 builder.std(target_compiler, target);
4082
4083 let mut cargo = builder::Cargo::new(
4084 builder,
4085 target_compiler,
4086 Mode::Codegen, SourceType::InTree,
4088 target,
4089 Kind::Run,
4090 );
4091
4092 cargo.current_dir(&builder.src.join("compiler/rustc_codegen_cranelift"));
4093 cargo
4094 .arg("--manifest-path")
4095 .arg(builder.src.join("compiler/rustc_codegen_cranelift/build_system/Cargo.toml"));
4096 compile::rustc_cargo_env(builder, &mut cargo, target);
4097
4098 cargo.env("CARGO_BUILD_INCREMENTAL", "false");
4100
4101 let _guard = builder.msg_test(
4102 "rustc_codegen_cranelift",
4103 target_compiler.host,
4104 target_compiler.stage,
4105 );
4106
4107 let download_dir = builder.out.join("cg_clif_download");
4109
4110 cargo
4111 .arg("--")
4112 .arg("test")
4113 .arg("--download-dir")
4114 .arg(&download_dir)
4115 .arg("--out-dir")
4116 .arg(builder.stage_out(build_compiler, Mode::Codegen).join("cg_clif"))
4117 .arg("--no-unstable-features")
4118 .arg("--use-backend")
4119 .arg("cranelift")
4120 .arg("--sysroot")
4122 .arg("llvm")
4123 .arg("--skip-test")
4126 .arg("testsuite.extended_sysroot");
4127
4128 cargo.into_cmd().run(builder);
4129 }
4130
4131 fn metadata(&self) -> Option<StepMetadata> {
4132 Some(
4133 StepMetadata::test("rustc_codegen_cranelift", self.target)
4134 .built_by(self.compilers.build_compiler()),
4135 )
4136 }
4137}
4138
4139#[derive(Debug, Clone, PartialEq, Eq, Hash)]
4140pub struct CodegenGCC {
4141 compilers: RustcPrivateCompilers,
4142 target: TargetSelection,
4143}
4144
4145impl Step for CodegenGCC {
4146 type Output = ();
4147 const IS_HOST: bool = true;
4148
4149 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
4150 run.path("compiler/rustc_codegen_gcc")
4151 }
4152
4153 fn is_default_step(_builder: &Builder<'_>) -> bool {
4154 true
4155 }
4156
4157 fn make_run(run: RunConfig<'_>) {
4158 let builder = run.builder;
4159 let host = run.build_triple();
4160 let compilers = RustcPrivateCompilers::new(run.builder, run.builder.top_stage, host);
4161
4162 if builder.test_target == TestTarget::DocOnly {
4163 return;
4164 }
4165
4166 if builder.download_rustc() {
4167 builder.info("CI rustc uses the default codegen backend. skipping");
4168 return;
4169 }
4170
4171 let triple = run.target.triple;
4172 let target_supported =
4173 if triple.contains("linux") { triple.contains("x86_64") } else { false };
4174 if !target_supported {
4175 builder.info("target not supported by rustc_codegen_gcc. skipping");
4176 return;
4177 }
4178
4179 if builder.remote_tested(run.target) {
4180 builder.info("remote testing is not supported by rustc_codegen_gcc. skipping");
4181 return;
4182 }
4183
4184 if !builder.config.enabled_codegen_backends(run.target).contains(&CodegenBackendKind::Gcc) {
4185 builder.info("gcc not in rust.codegen-backends. skipping");
4186 return;
4187 }
4188
4189 builder.ensure(CodegenGCC { compilers, target: run.target });
4190 }
4191
4192 fn run(self, builder: &Builder<'_>) {
4193 let compilers = self.compilers;
4194 let target = self.target;
4195
4196 let gcc = builder.ensure(Gcc { target_pair: GccTargetPair::for_native_build(target) });
4197
4198 builder.ensure(
4199 compile::Std::new(compilers.build_compiler(), target)
4200 .extra_rust_args(&["-Csymbol-mangling-version=v0", "-Cpanic=abort"]),
4201 );
4202
4203 let _guard = builder.msg_test(
4204 "rustc_codegen_gcc",
4205 compilers.target(),
4206 compilers.target_compiler().stage,
4207 );
4208
4209 let mut cargo = builder::Cargo::new(
4210 builder,
4211 compilers.build_compiler(),
4212 Mode::Codegen, SourceType::InTree,
4214 target,
4215 Kind::Run,
4216 );
4217
4218 cargo.current_dir(&builder.src.join("compiler/rustc_codegen_gcc"));
4219 cargo
4220 .arg("--manifest-path")
4221 .arg(builder.src.join("compiler/rustc_codegen_gcc/build_system/Cargo.toml"));
4222 compile::rustc_cargo_env(builder, &mut cargo, target);
4223 add_cg_gcc_cargo_flags(&mut cargo, &gcc);
4224
4225 cargo.env("CARGO_BUILD_INCREMENTAL", "false");
4227 cargo.rustflag("-Cpanic=abort");
4228
4229 cargo
4230 .env("CG_RUSTFLAGS", "-Alinker-messages")
4232 .arg("--")
4233 .arg("test")
4234 .arg("--use-backend")
4235 .arg("gcc")
4236 .arg("--gcc-path")
4237 .arg(gcc.libgccjit().parent().unwrap())
4238 .arg("--out-dir")
4239 .arg(builder.stage_out(compilers.build_compiler(), Mode::Codegen).join("cg_gcc"))
4240 .arg("--release")
4241 .arg("--mini-tests")
4242 .arg("--std-tests");
4243
4244 cargo.args(builder.config.test_args());
4245
4246 cargo.into_cmd().run(builder);
4247 }
4248
4249 fn metadata(&self) -> Option<StepMetadata> {
4250 Some(
4251 StepMetadata::test("rustc_codegen_gcc", self.target)
4252 .built_by(self.compilers.build_compiler()),
4253 )
4254 }
4255}
4256
4257#[derive(Debug, Clone, PartialEq, Eq, Hash)]
4262pub struct TestFloatParse {
4263 build_compiler: Compiler,
4272 target: TargetSelection,
4274}
4275
4276impl Step for TestFloatParse {
4277 type Output = ();
4278 const IS_HOST: bool = true;
4279
4280 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
4281 run.path("src/tools/test-float-parse")
4282 }
4283
4284 fn is_default_step(_builder: &Builder<'_>) -> bool {
4285 true
4286 }
4287
4288 fn make_run(run: RunConfig<'_>) {
4289 run.builder.ensure(Self {
4290 build_compiler: get_compiler_to_test(run.builder, run.target),
4291 target: run.target,
4292 });
4293 }
4294
4295 fn run(self, builder: &Builder<'_>) {
4296 let build_compiler = self.build_compiler;
4297 let target = self.target;
4298
4299 builder.std(build_compiler, target);
4301 builder.std(build_compiler, builder.host_target);
4302 let record_failed_tests = builder.ensure(SetupFailedTestsFile);
4303
4304 let mut cargo_test = tool::prepare_tool_cargo(
4306 builder,
4307 build_compiler,
4308 Mode::ToolStd,
4309 target,
4310 Kind::Test,
4311 "src/tools/test-float-parse",
4312 SourceType::InTree,
4313 &[],
4314 );
4315 cargo_test.allow_features(TEST_FLOAT_PARSE_ALLOW_FEATURES);
4316
4317 run_cargo_test(
4318 cargo_test,
4319 &[],
4320 &[],
4321 "test-float-parse",
4322 target,
4323 builder,
4324 record_failed_tests,
4325 );
4326
4327 let mut cargo_run = tool::prepare_tool_cargo(
4329 builder,
4330 build_compiler,
4331 Mode::ToolStd,
4332 target,
4333 Kind::Run,
4334 "src/tools/test-float-parse",
4335 SourceType::InTree,
4336 &[],
4337 );
4338 cargo_run.allow_features(TEST_FLOAT_PARSE_ALLOW_FEATURES);
4339
4340 if !matches!(env::var("FLOAT_PARSE_TESTS_NO_SKIP_HUGE").as_deref(), Ok("1") | Ok("true")) {
4341 cargo_run.args(["--", "--skip-huge"]);
4342 }
4343
4344 cargo_run.into_cmd().run(builder);
4345 }
4346}
4347
4348#[derive(Debug, Clone, Hash, PartialEq, Eq)]
4352pub struct CollectLicenseMetadata;
4353
4354impl Step for CollectLicenseMetadata {
4355 type Output = PathBuf;
4356 const IS_HOST: bool = true;
4357
4358 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
4359 run.path("src/tools/collect-license-metadata")
4360 }
4361
4362 fn make_run(run: RunConfig<'_>) {
4363 run.builder.ensure(CollectLicenseMetadata);
4364 }
4365
4366 fn run(self, builder: &Builder<'_>) -> Self::Output {
4367 let Some(reuse) = &builder.config.reuse else {
4368 panic!("REUSE is required to collect the license metadata");
4369 };
4370
4371 let dest = builder.src.join("license-metadata.json");
4372
4373 let mut cmd = builder.tool_cmd(Tool::CollectLicenseMetadata);
4374 cmd.env("REUSE_EXE", reuse);
4375 cmd.env("DEST", &dest);
4376 cmd.env("ONLY_CHECK", "1");
4377 cmd.run(builder);
4378
4379 dest
4380 }
4381}
4382
4383#[derive(Debug, Clone, PartialEq, Eq, Hash)]
4384pub struct RemoteTestClientTests {
4385 host: TargetSelection,
4386}
4387
4388impl Step for RemoteTestClientTests {
4389 type Output = ();
4390 const IS_HOST: bool = true;
4391
4392 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
4393 run.path("src/tools/remote-test-client")
4394 }
4395
4396 fn is_default_step(_builder: &Builder<'_>) -> bool {
4397 true
4398 }
4399
4400 fn make_run(run: RunConfig<'_>) {
4401 run.builder.ensure(Self { host: run.target });
4402 }
4403
4404 fn run(self, builder: &Builder<'_>) {
4405 let bootstrap_host = builder.config.host_target;
4406 let compiler = builder.compiler(0, bootstrap_host);
4407 let record_failed_tests = builder.ensure(SetupFailedTestsFile);
4408
4409 let cargo = tool::prepare_tool_cargo(
4410 builder,
4411 compiler,
4412 Mode::ToolBootstrap,
4413 bootstrap_host,
4414 Kind::Test,
4415 "src/tools/remote-test-client",
4416 SourceType::InTree,
4417 &[],
4418 );
4419
4420 run_cargo_test(
4421 cargo,
4422 &[],
4423 &[],
4424 "remote-test-client",
4425 bootstrap_host,
4426 builder,
4427 record_failed_tests,
4428 );
4429 }
4430}