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)]
1002pub struct IntrinsicTest {
1003 host: TargetSelection,
1004}
1005
1006impl Step for IntrinsicTest {
1007 type Output = ();
1008 const IS_HOST: bool = true;
1009
1010 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1011 run.path("library/stdarch/crates/intrinsic-test")
1012 }
1013
1014 fn make_run(run: RunConfig<'_>) {
1015 let target = run.target;
1016 if !target.contains("aarch64-unknown-linux") && !target.contains("x86_64-unknown-linux") {
1017 return;
1018 }
1019 run.builder.ensure(IntrinsicTest { host: target });
1020 }
1021
1022 fn run(self, builder: &Builder<'_>) {
1023 let host = self.host;
1024
1025 let (input_file, skip_file, cflags, sde_runner) = if host.contains("x86_64-unknown-linux") {
1026 let cpuid_def =
1027 builder.src.join("library/stdarch/ci/docker/x86_64-unknown-linux-gnu/cpuid.def");
1028 let sde_runner = format!(
1029 "/intel-sde/sde64 -cpuid-in {} -rtm-mode full -tsx --",
1030 cpuid_def.display()
1031 );
1032 (
1033 builder.src.join("library/stdarch/intrinsics_data/x86-intel.xml"),
1034 [
1035 builder
1036 .src
1037 .join("library/stdarch/crates/intrinsic-test/missing_x86_common.txt"),
1038 builder.src.join("library/stdarch/crates/intrinsic-test/missing_x86_gcc.txt"),
1039 ],
1040 "-I/usr/include/x86_64-linux-gnu/",
1041 Some(sde_runner),
1042 )
1043 } else if host.contains("aarch64-unknown-linux") {
1044 (
1045 builder.src.join("library/stdarch/intrinsics_data/arm_intrinsics.json"),
1046 [
1047 builder
1048 .src
1049 .join("library/stdarch/crates/intrinsic-test/missing_aarch64_common.txt"),
1050 builder
1051 .src
1052 .join("library/stdarch/crates/intrinsic-test/missing_aarch64_gcc.txt"),
1053 ],
1054 "-I/usr/aarch64-linux-gnu/include/",
1055 None,
1056 )
1057 } else {
1058 panic!("intrinsic-test only supports aarch64/x86_64 Linux, got {host}");
1059 };
1060
1061 let out_dir = builder.out.join(host).join("intrinsic-test");
1062 t!(fs::create_dir_all(&out_dir));
1063
1064 let crates_link = out_dir.join("crates");
1065 if !crates_link.exists() {
1066 t!(
1067 helpers::symlink_dir(
1068 &builder.config,
1069 &builder.src.join("library/stdarch/crates"),
1070 &crates_link
1071 ),
1072 format!("failed to symlink stdarch crates into {}", crates_link.display())
1073 );
1074 }
1075
1076 let mut cmd = builder.tool_cmd(Tool::IntrinsicTest);
1077 cmd.current_dir(&out_dir);
1078 cmd.arg(&input_file);
1079 cmd.arg("--target").arg(&*host.triple);
1080 for skip in &skip_file {
1081 cmd.arg("--skip").arg(skip);
1082 }
1083 cmd.arg("--sample-percentage").arg("10");
1084 cmd.arg("--cc-arg-style").arg("gcc");
1085 cmd.env("CC", builder.cc(host));
1086 cmd.env("CFLAGS", cflags);
1087 let rustfmt_path = builder.config.initial_rustfmt.clone().unwrap_or_else(|| {
1090 eprintln!("intrinsic-test: rustfmt is required but not available on this channel");
1091 crate::exit!(1);
1092 });
1093
1094 let mut path_dirs: Vec<PathBuf> = Vec::new();
1095 if let Some(cargo_dir) = builder.initial_cargo.parent() {
1096 path_dirs.push(cargo_dir.to_path_buf());
1097 }
1098 if let Some(rustfmt_dir) = rustfmt_path.parent() {
1099 path_dirs.push(rustfmt_dir.to_path_buf());
1100 }
1101 let old_path = env::var_os("PATH").unwrap_or_default();
1102 let new_path = env::join_paths(path_dirs.into_iter().chain(env::split_paths(&old_path)))
1103 .expect("could not build PATH for intrinsic-test");
1104 cmd.env("PATH", new_path);
1105 cmd.run(builder);
1106
1107 let tested_compiler = builder.compiler(builder.top_stage, host);
1108 builder.std(tested_compiler, host);
1109 let rustc = builder.rustc(tested_compiler);
1110
1111 let manifest = out_dir.join("rust_programs/Cargo.toml");
1112 let mut cargo = command(&builder.initial_cargo);
1113 cargo.arg("test");
1114 cargo.arg("--tests");
1115 cargo.arg("--manifest-path").arg(&manifest);
1116 cargo.arg("--target").arg(&*host.triple);
1117 cargo.arg("--profile").arg("release");
1118 cargo.env("CC", builder.cc(host));
1119 cargo.env("CFLAGS", cflags);
1120 cargo.env("RUSTC", rustc);
1121 cargo.env("RUSTC_BOOTSTRAP", "1");
1122 if let Some(runner) = sde_runner {
1123 cargo.env("CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER", runner);
1124 }
1125 cargo.run(builder);
1126 }
1127}
1128
1129#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1130pub struct Clippy {
1131 compilers: RustcPrivateCompilers,
1132}
1133
1134impl Step for Clippy {
1135 type Output = ();
1136 const IS_HOST: bool = true;
1137
1138 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1139 run.suite_path("src/tools/clippy/tests").path("src/tools/clippy")
1140 }
1141
1142 fn is_default_step(_builder: &Builder<'_>) -> bool {
1143 false
1144 }
1145
1146 fn make_run(run: RunConfig<'_>) {
1147 run.builder.ensure(Clippy {
1148 compilers: RustcPrivateCompilers::new(
1149 run.builder,
1150 run.builder.top_stage,
1151 run.builder.host_target,
1152 ),
1153 });
1154 }
1155
1156 fn run(self, builder: &Builder<'_>) {
1158 let target = self.compilers.target();
1159
1160 let target_compiler = self.compilers.target_compiler();
1164 let build_compiler = self.compilers.build_compiler();
1165
1166 builder.ensure(compile::Rustc::new(build_compiler, target));
1170
1171 let mut cargo = tool::prepare_tool_cargo(
1172 builder,
1173 build_compiler,
1174 Mode::ToolRustcPrivate,
1175 target,
1176 Kind::Test,
1177 "src/tools/clippy",
1178 SourceType::InTree,
1179 &[],
1180 );
1181
1182 cargo.env("RUSTC_TEST_SUITE", builder.rustc(build_compiler));
1183 cargo.env("RUSTC_LIB_PATH", builder.rustc_libdir(build_compiler));
1184 let host_libs = builder
1185 .stage_out(build_compiler, Mode::ToolRustcPrivate)
1186 .join(builder.cargo_dir(Mode::ToolRustcPrivate));
1187 cargo.env("HOST_LIBS", host_libs);
1188
1189 builder.std(target_compiler, target);
1191 cargo.env("TEST_SYSROOT", builder.sysroot(target_compiler));
1192 cargo.env("TEST_RUSTC", builder.rustc(target_compiler));
1193 cargo.env("TEST_RUSTC_LIB", builder.rustc_libdir(target_compiler));
1194
1195 'partially_test: {
1197 let paths = &builder.config.paths[..];
1198 let mut test_names = Vec::new();
1199 for path in paths {
1200 match helpers::is_valid_test_suite_arg(path, "src/tools/clippy/tests", builder) {
1201 TestFilterCategory::Arg(path) => {
1202 test_names.push(path);
1203 }
1204 TestFilterCategory::Fullsuite => {
1205 break 'partially_test;
1207 }
1208 TestFilterCategory::Uninteresting => {}
1209 }
1210 }
1211 cargo.env("TESTNAME", test_names.join(","));
1212 }
1213
1214 cargo.add_rustc_lib_path(builder);
1215 let cargo = prepare_cargo_test(cargo, &[], &[], target, builder);
1216
1217 let _guard = builder.msg_test("clippy", target, target_compiler.stage);
1218
1219 if cargo.allow_failure().run(builder) {
1221 return;
1223 }
1224
1225 if !builder.config.cmd.bless() {
1226 crate::exit!(1);
1227 }
1228 }
1229
1230 fn metadata(&self) -> Option<StepMetadata> {
1231 Some(
1232 StepMetadata::test("clippy", self.compilers.target())
1233 .built_by(self.compilers.build_compiler()),
1234 )
1235 }
1236}
1237
1238fn bin_path_for_cargo(builder: &Builder<'_>, compiler: Compiler) -> OsString {
1239 let path = builder.sysroot(compiler).join("bin");
1240 let old_path = env::var_os("PATH").unwrap_or_default();
1241 env::join_paths(iter::once(path).chain(env::split_paths(&old_path))).expect("")
1242}
1243
1244#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1246pub struct RustdocTheme {
1247 test_compiler: Compiler,
1249}
1250
1251impl Step for RustdocTheme {
1252 type Output = ();
1253 const IS_HOST: bool = true;
1254
1255 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1256 run.path("src/tools/rustdoc-themes")
1257 }
1258
1259 fn is_default_step(_builder: &Builder<'_>) -> bool {
1260 true
1261 }
1262
1263 fn make_run(run: RunConfig<'_>) {
1264 let test_compiler = run.builder.compiler(run.builder.top_stage, run.target);
1265
1266 run.builder.ensure(RustdocTheme { test_compiler });
1267 }
1268
1269 fn run(self, builder: &Builder<'_>) {
1270 let rustdoc = builder.bootstrap_out.join("rustdoc");
1271 let mut cmd = builder.tool_cmd(Tool::RustdocTheme);
1272 cmd.arg(rustdoc.to_str().unwrap())
1273 .arg(builder.src.join("src/librustdoc/html/static/css/rustdoc.css").to_str().unwrap())
1274 .env("RUSTC_STAGE", self.test_compiler.stage.to_string())
1275 .env("RUSTC_SYSROOT", builder.sysroot(self.test_compiler))
1276 .env(
1277 "RUSTDOC_LIBDIR",
1278 builder.sysroot_target_libdir(self.test_compiler, self.test_compiler.host),
1279 )
1280 .env("CFG_RELEASE_CHANNEL", &builder.config.channel)
1281 .env("RUSTDOC_REAL", builder.rustdoc_for_compiler(self.test_compiler))
1282 .env("RUSTC_BOOTSTRAP", "1");
1283 cmd.args(linker_args(builder, self.test_compiler.host, LldThreads::No));
1284
1285 cmd.delay_failure().run(builder);
1286 }
1287
1288 fn metadata(&self) -> Option<StepMetadata> {
1289 Some(
1290 StepMetadata::test("rustdoc-theme", self.test_compiler.host)
1291 .stage(self.test_compiler.stage),
1292 )
1293 }
1294}
1295
1296#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1298pub struct RustdocJSStd {
1299 build_compiler: Compiler,
1301 target: TargetSelection,
1302}
1303
1304impl Step for RustdocJSStd {
1305 type Output = ();
1306 const IS_HOST: bool = true;
1307
1308 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1309 run.suite_path("tests/rustdoc-js-std")
1310 }
1311
1312 fn is_default_step(builder: &Builder<'_>) -> bool {
1313 builder.config.nodejs.is_some()
1314 }
1315
1316 fn make_run(run: RunConfig<'_>) {
1317 run.builder.ensure(RustdocJSStd {
1318 build_compiler: run.builder.compiler(run.builder.top_stage, run.builder.host_target),
1319 target: run.target,
1320 });
1321 }
1322
1323 fn run(self, builder: &Builder<'_>) {
1324 let nodejs =
1325 builder.config.nodejs.as_ref().expect("need nodejs to run rustdoc-js-std tests");
1326 let mut command = command(nodejs);
1327 command
1328 .arg(builder.src.join("src/tools/rustdoc-js/tester.js"))
1329 .arg("--crate-name")
1330 .arg("std")
1331 .arg("--resource-suffix")
1332 .arg(&builder.version)
1333 .arg("--doc-folder")
1334 .arg(builder.doc_out(self.target))
1335 .arg("--test-folder")
1336 .arg(builder.src.join("tests/rustdoc-js-std"));
1337
1338 let full_suite = builder.paths.iter().any(|path| {
1339 matches!(
1340 helpers::is_valid_test_suite_arg(path, "tests/rustdoc-js-std", builder),
1341 TestFilterCategory::Fullsuite
1342 )
1343 });
1344
1345 if !full_suite {
1348 for path in &builder.paths {
1349 if let TestFilterCategory::Arg(p) =
1350 helpers::is_valid_test_suite_arg(path, "tests/rustdoc-js-std", builder)
1351 {
1352 if !p.ends_with(".js") {
1353 eprintln!("A non-js file was given: `{}`", path.display());
1354 panic!("Cannot run rustdoc-js-std tests");
1355 }
1356 command.arg("--test-file").arg(path);
1357 }
1358 }
1359 }
1360
1361 builder.ensure(crate::core::build_steps::doc::Std::from_build_compiler(
1362 self.build_compiler,
1363 self.target,
1364 DocumentationFormat::Html,
1365 ));
1366 let _guard = builder.msg_test("rustdoc-js-std", self.target, self.build_compiler.stage);
1367 command.run(builder);
1368 }
1369
1370 fn metadata(&self) -> Option<StepMetadata> {
1371 Some(StepMetadata::test("rustdoc-js-std", self.target).stage(self.build_compiler.stage))
1372 }
1373}
1374
1375#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1376pub struct RustdocJSNotStd {
1377 pub target: TargetSelection,
1378 pub compiler: Compiler,
1379}
1380
1381impl Step for RustdocJSNotStd {
1382 type Output = ();
1383 const IS_HOST: bool = true;
1384
1385 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1386 run.suite_path("tests/rustdoc-js")
1387 }
1388
1389 fn is_default_step(builder: &Builder<'_>) -> bool {
1390 builder.config.nodejs.is_some()
1391 }
1392
1393 fn make_run(run: RunConfig<'_>) {
1394 let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1395 run.builder.ensure(RustdocJSNotStd { target: run.target, compiler });
1396 }
1397
1398 fn run(self, builder: &Builder<'_>) {
1399 builder.ensure(Compiletest {
1400 test_compiler: self.compiler,
1401 target: self.target,
1402 mode: CompiletestMode::RustdocJs,
1403 suite: "rustdoc-js",
1404 path: "tests/rustdoc-js",
1405 compare_mode: None,
1406 });
1407 }
1408}
1409
1410fn get_browser_ui_test_version_inner(
1411 builder: &Builder<'_>,
1412 yarn: &Path,
1413 global: bool,
1414) -> Option<String> {
1415 let mut command = command(yarn);
1416 command
1417 .arg("--cwd")
1418 .arg(&builder.build.out)
1419 .arg("list")
1420 .arg("--parseable")
1421 .arg("--long")
1422 .arg("--depth=0");
1423 if global {
1424 command.arg("--global");
1425 }
1426 let lines = command.allow_failure().cached().run_capture(builder).stdout();
1429 lines
1430 .lines()
1431 .find_map(|l| l.split(':').nth(1)?.strip_prefix("browser-ui-test@"))
1432 .map(|v| v.to_owned())
1433}
1434
1435fn get_browser_ui_test_version(builder: &Builder<'_>) -> Option<String> {
1436 let yarn = builder.config.yarn.as_deref()?;
1437 get_browser_ui_test_version_inner(builder, yarn, false)
1438 .or_else(|| get_browser_ui_test_version_inner(builder, yarn, true))
1439}
1440
1441#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1443pub struct RustdocGUI {
1444 test_compiler: Compiler,
1446 target: TargetSelection,
1447}
1448
1449impl Step for RustdocGUI {
1450 type Output = ();
1451 const IS_HOST: bool = true;
1452
1453 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1454 run.suite_path("tests/rustdoc-gui")
1455 }
1456
1457 fn is_default_step(builder: &Builder<'_>) -> bool {
1458 builder.config.nodejs.is_some()
1459 && builder.test_target != TestTarget::DocOnly
1460 && get_browser_ui_test_version(builder).is_some()
1461 }
1462
1463 fn make_run(run: RunConfig<'_>) {
1464 let test_compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1465 run.builder.ensure(RustdocGUI { test_compiler, target: run.target });
1466 }
1467
1468 fn run(self, builder: &Builder<'_>) {
1469 builder.std(self.test_compiler, self.target);
1470 let record_failed_tests = builder.ensure(SetupFailedTestsFile);
1471
1472 let mut cmd = builder.tool_cmd(Tool::RustdocGUITest);
1473
1474 let out_dir = builder.test_out(self.target).join("rustdoc-gui");
1475 build_stamp::clear_if_dirty(
1476 builder,
1477 &out_dir,
1478 &builder.rustdoc_for_compiler(self.test_compiler),
1479 );
1480
1481 if let Some(src) = builder.config.src.to_str() {
1482 cmd.arg("--rust-src").arg(src);
1483 }
1484
1485 if let Some(out_dir) = out_dir.to_str() {
1486 cmd.arg("--out-dir").arg(out_dir);
1487 }
1488
1489 if let Some(initial_cargo) = builder.config.initial_cargo.to_str() {
1490 cmd.arg("--initial-cargo").arg(initial_cargo);
1491 }
1492
1493 cmd.arg("--jobs").arg(builder.jobs().to_string());
1494
1495 cmd.env("RUSTDOC", builder.rustdoc_for_compiler(self.test_compiler))
1496 .env("RUSTC", builder.rustc(self.test_compiler));
1497
1498 add_rustdoc_cargo_linker_args(&mut cmd, builder, self.test_compiler.host, LldThreads::No);
1499
1500 let full_suite = builder.paths.iter().any(|path| {
1501 matches!(
1502 helpers::is_valid_test_suite_arg(path, "tests/rustdoc-js-std", builder),
1503 TestFilterCategory::Fullsuite
1504 )
1505 });
1506
1507 if !full_suite {
1510 for path in &builder.paths {
1511 if let TestFilterCategory::Arg(p) =
1512 helpers::is_valid_test_suite_arg(path, "tests/rustdoc-gui", builder)
1513 {
1514 if !p.ends_with(".goml") {
1515 eprintln!("A non-goml file was given: `{}`", path.display());
1516 panic!("Cannot run rustdoc-gui tests");
1517 }
1518 if let Some(name) = path.file_name().and_then(|f| f.to_str()) {
1519 cmd.arg("--goml-file").arg(name);
1520 }
1521 }
1522 }
1523 }
1524
1525 for test_arg in builder.config.test_args() {
1526 cmd.arg("--test-arg").arg(test_arg);
1527 }
1528
1529 if let Some(ref nodejs) = builder.config.nodejs {
1530 cmd.arg("--nodejs").arg(nodejs);
1531 }
1532
1533 if let Some(ref yarn) = builder.config.yarn {
1534 cmd.arg("--yarn").arg(yarn);
1535 }
1536
1537 let _time = helpers::timeit(builder);
1538 let _guard = builder.msg_test("rustdoc-gui", self.target, self.test_compiler.stage);
1539 try_run_tests(builder, &mut cmd, true, record_failed_tests);
1540 }
1541
1542 fn metadata(&self) -> Option<StepMetadata> {
1543 Some(StepMetadata::test("rustdoc-gui", self.target).stage(self.test_compiler.stage))
1544 }
1545}
1546
1547#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1552pub struct Tidy;
1553
1554impl Step for Tidy {
1555 type Output = ();
1556 const IS_HOST: bool = true;
1557
1558 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1559 run.path("src/tools/tidy")
1560 }
1561
1562 fn is_default_step(builder: &Builder<'_>) -> bool {
1563 builder.test_target != TestTarget::DocOnly
1564 }
1565
1566 fn make_run(run: RunConfig<'_>) {
1567 run.builder.ensure(Tidy);
1568 }
1569
1570 fn run(self, builder: &Builder<'_>) {
1579 let mut cmd = builder.tool_cmd(Tool::Tidy);
1580 cmd.arg(format!("--root-path={}", builder.src.display()));
1581 cmd.arg(format!("--cargo-path={}", builder.initial_cargo.display()));
1582 cmd.arg(format!("--output-dir={}", builder.out.display()));
1583 let jobs = builder.config.jobs.unwrap_or_else(|| {
1585 8 * std::thread::available_parallelism().map_or(1, std::num::NonZeroUsize::get) as u32
1586 });
1587 cmd.arg(format!("--concurrency={jobs}"));
1588 if let Some(yarn) = &builder.config.yarn {
1590 cmd.arg(format!("--npm-path={}", yarn.display()));
1591 } else {
1592 cmd.arg("--npm-path=yarn");
1593 }
1594 if builder.is_verbose() {
1595 cmd.arg("--verbose");
1596 }
1597 if builder.config.cmd.bless() {
1598 cmd.arg("--bless");
1599 }
1600 if builder.config.is_running_on_ci() {
1601 cmd.arg("--ci=true");
1602 }
1603 if let Some(s) =
1604 builder.config.cmd.extra_checks().or(builder.config.tidy_extra_checks.as_deref())
1605 {
1606 cmd.arg(format!("--extra-checks={s}"));
1607 }
1608 let mut args = std::env::args_os();
1609 if args.any(|arg| arg == OsStr::new("--")) {
1610 cmd.arg("--");
1611 cmd.args(args);
1612 }
1613
1614 if builder.config.channel == "dev" || builder.config.channel == "nightly" {
1615 if !builder.config.json_output {
1616 builder.info("fmt check");
1617 if builder.config.initial_rustfmt.is_none() {
1618 let inferred_rustfmt_dir = builder.initial_sysroot.join("bin");
1619 eprintln!(
1620 "\
1621ERROR: no `rustfmt` binary found in {PATH}
1622INFO: `rust.channel` is currently set to \"{CHAN}\"
1623HELP: if you are testing a beta branch, set `rust.channel` to \"beta\" in the `bootstrap.toml` file
1624HELP: to skip test's attempt to check tidiness, pass `--skip src/tools/tidy` to `x.py test`",
1625 PATH = inferred_rustfmt_dir.display(),
1626 CHAN = builder.config.channel,
1627 );
1628 crate::exit!(1);
1629 }
1630 let all = false;
1631 crate::core::build_steps::format::format(
1632 builder,
1633 !builder.config.cmd.bless(),
1634 all,
1635 &[],
1636 );
1637 } else {
1638 eprintln!(
1639 "WARNING: `--json-output` is not supported on rustfmt, formatting will be skipped"
1640 );
1641 }
1642 }
1643
1644 builder.info("tidy check");
1645 cmd.delay_failure().run(builder);
1646
1647 builder.info("x.py completions check");
1648 let completion_paths = get_completion_paths(builder);
1649 if builder.config.cmd.bless() {
1650 builder.ensure(crate::core::build_steps::run::GenerateCompletions);
1651 } else if completion_paths
1652 .into_iter()
1653 .any(|(shell, path)| get_completion(shell, &path).is_some())
1654 {
1655 eprintln!(
1656 "x.py completions were changed; run `x.py run generate-completions` to update them"
1657 );
1658 crate::exit!(1);
1659 }
1660
1661 builder.info("x.py help check");
1662 if builder.config.cmd.bless() {
1663 builder.ensure(crate::core::build_steps::run::GenerateHelp);
1664 } else {
1665 let help_path = get_help_path(builder);
1666 let cur_help = std::fs::read_to_string(&help_path).unwrap_or_else(|err| {
1667 eprintln!("couldn't read {}: {}", help_path.display(), err);
1668 crate::exit!(1);
1669 });
1670 let new_help = top_level_help();
1671
1672 if new_help != cur_help {
1673 eprintln!("x.py help was changed; run `x.py run generate-help` to update it");
1674 crate::exit!(1);
1675 }
1676 }
1677 }
1678
1679 fn metadata(&self) -> Option<StepMetadata> {
1680 Some(StepMetadata::test("tidy", TargetSelection::default()))
1681 }
1682}
1683
1684#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1687pub struct CrateRunMakeSupport {
1688 host: TargetSelection,
1689}
1690
1691impl Step for CrateRunMakeSupport {
1692 type Output = ();
1693 const IS_HOST: bool = true;
1694
1695 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1696 run.path("src/tools/run-make-support")
1697 }
1698
1699 fn make_run(run: RunConfig<'_>) {
1700 run.builder.ensure(CrateRunMakeSupport { host: run.target });
1701 }
1702
1703 fn run(self, builder: &Builder<'_>) {
1705 let host = self.host;
1706 let compiler = builder.compiler(0, host);
1707 let record_failed_tests = builder.ensure(SetupFailedTestsFile);
1708
1709 let mut cargo = tool::prepare_tool_cargo(
1710 builder,
1711 compiler,
1712 Mode::ToolBootstrap,
1713 host,
1714 Kind::Test,
1715 "src/tools/run-make-support",
1716 SourceType::InTree,
1717 &[],
1718 );
1719 cargo.allow_features("test");
1720 run_cargo_test(
1721 cargo,
1722 &[],
1723 &[],
1724 "run-make-support self test",
1725 host,
1726 builder,
1727 record_failed_tests,
1728 );
1729 }
1730}
1731
1732#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1733pub struct CrateBuildHelper {
1734 host: TargetSelection,
1735}
1736
1737impl Step for CrateBuildHelper {
1738 type Output = ();
1739 const IS_HOST: bool = true;
1740
1741 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1742 run.path("src/build_helper")
1743 }
1744
1745 fn make_run(run: RunConfig<'_>) {
1746 run.builder.ensure(CrateBuildHelper { host: run.target });
1747 }
1748
1749 fn run(self, builder: &Builder<'_>) {
1751 let host = self.host;
1752 let compiler = builder.compiler(0, host);
1753 let record_failed_tests = builder.ensure(SetupFailedTestsFile);
1754
1755 let mut cargo = tool::prepare_tool_cargo(
1756 builder,
1757 compiler,
1758 Mode::ToolBootstrap,
1759 host,
1760 Kind::Test,
1761 "src/build_helper",
1762 SourceType::InTree,
1763 &[],
1764 );
1765 cargo.allow_features("test");
1766 run_cargo_test(
1767 cargo,
1768 &[],
1769 &[],
1770 "build_helper self test",
1771 host,
1772 builder,
1773 record_failed_tests,
1774 );
1775 }
1776}
1777
1778fn testdir(builder: &Builder<'_>, host: TargetSelection) -> PathBuf {
1779 builder.out.join(host).join("test")
1780}
1781
1782macro_rules! test {
1784 (
1785 $( #[$attr:meta] )* $name:ident {
1787 path: $path:expr,
1788 mode: $mode:expr,
1789 suite: $suite:expr,
1790 default: $default:expr
1791 $( , IS_HOST: $IS_HOST:expr )? $( , compare_mode: $compare_mode:expr )? $( , )? }
1795 ) => {
1796 $( #[$attr] )*
1797 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
1798 pub struct $name {
1799 test_compiler: Compiler,
1800 target: TargetSelection,
1801 }
1802
1803 impl Step for $name {
1804 type Output = ();
1805 const IS_HOST: bool = (const {
1806 #[allow(unused_assignments, unused_mut)]
1807 let mut value = false;
1808 $( value = $IS_HOST; )?
1809 value
1810 });
1811
1812 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1813 run.suite_path($path)
1814 }
1815
1816 fn is_default_step(_builder: &Builder<'_>) -> bool {
1817 const { $default }
1818 }
1819
1820 fn make_run(run: RunConfig<'_>) {
1821 let test_compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1822
1823 run.builder.ensure($name { test_compiler, target: run.target });
1824 }
1825
1826 fn run(self, builder: &Builder<'_>) {
1827 builder.ensure(Compiletest {
1828 test_compiler: self.test_compiler,
1829 target: self.target,
1830 mode: const { $mode },
1831 suite: $suite,
1832 path: $path,
1833 compare_mode: (const {
1834 #[allow(unused_assignments, unused_mut)]
1835 let mut value = None;
1836 $( value = $compare_mode; )?
1837 value
1838 }),
1839 })
1840 }
1841 }
1842 };
1843}
1844
1845test!(Ui { path: "tests/ui", mode: CompiletestMode::Ui, suite: "ui", default: true });
1846
1847test!(Crashes {
1848 path: "tests/crashes",
1849 mode: CompiletestMode::Crashes,
1850 suite: "crashes",
1851 default: true,
1852});
1853
1854test!(CodegenLlvm {
1855 path: "tests/codegen-llvm",
1856 mode: CompiletestMode::Codegen,
1857 suite: "codegen-llvm",
1858 default: true
1859});
1860
1861test!(CodegenUnits {
1862 path: "tests/codegen-units",
1863 mode: CompiletestMode::CodegenUnits,
1864 suite: "codegen-units",
1865 default: true,
1866});
1867
1868test!(Incremental {
1869 path: "tests/incremental",
1870 mode: CompiletestMode::Incremental,
1871 suite: "incremental",
1872 default: true,
1873});
1874
1875test!(Debuginfo {
1876 path: "tests/debuginfo",
1877 mode: CompiletestMode::Debuginfo,
1878 suite: "debuginfo",
1879 default: true,
1880 compare_mode: Some("split-dwarf"),
1881});
1882
1883test!(UiFullDeps {
1884 path: "tests/ui-fulldeps",
1885 mode: CompiletestMode::Ui,
1886 suite: "ui-fulldeps",
1887 default: true,
1888 IS_HOST: true,
1889});
1890
1891test!(RustdocHtml {
1892 path: "tests/rustdoc-html",
1893 mode: CompiletestMode::RustdocHtml,
1894 suite: "rustdoc-html",
1895 default: true,
1896 IS_HOST: true,
1897});
1898test!(RustdocUi {
1899 path: "tests/rustdoc-ui",
1900 mode: CompiletestMode::Ui,
1901 suite: "rustdoc-ui",
1902 default: true,
1903 IS_HOST: true,
1904});
1905
1906test!(RustdocJson {
1907 path: "tests/rustdoc-json",
1908 mode: CompiletestMode::RustdocJson,
1909 suite: "rustdoc-json",
1910 default: true,
1911 IS_HOST: true,
1912});
1913
1914test!(Pretty {
1915 path: "tests/pretty",
1916 mode: CompiletestMode::Pretty,
1917 suite: "pretty",
1918 default: true,
1919 IS_HOST: true,
1920});
1921
1922test!(RunMake {
1923 path: "tests/run-make",
1924 mode: CompiletestMode::RunMake,
1925 suite: "run-make",
1926 default: true,
1927});
1928test!(RunMakeCargo {
1929 path: "tests/run-make-cargo",
1930 mode: CompiletestMode::RunMake,
1931 suite: "run-make-cargo",
1932 default: true
1933});
1934test!(BuildStd {
1935 path: "tests/build-std",
1936 mode: CompiletestMode::RunMake,
1937 suite: "build-std",
1938 default: false
1939});
1940
1941test!(AssemblyLlvm {
1942 path: "tests/assembly-llvm",
1943 mode: CompiletestMode::Assembly,
1944 suite: "assembly-llvm",
1945 default: true
1946});
1947
1948#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1951pub struct Coverage {
1952 pub compiler: Compiler,
1953 pub target: TargetSelection,
1954 pub(crate) mode: CompiletestMode,
1955}
1956
1957impl Coverage {
1958 const PATH: &'static str = "tests/coverage";
1959 const SUITE: &'static str = "coverage";
1960 const ALL_MODES: &[CompiletestMode] =
1961 &[CompiletestMode::CoverageMap, CompiletestMode::CoverageRun];
1962}
1963
1964impl Step for Coverage {
1965 type Output = ();
1966 const IS_HOST: bool = false;
1968
1969 fn should_run(mut run: ShouldRun<'_>) -> ShouldRun<'_> {
1970 run = run.suite_path(Self::PATH);
1976 for mode in Self::ALL_MODES {
1977 run = run.alias(mode.as_str());
1978 }
1979 run
1980 }
1981
1982 fn is_default_step(_builder: &Builder<'_>) -> bool {
1983 true
1984 }
1985
1986 fn make_run(run: RunConfig<'_>) {
1987 let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1988 let target = run.target;
1989
1990 let mut modes = vec![];
1994
1995 for path in &run.paths {
1998 match path {
1999 PathSet::Set(_) => {
2000 for &mode in Self::ALL_MODES {
2001 if path.assert_single_path().path == Path::new(mode.as_str()) {
2002 modes.push(mode);
2003 break;
2004 }
2005 }
2006 }
2007 PathSet::Suite(_) => {
2008 modes.extend_from_slice(Self::ALL_MODES);
2009 break;
2010 }
2011 }
2012 }
2013
2014 modes.retain(|mode| {
2017 !run.builder.config.skip.iter().any(|skip| skip == Path::new(mode.as_str()))
2018 });
2019
2020 for mode in modes {
2028 run.builder.ensure(Coverage { compiler, target, mode });
2029 }
2030 }
2031
2032 fn run(self, builder: &Builder<'_>) {
2033 let Self { compiler, target, mode } = self;
2034 builder.ensure(Compiletest {
2037 test_compiler: compiler,
2038 target,
2039 mode,
2040 suite: Self::SUITE,
2041 path: Self::PATH,
2042 compare_mode: None,
2043 });
2044 }
2045}
2046
2047test!(CoverageRunRustdoc {
2048 path: "tests/coverage-run-rustdoc",
2049 mode: CompiletestMode::CoverageRun,
2050 suite: "coverage-run-rustdoc",
2051 default: true,
2052 IS_HOST: true,
2053});
2054
2055#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2057pub struct MirOpt {
2058 pub compiler: Compiler,
2059 pub target: TargetSelection,
2060}
2061
2062impl Step for MirOpt {
2063 type Output = ();
2064
2065 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2066 run.suite_path("tests/mir-opt")
2067 }
2068
2069 fn is_default_step(_builder: &Builder<'_>) -> bool {
2070 true
2071 }
2072
2073 fn make_run(run: RunConfig<'_>) {
2074 let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
2075 run.builder.ensure(MirOpt { compiler, target: run.target });
2076 }
2077
2078 fn run(self, builder: &Builder<'_>) {
2079 let run = |target| {
2080 builder.ensure(Compiletest {
2081 test_compiler: self.compiler,
2082 target,
2083 mode: CompiletestMode::MirOpt,
2084 suite: "mir-opt",
2085 path: "tests/mir-opt",
2086 compare_mode: None,
2087 })
2088 };
2089
2090 run(self.target);
2091
2092 if builder.config.cmd.bless() {
2095 for target in ["aarch64-unknown-linux-gnu", "i686-pc-windows-msvc"] {
2101 run(TargetSelection::from_user(target));
2102 }
2103
2104 for target in ["x86_64-apple-darwin", "i686-unknown-linux-musl"] {
2105 let target = TargetSelection::from_user(target);
2106 let panic_abort_target = builder.ensure(MirOptPanicAbortSyntheticTarget {
2107 compiler: self.compiler,
2108 base: target,
2109 });
2110 run(panic_abort_target);
2111 }
2112 }
2113 }
2114}
2115
2116#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2122struct Compiletest {
2123 test_compiler: Compiler,
2125 target: TargetSelection,
2126 mode: CompiletestMode,
2127 suite: &'static str,
2128 path: &'static str,
2129 compare_mode: Option<&'static str>,
2130}
2131
2132impl Step for Compiletest {
2133 type Output = ();
2134
2135 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2136 run.never()
2137 }
2138
2139 fn run(self, builder: &Builder<'_>) {
2140 if builder.test_target == TestTarget::DocOnly {
2141 return;
2142 }
2143
2144 if builder.top_stage == 0 && !builder.config.compiletest_allow_stage0 {
2145 eprintln!("\
2146ERROR: `--stage 0` runs compiletest on the stage0 (precompiled) compiler, not your local changes, and will almost always cause tests to fail
2147HELP: to test the compiler or standard library, omit the stage or explicitly use `--stage 1` instead
2148NOTE: 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`."
2149 );
2150 crate::exit!(1);
2151 }
2152
2153 let mut test_compiler = self.test_compiler;
2154 let target = self.target;
2155 let mode = self.mode;
2156 let suite = self.suite;
2157 let record_failed_tests = builder.ensure(SetupFailedTestsFile);
2158
2159 let suite_path = self.path;
2161
2162 if !builder.config.codegen_tests && mode == CompiletestMode::Codegen {
2164 return;
2165 }
2166
2167 let query_compiler;
2174 let (stage, stage_id) = if suite == "ui-fulldeps" && test_compiler.stage == 1 {
2175 query_compiler = Some(test_compiler);
2178 let build = builder.build.host_target;
2182 test_compiler = builder.compiler(test_compiler.stage - 1, build);
2183 let test_stage = test_compiler.stage + 1;
2184 (test_stage, format!("stage{test_stage}-{build}"))
2185 } else {
2186 query_compiler = None;
2187 let stage = test_compiler.stage;
2188 (stage, format!("stage{stage}-{target}"))
2189 };
2190
2191 if suite.ends_with("fulldeps") {
2192 builder.ensure(compile::Rustc::new(test_compiler, target));
2193 }
2194
2195 if suite == "debuginfo" {
2196 builder.ensure(dist::DebuggerScripts {
2197 sysroot: builder.sysroot(test_compiler).to_path_buf(),
2198 target,
2199 });
2200 }
2201 if mode == CompiletestMode::RunMake {
2202 builder.tool_exe(Tool::RunMakeSupport);
2203 }
2204
2205 if suite == "mir-opt" {
2207 builder.ensure(
2208 compile::Std::new(test_compiler, test_compiler.host).is_for_mir_opt_tests(true),
2209 );
2210 } else {
2211 builder.std(test_compiler, test_compiler.host);
2212 }
2213
2214 let mut cmd = builder.tool_cmd(Tool::Compiletest);
2215
2216 if suite == "mir-opt" {
2217 builder.ensure(compile::Std::new(test_compiler, target).is_for_mir_opt_tests(true));
2218 } else {
2219 builder.std(test_compiler, target);
2220 }
2221
2222 builder.ensure(RemoteCopyLibs { build_compiler: test_compiler, target });
2223
2224 cmd.arg("--stage").arg(stage.to_string());
2228 cmd.arg("--stage-id").arg(stage_id);
2229
2230 cmd.arg("--compile-lib-path").arg(builder.rustc_libdir(test_compiler));
2231 cmd.arg("--run-lib-path").arg(builder.sysroot_target_libdir(test_compiler, target));
2232 cmd.arg("--rustc-path").arg(builder.rustc(test_compiler));
2233 if let Some(query_compiler) = query_compiler {
2234 cmd.arg("--query-rustc-path").arg(builder.rustc(query_compiler));
2235 }
2236
2237 cmd.arg("--minicore-path")
2240 .arg(builder.src.join("tests").join("auxiliary").join("minicore.rs"));
2241
2242 let is_rustdoc = suite == "rustdoc-ui" || suite == "rustdoc-js";
2243
2244 if mode == CompiletestMode::RunMake {
2259 let stage0_rustc_path = builder.compiler(0, test_compiler.host);
2262 cmd.arg("--stage0-rustc-path").arg(builder.rustc(stage0_rustc_path));
2263
2264 if matches!(suite, "run-make-cargo" | "build-std") {
2265 let cargo_path = if test_compiler.stage == 0 {
2266 builder.initial_cargo.clone()
2268 } else {
2269 builder
2270 .ensure(tool::Cargo::from_build_compiler(
2271 builder.compiler(test_compiler.stage - 1, test_compiler.host),
2272 test_compiler.host,
2273 ))
2274 .tool_path
2275 };
2276
2277 cmd.arg("--cargo-path").arg(cargo_path);
2278 }
2279 }
2280
2281 if matches!(
2283 mode,
2284 CompiletestMode::RunMake
2285 | CompiletestMode::RustdocHtml
2286 | CompiletestMode::RustdocJs
2287 | CompiletestMode::RustdocJson
2288 ) || matches!(suite, "rustdoc-ui" | "coverage-run-rustdoc")
2289 {
2290 cmd.arg("--rustdoc-path").arg(builder.rustdoc_for_compiler(test_compiler));
2291 }
2292
2293 if mode == CompiletestMode::RustdocJson {
2294 let json_compiler = builder.compiler(0, builder.host_target);
2296 cmd.arg("--jsondocck-path")
2297 .arg(builder.ensure(tool::JsonDocCk { compiler: json_compiler, target }).tool_path);
2298 cmd.arg("--jsondoclint-path").arg(
2299 builder.ensure(tool::JsonDocLint { compiler: json_compiler, target }).tool_path,
2300 );
2301 }
2302
2303 if matches!(mode, CompiletestMode::CoverageMap | CompiletestMode::CoverageRun) {
2304 let coverage_dump = builder.tool_exe(Tool::CoverageDump);
2305 cmd.arg("--coverage-dump-path").arg(coverage_dump);
2306 }
2307
2308 cmd.arg("--src-root").arg(&builder.src);
2309 cmd.arg("--src-test-suite-root").arg(builder.src.join("tests").join(suite));
2310
2311 cmd.arg("--build-root").arg(&builder.out);
2315 cmd.arg("--build-test-suite-root").arg(testdir(builder, test_compiler.host).join(suite));
2316
2317 let sysroot = if builder.top_stage == 0 {
2322 builder.initial_sysroot.clone()
2323 } else {
2324 builder.sysroot(test_compiler)
2325 };
2326
2327 cmd.arg("--sysroot-base").arg(sysroot);
2328
2329 cmd.arg("--suite").arg(suite);
2330 cmd.arg("--mode").arg(mode.as_str());
2331 cmd.arg("--target").arg(target.rustc_target_arg());
2332 cmd.arg("--host").arg(&*test_compiler.host.triple);
2333 cmd.arg("--llvm-filecheck").arg(builder.llvm_filecheck(builder.config.host_target));
2334
2335 if let Some(codegen_backend) = builder.config.cmd.test_codegen_backend() {
2336 if !builder
2337 .config
2338 .enabled_codegen_backends(test_compiler.host)
2339 .contains(codegen_backend)
2340 {
2341 eprintln!(
2342 "\
2343ERROR: No configured backend named `{name}`
2344HELP: You can add it into `bootstrap.toml` in `rust.codegen-backends = [{name:?}]`",
2345 name = codegen_backend.name(),
2346 );
2347 crate::exit!(1);
2348 }
2349
2350 if let CodegenBackendKind::Gcc = codegen_backend
2351 && builder.config.rustc_debug_assertions
2352 {
2353 eprintln!(
2354 r#"WARNING: Running tests with the GCC codegen backend while rustc debug assertions are enabled. This might lead to test failures.
2355Please disable assertions with `rust.debug-assertions = false`.
2356 "#
2357 );
2358 }
2359
2360 cmd.arg("--override-codegen-backend").arg(codegen_backend.name());
2363 cmd.arg("--default-codegen-backend").arg(codegen_backend.name());
2366 } else {
2367 cmd.arg("--default-codegen-backend")
2370 .arg(builder.config.default_codegen_backend(test_compiler.host).name());
2371 }
2372 if builder.config.cmd.bypass_ignore_backends() {
2373 cmd.arg("--bypass-ignore-backends");
2374 }
2375
2376 if builder.build.config.llvm_enzyme {
2377 cmd.arg("--has-enzyme");
2378 }
2379
2380 if builder.build.config.llvm_offload {
2381 cmd.arg("--has-offload");
2382 }
2383
2384 if builder.config.cmd.bless() {
2385 cmd.arg("--bless");
2386 }
2387
2388 if builder.config.cmd.force_rerun() {
2389 cmd.arg("--force-rerun");
2390 }
2391
2392 if builder.config.cmd.no_capture() {
2393 cmd.arg("--no-capture");
2394 }
2395
2396 let compare_mode =
2397 builder.config.cmd.compare_mode().or_else(|| {
2398 if builder.config.test_compare_mode { self.compare_mode } else { None }
2399 });
2400
2401 if let Some(ref pass) = builder.config.cmd.pass() {
2402 cmd.arg("--pass");
2403 cmd.arg(pass);
2404 }
2405
2406 if let Some(ref run) = builder.config.cmd.run() {
2407 cmd.arg("--run");
2408 cmd.arg(run);
2409 }
2410
2411 if let Some(ref nodejs) = builder.config.nodejs {
2412 cmd.arg("--nodejs").arg(nodejs);
2413 } else if mode == CompiletestMode::RustdocJs {
2414 panic!("need nodejs to run rustdoc-js suite");
2415 }
2416 if builder.config.rust_optimize_tests {
2417 cmd.arg("--optimize-tests");
2418 }
2419 if builder.config.rust_randomize_layout {
2420 cmd.arg("--rust-randomized-layout");
2421 }
2422 if builder.config.cmd.only_modified() {
2423 cmd.arg("--only-modified");
2424 }
2425 if let Some(compiletest_diff_tool) = &builder.config.compiletest_diff_tool {
2426 cmd.arg("--compiletest-diff-tool").arg(compiletest_diff_tool);
2427 }
2428
2429 let mut flags = if is_rustdoc { Vec::new() } else { vec!["-Crpath".to_string()] };
2430 flags.push(format!(
2431 "-Cdebuginfo={}",
2432 if mode == CompiletestMode::Codegen {
2433 if builder.config.rust_debuginfo_level_tests
2436 != crate::core::config::DebuginfoLevel::None
2437 {
2438 println!(
2439 "NOTE: ignoring `rust.debuginfo-level-tests={}` for codegen tests",
2440 builder.config.rust_debuginfo_level_tests
2441 );
2442 }
2443 crate::core::config::DebuginfoLevel::None
2444 } else {
2445 builder.config.rust_debuginfo_level_tests
2446 }
2447 ));
2448 flags.extend(builder.config.cmd.compiletest_rustc_args().iter().map(|s| s.to_string()));
2449
2450 if suite != "mir-opt" {
2451 if let Some(linker) = builder.linker(target) {
2452 cmd.arg("--target-linker").arg(linker);
2453 }
2454 if let Some(linker) = builder.linker(test_compiler.host) {
2455 cmd.arg("--host-linker").arg(linker);
2456 }
2457 }
2458
2459 if suite == "ui-fulldeps" && target.ends_with("darwin") {
2461 flags.push("-Alinker_messages".into());
2462 }
2463
2464 let mut hostflags = flags.clone();
2465 hostflags.extend(linker_flags(builder, test_compiler.host, LldThreads::No));
2466
2467 let mut targetflags = flags;
2468
2469 if suite == "ui" || suite == "incremental" {
2471 builder.ensure(TestHelpers { target: test_compiler.host });
2472 builder.ensure(TestHelpers { target });
2473 hostflags.push(format!(
2474 "-Lnative={}",
2475 builder.test_helpers_out(test_compiler.host).display()
2476 ));
2477 targetflags.push(format!("-Lnative={}", builder.test_helpers_out(target).display()));
2478 }
2479
2480 for flag in hostflags {
2481 cmd.arg("--host-rustcflags").arg(flag);
2482 }
2483 for flag in targetflags {
2484 cmd.arg("--target-rustcflags").arg(flag);
2485 }
2486 if target.is_synthetic() {
2487 cmd.arg("--target-rustcflags").arg("-Zunstable-options");
2488 }
2489
2490 cmd.arg("--python").arg(
2491 builder.config.python.as_ref().expect("python is required for running rustdoc tests"),
2492 );
2493
2494 let android = android::discover_android(builder, target);
2496 if let Some(android::Android { adb_path, adb_test_dir, android_cross_path }) = &android {
2497 cmd.arg("--adb-path").arg(adb_path);
2498 cmd.arg("--adb-test-dir").arg(adb_test_dir);
2499 cmd.arg("--android-cross-path").arg(android_cross_path);
2500 }
2501
2502 if mode == CompiletestMode::Debuginfo {
2503 if let Some(debuggers::Cdb { cdb }) = debuggers::discover_cdb(target) {
2504 cmd.arg("--cdb").arg(cdb);
2505 }
2506
2507 if let Some(debuggers::Gdb { gdb }) = debuggers::discover_gdb(builder, android.as_ref())
2508 {
2509 cmd.arg("--gdb").arg(gdb.as_ref());
2510 }
2511
2512 if let Some(debuggers::Lldb { lldb_exe, lldb_version }) =
2513 debuggers::discover_lldb(builder)
2514 {
2515 cmd.arg("--lldb").arg(lldb_exe);
2516 cmd.arg("--lldb-version").arg(lldb_version);
2517 }
2518 }
2519
2520 if helpers::forcing_clang_based_tests() {
2521 let clang_exe = builder.llvm_out(target).join("bin").join("clang");
2522 cmd.arg("--run-clang-based-tests-with").arg(clang_exe);
2523 }
2524
2525 for exclude in &builder.config.skip {
2526 cmd.arg("--skip");
2527 cmd.arg(exclude);
2528 }
2529
2530 let mut paths = match &builder.config.cmd {
2532 Subcommand::Test { .. } => &builder.config.paths[..],
2533 _ => &[],
2534 };
2535
2536 let mut paths_v;
2539 if mode == CompiletestMode::RustdocJs {
2540 paths_v = paths.to_vec();
2541 for p in &mut paths_v {
2542 if let Some(ext) = p.extension()
2543 && ext == "js"
2544 {
2545 p.set_extension("rs");
2546 }
2547 }
2548 paths = &paths_v;
2549 }
2550
2551 let mut test_args = Vec::new();
2553 for p in paths {
2554 match helpers::is_valid_test_suite_arg(p, suite_path, builder) {
2555 TestFilterCategory::Fullsuite => {
2556 test_args.clear();
2561 break;
2562 }
2563 TestFilterCategory::Arg(a) => test_args.push(a),
2564 TestFilterCategory::Uninteresting => {}
2565 }
2566 }
2567
2568 test_args.append(&mut builder.config.test_args());
2569
2570 if cfg!(windows) {
2573 let test_args_win: Vec<String> =
2574 test_args.iter().map(|s| s.replace('/', "\\")).collect();
2575 cmd.args(&test_args_win);
2576 } else {
2577 cmd.args(&test_args);
2578 }
2579
2580 if builder.is_verbose() {
2581 cmd.arg("--verbose");
2582 }
2583
2584 if builder.config.cmd.verbose_run_make_subprocess_output() {
2585 cmd.arg("--verbose-run-make-subprocess-output");
2586 }
2587
2588 if builder.config.rustc_debug_assertions {
2589 cmd.arg("--with-rustc-debug-assertions");
2590 }
2591
2592 if builder.config.std_debug_assertions {
2593 cmd.arg("--with-std-debug-assertions");
2594 }
2595
2596 if builder.config.rust_remap_debuginfo {
2597 cmd.arg("--with-std-remap-debuginfo");
2598 }
2599
2600 cmd.arg("--jobs").arg(builder.jobs().to_string());
2601
2602 let mut llvm_components_passed = false;
2603 let mut copts_passed = false;
2604 if builder.config.llvm_enabled(test_compiler.host) {
2605 let llvm::LlvmResult { host_llvm_config, .. } =
2606 builder.ensure(llvm::Llvm { target: builder.config.host_target });
2607 if !builder.config.dry_run() {
2608 let llvm_version = get_llvm_version(builder, &host_llvm_config);
2609 let llvm_components = command(&host_llvm_config)
2610 .cached()
2611 .arg("--components")
2612 .run_capture_stdout(builder)
2613 .stdout();
2614 cmd.arg("--llvm-version")
2616 .arg(llvm_version.trim())
2617 .arg("--llvm-components")
2618 .arg(llvm_components.trim());
2619 llvm_components_passed = true;
2620 }
2621 if !builder.config.is_rust_llvm(target) {
2622 cmd.arg("--system-llvm");
2623 }
2624
2625 if !builder.config.dry_run() && suite.ends_with("fulldeps") {
2630 let llvm_libdir = command(&host_llvm_config)
2631 .cached()
2632 .arg("--libdir")
2633 .run_capture_stdout(builder)
2634 .stdout();
2635 let link_llvm = if target.is_msvc() {
2636 format!("-Clink-arg=-LIBPATH:{llvm_libdir}")
2637 } else {
2638 format!("-Clink-arg=-L{llvm_libdir}")
2639 };
2640 cmd.arg("--host-rustcflags").arg(link_llvm);
2641 }
2642
2643 if !builder.config.dry_run()
2644 && matches!(mode, CompiletestMode::RunMake | CompiletestMode::CoverageRun)
2645 {
2646 let llvm_bin_path = host_llvm_config
2651 .parent()
2652 .expect("Expected llvm-config to be contained in directory");
2653 assert!(llvm_bin_path.is_dir());
2654 cmd.arg("--llvm-bin-dir").arg(llvm_bin_path);
2655 }
2656
2657 if !builder.config.dry_run() && mode == CompiletestMode::RunMake {
2658 if builder.config.lld_enabled {
2660 let lld_install_root =
2661 builder.ensure(llvm::Lld { target: builder.config.host_target });
2662
2663 let lld_bin_path = lld_install_root.join("bin");
2664
2665 let old_path = env::var_os("PATH").unwrap_or_default();
2666 let new_path = env::join_paths(
2667 std::iter::once(lld_bin_path).chain(env::split_paths(&old_path)),
2668 )
2669 .expect("Could not add LLD bin path to PATH");
2670 cmd.env("PATH", new_path);
2671 }
2672 }
2673 }
2674
2675 if !builder.config.dry_run() && mode == CompiletestMode::RunMake {
2678 let mut cflags = builder.cc_handled_clags(target, CLang::C);
2679 cflags.extend(builder.cc_unhandled_cflags(target, GitRepo::Rustc, CLang::C));
2680 let mut cxxflags = builder.cc_handled_clags(target, CLang::Cxx);
2681 cxxflags.extend(builder.cc_unhandled_cflags(target, GitRepo::Rustc, CLang::Cxx));
2682 cmd.arg("--cc")
2683 .arg(builder.cc(target))
2684 .arg("--cxx")
2685 .arg(builder.cxx(target).unwrap())
2686 .arg("--cflags")
2687 .arg(cflags.join(" "))
2688 .arg("--cxxflags")
2689 .arg(cxxflags.join(" "));
2690 copts_passed = true;
2691 if let Some(ar) = builder.ar(target) {
2692 cmd.arg("--ar").arg(ar);
2693 }
2694 }
2695
2696 if !llvm_components_passed {
2697 cmd.arg("--llvm-components").arg("");
2698 }
2699 if !copts_passed {
2700 cmd.arg("--cc")
2701 .arg("")
2702 .arg("--cxx")
2703 .arg("")
2704 .arg("--cflags")
2705 .arg("")
2706 .arg("--cxxflags")
2707 .arg("");
2708 }
2709
2710 if builder.remote_tested(target) {
2711 cmd.arg("--remote-test-client").arg(builder.tool_exe(Tool::RemoteTestClient));
2712 } else if let Some(tool) = builder.runner(target) {
2713 cmd.arg("--runner").arg(tool);
2714 }
2715
2716 if suite != "mir-opt" {
2717 if !builder.config.dry_run() && target.is_msvc() {
2723 for (k, v) in builder.cc[&target].env() {
2724 if k != "PATH" {
2725 cmd.env(k, v);
2726 }
2727 }
2728 }
2729 }
2730
2731 if !builder.config.dry_run()
2733 && target.contains("msvc")
2734 && builder.config.sanitizers_enabled(target)
2735 {
2736 cmd.env("ASAN_WIN_CONTINUE_ON_INTERCEPTION_FAILURE", "1");
2739 let asan_runtime_path = builder.cc[&target].path().parent().unwrap().to_path_buf();
2741 let old_path = cmd
2742 .get_envs()
2743 .find_map(|(k, v)| (k == "PATH").then_some(v))
2744 .flatten()
2745 .map_or_else(|| env::var_os("PATH").unwrap_or_default(), |v| v.to_owned());
2746 let new_path = env::join_paths(
2747 env::split_paths(&old_path).chain(std::iter::once(asan_runtime_path)),
2748 )
2749 .expect("Could not add ASAN runtime path to PATH");
2750 cmd.env("PATH", new_path);
2751 }
2752
2753 cmd.env_remove("CARGO");
2756
2757 cmd.env("RUSTC_BOOTSTRAP", "1");
2758 cmd.env("RUSTC_FORCE_RUSTC_VERSION", "compiletest");
2761 cmd.env("DOC_RUST_LANG_ORG_CHANNEL", builder.doc_rust_lang_org_channel());
2762 builder.add_rust_test_threads(&mut cmd);
2763
2764 if builder.config.sanitizers_enabled(target) {
2765 cmd.env("RUSTC_SANITIZER_SUPPORT", "1");
2766 }
2767
2768 if builder.config.profiler_enabled(target) {
2769 cmd.arg("--profiler-runtime");
2770 }
2771
2772 cmd.env("RUST_TEST_TMPDIR", builder.tempdir());
2773
2774 if builder.config.cmd.rustfix_coverage() {
2775 cmd.arg("--rustfix-coverage");
2776 }
2777
2778 cmd.arg("--channel").arg(&builder.config.channel);
2779
2780 if !builder.config.omit_git_hash {
2781 cmd.arg("--git-hash");
2782 }
2783
2784 let git_config = builder.config.git_config();
2785 cmd.arg("--nightly-branch").arg(git_config.nightly_branch);
2786 cmd.arg("--git-merge-commit-email").arg(git_config.git_merge_commit_email);
2787
2788 #[cfg(feature = "build-metrics")]
2789 builder.metrics.begin_test_suite(
2790 build_helper::metrics::TestSuiteMetadata::Compiletest {
2791 suite: suite.into(),
2792 mode: mode.to_string(),
2793 compare_mode: None,
2794 target: self.target.triple.to_string(),
2795 host: self.test_compiler.host.triple.to_string(),
2796 stage: self.test_compiler.stage,
2797 },
2798 builder,
2799 );
2800
2801 let _group = builder.msg_test(
2802 format!("with compiletest suite={suite} mode={mode}"),
2803 target,
2804 test_compiler.stage,
2805 );
2806 try_run_tests(builder, &mut cmd, false, record_failed_tests.clone());
2807
2808 if let Some(compare_mode) = compare_mode {
2809 cmd.arg("--compare-mode").arg(compare_mode);
2810
2811 #[cfg(feature = "build-metrics")]
2812 builder.metrics.begin_test_suite(
2813 build_helper::metrics::TestSuiteMetadata::Compiletest {
2814 suite: suite.into(),
2815 mode: mode.to_string(),
2816 compare_mode: Some(compare_mode.into()),
2817 target: self.target.triple.to_string(),
2818 host: self.test_compiler.host.triple.to_string(),
2819 stage: self.test_compiler.stage,
2820 },
2821 builder,
2822 );
2823
2824 builder.info(&format!(
2825 "Check compiletest suite={} mode={} compare_mode={} ({} -> {})",
2826 suite, mode, compare_mode, test_compiler.host, target
2827 ));
2828 let _time = helpers::timeit(builder);
2829 try_run_tests(builder, &mut cmd, false, record_failed_tests);
2830 }
2831 }
2832
2833 fn metadata(&self) -> Option<StepMetadata> {
2834 Some(
2835 StepMetadata::test(&format!("compiletest-{}", self.suite), self.target)
2836 .stage(self.test_compiler.stage),
2837 )
2838 }
2839}
2840
2841#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2843struct BookTest {
2844 test_compiler: Compiler,
2845 path: PathBuf,
2846 name: &'static str,
2847 is_ext_doc: bool,
2848 dependencies: Vec<&'static str>,
2849}
2850
2851impl Step for BookTest {
2852 type Output = ();
2853 const IS_HOST: bool = true;
2854
2855 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2856 run.never()
2857 }
2858
2859 fn run(self, builder: &Builder<'_>) {
2860 if self.is_ext_doc {
2870 self.run_ext_doc(builder);
2871 } else {
2872 self.run_local_doc(builder);
2873 }
2874 }
2875}
2876
2877impl BookTest {
2878 fn run_ext_doc(self, builder: &Builder<'_>) {
2881 let test_compiler = self.test_compiler;
2882
2883 builder.std(test_compiler, test_compiler.host);
2884
2885 let mut rustdoc_path = builder.rustdoc_for_compiler(test_compiler);
2888 rustdoc_path.pop();
2889 let old_path = env::var_os("PATH").unwrap_or_default();
2890 let new_path = env::join_paths(iter::once(rustdoc_path).chain(env::split_paths(&old_path)))
2891 .expect("could not add rustdoc to PATH");
2892
2893 let mut rustbook_cmd = builder.tool_cmd(Tool::Rustbook);
2894 let path = builder.src.join(&self.path);
2895 rustbook_cmd.env("RUSTC_BOOTSTRAP", "1");
2897 rustbook_cmd.env("PATH", new_path).arg("test").arg(path);
2898
2899 let libs = if !self.dependencies.is_empty() {
2904 let mut lib_paths = vec![];
2905 for dep in self.dependencies {
2906 let mode = Mode::ToolRustcPrivate;
2907 let target = builder.config.host_target;
2908 let cargo = tool::prepare_tool_cargo(
2909 builder,
2910 test_compiler,
2911 mode,
2912 target,
2913 Kind::Build,
2914 dep,
2915 SourceType::Submodule,
2916 &[],
2917 );
2918
2919 let stamp = BuildStamp::new(&builder.cargo_out(test_compiler, mode, target))
2920 .with_prefix(PathBuf::from(dep).file_name().and_then(|v| v.to_str()).unwrap());
2921
2922 let output_paths =
2923 run_cargo(builder, cargo, vec![], &stamp, vec![], ArtifactKeepMode::OnlyRlib);
2924 let directories = output_paths
2925 .into_iter()
2926 .filter_map(|p| p.parent().map(ToOwned::to_owned))
2927 .fold(HashSet::new(), |mut set, dir| {
2928 set.insert(dir);
2929 set
2930 });
2931
2932 lib_paths.extend(directories);
2933 }
2934 lib_paths
2935 } else {
2936 vec![]
2937 };
2938
2939 if !libs.is_empty() {
2940 let paths = libs
2941 .into_iter()
2942 .map(|path| path.into_os_string())
2943 .collect::<Vec<OsString>>()
2944 .join(OsStr::new(","));
2945 rustbook_cmd.args([OsString::from("--library-path"), paths]);
2946 }
2947
2948 builder.add_rust_test_threads(&mut rustbook_cmd);
2949 let _guard = builder.msg_test(
2950 format_args!("mdbook {}", self.path.display()),
2951 test_compiler.host,
2952 test_compiler.stage,
2953 );
2954 let _time = helpers::timeit(builder);
2955 let toolstate = if rustbook_cmd.delay_failure().run(builder) {
2956 ToolState::TestPass
2957 } else {
2958 ToolState::TestFail
2959 };
2960 builder.save_toolstate(self.name, toolstate);
2961 }
2962
2963 fn run_local_doc(self, builder: &Builder<'_>) {
2965 let test_compiler = self.test_compiler;
2966 let host = self.test_compiler.host;
2967
2968 builder.std(test_compiler, host);
2969
2970 let _guard = builder.msg_test(
2971 format!("book {}", self.name),
2972 test_compiler.host,
2973 test_compiler.stage,
2974 );
2975
2976 let mut stack = vec![builder.src.join(self.path)];
2979 let _time = helpers::timeit(builder);
2980 let mut files = Vec::new();
2981 while let Some(p) = stack.pop() {
2982 if p.is_dir() {
2983 stack.extend(t!(p.read_dir()).map(|p| t!(p).path()));
2984 continue;
2985 }
2986
2987 if p.extension().and_then(|s| s.to_str()) != Some("md") {
2988 continue;
2989 }
2990
2991 files.push(p);
2992 }
2993
2994 files.sort();
2995
2996 for file in files {
2997 markdown_test(builder, test_compiler, &file);
2998 }
2999 }
3000}
3001
3002macro_rules! test_book {
3003 ($(
3004 $name:ident, $path:expr, $book_name:expr,
3005 default=$default:expr
3006 $(,submodules = $submodules:expr)?
3007 $(,dependencies=$dependencies:expr)?
3008 ;
3009 )+) => {
3010 $(
3011 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
3012 pub struct $name {
3013 test_compiler: Compiler,
3014 }
3015
3016 impl Step for $name {
3017 type Output = ();
3018 const IS_HOST: bool = true;
3019
3020 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3021 run.path($path)
3022 }
3023
3024 fn is_default_step(_builder: &Builder<'_>) -> bool {
3025 const { $default }
3026 }
3027
3028 fn make_run(run: RunConfig<'_>) {
3029 run.builder.ensure($name {
3030 test_compiler: run.builder.compiler(run.builder.top_stage, run.target),
3031 });
3032 }
3033
3034 fn run(self, builder: &Builder<'_>) {
3035 $(
3036 for submodule in $submodules {
3037 builder.require_submodule(submodule, None);
3038 }
3039 )*
3040
3041 let dependencies = vec![];
3042 $(
3043 let mut dependencies = dependencies;
3044 for dep in $dependencies {
3045 dependencies.push(dep);
3046 }
3047 )?
3048
3049 builder.ensure(BookTest {
3050 test_compiler: self.test_compiler,
3051 path: PathBuf::from($path),
3052 name: $book_name,
3053 is_ext_doc: !$default,
3054 dependencies,
3055 });
3056 }
3057 }
3058 )+
3059 }
3060}
3061
3062test_book!(
3063 Nomicon, "src/doc/nomicon", "nomicon", default=false, submodules=["src/doc/nomicon"];
3064 Reference, "src/doc/reference", "reference", default=false, submodules=["src/doc/reference"];
3065 RustdocBook, "src/doc/rustdoc", "rustdoc", default=true;
3066 RustcBook, "src/doc/rustc", "rustc", default=true;
3067 RustByExample, "src/doc/rust-by-example", "rust-by-example", default=false, submodules=["src/doc/rust-by-example"];
3068 EmbeddedBook, "src/doc/embedded-book", "embedded-book", default=false, submodules=["src/doc/embedded-book"];
3069 TheBook, "src/doc/book", "book", default=false, submodules=["src/doc/book"], dependencies=["src/doc/book/packages/trpl"];
3070 UnstableBook, "src/doc/unstable-book", "unstable-book", default=true;
3071 EditionGuide, "src/doc/edition-guide", "edition-guide", default=false, submodules=["src/doc/edition-guide"];
3072);
3073
3074#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3075pub struct ErrorIndex {
3076 compilers: RustcPrivateCompilers,
3077}
3078
3079impl Step for ErrorIndex {
3080 type Output = ();
3081 const IS_HOST: bool = true;
3082
3083 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3084 run.path("src/tools/error_index_generator").alias("error-index")
3087 }
3088
3089 fn is_default_step(_builder: &Builder<'_>) -> bool {
3090 true
3091 }
3092
3093 fn make_run(run: RunConfig<'_>) {
3094 let compilers = RustcPrivateCompilers::new(
3098 run.builder,
3099 run.builder.top_stage,
3100 run.builder.config.host_target,
3101 );
3102 run.builder.ensure(ErrorIndex { compilers });
3103 }
3104
3105 fn run(self, builder: &Builder<'_>) {
3112 let target_compiler = self.compilers.target_compiler();
3114
3115 let dir = testdir(builder, target_compiler.host);
3116 t!(fs::create_dir_all(&dir));
3117 let output = dir.join("error-index.md");
3118
3119 let mut tool = tool::ErrorIndex::command(builder, self.compilers);
3120 tool.arg("markdown").arg(&output);
3121
3122 let guard = builder.msg_test("error-index", target_compiler.host, target_compiler.stage);
3123 let _time = helpers::timeit(builder);
3124 tool.run_capture(builder);
3125 drop(guard);
3126 builder.std(target_compiler, target_compiler.host);
3129 markdown_test(builder, target_compiler, &output);
3130 }
3131}
3132
3133fn markdown_test(builder: &Builder<'_>, compiler: Compiler, markdown: &Path) -> bool {
3134 if let Ok(contents) = fs::read_to_string(markdown)
3135 && !contents.contains("```")
3136 {
3137 return true;
3138 }
3139
3140 builder.do_if_verbose(|| println!("doc tests for: {}", markdown.display()));
3141 let mut cmd = builder.rustdoc_cmd(compiler);
3142 builder.add_rust_test_threads(&mut cmd);
3143 cmd.arg("-Z");
3145 cmd.arg("unstable-options");
3146 cmd.arg("--test");
3147 cmd.arg(markdown);
3148 cmd.env("RUSTC_BOOTSTRAP", "1");
3149
3150 let test_args = builder.config.test_args().join(" ");
3151 cmd.arg("--test-args").arg(test_args);
3152
3153 cmd = cmd.delay_failure();
3154 if !builder.config.verbose_tests {
3155 cmd.run_capture(builder).is_success()
3156 } else {
3157 cmd.run(builder)
3158 }
3159}
3160
3161#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3166pub struct CrateLibrustc {
3167 build_compiler: Compiler,
3169 target: TargetSelection,
3170 crates: Vec<String>,
3171}
3172
3173impl Step for CrateLibrustc {
3174 type Output = ();
3175 const IS_HOST: bool = true;
3176
3177 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3178 run.crate_or_deps("rustc-main").path("compiler")
3179 }
3180
3181 fn is_default_step(_builder: &Builder<'_>) -> bool {
3182 true
3183 }
3184
3185 fn make_run(run: RunConfig<'_>) {
3186 let builder = run.builder;
3187 let host = run.build_triple();
3188 let build_compiler = builder.compiler(builder.top_stage - 1, host);
3189 let crates = run.make_run_crates(Alias::Compiler);
3190
3191 builder.ensure(CrateLibrustc { build_compiler, target: run.target, crates });
3192 }
3193
3194 fn run(self, builder: &Builder<'_>) {
3195 builder.std(self.build_compiler, self.target);
3196
3197 builder.ensure(Crate {
3199 build_compiler: self.build_compiler,
3200 target: self.target,
3201 mode: Mode::Rustc,
3202 crates: self.crates,
3203 });
3204 }
3205
3206 fn metadata(&self) -> Option<StepMetadata> {
3207 Some(StepMetadata::test("CrateLibrustc", self.target).built_by(self.build_compiler))
3208 }
3209}
3210
3211fn run_cargo_test<'a>(
3215 cargo: builder::Cargo,
3216 libtest_args: &[&str],
3217 crates: &[String],
3218 description: impl Into<Option<&'a str>>,
3219 target: TargetSelection,
3220 builder: &Builder<'_>,
3221 record_failed_tests: RecordFailedTests,
3222) -> bool {
3223 let compiler = cargo.compiler();
3224 let stage = match cargo.mode() {
3225 Mode::Std => compiler.stage,
3226 _ => compiler.stage + 1,
3227 };
3228
3229 let mut cargo = prepare_cargo_test(cargo, libtest_args, crates, target, builder);
3230 let _time = helpers::timeit(builder);
3231
3232 let _group = description.into().and_then(|what| builder.msg_test(what, target, stage));
3233
3234 #[cfg(feature = "build-metrics")]
3235 builder.metrics.begin_test_suite(
3236 build_helper::metrics::TestSuiteMetadata::CargoPackage {
3237 crates: crates.iter().map(|c| c.to_string()).collect(),
3238 target: target.triple.to_string(),
3239 host: compiler.host.triple.to_string(),
3240 stage: compiler.stage,
3241 },
3242 builder,
3243 );
3244 add_flags_and_try_run_tests(builder, &mut cargo, record_failed_tests)
3245}
3246
3247fn prepare_cargo_test(
3249 cargo: builder::Cargo,
3250 libtest_args: &[&str],
3251 crates: &[String],
3252 target: TargetSelection,
3253 builder: &Builder<'_>,
3254) -> BootstrapCommand {
3255 let compiler = cargo.compiler();
3256 let mut cargo: BootstrapCommand = cargo.into();
3257
3258 if builder.config.cmd.bless() && !cargo.get_envs().any(|v| v.0 == "RUSTC_BLESS") {
3262 cargo.env("RUSTC_BLESS", "Gesundheit");
3263 }
3264
3265 if builder.kind == Kind::Test && !builder.fail_fast {
3269 cargo.arg("--no-fail-fast");
3270 }
3271
3272 if builder.config.json_output {
3273 cargo.arg("--message-format=json");
3274 }
3275
3276 match builder.test_target {
3277 TestTarget::AllTargets => cargo.args(["--bins", "--examples", "--tests", "--benches"]),
3278 TestTarget::Default => &mut cargo,
3279 TestTarget::DocOnly => cargo.arg("--doc"),
3280 TestTarget::Tests => cargo.arg("--tests"),
3281 };
3282
3283 for krate in crates {
3284 cargo.arg("-p").arg(krate);
3285 }
3286
3287 cargo.arg("--").args(builder.config.test_args()).args(libtest_args);
3288 if !builder.config.verbose_tests {
3289 cargo.arg("--quiet");
3290 }
3291
3292 if builder.kind != Kind::Miri {
3301 let mut dylib_paths = builder.rustc_lib_paths(compiler);
3302 dylib_paths.push(builder.sysroot_target_libdir(compiler, target));
3303 helpers::add_dylib_path(dylib_paths, &mut cargo);
3304 }
3305
3306 if builder.remote_tested(target) {
3307 cargo.env(
3308 format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)),
3309 format!("{} run 0", builder.tool_exe(Tool::RemoteTestClient).display()),
3310 );
3311 } else if let Some(tool) = builder.runner(target) {
3312 cargo.env(format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)), tool);
3313 }
3314
3315 cargo
3316}
3317
3318#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3326pub struct Crate {
3327 build_compiler: Compiler,
3329 target: TargetSelection,
3330 mode: Mode,
3331 crates: Vec<String>,
3332}
3333
3334impl Step for Crate {
3335 type Output = ();
3336
3337 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3338 run.crate_or_deps("sysroot").crate_or_deps("coretests").crate_or_deps("alloctests")
3339 }
3340
3341 fn is_default_step(_builder: &Builder<'_>) -> bool {
3342 true
3343 }
3344
3345 fn make_run(run: RunConfig<'_>) {
3346 let builder = run.builder;
3347 let host = run.build_triple();
3348 let build_compiler = builder.compiler(builder.top_stage, host);
3349 let crates = run
3350 .paths
3351 .iter()
3352 .map(|p| builder.crate_paths[&p.assert_single_path().path].clone())
3353 .collect();
3354
3355 builder.ensure(Crate { build_compiler, target: run.target, mode: Mode::Std, crates });
3356 }
3357
3358 fn run(self, builder: &Builder<'_>) {
3367 let build_compiler = self.build_compiler;
3368 let target = self.target;
3369 let mode = self.mode;
3370
3371 builder.ensure(Std::new(build_compiler, build_compiler.host).force_recompile(true));
3374 let record_failed_tests = builder.ensure(SetupFailedTestsFile);
3375
3376 let mut cargo = if builder.kind == Kind::Miri {
3377 if builder.top_stage == 0 {
3378 eprintln!("ERROR: `x.py miri` requires stage 1 or higher");
3379 std::process::exit(1);
3380 }
3381
3382 let mut cargo = builder::Cargo::new(
3385 builder,
3386 build_compiler,
3387 mode,
3388 SourceType::InTree,
3389 target,
3390 Kind::MiriTest,
3391 );
3392 cargo.env("MIRI_REPLACE_LIBRS_IF_NOT_TEST", "1");
3404 cargo.rustflag("-Zforce-unstable-if-unmarked");
3408 cargo.env(
3413 "MIRIFLAGS",
3414 format!(
3415 "{} -Zmiri-env-forward=RUSTC_BOOTSTRAP",
3416 env::var("MIRIFLAGS").unwrap_or_default()
3417 ),
3418 );
3419 cargo
3420 } else {
3421 if !builder.config.is_host_target(target) {
3423 builder.ensure(compile::Std::new(build_compiler, target).force_recompile(true));
3424 builder.ensure(RemoteCopyLibs { build_compiler, target });
3425 }
3426
3427 builder::Cargo::new(
3429 builder,
3430 build_compiler,
3431 mode,
3432 SourceType::InTree,
3433 target,
3434 builder.kind,
3435 )
3436 };
3437
3438 match mode {
3439 Mode::Std => {
3440 if builder.kind == Kind::Miri {
3441 cargo
3447 .arg("--manifest-path")
3448 .arg(builder.src.join("library/sysroot/Cargo.toml"));
3449 } else {
3450 compile::std_cargo(builder, target, &mut cargo, &[]);
3451 }
3452 }
3453 Mode::Rustc => {
3454 compile::rustc_cargo(builder, &mut cargo, target, &build_compiler, &self.crates);
3455 }
3456 _ => panic!("can only test libraries"),
3457 };
3458
3459 let mut crates = self.crates.clone();
3460 if crates.iter().any(|crate_| crate_ == "core") {
3465 crates.push("coretests".to_owned());
3466 }
3467 if crates.iter().any(|crate_| crate_ == "alloc") {
3468 crates.push("alloctests".to_owned());
3469 };
3470 let description = crate_description(&self.crates);
3471 run_cargo_test(cargo, &[], &crates, &*description, target, builder, record_failed_tests);
3472 }
3473}
3474
3475#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3478pub struct CrateRustdoc {
3479 host: TargetSelection,
3480}
3481
3482impl Step for CrateRustdoc {
3483 type Output = ();
3484 const IS_HOST: bool = true;
3485
3486 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3487 run.selectors(&["src/librustdoc", "src/tools/rustdoc"])
3488 }
3489
3490 fn is_default_step(_builder: &Builder<'_>) -> bool {
3491 true
3492 }
3493
3494 fn make_run(run: RunConfig<'_>) {
3495 let builder = run.builder;
3496
3497 builder.ensure(CrateRustdoc { host: run.target });
3498 }
3499
3500 fn run(self, builder: &Builder<'_>) {
3501 let target = self.host;
3502 let record_failed_tests = builder.ensure(SetupFailedTestsFile);
3503
3504 let compiler = if builder.download_rustc() {
3505 builder.compiler(builder.top_stage, target)
3506 } else {
3507 builder.compiler_for(builder.top_stage, target, target)
3512 };
3513 builder.std(compiler, target);
3518 builder.ensure(compile::Rustc::new(compiler, target));
3519
3520 let mut cargo = tool::prepare_tool_cargo(
3521 builder,
3522 compiler,
3523 Mode::ToolRustcPrivate,
3524 target,
3525 builder.kind,
3526 "src/tools/rustdoc",
3527 SourceType::InTree,
3528 &[],
3529 );
3530 if self.host.contains("musl") {
3531 cargo.arg("'-Ctarget-feature=-crt-static'");
3532 }
3533
3534 let libdir = if builder.download_rustc() {
3561 builder.rustc_libdir(compiler)
3562 } else {
3563 builder.sysroot_target_libdir(compiler, target).to_path_buf()
3564 };
3565 let mut dylib_path = dylib_path();
3566 dylib_path.insert(0, PathBuf::from(&*libdir));
3567 cargo.env(dylib_path_var(), env::join_paths(&dylib_path).unwrap());
3568
3569 run_cargo_test(
3570 cargo,
3571 &[],
3572 &["rustdoc:0.0.0".to_string()],
3573 "rustdoc",
3574 target,
3575 builder,
3576 record_failed_tests,
3577 );
3578 }
3579}
3580
3581#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3582pub struct CrateRustdocJsonTypes {
3583 build_compiler: Compiler,
3584 target: TargetSelection,
3585}
3586
3587impl Step for CrateRustdocJsonTypes {
3588 type Output = ();
3589 const IS_HOST: bool = true;
3590
3591 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3592 run.path("src/rustdoc-json-types")
3593 }
3594
3595 fn is_default_step(_builder: &Builder<'_>) -> bool {
3596 true
3597 }
3598
3599 fn make_run(run: RunConfig<'_>) {
3600 let builder = run.builder;
3601
3602 builder.ensure(CrateRustdocJsonTypes {
3603 build_compiler: get_tool_target_compiler(
3604 builder,
3605 ToolTargetBuildMode::Build(run.target),
3606 ),
3607 target: run.target,
3608 });
3609 }
3610
3611 fn run(self, builder: &Builder<'_>) {
3612 let target = self.target;
3613 let record_failed_tests = builder.ensure(SetupFailedTestsFile);
3614
3615 let cargo = tool::prepare_tool_cargo(
3616 builder,
3617 self.build_compiler,
3618 Mode::ToolTarget,
3619 target,
3620 builder.kind,
3621 "src/rustdoc-json-types",
3622 SourceType::InTree,
3623 &["rkyv_0_8".to_owned()],
3624 );
3625
3626 let libtest_args = if target.contains("musl") {
3628 ["'-Ctarget-feature=-crt-static'"].as_slice()
3629 } else {
3630 &[]
3631 };
3632
3633 run_cargo_test(
3634 cargo,
3635 libtest_args,
3636 &["rustdoc-json-types".to_string()],
3637 "rustdoc-json-types",
3638 target,
3639 builder,
3640 record_failed_tests,
3641 );
3642 }
3643}
3644
3645#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3655pub struct RemoteCopyLibs {
3656 build_compiler: Compiler,
3657 target: TargetSelection,
3658}
3659
3660impl Step for RemoteCopyLibs {
3661 type Output = ();
3662
3663 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3664 run.never()
3665 }
3666
3667 fn run(self, builder: &Builder<'_>) {
3668 let build_compiler = self.build_compiler;
3669 let target = self.target;
3670 if !builder.remote_tested(target) {
3671 return;
3672 }
3673
3674 builder.std(build_compiler, target);
3675
3676 builder.info(&format!("REMOTE copy libs to emulator ({target})"));
3677
3678 let remote_test_server = builder.ensure(tool::RemoteTestServer { build_compiler, target });
3679
3680 let tool = builder.tool_exe(Tool::RemoteTestClient);
3682 let mut cmd = command(&tool);
3683 cmd.arg("spawn-emulator")
3684 .arg(target.triple)
3685 .arg(&remote_test_server.tool_path)
3686 .arg(builder.tempdir());
3687 if let Some(rootfs) = builder.qemu_rootfs(target) {
3688 cmd.arg(rootfs);
3689 }
3690 cmd.run(builder);
3691
3692 for f in t!(builder.sysroot_target_libdir(build_compiler, target).read_dir()) {
3694 let f = t!(f);
3695 if helpers::is_dylib(&f.path()) {
3696 command(&tool).arg("push").arg(f.path()).run(builder);
3697 }
3698 }
3699 }
3700}
3701
3702#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3703pub struct Distcheck;
3704
3705impl Step for Distcheck {
3706 type Output = ();
3707
3708 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3709 run.alias("distcheck")
3710 }
3711
3712 fn make_run(run: RunConfig<'_>) {
3713 run.builder.ensure(Distcheck);
3714 }
3715
3716 fn run(self, builder: &Builder<'_>) {
3726 let root_dir = std::env::temp_dir().join("distcheck");
3729
3730 distcheck_plain_source_tarball(builder, &root_dir.join("distcheck-rustc-src"));
3731 distcheck_rust_src(builder, &root_dir.join("distcheck-rust-src"));
3732 distcheck_rustc_dev(builder, &root_dir.join("distcheck-rustc-dev"));
3733 }
3734}
3735
3736fn distcheck_plain_source_tarball(builder: &Builder<'_>, plain_src_dir: &Path) {
3738 builder.info("Distcheck plain source tarball");
3739 let plain_src_tarball = builder.ensure(dist::PlainSourceTarball);
3740 builder.clear_dir(plain_src_dir);
3741
3742 let configure_args: Vec<String> = std::env::var("DISTCHECK_CONFIGURE_ARGS")
3743 .map(|args| args.split(" ").map(|s| s.to_string()).collect::<Vec<String>>())
3744 .unwrap_or_default();
3745
3746 command("tar")
3747 .arg("-xf")
3748 .arg(plain_src_tarball.tarball())
3749 .arg("--strip-components=1")
3750 .current_dir(plain_src_dir)
3751 .run(builder);
3752 command("./configure")
3753 .arg("--set")
3754 .arg("rust.omit-git-hash=false")
3755 .arg("--set")
3756 .arg("rust.remap-debuginfo=false")
3757 .args(&configure_args)
3758 .arg("--enable-vendor")
3759 .current_dir(plain_src_dir)
3760 .run(builder);
3761 command(helpers::make(&builder.config.host_target.triple))
3762 .arg("check")
3763 .env("GITHUB_ACTIONS", "0")
3766 .current_dir(plain_src_dir)
3767 .run(builder);
3768 builder.remove_dir(plain_src_dir);
3770}
3771
3772fn distcheck_rust_src(builder: &Builder<'_>, src_dir: &Path) {
3774 builder.info("Distcheck rust-src");
3775 let src_tarball = builder.ensure(dist::Src);
3776 builder.clear_dir(src_dir);
3777
3778 command("tar")
3779 .arg("-xf")
3780 .arg(src_tarball.tarball())
3781 .arg("--strip-components=1")
3782 .current_dir(src_dir)
3783 .run(builder);
3784
3785 let toml = src_dir.join("rust-src/lib/rustlib/src/rust/library/std/Cargo.toml");
3786 command(&builder.initial_cargo)
3787 .env("RUSTC_BOOTSTRAP", "1")
3790 .arg("generate-lockfile")
3791 .arg("--manifest-path")
3792 .arg(&toml)
3793 .current_dir(src_dir)
3794 .run(builder);
3795 builder.remove_dir(src_dir);
3797}
3798
3799fn distcheck_rustc_dev(builder: &Builder<'_>, dir: &Path) {
3801 builder.info("Distcheck rustc-dev");
3802 let tarball = builder.ensure(dist::RustcDev::new(builder, builder.host_target)).unwrap();
3803 builder.clear_dir(dir);
3804
3805 command("tar")
3806 .arg("-xf")
3807 .arg(tarball.tarball())
3808 .arg("--strip-components=1")
3809 .current_dir(dir)
3810 .run(builder);
3811
3812 command(&builder.initial_cargo)
3813 .arg("metadata")
3814 .arg("--manifest-path")
3815 .arg("rustc-dev/lib/rustlib/rustc-src/rust/compiler/rustc/Cargo.toml")
3816 .env("RUSTC_BOOTSTRAP", "1")
3817 .env("RUSTC", &builder.initial_rustc)
3819 .current_dir(dir)
3820 .run(builder);
3821 builder.remove_dir(dir);
3823}
3824
3825#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3827pub(crate) struct BootstrapPy;
3828
3829impl Step for BootstrapPy {
3830 type Output = ();
3831 const IS_HOST: bool = true;
3832
3833 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3834 run.alias("bootstrap-py")
3835 }
3836
3837 fn is_default_step(builder: &Builder<'_>) -> bool {
3838 builder.config.is_running_on_ci()
3842 }
3843
3844 fn make_run(run: RunConfig<'_>) {
3845 run.builder.ensure(BootstrapPy)
3846 }
3847
3848 fn run(self, builder: &Builder<'_>) -> Self::Output {
3849 let mut check_bootstrap = command(
3850 builder.config.python.as_ref().expect("python is required for running bootstrap tests"),
3851 );
3852 check_bootstrap
3853 .args(["-m", "unittest", "bootstrap_test.py"])
3854 .args(builder.config.test_args())
3856 .env("BUILD_DIR", &builder.out)
3857 .env("BUILD_PLATFORM", builder.build.host_target.triple)
3858 .env("BOOTSTRAP_TEST_RUSTC_BIN", &builder.initial_rustc)
3859 .env("BOOTSTRAP_TEST_CARGO_BIN", &builder.initial_cargo)
3860 .current_dir(builder.src.join("src/bootstrap/"));
3861 check_bootstrap.delay_failure().run(builder);
3862 }
3863}
3864
3865#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3866pub struct Bootstrap;
3867
3868impl Step for Bootstrap {
3869 type Output = ();
3870 const IS_HOST: bool = true;
3871
3872 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3873 run.path("src/bootstrap")
3874 }
3875
3876 fn is_default_step(builder: &Builder<'_>) -> bool {
3877 builder.config.is_running_on_ci()
3881 }
3882
3883 fn run(self, builder: &Builder<'_>) {
3885 let host = builder.config.host_target;
3886 let build_compiler = builder.compiler(0, host);
3887 let record_failed_tests = builder.ensure(SetupFailedTestsFile);
3888
3889 builder.build.require_submodule("src/tools/cargo", None);
3891
3892 let mut cargo = tool::prepare_tool_cargo(
3893 builder,
3894 build_compiler,
3895 Mode::ToolBootstrap,
3896 host,
3897 Kind::Test,
3898 "src/bootstrap",
3899 SourceType::InTree,
3900 &[],
3901 );
3902
3903 cargo.release_build(false);
3904
3905 cargo
3906 .rustflag("-Cdebuginfo=2")
3907 .env("CARGO_TARGET_DIR", builder.out.join("bootstrap"))
3908 .env("INSTA_WORKSPACE_ROOT", &builder.src)
3910 .env("RUSTC_BOOTSTRAP", "1");
3911
3912 if builder.config.cmd.bless() {
3913 cargo.env("INSTA_UPDATE", "always");
3917 }
3918
3919 run_cargo_test(cargo, &[], &[], None, host, builder, record_failed_tests);
3920 }
3921
3922 fn make_run(run: RunConfig<'_>) {
3923 run.builder.ensure(Bootstrap);
3924 }
3925}
3926
3927fn get_compiler_to_test(builder: &Builder<'_>, target: TargetSelection) -> Compiler {
3928 builder.compiler(builder.top_stage, target)
3929}
3930
3931#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3934pub struct TierCheck {
3935 test_compiler: Compiler,
3936}
3937
3938impl Step for TierCheck {
3939 type Output = ();
3940 const IS_HOST: bool = true;
3941
3942 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3943 run.path("src/tools/tier-check")
3944 }
3945
3946 fn is_default_step(_builder: &Builder<'_>) -> bool {
3947 true
3948 }
3949
3950 fn make_run(run: RunConfig<'_>) {
3951 run.builder
3952 .ensure(TierCheck { test_compiler: get_compiler_to_test(run.builder, run.target) });
3953 }
3954
3955 fn run(self, builder: &Builder<'_>) {
3956 let tool_build_compiler = builder.compiler(0, builder.host_target);
3957
3958 let mut cargo = tool::prepare_tool_cargo(
3959 builder,
3960 tool_build_compiler,
3961 Mode::ToolBootstrap,
3962 tool_build_compiler.host,
3963 Kind::Run,
3964 "src/tools/tier-check",
3965 SourceType::InTree,
3966 &[],
3967 );
3968 cargo.arg(builder.src.join("src/doc/rustc/src/platform-support.md"));
3969 cargo.arg(builder.rustc(self.test_compiler));
3970
3971 let _guard = builder.msg_test(
3972 "platform support check",
3973 self.test_compiler.host,
3974 self.test_compiler.stage,
3975 );
3976 BootstrapCommand::from(cargo).delay_failure().run(builder);
3977 }
3978
3979 fn metadata(&self) -> Option<StepMetadata> {
3980 Some(StepMetadata::test("tier-check", self.test_compiler.host))
3981 }
3982}
3983
3984#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3985pub struct LintDocs {
3986 build_compiler: Compiler,
3987 target: TargetSelection,
3988}
3989
3990impl Step for LintDocs {
3991 type Output = ();
3992 const IS_HOST: bool = true;
3993
3994 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3995 run.path("src/tools/lint-docs")
3996 }
3997
3998 fn is_default_step(builder: &Builder<'_>) -> bool {
3999 builder.top_stage >= 2
4002 }
4003
4004 fn make_run(run: RunConfig<'_>) {
4005 if run.builder.top_stage < 2 {
4006 eprintln!("WARNING: lint-docs tests might not work below stage 2");
4007 }
4008
4009 run.builder.ensure(LintDocs {
4010 build_compiler: prepare_doc_compiler(
4011 run.builder,
4012 run.builder.config.host_target,
4013 run.builder.top_stage,
4014 ),
4015 target: run.target,
4016 });
4017 }
4018
4019 fn run(self, builder: &Builder<'_>) {
4022 builder.ensure(crate::core::build_steps::doc::RustcBook::validate(
4023 self.build_compiler,
4024 self.target,
4025 ));
4026 }
4027
4028 fn metadata(&self) -> Option<StepMetadata> {
4029 Some(StepMetadata::test("lint-docs", self.target).built_by(self.build_compiler))
4030 }
4031}
4032
4033#[derive(Debug, Clone, PartialEq, Eq, Hash)]
4034pub struct RustInstaller;
4035
4036impl Step for RustInstaller {
4037 type Output = ();
4038 const IS_HOST: bool = true;
4039
4040 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
4041 run.path("src/tools/rust-installer")
4042 }
4043
4044 fn is_default_step(_builder: &Builder<'_>) -> bool {
4045 true
4046 }
4047
4048 fn make_run(run: RunConfig<'_>) {
4049 run.builder.ensure(Self);
4050 }
4051
4052 fn run(self, builder: &Builder<'_>) {
4054 let bootstrap_host = builder.config.host_target;
4055 let build_compiler = builder.compiler(0, bootstrap_host);
4056 let record_failed_tests = builder.ensure(SetupFailedTestsFile);
4057 let cargo = tool::prepare_tool_cargo(
4058 builder,
4059 build_compiler,
4060 Mode::ToolBootstrap,
4061 bootstrap_host,
4062 Kind::Test,
4063 "src/tools/rust-installer",
4064 SourceType::InTree,
4065 &[],
4066 );
4067
4068 let _guard = builder.msg_test("rust-installer", bootstrap_host, 1);
4069 run_cargo_test(cargo, &[], &[], None, bootstrap_host, builder, record_failed_tests);
4070
4071 if bootstrap_host != "x86_64-unknown-linux-gnu" {
4075 return;
4076 }
4077
4078 let mut cmd = command(builder.src.join("src/tools/rust-installer/test.sh"));
4079 let tmpdir = testdir(builder, build_compiler.host).join("rust-installer");
4080 let _ = std::fs::remove_dir_all(&tmpdir);
4081 let _ = std::fs::create_dir_all(&tmpdir);
4082 cmd.current_dir(&tmpdir);
4083 cmd.env("CARGO_TARGET_DIR", tmpdir.join("cargo-target"));
4084 cmd.env("CARGO", &builder.initial_cargo);
4085 cmd.env("RUSTC", &builder.initial_rustc);
4086 cmd.env("TMP_DIR", &tmpdir);
4087 cmd.delay_failure().run(builder);
4088 }
4089}
4090
4091#[derive(Debug, Clone, PartialEq, Eq, Hash)]
4092pub struct TestHelpers {
4093 pub target: TargetSelection,
4094}
4095
4096impl Step for TestHelpers {
4097 type Output = ();
4098
4099 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
4100 run.path("tests/auxiliary/rust_test_helpers.c")
4101 }
4102
4103 fn make_run(run: RunConfig<'_>) {
4104 run.builder.ensure(TestHelpers { target: run.target })
4105 }
4106
4107 fn run(self, builder: &Builder<'_>) {
4110 if builder.config.dry_run() {
4111 return;
4112 }
4113 let target = if self.target == "x86_64-fortanix-unknown-sgx" {
4117 TargetSelection::from_user("x86_64-unknown-linux-gnu")
4118 } else {
4119 self.target
4120 };
4121 let dst = builder.test_helpers_out(target);
4122 let src = builder.src.join("tests/auxiliary/rust_test_helpers.c");
4123 if up_to_date(&src, &dst.join("librust_test_helpers.a")) {
4124 return;
4125 }
4126
4127 let _guard = builder.msg_unstaged(Kind::Build, "test helpers", target);
4128 t!(fs::create_dir_all(&dst));
4129 let mut cfg = cc::Build::new();
4130
4131 if !target.is_msvc() {
4135 if let Some(ar) = builder.ar(target) {
4136 cfg.archiver(ar);
4137 }
4138 cfg.compiler(builder.cc(target));
4139 }
4140 cfg.cargo_metadata(false)
4141 .out_dir(&dst)
4142 .target(&target.triple)
4143 .host(&builder.config.host_target.triple)
4144 .opt_level(0)
4145 .warnings(false)
4146 .debug(false)
4147 .file(builder.src.join("tests/auxiliary/rust_test_helpers.c"))
4148 .compile("rust_test_helpers");
4149 }
4150}
4151
4152#[derive(Debug, Clone, PartialEq, Eq, Hash)]
4153pub struct CodegenCranelift {
4154 compilers: RustcPrivateCompilers,
4155 target: TargetSelection,
4156}
4157
4158impl Step for CodegenCranelift {
4159 type Output = ();
4160 const IS_HOST: bool = true;
4161
4162 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
4163 run.path("compiler/rustc_codegen_cranelift")
4164 }
4165
4166 fn is_default_step(_builder: &Builder<'_>) -> bool {
4167 true
4168 }
4169
4170 fn make_run(run: RunConfig<'_>) {
4171 let builder = run.builder;
4172 let host = run.build_triple();
4173 let compilers = RustcPrivateCompilers::new(run.builder, run.builder.top_stage, host);
4174
4175 if builder.test_target == TestTarget::DocOnly {
4176 return;
4177 }
4178
4179 if builder.download_rustc() {
4180 builder.info("CI rustc uses the default codegen backend. skipping");
4181 return;
4182 }
4183
4184 if !target_supports_cranelift_backend(run.target) {
4185 builder.info("target not supported by rustc_codegen_cranelift. skipping");
4186 return;
4187 }
4188
4189 if builder.remote_tested(run.target) {
4190 builder.info("remote testing is not supported by rustc_codegen_cranelift. skipping");
4191 return;
4192 }
4193
4194 if !builder
4195 .config
4196 .enabled_codegen_backends(run.target)
4197 .contains(&CodegenBackendKind::Cranelift)
4198 {
4199 builder.info("cranelift not in rust.codegen-backends. skipping");
4200 return;
4201 }
4202
4203 builder.ensure(CodegenCranelift { compilers, target: run.target });
4204 }
4205
4206 fn run(self, builder: &Builder<'_>) {
4207 let compilers = self.compilers;
4208 let build_compiler = compilers.build_compiler();
4209
4210 let target_compiler = compilers.target_compiler();
4213 let target = self.target;
4214
4215 builder.std(target_compiler, target);
4216
4217 let mut cargo = builder::Cargo::new(
4218 builder,
4219 target_compiler,
4220 Mode::Codegen, SourceType::InTree,
4222 target,
4223 Kind::Run,
4224 );
4225
4226 cargo.current_dir(&builder.src.join("compiler/rustc_codegen_cranelift"));
4227 cargo
4228 .arg("--manifest-path")
4229 .arg(builder.src.join("compiler/rustc_codegen_cranelift/build_system/Cargo.toml"));
4230 compile::rustc_cargo_env(builder, &mut cargo, target);
4231
4232 cargo.env("CARGO_BUILD_INCREMENTAL", "false");
4234
4235 let _guard = builder.msg_test(
4236 "rustc_codegen_cranelift",
4237 target_compiler.host,
4238 target_compiler.stage,
4239 );
4240
4241 let download_dir = builder.out.join("cg_clif_download");
4243
4244 cargo
4245 .arg("--")
4246 .arg("test")
4247 .arg("--download-dir")
4248 .arg(&download_dir)
4249 .arg("--out-dir")
4250 .arg(builder.stage_out(build_compiler, Mode::Codegen).join("cg_clif"))
4251 .arg("--no-unstable-features")
4252 .arg("--use-backend")
4253 .arg("cranelift")
4254 .arg("--sysroot")
4256 .arg("llvm")
4257 .arg("--skip-test")
4260 .arg("testsuite.extended_sysroot");
4261
4262 cargo.into_cmd().run(builder);
4263 }
4264
4265 fn metadata(&self) -> Option<StepMetadata> {
4266 Some(
4267 StepMetadata::test("rustc_codegen_cranelift", self.target)
4268 .built_by(self.compilers.build_compiler()),
4269 )
4270 }
4271}
4272
4273#[derive(Debug, Clone, PartialEq, Eq, Hash)]
4274pub struct CodegenGCC {
4275 compilers: RustcPrivateCompilers,
4276 target: TargetSelection,
4277}
4278
4279impl Step for CodegenGCC {
4280 type Output = ();
4281 const IS_HOST: bool = true;
4282
4283 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
4284 run.path("compiler/rustc_codegen_gcc")
4285 }
4286
4287 fn is_default_step(_builder: &Builder<'_>) -> bool {
4288 true
4289 }
4290
4291 fn make_run(run: RunConfig<'_>) {
4292 let builder = run.builder;
4293 let host = run.build_triple();
4294 let compilers = RustcPrivateCompilers::new(run.builder, run.builder.top_stage, host);
4295
4296 if builder.test_target == TestTarget::DocOnly {
4297 return;
4298 }
4299
4300 if builder.download_rustc() {
4301 builder.info("CI rustc uses the default codegen backend. skipping");
4302 return;
4303 }
4304
4305 let triple = run.target.triple;
4306 let target_supported =
4307 if triple.contains("linux") { triple.contains("x86_64") } else { false };
4308 if !target_supported {
4309 builder.info("target not supported by rustc_codegen_gcc. skipping");
4310 return;
4311 }
4312
4313 if builder.remote_tested(run.target) {
4314 builder.info("remote testing is not supported by rustc_codegen_gcc. skipping");
4315 return;
4316 }
4317
4318 if !builder.config.enabled_codegen_backends(run.target).contains(&CodegenBackendKind::Gcc) {
4319 builder.info("gcc not in rust.codegen-backends. skipping");
4320 return;
4321 }
4322
4323 builder.ensure(CodegenGCC { compilers, target: run.target });
4324 }
4325
4326 fn run(self, builder: &Builder<'_>) {
4327 let compilers = self.compilers;
4328 let target = self.target;
4329
4330 let gcc = builder.ensure(Gcc { target_pair: GccTargetPair::for_native_build(target) });
4331
4332 builder.ensure(
4333 compile::Std::new(compilers.build_compiler(), target)
4334 .extra_rust_args(&["-Csymbol-mangling-version=v0", "-Cpanic=abort"]),
4335 );
4336
4337 let _guard = builder.msg_test(
4338 "rustc_codegen_gcc",
4339 compilers.target(),
4340 compilers.target_compiler().stage,
4341 );
4342
4343 let mut cargo = builder::Cargo::new(
4344 builder,
4345 compilers.build_compiler(),
4346 Mode::Codegen, SourceType::InTree,
4348 target,
4349 Kind::Run,
4350 );
4351
4352 cargo.current_dir(&builder.src.join("compiler/rustc_codegen_gcc"));
4353 cargo
4354 .arg("--manifest-path")
4355 .arg(builder.src.join("compiler/rustc_codegen_gcc/build_system/Cargo.toml"));
4356 compile::rustc_cargo_env(builder, &mut cargo, target);
4357 add_cg_gcc_cargo_flags(&mut cargo, &gcc);
4358
4359 cargo.env("CARGO_BUILD_INCREMENTAL", "false");
4361 cargo.rustflag("-Cpanic=abort");
4362
4363 cargo
4364 .env("CG_RUSTFLAGS", "-Alinker-messages")
4366 .arg("--")
4367 .arg("test")
4368 .arg("--use-backend")
4369 .arg("gcc")
4370 .arg("--gcc-path")
4371 .arg(gcc.libgccjit().parent().unwrap())
4372 .arg("--out-dir")
4373 .arg(builder.stage_out(compilers.build_compiler(), Mode::Codegen).join("cg_gcc"))
4374 .arg("--release")
4375 .arg("--mini-tests")
4376 .arg("--std-tests");
4377
4378 cargo.args(builder.config.test_args());
4379
4380 cargo.into_cmd().run(builder);
4381 }
4382
4383 fn metadata(&self) -> Option<StepMetadata> {
4384 Some(
4385 StepMetadata::test("rustc_codegen_gcc", self.target)
4386 .built_by(self.compilers.build_compiler()),
4387 )
4388 }
4389}
4390
4391#[derive(Debug, Clone, PartialEq, Eq, Hash)]
4396pub struct TestFloatParse {
4397 build_compiler: Compiler,
4406 target: TargetSelection,
4408}
4409
4410impl Step for TestFloatParse {
4411 type Output = ();
4412 const IS_HOST: bool = true;
4413
4414 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
4415 run.path("src/tools/test-float-parse")
4416 }
4417
4418 fn is_default_step(_builder: &Builder<'_>) -> bool {
4419 true
4420 }
4421
4422 fn make_run(run: RunConfig<'_>) {
4423 run.builder.ensure(Self {
4424 build_compiler: get_compiler_to_test(run.builder, run.target),
4425 target: run.target,
4426 });
4427 }
4428
4429 fn run(self, builder: &Builder<'_>) {
4430 let build_compiler = self.build_compiler;
4431 let target = self.target;
4432
4433 builder.std(build_compiler, target);
4435 builder.std(build_compiler, builder.host_target);
4436 let record_failed_tests = builder.ensure(SetupFailedTestsFile);
4437
4438 let mut cargo_test = tool::prepare_tool_cargo(
4440 builder,
4441 build_compiler,
4442 Mode::ToolStd,
4443 target,
4444 Kind::Test,
4445 "src/tools/test-float-parse",
4446 SourceType::InTree,
4447 &[],
4448 );
4449 cargo_test.allow_features(TEST_FLOAT_PARSE_ALLOW_FEATURES);
4450
4451 run_cargo_test(
4452 cargo_test,
4453 &[],
4454 &[],
4455 "test-float-parse",
4456 target,
4457 builder,
4458 record_failed_tests,
4459 );
4460
4461 let mut cargo_run = tool::prepare_tool_cargo(
4463 builder,
4464 build_compiler,
4465 Mode::ToolStd,
4466 target,
4467 Kind::Run,
4468 "src/tools/test-float-parse",
4469 SourceType::InTree,
4470 &[],
4471 );
4472 cargo_run.allow_features(TEST_FLOAT_PARSE_ALLOW_FEATURES);
4473
4474 if !matches!(env::var("FLOAT_PARSE_TESTS_NO_SKIP_HUGE").as_deref(), Ok("1") | Ok("true")) {
4475 cargo_run.args(["--", "--skip-huge"]);
4476 }
4477
4478 cargo_run.into_cmd().run(builder);
4479 }
4480}
4481
4482#[derive(Debug, Clone, Hash, PartialEq, Eq)]
4486pub struct CollectLicenseMetadata;
4487
4488impl Step for CollectLicenseMetadata {
4489 type Output = PathBuf;
4490 const IS_HOST: bool = true;
4491
4492 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
4493 run.path("src/tools/collect-license-metadata")
4494 }
4495
4496 fn make_run(run: RunConfig<'_>) {
4497 run.builder.ensure(CollectLicenseMetadata);
4498 }
4499
4500 fn run(self, builder: &Builder<'_>) -> Self::Output {
4501 let Some(reuse) = &builder.config.reuse else {
4502 panic!("REUSE is required to collect the license metadata");
4503 };
4504
4505 let dest = builder.src.join("license-metadata.json");
4506
4507 let mut cmd = builder.tool_cmd(Tool::CollectLicenseMetadata);
4508 cmd.env("REUSE_EXE", reuse);
4509 cmd.env("DEST", &dest);
4510 cmd.env("ONLY_CHECK", "1");
4511 cmd.run(builder);
4512
4513 dest
4514 }
4515}
4516
4517#[derive(Debug, Clone, PartialEq, Eq, Hash)]
4518pub struct RemoteTestClientTests {
4519 host: TargetSelection,
4520}
4521
4522impl Step for RemoteTestClientTests {
4523 type Output = ();
4524 const IS_HOST: bool = true;
4525
4526 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
4527 run.path("src/tools/remote-test-client")
4528 }
4529
4530 fn is_default_step(_builder: &Builder<'_>) -> bool {
4531 true
4532 }
4533
4534 fn make_run(run: RunConfig<'_>) {
4535 run.builder.ensure(Self { host: run.target });
4536 }
4537
4538 fn run(self, builder: &Builder<'_>) {
4539 let bootstrap_host = builder.config.host_target;
4540 let compiler = builder.compiler(0, bootstrap_host);
4541 let record_failed_tests = builder.ensure(SetupFailedTestsFile);
4542
4543 let cargo = tool::prepare_tool_cargo(
4544 builder,
4545 compiler,
4546 Mode::ToolBootstrap,
4547 bootstrap_host,
4548 Kind::Test,
4549 "src/tools/remote-test-client",
4550 SourceType::InTree,
4551 &[],
4552 );
4553
4554 run_cargo_test(
4555 cargo,
4556 &[],
4557 &[],
4558 "remote-test-client",
4559 bootstrap_host,
4560 builder,
4561 record_failed_tests,
4562 );
4563 }
4564}