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