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