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