1use std::collections::HashSet;
7use std::env::split_paths;
8use std::ffi::{OsStr, OsString};
9use std::path::{Path, PathBuf};
10use std::{env, fs, iter};
11
12use build_helper::exit;
13
14use crate::core::build_steps::compile::{Std, run_cargo};
15use crate::core::build_steps::doc::{DocumentationFormat, prepare_doc_compiler};
16use crate::core::build_steps::gcc::{Gcc, add_cg_gcc_cargo_flags};
17use crate::core::build_steps::llvm::get_llvm_version;
18use crate::core::build_steps::run::get_completion_paths;
19use crate::core::build_steps::synthetic_targets::MirOptPanicAbortSyntheticTarget;
20use crate::core::build_steps::tool::{
21 self, RustcPrivateCompilers, SourceType, TEST_FLOAT_PARSE_ALLOW_FEATURES, Tool,
22 ToolTargetBuildMode, get_tool_target_compiler,
23};
24use crate::core::build_steps::toolstate::ToolState;
25use crate::core::build_steps::{compile, dist, llvm};
26use crate::core::builder::{
27 self, Alias, Builder, Compiler, Kind, RunConfig, ShouldRun, Step, StepMetadata,
28 crate_description,
29};
30use crate::core::config::TargetSelection;
31use crate::core::config::flags::{Subcommand, get_completion};
32use crate::utils::build_stamp::{self, BuildStamp};
33use crate::utils::exec::{BootstrapCommand, command};
34use crate::utils::helpers::{
35 self, LldThreads, add_dylib_path, add_rustdoc_cargo_linker_args, dylib_path, dylib_path_var,
36 linker_args, linker_flags, t, target_supports_cranelift_backend, up_to_date,
37};
38use crate::utils::render_tests::{add_flags_and_try_run_tests, try_run_tests};
39use crate::{CLang, CodegenBackendKind, DocTests, GitRepo, Mode, PathSet, envify};
40
41const ADB_TEST_DIR: &str = "/data/local/tmp/work";
42
43#[derive(Debug, Clone, PartialEq, Eq, Hash)]
45pub struct CrateBootstrap {
46 path: PathBuf,
47 host: TargetSelection,
48}
49
50impl Step for CrateBootstrap {
51 type Output = ();
52 const IS_HOST: bool = true;
53 const DEFAULT: bool = true;
54
55 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
56 run.path("src/tools/jsondoclint")
61 .path("src/tools/replace-version-placeholder")
62 .path("src/tools/coverage-dump")
63 .alias("tidyselftest")
66 }
67
68 fn make_run(run: RunConfig<'_>) {
69 for path in run.paths {
72 let path = path.assert_single_path().path.clone();
73 run.builder.ensure(CrateBootstrap { host: run.target, path });
74 }
75 }
76
77 fn run(self, builder: &Builder<'_>) {
78 let bootstrap_host = builder.config.host_target;
79 let compiler = builder.compiler(0, bootstrap_host);
80 let mut path = self.path.to_str().unwrap();
81
82 if path == "tidyselftest" {
84 path = "src/tools/tidy";
85 }
86
87 let cargo = tool::prepare_tool_cargo(
88 builder,
89 compiler,
90 Mode::ToolBootstrap,
91 bootstrap_host,
92 Kind::Test,
93 path,
94 SourceType::InTree,
95 &[],
96 );
97
98 let crate_name = path.rsplit_once('/').unwrap().1;
99 run_cargo_test(cargo, &[], &[], crate_name, bootstrap_host, builder);
100 }
101
102 fn metadata(&self) -> Option<StepMetadata> {
103 Some(
104 StepMetadata::test("crate-bootstrap", self.host)
105 .with_metadata(self.path.as_path().to_string_lossy().to_string()),
106 )
107 }
108}
109
110#[derive(Debug, Clone, PartialEq, Eq, Hash)]
111pub struct Linkcheck {
112 host: TargetSelection,
113}
114
115impl Step for Linkcheck {
116 type Output = ();
117 const IS_HOST: bool = true;
118 const DEFAULT: bool = true;
119
120 fn run(self, builder: &Builder<'_>) {
125 let host = self.host;
126 let hosts = &builder.hosts;
127 let targets = &builder.targets;
128
129 if (hosts != targets) && !hosts.is_empty() && !targets.is_empty() {
134 panic!(
135 "Linkcheck currently does not support builds with different hosts and targets.
136You can skip linkcheck with --skip src/tools/linkchecker"
137 );
138 }
139
140 builder.info(&format!("Linkcheck ({host})"));
141
142 let bootstrap_host = builder.config.host_target;
144 let compiler = builder.compiler(0, bootstrap_host);
145
146 let cargo = tool::prepare_tool_cargo(
147 builder,
148 compiler,
149 Mode::ToolBootstrap,
150 bootstrap_host,
151 Kind::Test,
152 "src/tools/linkchecker",
153 SourceType::InTree,
154 &[],
155 );
156 run_cargo_test(cargo, &[], &[], "linkchecker self tests", bootstrap_host, builder);
157
158 if builder.doc_tests == DocTests::No {
159 return;
160 }
161
162 builder.run_default_doc_steps();
164
165 let linkchecker = builder.tool_cmd(Tool::Linkchecker);
167
168 let _guard = builder.msg_test("Linkcheck", bootstrap_host, 1);
170 let _time = helpers::timeit(builder);
171 linkchecker.delay_failure().arg(builder.out.join(host).join("doc")).run(builder);
172 }
173
174 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
175 let builder = run.builder;
176 let run = run.path("src/tools/linkchecker");
177 run.default_condition(builder.config.docs)
178 }
179
180 fn make_run(run: RunConfig<'_>) {
181 run.builder.ensure(Linkcheck { host: run.target });
182 }
183
184 fn metadata(&self) -> Option<StepMetadata> {
185 Some(StepMetadata::test("link-check", self.host))
186 }
187}
188
189fn check_if_tidy_is_installed(builder: &Builder<'_>) -> bool {
190 command("tidy").allow_failure().arg("--version").run_capture_stdout(builder).is_success()
191}
192
193#[derive(Debug, Clone, PartialEq, Eq, Hash)]
194pub struct HtmlCheck {
195 target: TargetSelection,
196}
197
198impl Step for HtmlCheck {
199 type Output = ();
200 const DEFAULT: bool = true;
201 const IS_HOST: bool = true;
202
203 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
204 let builder = run.builder;
205 let run = run.path("src/tools/html-checker");
206 run.lazy_default_condition(Box::new(|| check_if_tidy_is_installed(builder)))
207 }
208
209 fn make_run(run: RunConfig<'_>) {
210 run.builder.ensure(HtmlCheck { target: run.target });
211 }
212
213 fn run(self, builder: &Builder<'_>) {
214 if !check_if_tidy_is_installed(builder) {
215 eprintln!("not running HTML-check tool because `tidy` is missing");
216 eprintln!(
217 "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."
218 );
219 panic!("Cannot run html-check tests");
220 }
221 builder.run_default_doc_steps();
223 builder.ensure(crate::core::build_steps::doc::Rustc::for_stage(
224 builder,
225 builder.top_stage,
226 self.target,
227 ));
228
229 builder
230 .tool_cmd(Tool::HtmlChecker)
231 .delay_failure()
232 .arg(builder.doc_out(self.target))
233 .run(builder);
234 }
235
236 fn metadata(&self) -> Option<StepMetadata> {
237 Some(StepMetadata::test("html-check", self.target))
238 }
239}
240
241#[derive(Debug, Clone, PartialEq, Eq, Hash)]
245pub struct Cargotest {
246 build_compiler: Compiler,
247 host: TargetSelection,
248}
249
250impl Step for Cargotest {
251 type Output = ();
252 const IS_HOST: bool = true;
253
254 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
255 run.path("src/tools/cargotest")
256 }
257
258 fn make_run(run: RunConfig<'_>) {
259 if run.builder.top_stage == 0 {
260 eprintln!(
261 "ERROR: running cargotest with stage 0 is currently unsupported. Use at least stage 1."
262 );
263 exit!(1);
264 }
265 run.builder.ensure(Cargotest {
269 build_compiler: run.builder.compiler(run.builder.top_stage - 1, run.target),
270 host: run.target,
271 });
272 }
273
274 fn run(self, builder: &Builder<'_>) {
279 let cargo =
289 builder.ensure(tool::Cargo::from_build_compiler(self.build_compiler, self.host));
290 let tested_compiler = builder.compiler(self.build_compiler.stage + 1, self.host);
291 builder.std(tested_compiler, self.host);
292
293 let out_dir = builder.out.join("ct");
297 t!(fs::create_dir_all(&out_dir));
298
299 let _time = helpers::timeit(builder);
300 let mut cmd = builder.tool_cmd(Tool::CargoTest);
301 cmd.arg(&cargo.tool_path)
302 .arg(&out_dir)
303 .args(builder.config.test_args())
304 .env("RUSTC", builder.rustc(tested_compiler))
305 .env("RUSTDOC", builder.rustdoc_for_compiler(tested_compiler));
306 add_rustdoc_cargo_linker_args(&mut cmd, builder, tested_compiler.host, LldThreads::No);
307 cmd.delay_failure().run(builder);
308 }
309
310 fn metadata(&self) -> Option<StepMetadata> {
311 Some(StepMetadata::test("cargotest", self.host).stage(self.build_compiler.stage + 1))
312 }
313}
314
315#[derive(Debug, Clone, PartialEq, Eq, Hash)]
318pub struct Cargo {
319 build_compiler: Compiler,
320 host: TargetSelection,
321}
322
323impl Cargo {
324 const CRATE_PATH: &str = "src/tools/cargo";
325}
326
327impl Step for Cargo {
328 type Output = ();
329 const IS_HOST: bool = true;
330
331 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
332 run.path(Self::CRATE_PATH)
333 }
334
335 fn make_run(run: RunConfig<'_>) {
336 run.builder.ensure(Cargo {
337 build_compiler: get_tool_target_compiler(
338 run.builder,
339 ToolTargetBuildMode::Build(run.target),
340 ),
341 host: run.target,
342 });
343 }
344
345 fn run(self, builder: &Builder<'_>) {
347 builder.ensure(tool::Cargo::from_build_compiler(self.build_compiler, self.host));
351
352 let tested_compiler = builder.compiler(self.build_compiler.stage + 1, self.host);
353 builder.std(tested_compiler, self.host);
354 builder.rustdoc_for_compiler(tested_compiler);
358
359 let cargo = tool::prepare_tool_cargo(
360 builder,
361 self.build_compiler,
362 Mode::ToolTarget,
363 self.host,
364 Kind::Test,
365 Self::CRATE_PATH,
366 SourceType::Submodule,
367 &[],
368 );
369
370 let mut cargo = prepare_cargo_test(cargo, &[], &[], self.host, builder);
372
373 cargo.env("CFG_DISABLE_CROSS_TESTS", "1");
376 cargo.env("CARGO_TEST_DISABLE_NIGHTLY", "1");
379
380 cargo.env("PATH", bin_path_for_cargo(builder, tested_compiler));
384
385 let mut existing_dylib_paths = cargo
390 .get_envs()
391 .find(|(k, _)| *k == OsStr::new(dylib_path_var()))
392 .and_then(|(_, v)| v)
393 .map(|value| split_paths(value).collect::<Vec<PathBuf>>())
394 .unwrap_or_default();
395 existing_dylib_paths.insert(0, builder.rustc_libdir(tested_compiler));
396 add_dylib_path(existing_dylib_paths, &mut cargo);
397
398 cargo.env("CARGO_RUSTC_CURRENT_DIR", builder.src.display().to_string());
402
403 #[cfg(feature = "build-metrics")]
404 builder.metrics.begin_test_suite(
405 build_helper::metrics::TestSuiteMetadata::CargoPackage {
406 crates: vec!["cargo".into()],
407 target: self.host.triple.to_string(),
408 host: self.host.triple.to_string(),
409 stage: self.build_compiler.stage + 1,
410 },
411 builder,
412 );
413
414 let _time = helpers::timeit(builder);
415 add_flags_and_try_run_tests(builder, &mut cargo);
416 }
417
418 fn metadata(&self) -> Option<StepMetadata> {
419 Some(StepMetadata::test("cargo", self.host).built_by(self.build_compiler))
420 }
421}
422
423#[derive(Debug, Clone, PartialEq, Eq, Hash)]
424pub struct RustAnalyzer {
425 compilers: RustcPrivateCompilers,
426}
427
428impl Step for RustAnalyzer {
429 type Output = ();
430 const IS_HOST: bool = true;
431 const DEFAULT: bool = true;
432
433 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
434 run.path("src/tools/rust-analyzer")
435 }
436
437 fn make_run(run: RunConfig<'_>) {
438 run.builder.ensure(Self {
439 compilers: RustcPrivateCompilers::new(
440 run.builder,
441 run.builder.top_stage,
442 run.builder.host_target,
443 ),
444 });
445 }
446
447 fn run(self, builder: &Builder<'_>) {
449 let host = self.compilers.target();
450
451 let workspace_path = "src/tools/rust-analyzer";
452 let crate_path = "src/tools/rust-analyzer/crates/proc-macro-srv";
455 let mut cargo = tool::prepare_tool_cargo(
456 builder,
457 self.compilers.build_compiler(),
458 Mode::ToolRustcPrivate,
459 host,
460 Kind::Test,
461 crate_path,
462 SourceType::InTree,
463 &["in-rust-tree".to_owned()],
464 );
465 cargo.allow_features(tool::RustAnalyzer::ALLOW_FEATURES);
466
467 let dir = builder.src.join(workspace_path);
468 cargo.env("CARGO_WORKSPACE_DIR", &dir);
471
472 cargo.env("SKIP_SLOW_TESTS", "1");
475
476 cargo.add_rustc_lib_path(builder);
477 run_cargo_test(cargo, &[], &[], "rust-analyzer", host, builder);
478 }
479
480 fn metadata(&self) -> Option<StepMetadata> {
481 Some(
482 StepMetadata::test("rust-analyzer", self.compilers.target())
483 .built_by(self.compilers.build_compiler()),
484 )
485 }
486}
487
488#[derive(Debug, Clone, PartialEq, Eq, Hash)]
490pub struct Rustfmt {
491 compilers: RustcPrivateCompilers,
492}
493
494impl Step for Rustfmt {
495 type Output = ();
496 const IS_HOST: bool = true;
497
498 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
499 run.path("src/tools/rustfmt")
500 }
501
502 fn make_run(run: RunConfig<'_>) {
503 run.builder.ensure(Rustfmt {
504 compilers: RustcPrivateCompilers::new(
505 run.builder,
506 run.builder.top_stage,
507 run.builder.host_target,
508 ),
509 });
510 }
511
512 fn run(self, builder: &Builder<'_>) {
514 let tool_result = builder.ensure(tool::Rustfmt::from_compilers(self.compilers));
515 let build_compiler = tool_result.build_compiler;
516 let target = self.compilers.target();
517
518 let mut cargo = tool::prepare_tool_cargo(
519 builder,
520 build_compiler,
521 Mode::ToolRustcPrivate,
522 target,
523 Kind::Test,
524 "src/tools/rustfmt",
525 SourceType::InTree,
526 &[],
527 );
528
529 let dir = testdir(builder, target);
530 t!(fs::create_dir_all(&dir));
531 cargo.env("RUSTFMT_TEST_DIR", dir);
532
533 cargo.add_rustc_lib_path(builder);
534
535 run_cargo_test(cargo, &[], &[], "rustfmt", target, builder);
536 }
537
538 fn metadata(&self) -> Option<StepMetadata> {
539 Some(
540 StepMetadata::test("rustfmt", self.compilers.target())
541 .built_by(self.compilers.build_compiler()),
542 )
543 }
544}
545
546#[derive(Debug, Clone, PartialEq, Eq, Hash)]
547pub struct Miri {
548 target: TargetSelection,
549}
550
551impl Miri {
552 pub fn build_miri_sysroot(
554 builder: &Builder<'_>,
555 compiler: Compiler,
556 target: TargetSelection,
557 ) -> PathBuf {
558 let miri_sysroot = builder.out.join(compiler.host).join("miri-sysroot");
559 let mut cargo = builder::Cargo::new(
560 builder,
561 compiler,
562 Mode::Std,
563 SourceType::Submodule,
564 target,
565 Kind::MiriSetup,
566 );
567
568 cargo.env("MIRI_LIB_SRC", builder.src.join("library"));
570 cargo.env("MIRI_SYSROOT", &miri_sysroot);
572
573 let mut cargo = BootstrapCommand::from(cargo);
574 let _guard =
575 builder.msg(Kind::Build, "miri sysroot", Mode::ToolRustcPrivate, compiler, target);
576 cargo.run(builder);
577
578 cargo.arg("--print-sysroot");
584
585 builder.do_if_verbose(|| println!("running: {cargo:?}"));
586 let stdout = cargo.run_capture_stdout(builder).stdout();
587 let sysroot = stdout.trim_end();
589 builder.do_if_verbose(|| println!("`cargo miri setup --print-sysroot` said: {sysroot:?}"));
590 PathBuf::from(sysroot)
591 }
592}
593
594impl Step for Miri {
595 type Output = ();
596
597 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
598 run.path("src/tools/miri")
599 }
600
601 fn make_run(run: RunConfig<'_>) {
602 run.builder.ensure(Miri { target: run.target });
603 }
604
605 fn run(self, builder: &Builder<'_>) {
607 let host = builder.build.host_target;
608 let target = self.target;
609 let stage = builder.top_stage;
610 if stage == 0 {
611 eprintln!("miri cannot be tested at stage 0");
612 std::process::exit(1);
613 }
614
615 let compilers = RustcPrivateCompilers::new(builder, stage, host);
617
618 let miri = builder.ensure(tool::Miri::from_compilers(compilers));
620 builder.ensure(tool::CargoMiri::from_compilers(compilers));
622
623 let target_compiler = compilers.target_compiler();
624
625 let miri_sysroot = Miri::build_miri_sysroot(builder, target_compiler, target);
628 builder.std(target_compiler, host);
629 let host_sysroot = builder.sysroot(target_compiler);
630
631 if !builder.config.dry_run() {
634 let ui_test_dep_dir = builder
637 .stage_out(miri.build_compiler, Mode::ToolStd)
638 .join(host)
639 .join("tmp")
640 .join("miri_ui");
641 build_stamp::clear_if_dirty(builder, &ui_test_dep_dir, &miri_sysroot);
645 }
646
647 let mut cargo = tool::prepare_tool_cargo(
650 builder,
651 miri.build_compiler,
652 Mode::ToolRustcPrivate,
653 host,
654 Kind::Test,
655 "src/tools/miri",
656 SourceType::InTree,
657 &[],
658 );
659
660 cargo.add_rustc_lib_path(builder);
661
662 let mut cargo = prepare_cargo_test(cargo, &[], &[], host, builder);
665
666 cargo.env("MIRI_SYSROOT", &miri_sysroot);
668 cargo.env("MIRI_HOST_SYSROOT", &host_sysroot);
669 cargo.env("MIRI", &miri.tool_path);
670
671 cargo.env("MIRI_TEST_TARGET", target.rustc_target_arg());
673
674 {
675 let _guard = builder.msg_test("miri", target, target_compiler.stage);
676 let _time = helpers::timeit(builder);
677 cargo.run(builder);
678 }
679
680 if builder.config.test_args().is_empty() {
682 cargo.env("MIRIFLAGS", "-O -Zmir-opt-level=4 -Cdebug-assertions=yes");
683 cargo.env("MIRI_SKIP_UI_CHECKS", "1");
685 cargo.env_remove("RUSTC_BLESS");
687 cargo.args(["tests/pass", "tests/panic"]);
689
690 {
691 let _guard =
692 builder.msg_test("miri (mir-opt-level 4)", target, target_compiler.stage);
693 let _time = helpers::timeit(builder);
694 cargo.run(builder);
695 }
696 }
697 }
698}
699
700#[derive(Debug, Clone, PartialEq, Eq, Hash)]
703pub struct CargoMiri {
704 target: TargetSelection,
705}
706
707impl Step for CargoMiri {
708 type Output = ();
709
710 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
711 run.path("src/tools/miri/cargo-miri")
712 }
713
714 fn make_run(run: RunConfig<'_>) {
715 run.builder.ensure(CargoMiri { target: run.target });
716 }
717
718 fn run(self, builder: &Builder<'_>) {
720 let host = builder.build.host_target;
721 let target = self.target;
722 let stage = builder.top_stage;
723 if stage == 0 {
724 eprintln!("cargo-miri cannot be tested at stage 0");
725 std::process::exit(1);
726 }
727
728 let build_compiler = builder.compiler(stage, host);
730
731 let mut cargo = tool::prepare_tool_cargo(
736 builder,
737 build_compiler,
738 Mode::ToolStd, target,
740 Kind::MiriTest,
741 "src/tools/miri/test-cargo-miri",
742 SourceType::Submodule,
743 &[],
744 );
745
746 match builder.doc_tests {
749 DocTests::Yes => {}
750 DocTests::No => {
751 cargo.args(["--lib", "--bins", "--examples", "--tests", "--benches"]);
752 }
753 DocTests::Only => {
754 cargo.arg("--doc");
755 }
756 }
757 cargo.arg("--").args(builder.config.test_args());
758
759 let mut cargo = BootstrapCommand::from(cargo);
761 {
762 let _guard = builder.msg_test("cargo-miri", target, stage);
763 let _time = helpers::timeit(builder);
764 cargo.run(builder);
765 }
766 }
767}
768
769#[derive(Debug, Clone, PartialEq, Eq, Hash)]
770pub struct CompiletestTest {
771 host: TargetSelection,
772}
773
774impl Step for CompiletestTest {
775 type Output = ();
776
777 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
778 run.path("src/tools/compiletest")
779 }
780
781 fn make_run(run: RunConfig<'_>) {
782 run.builder.ensure(CompiletestTest { host: run.target });
783 }
784
785 fn run(self, builder: &Builder<'_>) {
787 let host = self.host;
788
789 if builder.top_stage == 0 && !builder.config.compiletest_allow_stage0 {
795 eprintln!("\
796ERROR: `--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
797NOTE: 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`."
798 );
799 crate::exit!(1);
800 }
801
802 let bootstrap_compiler = builder.compiler(0, host);
803 let staged_compiler = builder.compiler(builder.top_stage, host);
804
805 let mut cargo = tool::prepare_tool_cargo(
806 builder,
807 bootstrap_compiler,
808 Mode::ToolBootstrap,
809 host,
810 Kind::Test,
811 "src/tools/compiletest",
812 SourceType::InTree,
813 &[],
814 );
815
816 cargo.env("TEST_RUSTC", builder.rustc(staged_compiler));
820
821 run_cargo_test(cargo, &[], &[], "compiletest self test", host, builder);
822 }
823}
824
825#[derive(Debug, Clone, PartialEq, Eq, Hash)]
826pub struct Clippy {
827 compilers: RustcPrivateCompilers,
828}
829
830impl Step for Clippy {
831 type Output = ();
832 const IS_HOST: bool = true;
833 const DEFAULT: bool = false;
834
835 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
836 run.suite_path("src/tools/clippy/tests").path("src/tools/clippy")
837 }
838
839 fn make_run(run: RunConfig<'_>) {
840 run.builder.ensure(Clippy {
841 compilers: RustcPrivateCompilers::new(
842 run.builder,
843 run.builder.top_stage,
844 run.builder.host_target,
845 ),
846 });
847 }
848
849 fn run(self, builder: &Builder<'_>) {
851 let target = self.compilers.target();
852
853 let compilers = self.compilers;
857 let target_compiler = compilers.target_compiler();
858
859 let tool_result = builder.ensure(tool::Clippy::from_compilers(compilers));
860 let build_compiler = tool_result.build_compiler;
861 let mut cargo = tool::prepare_tool_cargo(
862 builder,
863 build_compiler,
864 Mode::ToolRustcPrivate,
865 target,
866 Kind::Test,
867 "src/tools/clippy",
868 SourceType::InTree,
869 &[],
870 );
871
872 cargo.env("RUSTC_TEST_SUITE", builder.rustc(build_compiler));
873 cargo.env("RUSTC_LIB_PATH", builder.rustc_libdir(build_compiler));
874 let host_libs =
875 builder.stage_out(build_compiler, Mode::ToolRustcPrivate).join(builder.cargo_dir());
876 cargo.env("HOST_LIBS", host_libs);
877
878 builder.std(target_compiler, target);
880 cargo.env("TEST_SYSROOT", builder.sysroot(target_compiler));
881 cargo.env("TEST_RUSTC", builder.rustc(target_compiler));
882 cargo.env("TEST_RUSTC_LIB", builder.rustc_libdir(target_compiler));
883
884 'partially_test: {
886 let paths = &builder.config.paths[..];
887 let mut test_names = Vec::new();
888 for path in paths {
889 if let Some(path) =
890 helpers::is_valid_test_suite_arg(path, "src/tools/clippy/tests", builder)
891 {
892 test_names.push(path);
893 } else if path.ends_with("src/tools/clippy") {
894 break 'partially_test;
896 }
897 }
898 cargo.env("TESTNAME", test_names.join(","));
899 }
900
901 cargo.add_rustc_lib_path(builder);
902 let cargo = prepare_cargo_test(cargo, &[], &[], target, builder);
903
904 let _guard = builder.msg_test("clippy", target, target_compiler.stage);
905
906 if cargo.allow_failure().run(builder) {
908 return;
910 }
911
912 if !builder.config.cmd.bless() {
913 crate::exit!(1);
914 }
915 }
916
917 fn metadata(&self) -> Option<StepMetadata> {
918 Some(
919 StepMetadata::test("clippy", self.compilers.target())
920 .built_by(self.compilers.build_compiler()),
921 )
922 }
923}
924
925fn bin_path_for_cargo(builder: &Builder<'_>, compiler: Compiler) -> OsString {
926 let path = builder.sysroot(compiler).join("bin");
927 let old_path = env::var_os("PATH").unwrap_or_default();
928 env::join_paths(iter::once(path).chain(env::split_paths(&old_path))).expect("")
929}
930
931#[derive(Debug, Clone, Hash, PartialEq, Eq)]
933pub struct RustdocTheme {
934 test_compiler: Compiler,
936}
937
938impl Step for RustdocTheme {
939 type Output = ();
940 const DEFAULT: bool = true;
941 const IS_HOST: bool = true;
942
943 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
944 run.path("src/tools/rustdoc-themes")
945 }
946
947 fn make_run(run: RunConfig<'_>) {
948 let test_compiler = run.builder.compiler(run.builder.top_stage, run.target);
949
950 run.builder.ensure(RustdocTheme { test_compiler });
951 }
952
953 fn run(self, builder: &Builder<'_>) {
954 let rustdoc = builder.bootstrap_out.join("rustdoc");
955 let mut cmd = builder.tool_cmd(Tool::RustdocTheme);
956 cmd.arg(rustdoc.to_str().unwrap())
957 .arg(builder.src.join("src/librustdoc/html/static/css/rustdoc.css").to_str().unwrap())
958 .env("RUSTC_STAGE", self.test_compiler.stage.to_string())
959 .env("RUSTC_SYSROOT", builder.sysroot(self.test_compiler))
960 .env(
961 "RUSTDOC_LIBDIR",
962 builder.sysroot_target_libdir(self.test_compiler, self.test_compiler.host),
963 )
964 .env("CFG_RELEASE_CHANNEL", &builder.config.channel)
965 .env("RUSTDOC_REAL", builder.rustdoc_for_compiler(self.test_compiler))
966 .env("RUSTC_BOOTSTRAP", "1");
967 cmd.args(linker_args(builder, self.test_compiler.host, LldThreads::No));
968
969 cmd.delay_failure().run(builder);
970 }
971
972 fn metadata(&self) -> Option<StepMetadata> {
973 Some(
974 StepMetadata::test("rustdoc-theme", self.test_compiler.host)
975 .stage(self.test_compiler.stage),
976 )
977 }
978}
979
980#[derive(Debug, Clone, Hash, PartialEq, Eq)]
982pub struct RustdocJSStd {
983 build_compiler: Compiler,
985 target: TargetSelection,
986}
987
988impl Step for RustdocJSStd {
989 type Output = ();
990 const DEFAULT: bool = true;
991 const IS_HOST: bool = true;
992
993 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
994 let default = run.builder.config.nodejs.is_some();
995 run.suite_path("tests/rustdoc-js-std").default_condition(default)
996 }
997
998 fn make_run(run: RunConfig<'_>) {
999 run.builder.ensure(RustdocJSStd {
1000 build_compiler: run.builder.compiler(run.builder.top_stage, run.builder.host_target),
1001 target: run.target,
1002 });
1003 }
1004
1005 fn run(self, builder: &Builder<'_>) {
1006 let nodejs =
1007 builder.config.nodejs.as_ref().expect("need nodejs to run rustdoc-js-std tests");
1008 let mut command = command(nodejs);
1009 command
1010 .arg(builder.src.join("src/tools/rustdoc-js/tester.js"))
1011 .arg("--crate-name")
1012 .arg("std")
1013 .arg("--resource-suffix")
1014 .arg(&builder.version)
1015 .arg("--doc-folder")
1016 .arg(builder.doc_out(self.target))
1017 .arg("--test-folder")
1018 .arg(builder.src.join("tests/rustdoc-js-std"));
1019 for path in &builder.paths {
1020 if let Some(p) = helpers::is_valid_test_suite_arg(path, "tests/rustdoc-js-std", builder)
1021 {
1022 if !p.ends_with(".js") {
1023 eprintln!("A non-js file was given: `{}`", path.display());
1024 panic!("Cannot run rustdoc-js-std tests");
1025 }
1026 command.arg("--test-file").arg(path);
1027 }
1028 }
1029 builder.ensure(crate::core::build_steps::doc::Std::from_build_compiler(
1030 self.build_compiler,
1031 self.target,
1032 DocumentationFormat::Html,
1033 ));
1034 let _guard = builder.msg_test("rustdoc-js-std", self.target, self.build_compiler.stage);
1035 command.run(builder);
1036 }
1037
1038 fn metadata(&self) -> Option<StepMetadata> {
1039 Some(StepMetadata::test("rustdoc-js-std", self.target).stage(self.build_compiler.stage))
1040 }
1041}
1042
1043#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1044pub struct RustdocJSNotStd {
1045 pub target: TargetSelection,
1046 pub compiler: Compiler,
1047}
1048
1049impl Step for RustdocJSNotStd {
1050 type Output = ();
1051 const DEFAULT: bool = true;
1052 const IS_HOST: bool = true;
1053
1054 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1055 let default = run.builder.config.nodejs.is_some();
1056 run.suite_path("tests/rustdoc-js").default_condition(default)
1057 }
1058
1059 fn make_run(run: RunConfig<'_>) {
1060 let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1061 run.builder.ensure(RustdocJSNotStd { target: run.target, compiler });
1062 }
1063
1064 fn run(self, builder: &Builder<'_>) {
1065 builder.ensure(Compiletest {
1066 test_compiler: self.compiler,
1067 target: self.target,
1068 mode: "rustdoc-js",
1069 suite: "rustdoc-js",
1070 path: "tests/rustdoc-js",
1071 compare_mode: None,
1072 });
1073 }
1074}
1075
1076fn get_browser_ui_test_version_inner(
1077 builder: &Builder<'_>,
1078 npm: &Path,
1079 global: bool,
1080) -> Option<String> {
1081 let mut command = command(npm);
1082 command.arg("list").arg("--parseable").arg("--long").arg("--depth=0");
1083 if global {
1084 command.arg("--global");
1085 }
1086 let lines = command.allow_failure().run_capture(builder).stdout();
1087 lines
1088 .lines()
1089 .find_map(|l| l.split(':').nth(1)?.strip_prefix("browser-ui-test@"))
1090 .map(|v| v.to_owned())
1091}
1092
1093fn get_browser_ui_test_version(builder: &Builder<'_>, npm: &Path) -> Option<String> {
1094 get_browser_ui_test_version_inner(builder, npm, false)
1095 .or_else(|| get_browser_ui_test_version_inner(builder, npm, true))
1096}
1097
1098#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1100pub struct RustdocGUI {
1101 test_compiler: Compiler,
1103 target: TargetSelection,
1104}
1105
1106impl Step for RustdocGUI {
1107 type Output = ();
1108 const DEFAULT: bool = true;
1109 const IS_HOST: bool = true;
1110
1111 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1112 let builder = run.builder;
1113 let run = run.suite_path("tests/rustdoc-gui");
1114 run.lazy_default_condition(Box::new(move || {
1115 builder.config.nodejs.is_some()
1116 && builder.doc_tests != DocTests::Only
1117 && builder
1118 .config
1119 .npm
1120 .as_ref()
1121 .map(|p| get_browser_ui_test_version(builder, p).is_some())
1122 .unwrap_or(false)
1123 }))
1124 }
1125
1126 fn make_run(run: RunConfig<'_>) {
1127 let test_compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1128 run.builder.ensure(RustdocGUI { test_compiler, target: run.target });
1129 }
1130
1131 fn run(self, builder: &Builder<'_>) {
1132 builder.std(self.test_compiler, self.target);
1133
1134 let mut cmd = builder.tool_cmd(Tool::RustdocGUITest);
1135
1136 let out_dir = builder.test_out(self.target).join("rustdoc-gui");
1137 build_stamp::clear_if_dirty(
1138 builder,
1139 &out_dir,
1140 &builder.rustdoc_for_compiler(self.test_compiler),
1141 );
1142
1143 if let Some(src) = builder.config.src.to_str() {
1144 cmd.arg("--rust-src").arg(src);
1145 }
1146
1147 if let Some(out_dir) = out_dir.to_str() {
1148 cmd.arg("--out-dir").arg(out_dir);
1149 }
1150
1151 if let Some(initial_cargo) = builder.config.initial_cargo.to_str() {
1152 cmd.arg("--initial-cargo").arg(initial_cargo);
1153 }
1154
1155 cmd.arg("--jobs").arg(builder.jobs().to_string());
1156
1157 cmd.env("RUSTDOC", builder.rustdoc_for_compiler(self.test_compiler))
1158 .env("RUSTC", builder.rustc(self.test_compiler));
1159
1160 add_rustdoc_cargo_linker_args(&mut cmd, builder, self.test_compiler.host, LldThreads::No);
1161
1162 for path in &builder.paths {
1163 if let Some(p) = helpers::is_valid_test_suite_arg(path, "tests/rustdoc-gui", builder) {
1164 if !p.ends_with(".goml") {
1165 eprintln!("A non-goml file was given: `{}`", path.display());
1166 panic!("Cannot run rustdoc-gui tests");
1167 }
1168 if let Some(name) = path.file_name().and_then(|f| f.to_str()) {
1169 cmd.arg("--goml-file").arg(name);
1170 }
1171 }
1172 }
1173
1174 for test_arg in builder.config.test_args() {
1175 cmd.arg("--test-arg").arg(test_arg);
1176 }
1177
1178 if let Some(ref nodejs) = builder.config.nodejs {
1179 cmd.arg("--nodejs").arg(nodejs);
1180 }
1181
1182 if let Some(ref npm) = builder.config.npm {
1183 cmd.arg("--npm").arg(npm);
1184 }
1185
1186 let _time = helpers::timeit(builder);
1187 let _guard = builder.msg_test("rustdoc-gui", self.target, self.test_compiler.stage);
1188 try_run_tests(builder, &mut cmd, true);
1189 }
1190
1191 fn metadata(&self) -> Option<StepMetadata> {
1192 Some(StepMetadata::test("rustdoc-gui", self.target).stage(self.test_compiler.stage))
1193 }
1194}
1195
1196#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1201pub struct Tidy;
1202
1203impl Step for Tidy {
1204 type Output = ();
1205 const DEFAULT: bool = true;
1206 const IS_HOST: bool = true;
1207
1208 fn run(self, builder: &Builder<'_>) {
1217 let mut cmd = builder.tool_cmd(Tool::Tidy);
1218 cmd.arg(&builder.src);
1219 cmd.arg(&builder.initial_cargo);
1220 cmd.arg(&builder.out);
1221 let jobs = builder.config.jobs.unwrap_or_else(|| {
1223 8 * std::thread::available_parallelism().map_or(1, std::num::NonZeroUsize::get) as u32
1224 });
1225 cmd.arg(jobs.to_string());
1226 if let Some(npm) = &builder.config.npm {
1228 cmd.arg(npm);
1229 } else {
1230 cmd.arg("npm");
1231 }
1232 if builder.is_verbose() {
1233 cmd.arg("--verbose");
1234 }
1235 if builder.config.cmd.bless() {
1236 cmd.arg("--bless");
1237 }
1238 if let Some(s) =
1239 builder.config.cmd.extra_checks().or(builder.config.tidy_extra_checks.as_deref())
1240 {
1241 cmd.arg(format!("--extra-checks={s}"));
1242 }
1243 let mut args = std::env::args_os();
1244 if args.any(|arg| arg == OsStr::new("--")) {
1245 cmd.arg("--");
1246 cmd.args(args);
1247 }
1248
1249 if builder.config.channel == "dev" || builder.config.channel == "nightly" {
1250 if !builder.config.json_output {
1251 builder.info("fmt check");
1252 if builder.config.initial_rustfmt.is_none() {
1253 let inferred_rustfmt_dir = builder.initial_sysroot.join("bin");
1254 eprintln!(
1255 "\
1256ERROR: no `rustfmt` binary found in {PATH}
1257INFO: `rust.channel` is currently set to \"{CHAN}\"
1258HELP: if you are testing a beta branch, set `rust.channel` to \"beta\" in the `bootstrap.toml` file
1259HELP: to skip test's attempt to check tidiness, pass `--skip src/tools/tidy` to `x.py test`",
1260 PATH = inferred_rustfmt_dir.display(),
1261 CHAN = builder.config.channel,
1262 );
1263 crate::exit!(1);
1264 }
1265 let all = false;
1266 crate::core::build_steps::format::format(
1267 builder,
1268 !builder.config.cmd.bless(),
1269 all,
1270 &[],
1271 );
1272 } else {
1273 eprintln!(
1274 "WARNING: `--json-output` is not supported on rustfmt, formatting will be skipped"
1275 );
1276 }
1277 }
1278
1279 builder.info("tidy check");
1280 cmd.delay_failure().run(builder);
1281
1282 builder.info("x.py completions check");
1283 let completion_paths = get_completion_paths(builder);
1284 if builder.config.cmd.bless() {
1285 builder.ensure(crate::core::build_steps::run::GenerateCompletions);
1286 } else if completion_paths
1287 .into_iter()
1288 .any(|(shell, path)| get_completion(shell, &path).is_some())
1289 {
1290 eprintln!(
1291 "x.py completions were changed; run `x.py run generate-completions` to update them"
1292 );
1293 crate::exit!(1);
1294 }
1295 }
1296
1297 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1298 let default = run.builder.doc_tests != DocTests::Only;
1299 run.path("src/tools/tidy").default_condition(default)
1300 }
1301
1302 fn make_run(run: RunConfig<'_>) {
1303 run.builder.ensure(Tidy);
1304 }
1305
1306 fn metadata(&self) -> Option<StepMetadata> {
1307 Some(StepMetadata::test("tidy", TargetSelection::default()))
1308 }
1309}
1310
1311#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1314pub struct CrateRunMakeSupport {
1315 host: TargetSelection,
1316}
1317
1318impl Step for CrateRunMakeSupport {
1319 type Output = ();
1320 const IS_HOST: bool = true;
1321
1322 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1323 run.path("src/tools/run-make-support")
1324 }
1325
1326 fn make_run(run: RunConfig<'_>) {
1327 run.builder.ensure(CrateRunMakeSupport { host: run.target });
1328 }
1329
1330 fn run(self, builder: &Builder<'_>) {
1332 let host = self.host;
1333 let compiler = builder.compiler(0, host);
1334
1335 let mut cargo = tool::prepare_tool_cargo(
1336 builder,
1337 compiler,
1338 Mode::ToolBootstrap,
1339 host,
1340 Kind::Test,
1341 "src/tools/run-make-support",
1342 SourceType::InTree,
1343 &[],
1344 );
1345 cargo.allow_features("test");
1346 run_cargo_test(cargo, &[], &[], "run-make-support self test", host, builder);
1347 }
1348}
1349
1350#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1351pub struct CrateBuildHelper {
1352 host: TargetSelection,
1353}
1354
1355impl Step for CrateBuildHelper {
1356 type Output = ();
1357 const IS_HOST: bool = true;
1358
1359 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1360 run.path("src/build_helper")
1361 }
1362
1363 fn make_run(run: RunConfig<'_>) {
1364 run.builder.ensure(CrateBuildHelper { host: run.target });
1365 }
1366
1367 fn run(self, builder: &Builder<'_>) {
1369 let host = self.host;
1370 let compiler = builder.compiler(0, host);
1371
1372 let mut cargo = tool::prepare_tool_cargo(
1373 builder,
1374 compiler,
1375 Mode::ToolBootstrap,
1376 host,
1377 Kind::Test,
1378 "src/build_helper",
1379 SourceType::InTree,
1380 &[],
1381 );
1382 cargo.allow_features("test");
1383 run_cargo_test(cargo, &[], &[], "build_helper self test", host, builder);
1384 }
1385}
1386
1387fn testdir(builder: &Builder<'_>, host: TargetSelection) -> PathBuf {
1388 builder.out.join(host).join("test")
1389}
1390
1391macro_rules! test {
1393 (
1394 $( #[$attr:meta] )* $name:ident {
1396 path: $path:expr,
1397 mode: $mode:expr,
1398 suite: $suite:expr,
1399 default: $default:expr
1400 $( , IS_HOST: $IS_HOST:expr )? $( , compare_mode: $compare_mode:expr )? $( , )? }
1404 ) => {
1405 $( #[$attr] )*
1406 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
1407 pub struct $name {
1408 test_compiler: Compiler,
1409 target: TargetSelection,
1410 }
1411
1412 impl Step for $name {
1413 type Output = ();
1414 const DEFAULT: bool = $default;
1415 const IS_HOST: bool = (const {
1416 #[allow(unused_assignments, unused_mut)]
1417 let mut value = false;
1418 $( value = $IS_HOST; )?
1419 value
1420 });
1421
1422 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1423 run.suite_path($path)
1424 }
1425
1426 fn make_run(run: RunConfig<'_>) {
1427 let test_compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1428
1429 run.builder.ensure($name { test_compiler, target: run.target });
1430 }
1431
1432 fn run(self, builder: &Builder<'_>) {
1433 builder.ensure(Compiletest {
1434 test_compiler: self.test_compiler,
1435 target: self.target,
1436 mode: $mode,
1437 suite: $suite,
1438 path: $path,
1439 compare_mode: (const {
1440 #[allow(unused_assignments, unused_mut)]
1441 let mut value = None;
1442 $( value = $compare_mode; )?
1443 value
1444 }),
1445 })
1446 }
1447 }
1448 };
1449}
1450
1451test!(Ui { path: "tests/ui", mode: "ui", suite: "ui", default: true });
1452
1453test!(Crashes { path: "tests/crashes", mode: "crashes", suite: "crashes", default: true });
1454
1455test!(CodegenLlvm {
1456 path: "tests/codegen-llvm",
1457 mode: "codegen",
1458 suite: "codegen-llvm",
1459 default: true
1460});
1461
1462test!(CodegenUnits {
1463 path: "tests/codegen-units",
1464 mode: "codegen-units",
1465 suite: "codegen-units",
1466 default: true,
1467});
1468
1469test!(Incremental {
1470 path: "tests/incremental",
1471 mode: "incremental",
1472 suite: "incremental",
1473 default: true,
1474});
1475
1476test!(Debuginfo {
1477 path: "tests/debuginfo",
1478 mode: "debuginfo",
1479 suite: "debuginfo",
1480 default: true,
1481 compare_mode: Some("split-dwarf"),
1482});
1483
1484test!(UiFullDeps {
1485 path: "tests/ui-fulldeps",
1486 mode: "ui",
1487 suite: "ui-fulldeps",
1488 default: true,
1489 IS_HOST: true,
1490});
1491
1492test!(Rustdoc {
1493 path: "tests/rustdoc",
1494 mode: "rustdoc",
1495 suite: "rustdoc",
1496 default: true,
1497 IS_HOST: true,
1498});
1499test!(RustdocUi {
1500 path: "tests/rustdoc-ui",
1501 mode: "ui",
1502 suite: "rustdoc-ui",
1503 default: true,
1504 IS_HOST: true,
1505});
1506
1507test!(RustdocJson {
1508 path: "tests/rustdoc-json",
1509 mode: "rustdoc-json",
1510 suite: "rustdoc-json",
1511 default: true,
1512 IS_HOST: true,
1513});
1514
1515test!(Pretty {
1516 path: "tests/pretty",
1517 mode: "pretty",
1518 suite: "pretty",
1519 default: true,
1520 IS_HOST: true,
1521});
1522
1523test!(RunMake { path: "tests/run-make", mode: "run-make", suite: "run-make", default: true });
1524test!(RunMakeCargo {
1525 path: "tests/run-make-cargo",
1526 mode: "run-make",
1527 suite: "run-make-cargo",
1528 default: true
1529});
1530
1531test!(AssemblyLlvm {
1532 path: "tests/assembly-llvm",
1533 mode: "assembly",
1534 suite: "assembly-llvm",
1535 default: true
1536});
1537
1538#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
1541pub struct Coverage {
1542 pub compiler: Compiler,
1543 pub target: TargetSelection,
1544 pub mode: &'static str,
1545}
1546
1547impl Coverage {
1548 const PATH: &'static str = "tests/coverage";
1549 const SUITE: &'static str = "coverage";
1550 const ALL_MODES: &[&str] = &["coverage-map", "coverage-run"];
1551}
1552
1553impl Step for Coverage {
1554 type Output = ();
1555 const DEFAULT: bool = true;
1556 const IS_HOST: bool = false;
1558
1559 fn should_run(mut run: ShouldRun<'_>) -> ShouldRun<'_> {
1560 run = run.suite_path(Self::PATH);
1566 for mode in Self::ALL_MODES {
1567 run = run.alias(mode);
1568 }
1569 run
1570 }
1571
1572 fn make_run(run: RunConfig<'_>) {
1573 let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1574 let target = run.target;
1575
1576 let mut modes = vec![];
1580
1581 for path in &run.paths {
1584 match path {
1585 PathSet::Set(_) => {
1586 for mode in Self::ALL_MODES {
1587 if path.assert_single_path().path == Path::new(mode) {
1588 modes.push(mode);
1589 break;
1590 }
1591 }
1592 }
1593 PathSet::Suite(_) => {
1594 modes.extend(Self::ALL_MODES);
1595 break;
1596 }
1597 }
1598 }
1599
1600 modes.retain(|mode| !run.builder.config.skip.iter().any(|skip| skip == Path::new(mode)));
1603
1604 for mode in modes {
1612 run.builder.ensure(Coverage { compiler, target, mode });
1613 }
1614 }
1615
1616 fn run(self, builder: &Builder<'_>) {
1617 let Self { compiler, target, mode } = self;
1618 builder.ensure(Compiletest {
1621 test_compiler: compiler,
1622 target,
1623 mode,
1624 suite: Self::SUITE,
1625 path: Self::PATH,
1626 compare_mode: None,
1627 });
1628 }
1629}
1630
1631test!(CoverageRunRustdoc {
1632 path: "tests/coverage-run-rustdoc",
1633 mode: "coverage-run",
1634 suite: "coverage-run-rustdoc",
1635 default: true,
1636 IS_HOST: true,
1637});
1638
1639#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1641pub struct MirOpt {
1642 pub compiler: Compiler,
1643 pub target: TargetSelection,
1644}
1645
1646impl Step for MirOpt {
1647 type Output = ();
1648 const DEFAULT: bool = true;
1649
1650 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1651 run.suite_path("tests/mir-opt")
1652 }
1653
1654 fn make_run(run: RunConfig<'_>) {
1655 let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1656 run.builder.ensure(MirOpt { compiler, target: run.target });
1657 }
1658
1659 fn run(self, builder: &Builder<'_>) {
1660 let run = |target| {
1661 builder.ensure(Compiletest {
1662 test_compiler: self.compiler,
1663 target,
1664 mode: "mir-opt",
1665 suite: "mir-opt",
1666 path: "tests/mir-opt",
1667 compare_mode: None,
1668 })
1669 };
1670
1671 run(self.target);
1672
1673 if builder.config.cmd.bless() {
1676 for target in ["aarch64-unknown-linux-gnu", "i686-pc-windows-msvc"] {
1682 run(TargetSelection::from_user(target));
1683 }
1684
1685 for target in ["x86_64-apple-darwin", "i686-unknown-linux-musl"] {
1686 let target = TargetSelection::from_user(target);
1687 let panic_abort_target = builder.ensure(MirOptPanicAbortSyntheticTarget {
1688 compiler: self.compiler,
1689 base: target,
1690 });
1691 run(panic_abort_target);
1692 }
1693 }
1694 }
1695}
1696
1697#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1703struct Compiletest {
1704 test_compiler: Compiler,
1706 target: TargetSelection,
1707 mode: &'static str,
1708 suite: &'static str,
1709 path: &'static str,
1710 compare_mode: Option<&'static str>,
1711}
1712
1713impl Step for Compiletest {
1714 type Output = ();
1715
1716 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1717 run.never()
1718 }
1719
1720 fn run(self, builder: &Builder<'_>) {
1721 if builder.doc_tests == DocTests::Only {
1722 return;
1723 }
1724
1725 if builder.top_stage == 0 && !builder.config.compiletest_allow_stage0 {
1726 eprintln!("\
1727ERROR: `--stage 0` runs compiletest on the stage0 (precompiled) compiler, not your local changes, and will almost always cause tests to fail
1728HELP: to test the compiler or standard library, omit the stage or explicitly use `--stage 1` instead
1729NOTE: 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`."
1730 );
1731 crate::exit!(1);
1732 }
1733
1734 let mut test_compiler = self.test_compiler;
1735 let target = self.target;
1736 let mode = self.mode;
1737 let suite = self.suite;
1738
1739 let suite_path = self.path;
1741
1742 if !builder.config.codegen_tests && mode == "codegen" {
1744 return;
1745 }
1746
1747 let query_compiler;
1754 let (stage, stage_id) = if suite == "ui-fulldeps" && test_compiler.stage == 1 {
1755 query_compiler = Some(test_compiler);
1758 let build = builder.build.host_target;
1762 test_compiler = builder.compiler(test_compiler.stage - 1, build);
1763 let test_stage = test_compiler.stage + 1;
1764 (test_stage, format!("stage{test_stage}-{build}"))
1765 } else {
1766 query_compiler = None;
1767 let stage = test_compiler.stage;
1768 (stage, format!("stage{stage}-{target}"))
1769 };
1770
1771 if suite.ends_with("fulldeps") {
1772 builder.ensure(compile::Rustc::new(test_compiler, target));
1773 }
1774
1775 if suite == "debuginfo" {
1776 builder.ensure(dist::DebuggerScripts {
1777 sysroot: builder.sysroot(test_compiler).to_path_buf(),
1778 target,
1779 });
1780 }
1781 if mode == "run-make" {
1782 builder.tool_exe(Tool::RunMakeSupport);
1783 }
1784
1785 if suite == "mir-opt" {
1787 builder.ensure(
1788 compile::Std::new(test_compiler, test_compiler.host).is_for_mir_opt_tests(true),
1789 );
1790 } else {
1791 builder.std(test_compiler, test_compiler.host);
1792 }
1793
1794 let mut cmd = builder.tool_cmd(Tool::Compiletest);
1795
1796 if suite == "mir-opt" {
1797 builder.ensure(compile::Std::new(test_compiler, target).is_for_mir_opt_tests(true));
1798 } else {
1799 builder.std(test_compiler, target);
1800 }
1801
1802 builder.ensure(RemoteCopyLibs { build_compiler: test_compiler, target });
1803
1804 cmd.arg("--stage").arg(stage.to_string());
1808 cmd.arg("--stage-id").arg(stage_id);
1809
1810 cmd.arg("--compile-lib-path").arg(builder.rustc_libdir(test_compiler));
1811 cmd.arg("--run-lib-path").arg(builder.sysroot_target_libdir(test_compiler, target));
1812 cmd.arg("--rustc-path").arg(builder.rustc(test_compiler));
1813 if let Some(query_compiler) = query_compiler {
1814 cmd.arg("--query-rustc-path").arg(builder.rustc(query_compiler));
1815 }
1816
1817 cmd.arg("--minicore-path")
1820 .arg(builder.src.join("tests").join("auxiliary").join("minicore.rs"));
1821
1822 let is_rustdoc = suite == "rustdoc-ui" || suite == "rustdoc-js";
1823
1824 if mode == "run-make" {
1839 let stage0_rustc_path = builder.compiler(0, test_compiler.host);
1842 cmd.arg("--stage0-rustc-path").arg(builder.rustc(stage0_rustc_path));
1843
1844 if suite == "run-make-cargo" {
1845 let cargo_path = if test_compiler.stage == 0 {
1846 builder.initial_cargo.clone()
1848 } else {
1849 builder
1850 .ensure(tool::Cargo::from_build_compiler(
1851 builder.compiler(test_compiler.stage - 1, test_compiler.host),
1852 test_compiler.host,
1853 ))
1854 .tool_path
1855 };
1856
1857 cmd.arg("--cargo-path").arg(cargo_path);
1858 }
1859 }
1860
1861 if mode == "rustdoc"
1863 || mode == "run-make"
1864 || (mode == "ui" && is_rustdoc)
1865 || mode == "rustdoc-js"
1866 || mode == "rustdoc-json"
1867 || suite == "coverage-run-rustdoc"
1868 {
1869 cmd.arg("--rustdoc-path").arg(builder.rustdoc_for_compiler(test_compiler));
1870 }
1871
1872 if mode == "rustdoc-json" {
1873 let json_compiler = builder.compiler(0, builder.host_target);
1875 cmd.arg("--jsondocck-path")
1876 .arg(builder.ensure(tool::JsonDocCk { compiler: json_compiler, target }).tool_path);
1877 cmd.arg("--jsondoclint-path").arg(
1878 builder.ensure(tool::JsonDocLint { compiler: json_compiler, target }).tool_path,
1879 );
1880 }
1881
1882 if matches!(mode, "coverage-map" | "coverage-run") {
1883 let coverage_dump = builder.tool_exe(Tool::CoverageDump);
1884 cmd.arg("--coverage-dump-path").arg(coverage_dump);
1885 }
1886
1887 cmd.arg("--src-root").arg(&builder.src);
1888 cmd.arg("--src-test-suite-root").arg(builder.src.join("tests").join(suite));
1889
1890 cmd.arg("--build-root").arg(&builder.out);
1894 cmd.arg("--build-test-suite-root").arg(testdir(builder, test_compiler.host).join(suite));
1895
1896 let sysroot = if builder.top_stage == 0 {
1901 builder.initial_sysroot.clone()
1902 } else {
1903 builder.sysroot(test_compiler)
1904 };
1905
1906 cmd.arg("--sysroot-base").arg(sysroot);
1907
1908 cmd.arg("--suite").arg(suite);
1909 cmd.arg("--mode").arg(mode);
1910 cmd.arg("--target").arg(target.rustc_target_arg());
1911 cmd.arg("--host").arg(&*test_compiler.host.triple);
1912 cmd.arg("--llvm-filecheck").arg(builder.llvm_filecheck(builder.config.host_target));
1913
1914 if let Some(codegen_backend) = builder.config.cmd.test_codegen_backend() {
1915 if !builder
1916 .config
1917 .enabled_codegen_backends(test_compiler.host)
1918 .contains(codegen_backend)
1919 {
1920 eprintln!(
1921 "\
1922ERROR: No configured backend named `{name}`
1923HELP: You can add it into `bootstrap.toml` in `rust.codegen-backends = [{name:?}]`",
1924 name = codegen_backend.name(),
1925 );
1926 crate::exit!(1);
1927 }
1928 cmd.arg("--override-codegen-backend").arg(codegen_backend.name());
1931 cmd.arg("--default-codegen-backend").arg(codegen_backend.name());
1934 } else {
1935 cmd.arg("--default-codegen-backend")
1938 .arg(builder.config.default_codegen_backend(test_compiler.host).name());
1939 }
1940
1941 if builder.build.config.llvm_enzyme {
1942 cmd.arg("--has-enzyme");
1943 }
1944
1945 if builder.config.cmd.bless() {
1946 cmd.arg("--bless");
1947 }
1948
1949 if builder.config.cmd.force_rerun() {
1950 cmd.arg("--force-rerun");
1951 }
1952
1953 if builder.config.cmd.no_capture() {
1954 cmd.arg("--no-capture");
1955 }
1956
1957 let compare_mode =
1958 builder.config.cmd.compare_mode().or_else(|| {
1959 if builder.config.test_compare_mode { self.compare_mode } else { None }
1960 });
1961
1962 if let Some(ref pass) = builder.config.cmd.pass() {
1963 cmd.arg("--pass");
1964 cmd.arg(pass);
1965 }
1966
1967 if let Some(ref run) = builder.config.cmd.run() {
1968 cmd.arg("--run");
1969 cmd.arg(run);
1970 }
1971
1972 if let Some(ref nodejs) = builder.config.nodejs {
1973 cmd.arg("--nodejs").arg(nodejs);
1974 } else if mode == "rustdoc-js" {
1975 panic!("need nodejs to run rustdoc-js suite");
1976 }
1977 if let Some(ref npm) = builder.config.npm {
1978 cmd.arg("--npm").arg(npm);
1979 }
1980 if builder.config.rust_optimize_tests {
1981 cmd.arg("--optimize-tests");
1982 }
1983 if builder.config.rust_randomize_layout {
1984 cmd.arg("--rust-randomized-layout");
1985 }
1986 if builder.config.cmd.only_modified() {
1987 cmd.arg("--only-modified");
1988 }
1989 if let Some(compiletest_diff_tool) = &builder.config.compiletest_diff_tool {
1990 cmd.arg("--compiletest-diff-tool").arg(compiletest_diff_tool);
1991 }
1992
1993 let mut flags = if is_rustdoc { Vec::new() } else { vec!["-Crpath".to_string()] };
1994 flags.push(format!(
1995 "-Cdebuginfo={}",
1996 if mode == "codegen" {
1997 if builder.config.rust_debuginfo_level_tests
2000 != crate::core::config::DebuginfoLevel::None
2001 {
2002 println!(
2003 "NOTE: ignoring `rust.debuginfo-level-tests={}` for codegen tests",
2004 builder.config.rust_debuginfo_level_tests
2005 );
2006 }
2007 crate::core::config::DebuginfoLevel::None
2008 } else {
2009 builder.config.rust_debuginfo_level_tests
2010 }
2011 ));
2012 flags.extend(builder.config.cmd.compiletest_rustc_args().iter().map(|s| s.to_string()));
2013
2014 if suite != "mir-opt" {
2015 if let Some(linker) = builder.linker(target) {
2016 cmd.arg("--target-linker").arg(linker);
2017 }
2018 if let Some(linker) = builder.linker(test_compiler.host) {
2019 cmd.arg("--host-linker").arg(linker);
2020 }
2021 }
2022
2023 if suite == "ui-fulldeps" && target.ends_with("darwin") {
2025 flags.push("-Alinker_messages".into());
2026 }
2027
2028 let mut hostflags = flags.clone();
2029 hostflags.extend(linker_flags(builder, test_compiler.host, LldThreads::No));
2030
2031 let mut targetflags = flags;
2032
2033 if suite == "ui" || suite == "incremental" {
2035 builder.ensure(TestHelpers { target: test_compiler.host });
2036 builder.ensure(TestHelpers { target });
2037 hostflags.push(format!(
2038 "-Lnative={}",
2039 builder.test_helpers_out(test_compiler.host).display()
2040 ));
2041 targetflags.push(format!("-Lnative={}", builder.test_helpers_out(target).display()));
2042 }
2043
2044 for flag in hostflags {
2045 cmd.arg("--host-rustcflags").arg(flag);
2046 }
2047 for flag in targetflags {
2048 cmd.arg("--target-rustcflags").arg(flag);
2049 }
2050
2051 cmd.arg("--python").arg(builder.python());
2052
2053 if let Some(ref gdb) = builder.config.gdb {
2054 cmd.arg("--gdb").arg(gdb);
2055 }
2056
2057 let lldb_exe = builder.config.lldb.clone().unwrap_or_else(|| PathBuf::from("lldb"));
2058 let lldb_version = command(&lldb_exe)
2059 .allow_failure()
2060 .arg("--version")
2061 .run_capture(builder)
2062 .stdout_if_ok()
2063 .and_then(|v| if v.trim().is_empty() { None } else { Some(v) });
2064 if let Some(ref vers) = lldb_version {
2065 cmd.arg("--lldb-version").arg(vers);
2066 let lldb_python_dir = command(&lldb_exe)
2067 .allow_failure()
2068 .arg("-P")
2069 .run_capture_stdout(builder)
2070 .stdout_if_ok()
2071 .map(|p| p.lines().next().expect("lldb Python dir not found").to_string());
2072 if let Some(ref dir) = lldb_python_dir {
2073 cmd.arg("--lldb-python-dir").arg(dir);
2074 }
2075 }
2076
2077 if helpers::forcing_clang_based_tests() {
2078 let clang_exe = builder.llvm_out(target).join("bin").join("clang");
2079 cmd.arg("--run-clang-based-tests-with").arg(clang_exe);
2080 }
2081
2082 for exclude in &builder.config.skip {
2083 cmd.arg("--skip");
2084 cmd.arg(exclude);
2085 }
2086
2087 let mut paths = match &builder.config.cmd {
2089 Subcommand::Test { .. } => &builder.config.paths[..],
2090 _ => &[],
2091 };
2092
2093 let mut paths_v;
2096 if mode == "rustdoc-js" {
2097 paths_v = paths.to_vec();
2098 for p in &mut paths_v {
2099 if let Some(ext) = p.extension()
2100 && ext == "js"
2101 {
2102 p.set_extension("rs");
2103 }
2104 }
2105 paths = &paths_v;
2106 }
2107 let mut test_args: Vec<&str> = paths
2109 .iter()
2110 .filter_map(|p| helpers::is_valid_test_suite_arg(p, suite_path, builder))
2111 .collect();
2112
2113 test_args.append(&mut builder.config.test_args());
2114
2115 if cfg!(windows) {
2118 let test_args_win: Vec<String> =
2119 test_args.iter().map(|s| s.replace('/', "\\")).collect();
2120 cmd.args(&test_args_win);
2121 } else {
2122 cmd.args(&test_args);
2123 }
2124
2125 if builder.is_verbose() {
2126 cmd.arg("--verbose");
2127 }
2128
2129 if builder.config.rustc_debug_assertions {
2130 cmd.arg("--with-rustc-debug-assertions");
2131 }
2132
2133 if builder.config.std_debug_assertions {
2134 cmd.arg("--with-std-debug-assertions");
2135 }
2136
2137 let mut llvm_components_passed = false;
2138 let mut copts_passed = false;
2139 if builder.config.llvm_enabled(test_compiler.host) {
2140 let llvm::LlvmResult { host_llvm_config, .. } =
2141 builder.ensure(llvm::Llvm { target: builder.config.host_target });
2142 if !builder.config.dry_run() {
2143 let llvm_version = get_llvm_version(builder, &host_llvm_config);
2144 let llvm_components = command(&host_llvm_config)
2145 .cached()
2146 .arg("--components")
2147 .run_capture_stdout(builder)
2148 .stdout();
2149 cmd.arg("--llvm-version")
2151 .arg(llvm_version.trim())
2152 .arg("--llvm-components")
2153 .arg(llvm_components.trim());
2154 llvm_components_passed = true;
2155 }
2156 if !builder.config.is_rust_llvm(target) {
2157 cmd.arg("--system-llvm");
2158 }
2159
2160 if !builder.config.dry_run() && suite.ends_with("fulldeps") {
2165 let llvm_libdir = command(&host_llvm_config)
2166 .cached()
2167 .arg("--libdir")
2168 .run_capture_stdout(builder)
2169 .stdout();
2170 let link_llvm = if target.is_msvc() {
2171 format!("-Clink-arg=-LIBPATH:{llvm_libdir}")
2172 } else {
2173 format!("-Clink-arg=-L{llvm_libdir}")
2174 };
2175 cmd.arg("--host-rustcflags").arg(link_llvm);
2176 }
2177
2178 if !builder.config.dry_run() && matches!(mode, "run-make" | "coverage-run") {
2179 let llvm_bin_path = host_llvm_config
2184 .parent()
2185 .expect("Expected llvm-config to be contained in directory");
2186 assert!(llvm_bin_path.is_dir());
2187 cmd.arg("--llvm-bin-dir").arg(llvm_bin_path);
2188 }
2189
2190 if !builder.config.dry_run() && mode == "run-make" {
2191 if builder.config.lld_enabled {
2193 let lld_install_root =
2194 builder.ensure(llvm::Lld { target: builder.config.host_target });
2195
2196 let lld_bin_path = lld_install_root.join("bin");
2197
2198 let old_path = env::var_os("PATH").unwrap_or_default();
2199 let new_path = env::join_paths(
2200 std::iter::once(lld_bin_path).chain(env::split_paths(&old_path)),
2201 )
2202 .expect("Could not add LLD bin path to PATH");
2203 cmd.env("PATH", new_path);
2204 }
2205 }
2206 }
2207
2208 if !builder.config.dry_run() && mode == "run-make" {
2211 let mut cflags = builder.cc_handled_clags(target, CLang::C);
2212 cflags.extend(builder.cc_unhandled_cflags(target, GitRepo::Rustc, CLang::C));
2213 let mut cxxflags = builder.cc_handled_clags(target, CLang::Cxx);
2214 cxxflags.extend(builder.cc_unhandled_cflags(target, GitRepo::Rustc, CLang::Cxx));
2215 cmd.arg("--cc")
2216 .arg(builder.cc(target))
2217 .arg("--cxx")
2218 .arg(builder.cxx(target).unwrap())
2219 .arg("--cflags")
2220 .arg(cflags.join(" "))
2221 .arg("--cxxflags")
2222 .arg(cxxflags.join(" "));
2223 copts_passed = true;
2224 if let Some(ar) = builder.ar(target) {
2225 cmd.arg("--ar").arg(ar);
2226 }
2227 }
2228
2229 if !llvm_components_passed {
2230 cmd.arg("--llvm-components").arg("");
2231 }
2232 if !copts_passed {
2233 cmd.arg("--cc")
2234 .arg("")
2235 .arg("--cxx")
2236 .arg("")
2237 .arg("--cflags")
2238 .arg("")
2239 .arg("--cxxflags")
2240 .arg("");
2241 }
2242
2243 if builder.remote_tested(target) {
2244 cmd.arg("--remote-test-client").arg(builder.tool_exe(Tool::RemoteTestClient));
2245 } else if let Some(tool) = builder.runner(target) {
2246 cmd.arg("--runner").arg(tool);
2247 }
2248
2249 if suite != "mir-opt" {
2250 if !builder.config.dry_run() && target.is_msvc() {
2256 for (k, v) in builder.cc[&target].env() {
2257 if k != "PATH" {
2258 cmd.env(k, v);
2259 }
2260 }
2261 }
2262 }
2263
2264 if !builder.config.dry_run()
2266 && target.contains("msvc")
2267 && builder.config.sanitizers_enabled(target)
2268 {
2269 cmd.env("ASAN_WIN_CONTINUE_ON_INTERCEPTION_FAILURE", "1");
2272 let asan_runtime_path = builder.cc[&target].path().parent().unwrap().to_path_buf();
2274 let old_path = cmd
2275 .get_envs()
2276 .find_map(|(k, v)| (k == "PATH").then_some(v))
2277 .flatten()
2278 .map_or_else(|| env::var_os("PATH").unwrap_or_default(), |v| v.to_owned());
2279 let new_path = env::join_paths(
2280 env::split_paths(&old_path).chain(std::iter::once(asan_runtime_path)),
2281 )
2282 .expect("Could not add ASAN runtime path to PATH");
2283 cmd.env("PATH", new_path);
2284 }
2285
2286 cmd.env_remove("CARGO");
2289
2290 cmd.env("RUSTC_BOOTSTRAP", "1");
2291 cmd.env("RUSTC_FORCE_RUSTC_VERSION", "compiletest");
2294 cmd.env("DOC_RUST_LANG_ORG_CHANNEL", builder.doc_rust_lang_org_channel());
2295 builder.add_rust_test_threads(&mut cmd);
2296
2297 if builder.config.sanitizers_enabled(target) {
2298 cmd.env("RUSTC_SANITIZER_SUPPORT", "1");
2299 }
2300
2301 if builder.config.profiler_enabled(target) {
2302 cmd.arg("--profiler-runtime");
2303 }
2304
2305 cmd.env("RUST_TEST_TMPDIR", builder.tempdir());
2306
2307 cmd.arg("--adb-path").arg("adb");
2308 cmd.arg("--adb-test-dir").arg(ADB_TEST_DIR);
2309 if target.contains("android") && !builder.config.dry_run() {
2310 cmd.arg("--android-cross-path")
2312 .arg(builder.cc(target).parent().unwrap().parent().unwrap());
2313 } else {
2314 cmd.arg("--android-cross-path").arg("");
2315 }
2316
2317 if builder.config.cmd.rustfix_coverage() {
2318 cmd.arg("--rustfix-coverage");
2319 }
2320
2321 cmd.arg("--channel").arg(&builder.config.channel);
2322
2323 if !builder.config.omit_git_hash {
2324 cmd.arg("--git-hash");
2325 }
2326
2327 let git_config = builder.config.git_config();
2328 cmd.arg("--nightly-branch").arg(git_config.nightly_branch);
2329 cmd.arg("--git-merge-commit-email").arg(git_config.git_merge_commit_email);
2330 cmd.force_coloring_in_ci();
2331
2332 #[cfg(feature = "build-metrics")]
2333 builder.metrics.begin_test_suite(
2334 build_helper::metrics::TestSuiteMetadata::Compiletest {
2335 suite: suite.into(),
2336 mode: mode.into(),
2337 compare_mode: None,
2338 target: self.target.triple.to_string(),
2339 host: self.test_compiler.host.triple.to_string(),
2340 stage: self.test_compiler.stage,
2341 },
2342 builder,
2343 );
2344
2345 let _group = builder.msg_test(
2346 format!("with compiletest suite={suite} mode={mode}"),
2347 target,
2348 test_compiler.stage,
2349 );
2350 try_run_tests(builder, &mut cmd, false);
2351
2352 if let Some(compare_mode) = compare_mode {
2353 cmd.arg("--compare-mode").arg(compare_mode);
2354
2355 #[cfg(feature = "build-metrics")]
2356 builder.metrics.begin_test_suite(
2357 build_helper::metrics::TestSuiteMetadata::Compiletest {
2358 suite: suite.into(),
2359 mode: mode.into(),
2360 compare_mode: Some(compare_mode.into()),
2361 target: self.target.triple.to_string(),
2362 host: self.test_compiler.host.triple.to_string(),
2363 stage: self.test_compiler.stage,
2364 },
2365 builder,
2366 );
2367
2368 builder.info(&format!(
2369 "Check compiletest suite={} mode={} compare_mode={} ({} -> {})",
2370 suite, mode, compare_mode, &test_compiler.host, target
2371 ));
2372 let _time = helpers::timeit(builder);
2373 try_run_tests(builder, &mut cmd, false);
2374 }
2375 }
2376
2377 fn metadata(&self) -> Option<StepMetadata> {
2378 Some(
2379 StepMetadata::test(&format!("compiletest-{}", self.suite), self.target)
2380 .stage(self.test_compiler.stage),
2381 )
2382 }
2383}
2384
2385#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2387struct BookTest {
2388 test_compiler: Compiler,
2389 path: PathBuf,
2390 name: &'static str,
2391 is_ext_doc: bool,
2392 dependencies: Vec<&'static str>,
2393}
2394
2395impl Step for BookTest {
2396 type Output = ();
2397 const IS_HOST: bool = true;
2398
2399 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2400 run.never()
2401 }
2402
2403 fn run(self, builder: &Builder<'_>) {
2404 if self.is_ext_doc {
2414 self.run_ext_doc(builder);
2415 } else {
2416 self.run_local_doc(builder);
2417 }
2418 }
2419}
2420
2421impl BookTest {
2422 fn run_ext_doc(self, builder: &Builder<'_>) {
2425 let test_compiler = self.test_compiler;
2426
2427 builder.std(test_compiler, test_compiler.host);
2428
2429 let mut rustdoc_path = builder.rustdoc_for_compiler(test_compiler);
2432 rustdoc_path.pop();
2433 let old_path = env::var_os("PATH").unwrap_or_default();
2434 let new_path = env::join_paths(iter::once(rustdoc_path).chain(env::split_paths(&old_path)))
2435 .expect("could not add rustdoc to PATH");
2436
2437 let mut rustbook_cmd = builder.tool_cmd(Tool::Rustbook);
2438 let path = builder.src.join(&self.path);
2439 rustbook_cmd.env("RUSTC_BOOTSTRAP", "1");
2441 rustbook_cmd.env("PATH", new_path).arg("test").arg(path);
2442
2443 let libs = if !self.dependencies.is_empty() {
2448 let mut lib_paths = vec![];
2449 for dep in self.dependencies {
2450 let mode = Mode::ToolRustcPrivate;
2451 let target = builder.config.host_target;
2452 let cargo = tool::prepare_tool_cargo(
2453 builder,
2454 test_compiler,
2455 mode,
2456 target,
2457 Kind::Build,
2458 dep,
2459 SourceType::Submodule,
2460 &[],
2461 );
2462
2463 let stamp = BuildStamp::new(&builder.cargo_out(test_compiler, mode, target))
2464 .with_prefix(PathBuf::from(dep).file_name().and_then(|v| v.to_str()).unwrap());
2465
2466 let output_paths = run_cargo(builder, cargo, vec![], &stamp, vec![], false, false);
2467 let directories = output_paths
2468 .into_iter()
2469 .filter_map(|p| p.parent().map(ToOwned::to_owned))
2470 .fold(HashSet::new(), |mut set, dir| {
2471 set.insert(dir);
2472 set
2473 });
2474
2475 lib_paths.extend(directories);
2476 }
2477 lib_paths
2478 } else {
2479 vec![]
2480 };
2481
2482 if !libs.is_empty() {
2483 let paths = libs
2484 .into_iter()
2485 .map(|path| path.into_os_string())
2486 .collect::<Vec<OsString>>()
2487 .join(OsStr::new(","));
2488 rustbook_cmd.args([OsString::from("--library-path"), paths]);
2489 }
2490
2491 builder.add_rust_test_threads(&mut rustbook_cmd);
2492 let _guard = builder.msg_test(
2493 format_args!("mdbook {}", self.path.display()),
2494 test_compiler.host,
2495 test_compiler.stage,
2496 );
2497 let _time = helpers::timeit(builder);
2498 let toolstate = if rustbook_cmd.delay_failure().run(builder) {
2499 ToolState::TestPass
2500 } else {
2501 ToolState::TestFail
2502 };
2503 builder.save_toolstate(self.name, toolstate);
2504 }
2505
2506 fn run_local_doc(self, builder: &Builder<'_>) {
2508 let test_compiler = self.test_compiler;
2509 let host = self.test_compiler.host;
2510
2511 builder.std(test_compiler, host);
2512
2513 let _guard = builder.msg_test(
2514 format!("book {}", self.name),
2515 test_compiler.host,
2516 test_compiler.stage,
2517 );
2518
2519 let mut stack = vec![builder.src.join(self.path)];
2522 let _time = helpers::timeit(builder);
2523 let mut files = Vec::new();
2524 while let Some(p) = stack.pop() {
2525 if p.is_dir() {
2526 stack.extend(t!(p.read_dir()).map(|p| t!(p).path()));
2527 continue;
2528 }
2529
2530 if p.extension().and_then(|s| s.to_str()) != Some("md") {
2531 continue;
2532 }
2533
2534 files.push(p);
2535 }
2536
2537 files.sort();
2538
2539 for file in files {
2540 markdown_test(builder, test_compiler, &file);
2541 }
2542 }
2543}
2544
2545macro_rules! test_book {
2546 ($(
2547 $name:ident, $path:expr, $book_name:expr,
2548 default=$default:expr
2549 $(,submodules = $submodules:expr)?
2550 $(,dependencies=$dependencies:expr)?
2551 ;
2552 )+) => {
2553 $(
2554 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
2555 pub struct $name {
2556 test_compiler: Compiler,
2557 }
2558
2559 impl Step for $name {
2560 type Output = ();
2561 const DEFAULT: bool = $default;
2562 const IS_HOST: bool = true;
2563
2564 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2565 run.path($path)
2566 }
2567
2568 fn make_run(run: RunConfig<'_>) {
2569 run.builder.ensure($name {
2570 test_compiler: run.builder.compiler(run.builder.top_stage, run.target),
2571 });
2572 }
2573
2574 fn run(self, builder: &Builder<'_>) {
2575 $(
2576 for submodule in $submodules {
2577 builder.require_submodule(submodule, None);
2578 }
2579 )*
2580
2581 let dependencies = vec![];
2582 $(
2583 let mut dependencies = dependencies;
2584 for dep in $dependencies {
2585 dependencies.push(dep);
2586 }
2587 )?
2588
2589 builder.ensure(BookTest {
2590 test_compiler: self.test_compiler,
2591 path: PathBuf::from($path),
2592 name: $book_name,
2593 is_ext_doc: !$default,
2594 dependencies,
2595 });
2596 }
2597 }
2598 )+
2599 }
2600}
2601
2602test_book!(
2603 Nomicon, "src/doc/nomicon", "nomicon", default=false, submodules=["src/doc/nomicon"];
2604 Reference, "src/doc/reference", "reference", default=false, submodules=["src/doc/reference"];
2605 RustdocBook, "src/doc/rustdoc", "rustdoc", default=true;
2606 RustcBook, "src/doc/rustc", "rustc", default=true;
2607 RustByExample, "src/doc/rust-by-example", "rust-by-example", default=false, submodules=["src/doc/rust-by-example"];
2608 EmbeddedBook, "src/doc/embedded-book", "embedded-book", default=false, submodules=["src/doc/embedded-book"];
2609 TheBook, "src/doc/book", "book", default=false, submodules=["src/doc/book"], dependencies=["src/doc/book/packages/trpl"];
2610 UnstableBook, "src/doc/unstable-book", "unstable-book", default=true;
2611 EditionGuide, "src/doc/edition-guide", "edition-guide", default=false, submodules=["src/doc/edition-guide"];
2612);
2613
2614#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2615pub struct ErrorIndex {
2616 compilers: RustcPrivateCompilers,
2617}
2618
2619impl Step for ErrorIndex {
2620 type Output = ();
2621 const DEFAULT: bool = true;
2622 const IS_HOST: bool = true;
2623
2624 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2625 run.path("src/tools/error_index_generator").alias("error-index")
2628 }
2629
2630 fn make_run(run: RunConfig<'_>) {
2631 let compilers = RustcPrivateCompilers::new(
2635 run.builder,
2636 run.builder.top_stage,
2637 run.builder.config.host_target,
2638 );
2639 run.builder.ensure(ErrorIndex { compilers });
2640 }
2641
2642 fn run(self, builder: &Builder<'_>) {
2649 let target_compiler = self.compilers.target_compiler();
2651
2652 let dir = testdir(builder, target_compiler.host);
2653 t!(fs::create_dir_all(&dir));
2654 let output = dir.join("error-index.md");
2655
2656 let mut tool = tool::ErrorIndex::command(builder, self.compilers);
2657 tool.arg("markdown").arg(&output);
2658
2659 let guard = builder.msg_test("error-index", target_compiler.host, target_compiler.stage);
2660 let _time = helpers::timeit(builder);
2661 tool.run_capture(builder);
2662 drop(guard);
2663 builder.std(target_compiler, target_compiler.host);
2666 markdown_test(builder, target_compiler, &output);
2667 }
2668}
2669
2670fn markdown_test(builder: &Builder<'_>, compiler: Compiler, markdown: &Path) -> bool {
2671 if let Ok(contents) = fs::read_to_string(markdown)
2672 && !contents.contains("```")
2673 {
2674 return true;
2675 }
2676
2677 builder.do_if_verbose(|| println!("doc tests for: {}", markdown.display()));
2678 let mut cmd = builder.rustdoc_cmd(compiler);
2679 builder.add_rust_test_threads(&mut cmd);
2680 cmd.arg("-Z");
2682 cmd.arg("unstable-options");
2683 cmd.arg("--test");
2684 cmd.arg(markdown);
2685 cmd.env("RUSTC_BOOTSTRAP", "1");
2686
2687 let test_args = builder.config.test_args().join(" ");
2688 cmd.arg("--test-args").arg(test_args);
2689
2690 cmd = cmd.delay_failure();
2691 if !builder.config.verbose_tests {
2692 cmd.run_capture(builder).is_success()
2693 } else {
2694 cmd.run(builder)
2695 }
2696}
2697
2698#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2703pub struct CrateLibrustc {
2704 build_compiler: Compiler,
2706 target: TargetSelection,
2707 crates: Vec<String>,
2708}
2709
2710impl Step for CrateLibrustc {
2711 type Output = ();
2712 const DEFAULT: bool = true;
2713 const IS_HOST: bool = true;
2714
2715 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2716 run.crate_or_deps("rustc-main").path("compiler")
2717 }
2718
2719 fn make_run(run: RunConfig<'_>) {
2720 let builder = run.builder;
2721 let host = run.build_triple();
2722 let build_compiler = builder.compiler(builder.top_stage - 1, host);
2723 let crates = run.make_run_crates(Alias::Compiler);
2724
2725 builder.ensure(CrateLibrustc { build_compiler, target: run.target, crates });
2726 }
2727
2728 fn run(self, builder: &Builder<'_>) {
2729 builder.std(self.build_compiler, self.target);
2730
2731 builder.ensure(Crate {
2733 build_compiler: self.build_compiler,
2734 target: self.target,
2735 mode: Mode::Rustc,
2736 crates: self.crates,
2737 });
2738 }
2739
2740 fn metadata(&self) -> Option<StepMetadata> {
2741 Some(StepMetadata::test("CrateLibrustc", self.target).built_by(self.build_compiler))
2742 }
2743}
2744
2745fn run_cargo_test<'a>(
2749 cargo: builder::Cargo,
2750 libtest_args: &[&str],
2751 crates: &[String],
2752 description: impl Into<Option<&'a str>>,
2753 target: TargetSelection,
2754 builder: &Builder<'_>,
2755) -> bool {
2756 let compiler = cargo.compiler();
2757 let mut cargo = prepare_cargo_test(cargo, libtest_args, crates, target, builder);
2758 let _time = helpers::timeit(builder);
2759 let _group =
2760 description.into().and_then(|what| builder.msg_test(what, target, compiler.stage + 1));
2761
2762 #[cfg(feature = "build-metrics")]
2763 builder.metrics.begin_test_suite(
2764 build_helper::metrics::TestSuiteMetadata::CargoPackage {
2765 crates: crates.iter().map(|c| c.to_string()).collect(),
2766 target: target.triple.to_string(),
2767 host: compiler.host.triple.to_string(),
2768 stage: compiler.stage,
2769 },
2770 builder,
2771 );
2772 add_flags_and_try_run_tests(builder, &mut cargo)
2773}
2774
2775fn prepare_cargo_test(
2777 cargo: builder::Cargo,
2778 libtest_args: &[&str],
2779 crates: &[String],
2780 target: TargetSelection,
2781 builder: &Builder<'_>,
2782) -> BootstrapCommand {
2783 let compiler = cargo.compiler();
2784 let mut cargo: BootstrapCommand = cargo.into();
2785
2786 if builder.config.cmd.bless() && !cargo.get_envs().any(|v| v.0 == "RUSTC_BLESS") {
2790 cargo.env("RUSTC_BLESS", "Gesundheit");
2791 }
2792
2793 if builder.kind == Kind::Test && !builder.fail_fast {
2797 cargo.arg("--no-fail-fast");
2798 }
2799
2800 if builder.config.json_output {
2801 cargo.arg("--message-format=json");
2802 }
2803
2804 match builder.doc_tests {
2805 DocTests::Only => {
2806 cargo.arg("--doc");
2807 }
2808 DocTests::No => {
2809 cargo.args(["--bins", "--examples", "--tests", "--benches"]);
2810 }
2811 DocTests::Yes => {}
2812 }
2813
2814 for krate in crates {
2815 cargo.arg("-p").arg(krate);
2816 }
2817
2818 cargo.arg("--").args(builder.config.test_args()).args(libtest_args);
2819 if !builder.config.verbose_tests {
2820 cargo.arg("--quiet");
2821 }
2822
2823 if builder.kind != Kind::Miri {
2832 let mut dylib_paths = builder.rustc_lib_paths(compiler);
2833 dylib_paths.push(builder.sysroot_target_libdir(compiler, target));
2834 helpers::add_dylib_path(dylib_paths, &mut cargo);
2835 }
2836
2837 if builder.remote_tested(target) {
2838 cargo.env(
2839 format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)),
2840 format!("{} run 0", builder.tool_exe(Tool::RemoteTestClient).display()),
2841 );
2842 } else if let Some(tool) = builder.runner(target) {
2843 cargo.env(format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)), tool);
2844 }
2845
2846 cargo
2847}
2848
2849#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2857pub struct Crate {
2858 build_compiler: Compiler,
2860 target: TargetSelection,
2861 mode: Mode,
2862 crates: Vec<String>,
2863}
2864
2865impl Step for Crate {
2866 type Output = ();
2867 const DEFAULT: bool = true;
2868
2869 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2870 run.crate_or_deps("sysroot").crate_or_deps("coretests").crate_or_deps("alloctests")
2871 }
2872
2873 fn make_run(run: RunConfig<'_>) {
2874 let builder = run.builder;
2875 let host = run.build_triple();
2876 let build_compiler = builder.compiler(builder.top_stage, host);
2877 let crates = run
2878 .paths
2879 .iter()
2880 .map(|p| builder.crate_paths[&p.assert_single_path().path].clone())
2881 .collect();
2882
2883 builder.ensure(Crate { build_compiler, target: run.target, mode: Mode::Std, crates });
2884 }
2885
2886 fn run(self, builder: &Builder<'_>) {
2895 let build_compiler = self.build_compiler;
2896 let target = self.target;
2897 let mode = self.mode;
2898
2899 builder.ensure(Std::new(build_compiler, build_compiler.host).force_recompile(true));
2902
2903 let mut cargo = if builder.kind == Kind::Miri {
2904 if builder.top_stage == 0 {
2905 eprintln!("ERROR: `x.py miri` requires stage 1 or higher");
2906 std::process::exit(1);
2907 }
2908
2909 let mut cargo = builder::Cargo::new(
2912 builder,
2913 build_compiler,
2914 mode,
2915 SourceType::InTree,
2916 target,
2917 Kind::MiriTest,
2918 );
2919 cargo.env("MIRI_REPLACE_LIBRS_IF_NOT_TEST", "1");
2931 cargo.rustflag("-Zforce-unstable-if-unmarked");
2935 cargo
2936 } else {
2937 if !builder.config.is_host_target(target) {
2939 builder.ensure(compile::Std::new(build_compiler, target).force_recompile(true));
2940 builder.ensure(RemoteCopyLibs { build_compiler, target });
2941 }
2942
2943 builder::Cargo::new(
2945 builder,
2946 build_compiler,
2947 mode,
2948 SourceType::InTree,
2949 target,
2950 builder.kind,
2951 )
2952 };
2953
2954 match mode {
2955 Mode::Std => {
2956 if builder.kind == Kind::Miri {
2957 cargo
2963 .arg("--manifest-path")
2964 .arg(builder.src.join("library/sysroot/Cargo.toml"));
2965 } else {
2966 compile::std_cargo(builder, target, &mut cargo);
2967 }
2968 }
2969 Mode::Rustc => {
2970 compile::rustc_cargo(builder, &mut cargo, target, &build_compiler, &self.crates);
2971 }
2972 _ => panic!("can only test libraries"),
2973 };
2974
2975 let mut crates = self.crates.clone();
2976 if crates.iter().any(|crate_| crate_ == "core") {
2981 crates.push("coretests".to_owned());
2982 }
2983 if crates.iter().any(|crate_| crate_ == "alloc") {
2984 crates.push("alloctests".to_owned());
2985 }
2986
2987 run_cargo_test(cargo, &[], &crates, &*crate_description(&self.crates), target, builder);
2988 }
2989}
2990
2991#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2994pub struct CrateRustdoc {
2995 host: TargetSelection,
2996}
2997
2998impl Step for CrateRustdoc {
2999 type Output = ();
3000 const DEFAULT: bool = true;
3001 const IS_HOST: bool = true;
3002
3003 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3004 run.paths(&["src/librustdoc", "src/tools/rustdoc"])
3005 }
3006
3007 fn make_run(run: RunConfig<'_>) {
3008 let builder = run.builder;
3009
3010 builder.ensure(CrateRustdoc { host: run.target });
3011 }
3012
3013 fn run(self, builder: &Builder<'_>) {
3014 let target = self.host;
3015
3016 let compiler = if builder.download_rustc() {
3017 builder.compiler(builder.top_stage, target)
3018 } else {
3019 builder.compiler_for(builder.top_stage, target, target)
3024 };
3025 builder.std(compiler, target);
3030 builder.ensure(compile::Rustc::new(compiler, target));
3031
3032 let mut cargo = tool::prepare_tool_cargo(
3033 builder,
3034 compiler,
3035 Mode::ToolRustcPrivate,
3036 target,
3037 builder.kind,
3038 "src/tools/rustdoc",
3039 SourceType::InTree,
3040 &[],
3041 );
3042 if self.host.contains("musl") {
3043 cargo.arg("'-Ctarget-feature=-crt-static'");
3044 }
3045
3046 let libdir = if builder.download_rustc() {
3073 builder.rustc_libdir(compiler)
3074 } else {
3075 builder.sysroot_target_libdir(compiler, target).to_path_buf()
3076 };
3077 let mut dylib_path = dylib_path();
3078 dylib_path.insert(0, PathBuf::from(&*libdir));
3079 cargo.env(dylib_path_var(), env::join_paths(&dylib_path).unwrap());
3080
3081 run_cargo_test(cargo, &[], &["rustdoc:0.0.0".to_string()], "rustdoc", target, builder);
3082 }
3083}
3084
3085#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3086pub struct CrateRustdocJsonTypes {
3087 build_compiler: Compiler,
3088 target: TargetSelection,
3089}
3090
3091impl Step for CrateRustdocJsonTypes {
3092 type Output = ();
3093 const DEFAULT: bool = true;
3094 const IS_HOST: bool = true;
3095
3096 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3097 run.path("src/rustdoc-json-types")
3098 }
3099
3100 fn make_run(run: RunConfig<'_>) {
3101 let builder = run.builder;
3102
3103 builder.ensure(CrateRustdocJsonTypes {
3104 build_compiler: get_tool_target_compiler(
3105 builder,
3106 ToolTargetBuildMode::Build(run.target),
3107 ),
3108 target: run.target,
3109 });
3110 }
3111
3112 fn run(self, builder: &Builder<'_>) {
3113 let target = self.target;
3114
3115 let cargo = tool::prepare_tool_cargo(
3116 builder,
3117 self.build_compiler,
3118 Mode::ToolTarget,
3119 target,
3120 builder.kind,
3121 "src/rustdoc-json-types",
3122 SourceType::InTree,
3123 &[],
3124 );
3125
3126 let libtest_args = if target.contains("musl") {
3128 ["'-Ctarget-feature=-crt-static'"].as_slice()
3129 } else {
3130 &[]
3131 };
3132
3133 run_cargo_test(
3134 cargo,
3135 libtest_args,
3136 &["rustdoc-json-types".to_string()],
3137 "rustdoc-json-types",
3138 target,
3139 builder,
3140 );
3141 }
3142}
3143
3144#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3154pub struct RemoteCopyLibs {
3155 build_compiler: Compiler,
3156 target: TargetSelection,
3157}
3158
3159impl Step for RemoteCopyLibs {
3160 type Output = ();
3161
3162 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3163 run.never()
3164 }
3165
3166 fn run(self, builder: &Builder<'_>) {
3167 let build_compiler = self.build_compiler;
3168 let target = self.target;
3169 if !builder.remote_tested(target) {
3170 return;
3171 }
3172
3173 builder.std(build_compiler, target);
3174
3175 builder.info(&format!("REMOTE copy libs to emulator ({target})"));
3176
3177 let remote_test_server = builder.ensure(tool::RemoteTestServer { build_compiler, target });
3178
3179 let tool = builder.tool_exe(Tool::RemoteTestClient);
3181 let mut cmd = command(&tool);
3182 cmd.arg("spawn-emulator")
3183 .arg(target.triple)
3184 .arg(&remote_test_server.tool_path)
3185 .arg(builder.tempdir());
3186 if let Some(rootfs) = builder.qemu_rootfs(target) {
3187 cmd.arg(rootfs);
3188 }
3189 cmd.run(builder);
3190
3191 for f in t!(builder.sysroot_target_libdir(build_compiler, target).read_dir()) {
3193 let f = t!(f);
3194 if helpers::is_dylib(&f.path()) {
3195 command(&tool).arg("push").arg(f.path()).run(builder);
3196 }
3197 }
3198 }
3199}
3200
3201#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3202pub struct Distcheck;
3203
3204impl Step for Distcheck {
3205 type Output = ();
3206
3207 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3208 run.alias("distcheck")
3209 }
3210
3211 fn make_run(run: RunConfig<'_>) {
3212 run.builder.ensure(Distcheck);
3213 }
3214
3215 fn run(self, builder: &Builder<'_>) {
3225 let root_dir = std::env::temp_dir().join("distcheck");
3228
3229 distcheck_plain_source_tarball(builder, &root_dir.join("distcheck-rustc-src"));
3230 distcheck_rust_src(builder, &root_dir.join("distcheck-rust-src"));
3231 distcheck_rustc_dev(builder, &root_dir.join("distcheck-rustc-dev"));
3232 }
3233}
3234
3235fn distcheck_plain_source_tarball(builder: &Builder<'_>, plain_src_dir: &Path) {
3237 builder.info("Distcheck plain source tarball");
3238 let plain_src_tarball = builder.ensure(dist::PlainSourceTarball);
3239 builder.clear_dir(plain_src_dir);
3240
3241 let configure_args: Vec<String> = std::env::var("DISTCHECK_CONFIGURE_ARGS")
3242 .map(|args| args.split(" ").map(|s| s.to_string()).collect::<Vec<String>>())
3243 .unwrap_or_default();
3244
3245 command("tar")
3246 .arg("-xf")
3247 .arg(plain_src_tarball.tarball())
3248 .arg("--strip-components=1")
3249 .current_dir(plain_src_dir)
3250 .run(builder);
3251 command("./configure")
3252 .arg("--set")
3253 .arg("rust.omit-git-hash=false")
3254 .args(&configure_args)
3255 .arg("--enable-vendor")
3256 .current_dir(plain_src_dir)
3257 .run(builder);
3258 command(helpers::make(&builder.config.host_target.triple))
3259 .arg("check")
3260 .env("GITHUB_ACTIONS", "0")
3263 .current_dir(plain_src_dir)
3264 .run(builder);
3265}
3266
3267fn distcheck_rust_src(builder: &Builder<'_>, src_dir: &Path) {
3269 builder.info("Distcheck rust-src");
3270 let src_tarball = builder.ensure(dist::Src);
3271 builder.clear_dir(src_dir);
3272
3273 command("tar")
3274 .arg("-xf")
3275 .arg(src_tarball.tarball())
3276 .arg("--strip-components=1")
3277 .current_dir(src_dir)
3278 .run(builder);
3279
3280 let toml = src_dir.join("rust-src/lib/rustlib/src/rust/library/std/Cargo.toml");
3281 command(&builder.initial_cargo)
3282 .env("RUSTC_BOOTSTRAP", "1")
3285 .arg("generate-lockfile")
3286 .arg("--manifest-path")
3287 .arg(&toml)
3288 .current_dir(src_dir)
3289 .run(builder);
3290}
3291
3292fn distcheck_rustc_dev(builder: &Builder<'_>, dir: &Path) {
3294 builder.info("Distcheck rustc-dev");
3295 let tarball = builder.ensure(dist::RustcDev::new(builder, builder.host_target)).unwrap();
3296 builder.clear_dir(dir);
3297
3298 command("tar")
3299 .arg("-xf")
3300 .arg(tarball.tarball())
3301 .arg("--strip-components=1")
3302 .current_dir(dir)
3303 .run(builder);
3304
3305 command(&builder.initial_cargo)
3306 .arg("metadata")
3307 .arg("--manifest-path")
3308 .arg("rustc-dev/lib/rustlib/rustc-src/rust/compiler/rustc/Cargo.toml")
3309 .env("RUSTC_BOOTSTRAP", "1")
3310 .env("RUSTC", &builder.initial_rustc)
3312 .current_dir(dir)
3313 .run(builder);
3314}
3315
3316#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3317pub struct Bootstrap;
3318
3319impl Step for Bootstrap {
3320 type Output = ();
3321 const DEFAULT: bool = true;
3322 const IS_HOST: bool = true;
3323
3324 fn run(self, builder: &Builder<'_>) {
3326 let host = builder.config.host_target;
3327 let build_compiler = builder.compiler(0, host);
3328
3329 builder.build.require_submodule("src/tools/cargo", None);
3331
3332 let mut check_bootstrap = command(builder.python());
3333 check_bootstrap
3334 .args(["-m", "unittest", "bootstrap_test.py"])
3335 .env("BUILD_DIR", &builder.out)
3336 .env("BUILD_PLATFORM", builder.build.host_target.triple)
3337 .env("BOOTSTRAP_TEST_RUSTC_BIN", &builder.initial_rustc)
3338 .env("BOOTSTRAP_TEST_CARGO_BIN", &builder.initial_cargo)
3339 .current_dir(builder.src.join("src/bootstrap/"));
3340 check_bootstrap.delay_failure().run(builder);
3343
3344 let mut cargo = tool::prepare_tool_cargo(
3345 builder,
3346 build_compiler,
3347 Mode::ToolBootstrap,
3348 host,
3349 Kind::Test,
3350 "src/bootstrap",
3351 SourceType::InTree,
3352 &[],
3353 );
3354
3355 cargo.release_build(false);
3356
3357 cargo
3358 .rustflag("-Cdebuginfo=2")
3359 .env("CARGO_TARGET_DIR", builder.out.join("bootstrap"))
3360 .env("INSTA_WORKSPACE_ROOT", &builder.src)
3362 .env("RUSTC_BOOTSTRAP", "1");
3363
3364 run_cargo_test(cargo, &[], &[], None, host, builder);
3365 }
3366
3367 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3368 let runs_on_ci = run.builder.config.is_running_on_ci;
3372 run.path("src/bootstrap").default_condition(runs_on_ci)
3373 }
3374
3375 fn make_run(run: RunConfig<'_>) {
3376 run.builder.ensure(Bootstrap);
3377 }
3378}
3379
3380fn get_compiler_to_test(builder: &Builder<'_>, target: TargetSelection) -> Compiler {
3381 builder.compiler(builder.top_stage, target)
3382}
3383
3384#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3387pub struct TierCheck {
3388 test_compiler: Compiler,
3389}
3390
3391impl Step for TierCheck {
3392 type Output = ();
3393 const DEFAULT: bool = true;
3394 const IS_HOST: bool = true;
3395
3396 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3397 run.path("src/tools/tier-check")
3398 }
3399
3400 fn make_run(run: RunConfig<'_>) {
3401 run.builder
3402 .ensure(TierCheck { test_compiler: get_compiler_to_test(run.builder, run.target) });
3403 }
3404
3405 fn run(self, builder: &Builder<'_>) {
3406 let tool_build_compiler = builder.compiler(0, builder.host_target);
3407
3408 let mut cargo = tool::prepare_tool_cargo(
3409 builder,
3410 tool_build_compiler,
3411 Mode::ToolBootstrap,
3412 tool_build_compiler.host,
3413 Kind::Run,
3414 "src/tools/tier-check",
3415 SourceType::InTree,
3416 &[],
3417 );
3418 cargo.arg(builder.src.join("src/doc/rustc/src/platform-support.md"));
3419 cargo.arg(builder.rustc(self.test_compiler));
3420
3421 let _guard = builder.msg_test(
3422 "platform support check",
3423 self.test_compiler.host,
3424 self.test_compiler.stage,
3425 );
3426 BootstrapCommand::from(cargo).delay_failure().run(builder);
3427 }
3428
3429 fn metadata(&self) -> Option<StepMetadata> {
3430 Some(StepMetadata::test("tier-check", self.test_compiler.host))
3431 }
3432}
3433
3434#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3435pub struct LintDocs {
3436 build_compiler: Compiler,
3437 target: TargetSelection,
3438}
3439
3440impl Step for LintDocs {
3441 type Output = ();
3442 const DEFAULT: bool = true;
3443 const IS_HOST: bool = true;
3444
3445 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3446 let stage = run.builder.top_stage;
3447 run.path("src/tools/lint-docs").default_condition(stage > 1)
3450 }
3451
3452 fn make_run(run: RunConfig<'_>) {
3453 if run.builder.top_stage < 2 {
3454 eprintln!("WARNING: lint-docs tests might not work below stage 2");
3455 }
3456
3457 run.builder.ensure(LintDocs {
3458 build_compiler: prepare_doc_compiler(
3459 run.builder,
3460 run.builder.config.host_target,
3461 run.builder.top_stage,
3462 ),
3463 target: run.target,
3464 });
3465 }
3466
3467 fn run(self, builder: &Builder<'_>) {
3470 builder.ensure(crate::core::build_steps::doc::RustcBook::validate(
3471 self.build_compiler,
3472 self.target,
3473 ));
3474 }
3475
3476 fn metadata(&self) -> Option<StepMetadata> {
3477 Some(StepMetadata::test("lint-docs", self.target).built_by(self.build_compiler))
3478 }
3479}
3480
3481#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3482pub struct RustInstaller;
3483
3484impl Step for RustInstaller {
3485 type Output = ();
3486 const IS_HOST: bool = true;
3487 const DEFAULT: bool = true;
3488
3489 fn run(self, builder: &Builder<'_>) {
3491 let bootstrap_host = builder.config.host_target;
3492 let build_compiler = builder.compiler(0, bootstrap_host);
3493 let cargo = tool::prepare_tool_cargo(
3494 builder,
3495 build_compiler,
3496 Mode::ToolBootstrap,
3497 bootstrap_host,
3498 Kind::Test,
3499 "src/tools/rust-installer",
3500 SourceType::InTree,
3501 &[],
3502 );
3503
3504 let _guard = builder.msg_test("rust-installer", bootstrap_host, 1);
3505 run_cargo_test(cargo, &[], &[], None, bootstrap_host, builder);
3506
3507 if bootstrap_host != "x86_64-unknown-linux-gnu" {
3511 return;
3512 }
3513
3514 let mut cmd = command(builder.src.join("src/tools/rust-installer/test.sh"));
3515 let tmpdir = testdir(builder, build_compiler.host).join("rust-installer");
3516 let _ = std::fs::remove_dir_all(&tmpdir);
3517 let _ = std::fs::create_dir_all(&tmpdir);
3518 cmd.current_dir(&tmpdir);
3519 cmd.env("CARGO_TARGET_DIR", tmpdir.join("cargo-target"));
3520 cmd.env("CARGO", &builder.initial_cargo);
3521 cmd.env("RUSTC", &builder.initial_rustc);
3522 cmd.env("TMP_DIR", &tmpdir);
3523 cmd.delay_failure().run(builder);
3524 }
3525
3526 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3527 run.path("src/tools/rust-installer")
3528 }
3529
3530 fn make_run(run: RunConfig<'_>) {
3531 run.builder.ensure(Self);
3532 }
3533}
3534
3535#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3536pub struct TestHelpers {
3537 pub target: TargetSelection,
3538}
3539
3540impl Step for TestHelpers {
3541 type Output = ();
3542
3543 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3544 run.path("tests/auxiliary/rust_test_helpers.c")
3545 }
3546
3547 fn make_run(run: RunConfig<'_>) {
3548 run.builder.ensure(TestHelpers { target: run.target })
3549 }
3550
3551 fn run(self, builder: &Builder<'_>) {
3554 if builder.config.dry_run() {
3555 return;
3556 }
3557 let target = if self.target == "x86_64-fortanix-unknown-sgx" {
3561 TargetSelection::from_user("x86_64-unknown-linux-gnu")
3562 } else {
3563 self.target
3564 };
3565 let dst = builder.test_helpers_out(target);
3566 let src = builder.src.join("tests/auxiliary/rust_test_helpers.c");
3567 if up_to_date(&src, &dst.join("librust_test_helpers.a")) {
3568 return;
3569 }
3570
3571 let _guard = builder.msg_unstaged(Kind::Build, "test helpers", target);
3572 t!(fs::create_dir_all(&dst));
3573 let mut cfg = cc::Build::new();
3574
3575 if !target.is_msvc() {
3579 if let Some(ar) = builder.ar(target) {
3580 cfg.archiver(ar);
3581 }
3582 cfg.compiler(builder.cc(target));
3583 }
3584 cfg.cargo_metadata(false)
3585 .out_dir(&dst)
3586 .target(&target.triple)
3587 .host(&builder.config.host_target.triple)
3588 .opt_level(0)
3589 .warnings(false)
3590 .debug(false)
3591 .file(builder.src.join("tests/auxiliary/rust_test_helpers.c"))
3592 .compile("rust_test_helpers");
3593 }
3594}
3595
3596#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3597pub struct CodegenCranelift {
3598 compilers: RustcPrivateCompilers,
3599 target: TargetSelection,
3600}
3601
3602impl Step for CodegenCranelift {
3603 type Output = ();
3604 const DEFAULT: bool = true;
3605 const IS_HOST: bool = true;
3606
3607 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3608 run.paths(&["compiler/rustc_codegen_cranelift"])
3609 }
3610
3611 fn make_run(run: RunConfig<'_>) {
3612 let builder = run.builder;
3613 let host = run.build_triple();
3614 let compilers = RustcPrivateCompilers::new(run.builder, run.builder.top_stage, host);
3615
3616 if builder.doc_tests == DocTests::Only {
3617 return;
3618 }
3619
3620 if builder.download_rustc() {
3621 builder.info("CI rustc uses the default codegen backend. skipping");
3622 return;
3623 }
3624
3625 if !target_supports_cranelift_backend(run.target) {
3626 builder.info("target not supported by rustc_codegen_cranelift. skipping");
3627 return;
3628 }
3629
3630 if builder.remote_tested(run.target) {
3631 builder.info("remote testing is not supported by rustc_codegen_cranelift. skipping");
3632 return;
3633 }
3634
3635 if !builder
3636 .config
3637 .enabled_codegen_backends(run.target)
3638 .contains(&CodegenBackendKind::Cranelift)
3639 {
3640 builder.info("cranelift not in rust.codegen-backends. skipping");
3641 return;
3642 }
3643
3644 builder.ensure(CodegenCranelift { compilers, target: run.target });
3645 }
3646
3647 fn run(self, builder: &Builder<'_>) {
3648 let compilers = self.compilers;
3649 let build_compiler = compilers.build_compiler();
3650
3651 let target_compiler = compilers.target_compiler();
3654 let target = self.target;
3655
3656 builder.std(target_compiler, target);
3657
3658 let mut cargo = builder::Cargo::new(
3659 builder,
3660 target_compiler,
3661 Mode::Codegen, SourceType::InTree,
3663 target,
3664 Kind::Run,
3665 );
3666
3667 cargo.current_dir(&builder.src.join("compiler/rustc_codegen_cranelift"));
3668 cargo
3669 .arg("--manifest-path")
3670 .arg(builder.src.join("compiler/rustc_codegen_cranelift/build_system/Cargo.toml"));
3671 compile::rustc_cargo_env(builder, &mut cargo, target);
3672
3673 cargo.env("CARGO_BUILD_INCREMENTAL", "false");
3675
3676 let _guard = builder.msg_test(
3677 "rustc_codegen_cranelift",
3678 target_compiler.host,
3679 target_compiler.stage,
3680 );
3681
3682 let download_dir = builder.out.join("cg_clif_download");
3684
3685 cargo
3686 .arg("--")
3687 .arg("test")
3688 .arg("--download-dir")
3689 .arg(&download_dir)
3690 .arg("--out-dir")
3691 .arg(builder.stage_out(build_compiler, Mode::Codegen).join("cg_clif"))
3692 .arg("--no-unstable-features")
3693 .arg("--use-backend")
3694 .arg("cranelift")
3695 .arg("--sysroot")
3697 .arg("llvm")
3698 .arg("--skip-test")
3701 .arg("testsuite.extended_sysroot");
3702
3703 cargo.into_cmd().run(builder);
3704 }
3705
3706 fn metadata(&self) -> Option<StepMetadata> {
3707 Some(
3708 StepMetadata::test("rustc_codegen_cranelift", self.target)
3709 .built_by(self.compilers.build_compiler()),
3710 )
3711 }
3712}
3713
3714#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3715pub struct CodegenGCC {
3716 compilers: RustcPrivateCompilers,
3717 target: TargetSelection,
3718}
3719
3720impl Step for CodegenGCC {
3721 type Output = ();
3722 const DEFAULT: bool = true;
3723 const IS_HOST: bool = true;
3724
3725 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3726 run.paths(&["compiler/rustc_codegen_gcc"])
3727 }
3728
3729 fn make_run(run: RunConfig<'_>) {
3730 let builder = run.builder;
3731 let host = run.build_triple();
3732 let compilers = RustcPrivateCompilers::new(run.builder, run.builder.top_stage, host);
3733
3734 if builder.doc_tests == DocTests::Only {
3735 return;
3736 }
3737
3738 if builder.download_rustc() {
3739 builder.info("CI rustc uses the default codegen backend. skipping");
3740 return;
3741 }
3742
3743 let triple = run.target.triple;
3744 let target_supported =
3745 if triple.contains("linux") { triple.contains("x86_64") } else { false };
3746 if !target_supported {
3747 builder.info("target not supported by rustc_codegen_gcc. skipping");
3748 return;
3749 }
3750
3751 if builder.remote_tested(run.target) {
3752 builder.info("remote testing is not supported by rustc_codegen_gcc. skipping");
3753 return;
3754 }
3755
3756 if !builder.config.enabled_codegen_backends(run.target).contains(&CodegenBackendKind::Gcc) {
3757 builder.info("gcc not in rust.codegen-backends. skipping");
3758 return;
3759 }
3760
3761 builder.ensure(CodegenGCC { compilers, target: run.target });
3762 }
3763
3764 fn run(self, builder: &Builder<'_>) {
3765 let compilers = self.compilers;
3766 let target = self.target;
3767
3768 let gcc = builder.ensure(Gcc { target });
3769
3770 builder.ensure(
3771 compile::Std::new(compilers.build_compiler(), target)
3772 .extra_rust_args(&["-Csymbol-mangling-version=v0", "-Cpanic=abort"]),
3773 );
3774
3775 let _guard = builder.msg_test(
3776 "rustc_codegen_gcc",
3777 compilers.target(),
3778 compilers.target_compiler().stage,
3779 );
3780
3781 let mut cargo = builder::Cargo::new(
3782 builder,
3783 compilers.build_compiler(),
3784 Mode::Codegen, SourceType::InTree,
3786 target,
3787 Kind::Run,
3788 );
3789
3790 cargo.current_dir(&builder.src.join("compiler/rustc_codegen_gcc"));
3791 cargo
3792 .arg("--manifest-path")
3793 .arg(builder.src.join("compiler/rustc_codegen_gcc/build_system/Cargo.toml"));
3794 compile::rustc_cargo_env(builder, &mut cargo, target);
3795 add_cg_gcc_cargo_flags(&mut cargo, &gcc);
3796
3797 cargo.env("CARGO_BUILD_INCREMENTAL", "false");
3799 cargo.rustflag("-Cpanic=abort");
3800
3801 cargo
3802 .env("CG_RUSTFLAGS", "-Alinker-messages")
3804 .arg("--")
3805 .arg("test")
3806 .arg("--use-backend")
3807 .arg("gcc")
3808 .arg("--gcc-path")
3809 .arg(gcc.libgccjit.parent().unwrap())
3810 .arg("--out-dir")
3811 .arg(builder.stage_out(compilers.build_compiler(), Mode::Codegen).join("cg_gcc"))
3812 .arg("--release")
3813 .arg("--mini-tests")
3814 .arg("--std-tests");
3815 cargo.args(builder.config.test_args());
3816
3817 cargo.into_cmd().run(builder);
3818 }
3819
3820 fn metadata(&self) -> Option<StepMetadata> {
3821 Some(
3822 StepMetadata::test("rustc_codegen_gcc", self.target)
3823 .built_by(self.compilers.build_compiler()),
3824 )
3825 }
3826}
3827
3828#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3833pub struct TestFloatParse {
3834 build_compiler: Compiler,
3843 target: TargetSelection,
3845}
3846
3847impl Step for TestFloatParse {
3848 type Output = ();
3849 const IS_HOST: bool = true;
3850 const DEFAULT: bool = true;
3851
3852 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3853 run.path("src/tools/test-float-parse")
3854 }
3855
3856 fn make_run(run: RunConfig<'_>) {
3857 run.builder.ensure(Self {
3858 build_compiler: get_compiler_to_test(run.builder, run.target),
3859 target: run.target,
3860 });
3861 }
3862
3863 fn run(self, builder: &Builder<'_>) {
3864 let build_compiler = self.build_compiler;
3865 let target = self.target;
3866
3867 builder.std(build_compiler, target);
3869 builder.std(build_compiler, builder.host_target);
3870
3871 let mut cargo_test = tool::prepare_tool_cargo(
3873 builder,
3874 build_compiler,
3875 Mode::ToolStd,
3876 target,
3877 Kind::Test,
3878 "src/tools/test-float-parse",
3879 SourceType::InTree,
3880 &[],
3881 );
3882 cargo_test.allow_features(TEST_FLOAT_PARSE_ALLOW_FEATURES);
3883
3884 run_cargo_test(cargo_test, &[], &[], "test-float-parse", target, builder);
3885
3886 let mut cargo_run = tool::prepare_tool_cargo(
3888 builder,
3889 build_compiler,
3890 Mode::ToolStd,
3891 target,
3892 Kind::Run,
3893 "src/tools/test-float-parse",
3894 SourceType::InTree,
3895 &[],
3896 );
3897 cargo_run.allow_features(TEST_FLOAT_PARSE_ALLOW_FEATURES);
3898
3899 if !matches!(env::var("FLOAT_PARSE_TESTS_NO_SKIP_HUGE").as_deref(), Ok("1") | Ok("true")) {
3900 cargo_run.args(["--", "--skip-huge"]);
3901 }
3902
3903 cargo_run.into_cmd().run(builder);
3904 }
3905}
3906
3907#[derive(Debug, Clone, Hash, PartialEq, Eq)]
3911pub struct CollectLicenseMetadata;
3912
3913impl Step for CollectLicenseMetadata {
3914 type Output = PathBuf;
3915 const IS_HOST: bool = true;
3916
3917 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3918 run.path("src/tools/collect-license-metadata")
3919 }
3920
3921 fn make_run(run: RunConfig<'_>) {
3922 run.builder.ensure(CollectLicenseMetadata);
3923 }
3924
3925 fn run(self, builder: &Builder<'_>) -> Self::Output {
3926 let Some(reuse) = &builder.config.reuse else {
3927 panic!("REUSE is required to collect the license metadata");
3928 };
3929
3930 let dest = builder.src.join("license-metadata.json");
3931
3932 let mut cmd = builder.tool_cmd(Tool::CollectLicenseMetadata);
3933 cmd.env("REUSE_EXE", reuse);
3934 cmd.env("DEST", &dest);
3935 cmd.env("ONLY_CHECK", "1");
3936 cmd.run(builder);
3937
3938 dest
3939 }
3940}