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