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, get_help_path};
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, top_level_help};
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 builder.info("x.py help check");
1297 if builder.config.cmd.bless() {
1298 builder.ensure(crate::core::build_steps::run::GenerateHelp);
1299 } else {
1300 let help_path = get_help_path(builder);
1301 let cur_help = std::fs::read_to_string(&help_path).unwrap_or_else(|err| {
1302 eprintln!("couldn't read {}: {}", help_path.display(), err);
1303 crate::exit!(1);
1304 });
1305 let new_help = top_level_help();
1306
1307 if new_help != cur_help {
1308 eprintln!("x.py help was changed; run `x.py run generate-help` to update it");
1309 crate::exit!(1);
1310 }
1311 }
1312 }
1313
1314 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1315 let default = run.builder.doc_tests != DocTests::Only;
1316 run.path("src/tools/tidy").default_condition(default)
1317 }
1318
1319 fn make_run(run: RunConfig<'_>) {
1320 run.builder.ensure(Tidy);
1321 }
1322
1323 fn metadata(&self) -> Option<StepMetadata> {
1324 Some(StepMetadata::test("tidy", TargetSelection::default()))
1325 }
1326}
1327
1328#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1331pub struct CrateRunMakeSupport {
1332 host: TargetSelection,
1333}
1334
1335impl Step for CrateRunMakeSupport {
1336 type Output = ();
1337 const IS_HOST: bool = true;
1338
1339 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1340 run.path("src/tools/run-make-support")
1341 }
1342
1343 fn make_run(run: RunConfig<'_>) {
1344 run.builder.ensure(CrateRunMakeSupport { host: run.target });
1345 }
1346
1347 fn run(self, builder: &Builder<'_>) {
1349 let host = self.host;
1350 let compiler = builder.compiler(0, host);
1351
1352 let mut cargo = tool::prepare_tool_cargo(
1353 builder,
1354 compiler,
1355 Mode::ToolBootstrap,
1356 host,
1357 Kind::Test,
1358 "src/tools/run-make-support",
1359 SourceType::InTree,
1360 &[],
1361 );
1362 cargo.allow_features("test");
1363 run_cargo_test(cargo, &[], &[], "run-make-support self test", host, builder);
1364 }
1365}
1366
1367#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1368pub struct CrateBuildHelper {
1369 host: TargetSelection,
1370}
1371
1372impl Step for CrateBuildHelper {
1373 type Output = ();
1374 const IS_HOST: bool = true;
1375
1376 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1377 run.path("src/build_helper")
1378 }
1379
1380 fn make_run(run: RunConfig<'_>) {
1381 run.builder.ensure(CrateBuildHelper { host: run.target });
1382 }
1383
1384 fn run(self, builder: &Builder<'_>) {
1386 let host = self.host;
1387 let compiler = builder.compiler(0, host);
1388
1389 let mut cargo = tool::prepare_tool_cargo(
1390 builder,
1391 compiler,
1392 Mode::ToolBootstrap,
1393 host,
1394 Kind::Test,
1395 "src/build_helper",
1396 SourceType::InTree,
1397 &[],
1398 );
1399 cargo.allow_features("test");
1400 run_cargo_test(cargo, &[], &[], "build_helper self test", host, builder);
1401 }
1402}
1403
1404fn testdir(builder: &Builder<'_>, host: TargetSelection) -> PathBuf {
1405 builder.out.join(host).join("test")
1406}
1407
1408macro_rules! test {
1410 (
1411 $( #[$attr:meta] )* $name:ident {
1413 path: $path:expr,
1414 mode: $mode:expr,
1415 suite: $suite:expr,
1416 default: $default:expr
1417 $( , IS_HOST: $IS_HOST:expr )? $( , compare_mode: $compare_mode:expr )? $( , )? }
1421 ) => {
1422 $( #[$attr] )*
1423 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
1424 pub struct $name {
1425 test_compiler: Compiler,
1426 target: TargetSelection,
1427 }
1428
1429 impl Step for $name {
1430 type Output = ();
1431 const DEFAULT: bool = $default;
1432 const IS_HOST: bool = (const {
1433 #[allow(unused_assignments, unused_mut)]
1434 let mut value = false;
1435 $( value = $IS_HOST; )?
1436 value
1437 });
1438
1439 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1440 run.suite_path($path)
1441 }
1442
1443 fn make_run(run: RunConfig<'_>) {
1444 let test_compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1445
1446 run.builder.ensure($name { test_compiler, target: run.target });
1447 }
1448
1449 fn run(self, builder: &Builder<'_>) {
1450 builder.ensure(Compiletest {
1451 test_compiler: self.test_compiler,
1452 target: self.target,
1453 mode: $mode,
1454 suite: $suite,
1455 path: $path,
1456 compare_mode: (const {
1457 #[allow(unused_assignments, unused_mut)]
1458 let mut value = None;
1459 $( value = $compare_mode; )?
1460 value
1461 }),
1462 })
1463 }
1464 }
1465 };
1466}
1467
1468test!(Ui { path: "tests/ui", mode: "ui", suite: "ui", default: true });
1469
1470test!(Crashes { path: "tests/crashes", mode: "crashes", suite: "crashes", default: true });
1471
1472test!(CodegenLlvm {
1473 path: "tests/codegen-llvm",
1474 mode: "codegen",
1475 suite: "codegen-llvm",
1476 default: true
1477});
1478
1479test!(CodegenUnits {
1480 path: "tests/codegen-units",
1481 mode: "codegen-units",
1482 suite: "codegen-units",
1483 default: true,
1484});
1485
1486test!(Incremental {
1487 path: "tests/incremental",
1488 mode: "incremental",
1489 suite: "incremental",
1490 default: true,
1491});
1492
1493test!(Debuginfo {
1494 path: "tests/debuginfo",
1495 mode: "debuginfo",
1496 suite: "debuginfo",
1497 default: true,
1498 compare_mode: Some("split-dwarf"),
1499});
1500
1501test!(UiFullDeps {
1502 path: "tests/ui-fulldeps",
1503 mode: "ui",
1504 suite: "ui-fulldeps",
1505 default: true,
1506 IS_HOST: true,
1507});
1508
1509test!(Rustdoc {
1510 path: "tests/rustdoc",
1511 mode: "rustdoc",
1512 suite: "rustdoc",
1513 default: true,
1514 IS_HOST: true,
1515});
1516test!(RustdocUi {
1517 path: "tests/rustdoc-ui",
1518 mode: "ui",
1519 suite: "rustdoc-ui",
1520 default: true,
1521 IS_HOST: true,
1522});
1523
1524test!(RustdocJson {
1525 path: "tests/rustdoc-json",
1526 mode: "rustdoc-json",
1527 suite: "rustdoc-json",
1528 default: true,
1529 IS_HOST: true,
1530});
1531
1532test!(Pretty {
1533 path: "tests/pretty",
1534 mode: "pretty",
1535 suite: "pretty",
1536 default: true,
1537 IS_HOST: true,
1538});
1539
1540test!(RunMake { path: "tests/run-make", mode: "run-make", suite: "run-make", default: true });
1541test!(RunMakeCargo {
1542 path: "tests/run-make-cargo",
1543 mode: "run-make",
1544 suite: "run-make-cargo",
1545 default: true
1546});
1547
1548test!(AssemblyLlvm {
1549 path: "tests/assembly-llvm",
1550 mode: "assembly",
1551 suite: "assembly-llvm",
1552 default: true
1553});
1554
1555#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
1558pub struct Coverage {
1559 pub compiler: Compiler,
1560 pub target: TargetSelection,
1561 pub mode: &'static str,
1562}
1563
1564impl Coverage {
1565 const PATH: &'static str = "tests/coverage";
1566 const SUITE: &'static str = "coverage";
1567 const ALL_MODES: &[&str] = &["coverage-map", "coverage-run"];
1568}
1569
1570impl Step for Coverage {
1571 type Output = ();
1572 const DEFAULT: bool = true;
1573 const IS_HOST: bool = false;
1575
1576 fn should_run(mut run: ShouldRun<'_>) -> ShouldRun<'_> {
1577 run = run.suite_path(Self::PATH);
1583 for mode in Self::ALL_MODES {
1584 run = run.alias(mode);
1585 }
1586 run
1587 }
1588
1589 fn make_run(run: RunConfig<'_>) {
1590 let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1591 let target = run.target;
1592
1593 let mut modes = vec![];
1597
1598 for path in &run.paths {
1601 match path {
1602 PathSet::Set(_) => {
1603 for mode in Self::ALL_MODES {
1604 if path.assert_single_path().path == Path::new(mode) {
1605 modes.push(mode);
1606 break;
1607 }
1608 }
1609 }
1610 PathSet::Suite(_) => {
1611 modes.extend(Self::ALL_MODES);
1612 break;
1613 }
1614 }
1615 }
1616
1617 modes.retain(|mode| !run.builder.config.skip.iter().any(|skip| skip == Path::new(mode)));
1620
1621 for mode in modes {
1629 run.builder.ensure(Coverage { compiler, target, mode });
1630 }
1631 }
1632
1633 fn run(self, builder: &Builder<'_>) {
1634 let Self { compiler, target, mode } = self;
1635 builder.ensure(Compiletest {
1638 test_compiler: compiler,
1639 target,
1640 mode,
1641 suite: Self::SUITE,
1642 path: Self::PATH,
1643 compare_mode: None,
1644 });
1645 }
1646}
1647
1648test!(CoverageRunRustdoc {
1649 path: "tests/coverage-run-rustdoc",
1650 mode: "coverage-run",
1651 suite: "coverage-run-rustdoc",
1652 default: true,
1653 IS_HOST: true,
1654});
1655
1656#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1658pub struct MirOpt {
1659 pub compiler: Compiler,
1660 pub target: TargetSelection,
1661}
1662
1663impl Step for MirOpt {
1664 type Output = ();
1665 const DEFAULT: bool = true;
1666
1667 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1668 run.suite_path("tests/mir-opt")
1669 }
1670
1671 fn make_run(run: RunConfig<'_>) {
1672 let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1673 run.builder.ensure(MirOpt { compiler, target: run.target });
1674 }
1675
1676 fn run(self, builder: &Builder<'_>) {
1677 let run = |target| {
1678 builder.ensure(Compiletest {
1679 test_compiler: self.compiler,
1680 target,
1681 mode: "mir-opt",
1682 suite: "mir-opt",
1683 path: "tests/mir-opt",
1684 compare_mode: None,
1685 })
1686 };
1687
1688 run(self.target);
1689
1690 if builder.config.cmd.bless() {
1693 for target in ["aarch64-unknown-linux-gnu", "i686-pc-windows-msvc"] {
1699 run(TargetSelection::from_user(target));
1700 }
1701
1702 for target in ["x86_64-apple-darwin", "i686-unknown-linux-musl"] {
1703 let target = TargetSelection::from_user(target);
1704 let panic_abort_target = builder.ensure(MirOptPanicAbortSyntheticTarget {
1705 compiler: self.compiler,
1706 base: target,
1707 });
1708 run(panic_abort_target);
1709 }
1710 }
1711 }
1712}
1713
1714#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1720struct Compiletest {
1721 test_compiler: Compiler,
1723 target: TargetSelection,
1724 mode: &'static str,
1725 suite: &'static str,
1726 path: &'static str,
1727 compare_mode: Option<&'static str>,
1728}
1729
1730impl Step for Compiletest {
1731 type Output = ();
1732
1733 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1734 run.never()
1735 }
1736
1737 fn run(self, builder: &Builder<'_>) {
1738 if builder.doc_tests == DocTests::Only {
1739 return;
1740 }
1741
1742 if builder.top_stage == 0 && !builder.config.compiletest_allow_stage0 {
1743 eprintln!("\
1744ERROR: `--stage 0` runs compiletest on the stage0 (precompiled) compiler, not your local changes, and will almost always cause tests to fail
1745HELP: to test the compiler or standard library, omit the stage or explicitly use `--stage 1` instead
1746NOTE: 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`."
1747 );
1748 crate::exit!(1);
1749 }
1750
1751 let mut test_compiler = self.test_compiler;
1752 let target = self.target;
1753 let mode = self.mode;
1754 let suite = self.suite;
1755
1756 let suite_path = self.path;
1758
1759 if !builder.config.codegen_tests && mode == "codegen" {
1761 return;
1762 }
1763
1764 let query_compiler;
1771 let (stage, stage_id) = if suite == "ui-fulldeps" && test_compiler.stage == 1 {
1772 query_compiler = Some(test_compiler);
1775 let build = builder.build.host_target;
1779 test_compiler = builder.compiler(test_compiler.stage - 1, build);
1780 let test_stage = test_compiler.stage + 1;
1781 (test_stage, format!("stage{test_stage}-{build}"))
1782 } else {
1783 query_compiler = None;
1784 let stage = test_compiler.stage;
1785 (stage, format!("stage{stage}-{target}"))
1786 };
1787
1788 if suite.ends_with("fulldeps") {
1789 builder.ensure(compile::Rustc::new(test_compiler, target));
1790 }
1791
1792 if suite == "debuginfo" {
1793 builder.ensure(dist::DebuggerScripts {
1794 sysroot: builder.sysroot(test_compiler).to_path_buf(),
1795 target,
1796 });
1797 }
1798 if mode == "run-make" {
1799 builder.tool_exe(Tool::RunMakeSupport);
1800 }
1801
1802 if suite == "mir-opt" {
1804 builder.ensure(
1805 compile::Std::new(test_compiler, test_compiler.host).is_for_mir_opt_tests(true),
1806 );
1807 } else {
1808 builder.std(test_compiler, test_compiler.host);
1809 }
1810
1811 let mut cmd = builder.tool_cmd(Tool::Compiletest);
1812
1813 if suite == "mir-opt" {
1814 builder.ensure(compile::Std::new(test_compiler, target).is_for_mir_opt_tests(true));
1815 } else {
1816 builder.std(test_compiler, target);
1817 }
1818
1819 builder.ensure(RemoteCopyLibs { build_compiler: test_compiler, target });
1820
1821 cmd.arg("--stage").arg(stage.to_string());
1825 cmd.arg("--stage-id").arg(stage_id);
1826
1827 cmd.arg("--compile-lib-path").arg(builder.rustc_libdir(test_compiler));
1828 cmd.arg("--run-lib-path").arg(builder.sysroot_target_libdir(test_compiler, target));
1829 cmd.arg("--rustc-path").arg(builder.rustc(test_compiler));
1830 if let Some(query_compiler) = query_compiler {
1831 cmd.arg("--query-rustc-path").arg(builder.rustc(query_compiler));
1832 }
1833
1834 cmd.arg("--minicore-path")
1837 .arg(builder.src.join("tests").join("auxiliary").join("minicore.rs"));
1838
1839 let is_rustdoc = suite == "rustdoc-ui" || suite == "rustdoc-js";
1840
1841 if mode == "run-make" {
1856 let stage0_rustc_path = builder.compiler(0, test_compiler.host);
1859 cmd.arg("--stage0-rustc-path").arg(builder.rustc(stage0_rustc_path));
1860
1861 if suite == "run-make-cargo" {
1862 let cargo_path = if test_compiler.stage == 0 {
1863 builder.initial_cargo.clone()
1865 } else {
1866 builder
1867 .ensure(tool::Cargo::from_build_compiler(
1868 builder.compiler(test_compiler.stage - 1, test_compiler.host),
1869 test_compiler.host,
1870 ))
1871 .tool_path
1872 };
1873
1874 cmd.arg("--cargo-path").arg(cargo_path);
1875 }
1876 }
1877
1878 if mode == "rustdoc"
1880 || mode == "run-make"
1881 || (mode == "ui" && is_rustdoc)
1882 || mode == "rustdoc-js"
1883 || mode == "rustdoc-json"
1884 || suite == "coverage-run-rustdoc"
1885 {
1886 cmd.arg("--rustdoc-path").arg(builder.rustdoc_for_compiler(test_compiler));
1887 }
1888
1889 if mode == "rustdoc-json" {
1890 let json_compiler = builder.compiler(0, builder.host_target);
1892 cmd.arg("--jsondocck-path")
1893 .arg(builder.ensure(tool::JsonDocCk { compiler: json_compiler, target }).tool_path);
1894 cmd.arg("--jsondoclint-path").arg(
1895 builder.ensure(tool::JsonDocLint { compiler: json_compiler, target }).tool_path,
1896 );
1897 }
1898
1899 if matches!(mode, "coverage-map" | "coverage-run") {
1900 let coverage_dump = builder.tool_exe(Tool::CoverageDump);
1901 cmd.arg("--coverage-dump-path").arg(coverage_dump);
1902 }
1903
1904 cmd.arg("--src-root").arg(&builder.src);
1905 cmd.arg("--src-test-suite-root").arg(builder.src.join("tests").join(suite));
1906
1907 cmd.arg("--build-root").arg(&builder.out);
1911 cmd.arg("--build-test-suite-root").arg(testdir(builder, test_compiler.host).join(suite));
1912
1913 let sysroot = if builder.top_stage == 0 {
1918 builder.initial_sysroot.clone()
1919 } else {
1920 builder.sysroot(test_compiler)
1921 };
1922
1923 cmd.arg("--sysroot-base").arg(sysroot);
1924
1925 cmd.arg("--suite").arg(suite);
1926 cmd.arg("--mode").arg(mode);
1927 cmd.arg("--target").arg(target.rustc_target_arg());
1928 cmd.arg("--host").arg(&*test_compiler.host.triple);
1929 cmd.arg("--llvm-filecheck").arg(builder.llvm_filecheck(builder.config.host_target));
1930
1931 if let Some(codegen_backend) = builder.config.cmd.test_codegen_backend() {
1932 if !builder
1933 .config
1934 .enabled_codegen_backends(test_compiler.host)
1935 .contains(codegen_backend)
1936 {
1937 eprintln!(
1938 "\
1939ERROR: No configured backend named `{name}`
1940HELP: You can add it into `bootstrap.toml` in `rust.codegen-backends = [{name:?}]`",
1941 name = codegen_backend.name(),
1942 );
1943 crate::exit!(1);
1944 }
1945
1946 if let CodegenBackendKind::Gcc = codegen_backend
1947 && builder.config.rustc_debug_assertions
1948 {
1949 eprintln!(
1950 r#"WARNING: Running tests with the GCC codegen backend while rustc debug assertions are enabled. This might lead to test failures.
1951Please disable assertions with `rust.debug-assertions = false`.
1952 "#
1953 );
1954 }
1955
1956 cmd.arg("--override-codegen-backend").arg(codegen_backend.name());
1959 cmd.arg("--default-codegen-backend").arg(codegen_backend.name());
1962 } else {
1963 cmd.arg("--default-codegen-backend")
1966 .arg(builder.config.default_codegen_backend(test_compiler.host).name());
1967 }
1968
1969 if builder.build.config.llvm_enzyme {
1970 cmd.arg("--has-enzyme");
1971 }
1972
1973 if builder.config.cmd.bless() {
1974 cmd.arg("--bless");
1975 }
1976
1977 if builder.config.cmd.force_rerun() {
1978 cmd.arg("--force-rerun");
1979 }
1980
1981 if builder.config.cmd.no_capture() {
1982 cmd.arg("--no-capture");
1983 }
1984
1985 let compare_mode =
1986 builder.config.cmd.compare_mode().or_else(|| {
1987 if builder.config.test_compare_mode { self.compare_mode } else { None }
1988 });
1989
1990 if let Some(ref pass) = builder.config.cmd.pass() {
1991 cmd.arg("--pass");
1992 cmd.arg(pass);
1993 }
1994
1995 if let Some(ref run) = builder.config.cmd.run() {
1996 cmd.arg("--run");
1997 cmd.arg(run);
1998 }
1999
2000 if let Some(ref nodejs) = builder.config.nodejs {
2001 cmd.arg("--nodejs").arg(nodejs);
2002 } else if mode == "rustdoc-js" {
2003 panic!("need nodejs to run rustdoc-js suite");
2004 }
2005 if builder.config.rust_optimize_tests {
2006 cmd.arg("--optimize-tests");
2007 }
2008 if builder.config.rust_randomize_layout {
2009 cmd.arg("--rust-randomized-layout");
2010 }
2011 if builder.config.cmd.only_modified() {
2012 cmd.arg("--only-modified");
2013 }
2014 if let Some(compiletest_diff_tool) = &builder.config.compiletest_diff_tool {
2015 cmd.arg("--compiletest-diff-tool").arg(compiletest_diff_tool);
2016 }
2017
2018 let mut flags = if is_rustdoc { Vec::new() } else { vec!["-Crpath".to_string()] };
2019 flags.push(format!(
2020 "-Cdebuginfo={}",
2021 if mode == "codegen" {
2022 if builder.config.rust_debuginfo_level_tests
2025 != crate::core::config::DebuginfoLevel::None
2026 {
2027 println!(
2028 "NOTE: ignoring `rust.debuginfo-level-tests={}` for codegen tests",
2029 builder.config.rust_debuginfo_level_tests
2030 );
2031 }
2032 crate::core::config::DebuginfoLevel::None
2033 } else {
2034 builder.config.rust_debuginfo_level_tests
2035 }
2036 ));
2037 flags.extend(builder.config.cmd.compiletest_rustc_args().iter().map(|s| s.to_string()));
2038
2039 if suite != "mir-opt" {
2040 if let Some(linker) = builder.linker(target) {
2041 cmd.arg("--target-linker").arg(linker);
2042 }
2043 if let Some(linker) = builder.linker(test_compiler.host) {
2044 cmd.arg("--host-linker").arg(linker);
2045 }
2046 }
2047
2048 if suite == "ui-fulldeps" && target.ends_with("darwin") {
2050 flags.push("-Alinker_messages".into());
2051 }
2052
2053 let mut hostflags = flags.clone();
2054 hostflags.extend(linker_flags(builder, test_compiler.host, LldThreads::No));
2055
2056 let mut targetflags = flags;
2057
2058 if suite == "ui" || suite == "incremental" {
2060 builder.ensure(TestHelpers { target: test_compiler.host });
2061 builder.ensure(TestHelpers { target });
2062 hostflags.push(format!(
2063 "-Lnative={}",
2064 builder.test_helpers_out(test_compiler.host).display()
2065 ));
2066 targetflags.push(format!("-Lnative={}", builder.test_helpers_out(target).display()));
2067 }
2068
2069 for flag in hostflags {
2070 cmd.arg("--host-rustcflags").arg(flag);
2071 }
2072 for flag in targetflags {
2073 cmd.arg("--target-rustcflags").arg(flag);
2074 }
2075
2076 cmd.arg("--python").arg(builder.python());
2077
2078 if let Some(ref gdb) = builder.config.gdb {
2079 cmd.arg("--gdb").arg(gdb);
2080 }
2081
2082 let lldb_exe = builder.config.lldb.clone().unwrap_or_else(|| PathBuf::from("lldb"));
2083 let lldb_version = command(&lldb_exe)
2084 .allow_failure()
2085 .arg("--version")
2086 .run_capture(builder)
2087 .stdout_if_ok()
2088 .and_then(|v| if v.trim().is_empty() { None } else { Some(v) });
2089 if let Some(ref vers) = lldb_version {
2090 cmd.arg("--lldb-version").arg(vers);
2091 let lldb_python_dir = command(&lldb_exe)
2092 .allow_failure()
2093 .arg("-P")
2094 .run_capture_stdout(builder)
2095 .stdout_if_ok()
2096 .map(|p| p.lines().next().expect("lldb Python dir not found").to_string());
2097 if let Some(ref dir) = lldb_python_dir {
2098 cmd.arg("--lldb-python-dir").arg(dir);
2099 }
2100 }
2101
2102 if helpers::forcing_clang_based_tests() {
2103 let clang_exe = builder.llvm_out(target).join("bin").join("clang");
2104 cmd.arg("--run-clang-based-tests-with").arg(clang_exe);
2105 }
2106
2107 for exclude in &builder.config.skip {
2108 cmd.arg("--skip");
2109 cmd.arg(exclude);
2110 }
2111
2112 let mut paths = match &builder.config.cmd {
2114 Subcommand::Test { .. } => &builder.config.paths[..],
2115 _ => &[],
2116 };
2117
2118 let mut paths_v;
2121 if mode == "rustdoc-js" {
2122 paths_v = paths.to_vec();
2123 for p in &mut paths_v {
2124 if let Some(ext) = p.extension()
2125 && ext == "js"
2126 {
2127 p.set_extension("rs");
2128 }
2129 }
2130 paths = &paths_v;
2131 }
2132 let mut test_args: Vec<&str> = paths
2134 .iter()
2135 .filter_map(|p| helpers::is_valid_test_suite_arg(p, suite_path, builder))
2136 .collect();
2137
2138 test_args.append(&mut builder.config.test_args());
2139
2140 if cfg!(windows) {
2143 let test_args_win: Vec<String> =
2144 test_args.iter().map(|s| s.replace('/', "\\")).collect();
2145 cmd.args(&test_args_win);
2146 } else {
2147 cmd.args(&test_args);
2148 }
2149
2150 if builder.is_verbose() {
2151 cmd.arg("--verbose");
2152 }
2153
2154 if builder.config.rustc_debug_assertions {
2155 cmd.arg("--with-rustc-debug-assertions");
2156 }
2157
2158 if builder.config.std_debug_assertions {
2159 cmd.arg("--with-std-debug-assertions");
2160 }
2161
2162 let mut llvm_components_passed = false;
2163 let mut copts_passed = false;
2164 if builder.config.llvm_enabled(test_compiler.host) {
2165 let llvm::LlvmResult { host_llvm_config, .. } =
2166 builder.ensure(llvm::Llvm { target: builder.config.host_target });
2167 if !builder.config.dry_run() {
2168 let llvm_version = get_llvm_version(builder, &host_llvm_config);
2169 let llvm_components = command(&host_llvm_config)
2170 .cached()
2171 .arg("--components")
2172 .run_capture_stdout(builder)
2173 .stdout();
2174 cmd.arg("--llvm-version")
2176 .arg(llvm_version.trim())
2177 .arg("--llvm-components")
2178 .arg(llvm_components.trim());
2179 llvm_components_passed = true;
2180 }
2181 if !builder.config.is_rust_llvm(target) {
2182 cmd.arg("--system-llvm");
2183 }
2184
2185 if !builder.config.dry_run() && suite.ends_with("fulldeps") {
2190 let llvm_libdir = command(&host_llvm_config)
2191 .cached()
2192 .arg("--libdir")
2193 .run_capture_stdout(builder)
2194 .stdout();
2195 let link_llvm = if target.is_msvc() {
2196 format!("-Clink-arg=-LIBPATH:{llvm_libdir}")
2197 } else {
2198 format!("-Clink-arg=-L{llvm_libdir}")
2199 };
2200 cmd.arg("--host-rustcflags").arg(link_llvm);
2201 }
2202
2203 if !builder.config.dry_run() && matches!(mode, "run-make" | "coverage-run") {
2204 let llvm_bin_path = host_llvm_config
2209 .parent()
2210 .expect("Expected llvm-config to be contained in directory");
2211 assert!(llvm_bin_path.is_dir());
2212 cmd.arg("--llvm-bin-dir").arg(llvm_bin_path);
2213 }
2214
2215 if !builder.config.dry_run() && mode == "run-make" {
2216 if builder.config.lld_enabled {
2218 let lld_install_root =
2219 builder.ensure(llvm::Lld { target: builder.config.host_target });
2220
2221 let lld_bin_path = lld_install_root.join("bin");
2222
2223 let old_path = env::var_os("PATH").unwrap_or_default();
2224 let new_path = env::join_paths(
2225 std::iter::once(lld_bin_path).chain(env::split_paths(&old_path)),
2226 )
2227 .expect("Could not add LLD bin path to PATH");
2228 cmd.env("PATH", new_path);
2229 }
2230 }
2231 }
2232
2233 if !builder.config.dry_run() && mode == "run-make" {
2236 let mut cflags = builder.cc_handled_clags(target, CLang::C);
2237 cflags.extend(builder.cc_unhandled_cflags(target, GitRepo::Rustc, CLang::C));
2238 let mut cxxflags = builder.cc_handled_clags(target, CLang::Cxx);
2239 cxxflags.extend(builder.cc_unhandled_cflags(target, GitRepo::Rustc, CLang::Cxx));
2240 cmd.arg("--cc")
2241 .arg(builder.cc(target))
2242 .arg("--cxx")
2243 .arg(builder.cxx(target).unwrap())
2244 .arg("--cflags")
2245 .arg(cflags.join(" "))
2246 .arg("--cxxflags")
2247 .arg(cxxflags.join(" "));
2248 copts_passed = true;
2249 if let Some(ar) = builder.ar(target) {
2250 cmd.arg("--ar").arg(ar);
2251 }
2252 }
2253
2254 if !llvm_components_passed {
2255 cmd.arg("--llvm-components").arg("");
2256 }
2257 if !copts_passed {
2258 cmd.arg("--cc")
2259 .arg("")
2260 .arg("--cxx")
2261 .arg("")
2262 .arg("--cflags")
2263 .arg("")
2264 .arg("--cxxflags")
2265 .arg("");
2266 }
2267
2268 if builder.remote_tested(target) {
2269 cmd.arg("--remote-test-client").arg(builder.tool_exe(Tool::RemoteTestClient));
2270 } else if let Some(tool) = builder.runner(target) {
2271 cmd.arg("--runner").arg(tool);
2272 }
2273
2274 if suite != "mir-opt" {
2275 if !builder.config.dry_run() && target.is_msvc() {
2281 for (k, v) in builder.cc[&target].env() {
2282 if k != "PATH" {
2283 cmd.env(k, v);
2284 }
2285 }
2286 }
2287 }
2288
2289 if !builder.config.dry_run()
2291 && target.contains("msvc")
2292 && builder.config.sanitizers_enabled(target)
2293 {
2294 cmd.env("ASAN_WIN_CONTINUE_ON_INTERCEPTION_FAILURE", "1");
2297 let asan_runtime_path = builder.cc[&target].path().parent().unwrap().to_path_buf();
2299 let old_path = cmd
2300 .get_envs()
2301 .find_map(|(k, v)| (k == "PATH").then_some(v))
2302 .flatten()
2303 .map_or_else(|| env::var_os("PATH").unwrap_or_default(), |v| v.to_owned());
2304 let new_path = env::join_paths(
2305 env::split_paths(&old_path).chain(std::iter::once(asan_runtime_path)),
2306 )
2307 .expect("Could not add ASAN runtime path to PATH");
2308 cmd.env("PATH", new_path);
2309 }
2310
2311 cmd.env_remove("CARGO");
2314
2315 cmd.env("RUSTC_BOOTSTRAP", "1");
2316 cmd.env("RUSTC_FORCE_RUSTC_VERSION", "compiletest");
2319 cmd.env("DOC_RUST_LANG_ORG_CHANNEL", builder.doc_rust_lang_org_channel());
2320 builder.add_rust_test_threads(&mut cmd);
2321
2322 if builder.config.sanitizers_enabled(target) {
2323 cmd.env("RUSTC_SANITIZER_SUPPORT", "1");
2324 }
2325
2326 if builder.config.profiler_enabled(target) {
2327 cmd.arg("--profiler-runtime");
2328 }
2329
2330 cmd.env("RUST_TEST_TMPDIR", builder.tempdir());
2331
2332 cmd.arg("--adb-path").arg("adb");
2333 cmd.arg("--adb-test-dir").arg(ADB_TEST_DIR);
2334 if target.contains("android") && !builder.config.dry_run() {
2335 cmd.arg("--android-cross-path")
2337 .arg(builder.cc(target).parent().unwrap().parent().unwrap());
2338 } else {
2339 cmd.arg("--android-cross-path").arg("");
2340 }
2341
2342 if builder.config.cmd.rustfix_coverage() {
2343 cmd.arg("--rustfix-coverage");
2344 }
2345
2346 cmd.arg("--channel").arg(&builder.config.channel);
2347
2348 if !builder.config.omit_git_hash {
2349 cmd.arg("--git-hash");
2350 }
2351
2352 let git_config = builder.config.git_config();
2353 cmd.arg("--nightly-branch").arg(git_config.nightly_branch);
2354 cmd.arg("--git-merge-commit-email").arg(git_config.git_merge_commit_email);
2355 cmd.force_coloring_in_ci();
2356
2357 #[cfg(feature = "build-metrics")]
2358 builder.metrics.begin_test_suite(
2359 build_helper::metrics::TestSuiteMetadata::Compiletest {
2360 suite: suite.into(),
2361 mode: mode.into(),
2362 compare_mode: None,
2363 target: self.target.triple.to_string(),
2364 host: self.test_compiler.host.triple.to_string(),
2365 stage: self.test_compiler.stage,
2366 },
2367 builder,
2368 );
2369
2370 let _group = builder.msg_test(
2371 format!("with compiletest suite={suite} mode={mode}"),
2372 target,
2373 test_compiler.stage,
2374 );
2375 try_run_tests(builder, &mut cmd, false);
2376
2377 if let Some(compare_mode) = compare_mode {
2378 cmd.arg("--compare-mode").arg(compare_mode);
2379
2380 #[cfg(feature = "build-metrics")]
2381 builder.metrics.begin_test_suite(
2382 build_helper::metrics::TestSuiteMetadata::Compiletest {
2383 suite: suite.into(),
2384 mode: mode.into(),
2385 compare_mode: Some(compare_mode.into()),
2386 target: self.target.triple.to_string(),
2387 host: self.test_compiler.host.triple.to_string(),
2388 stage: self.test_compiler.stage,
2389 },
2390 builder,
2391 );
2392
2393 builder.info(&format!(
2394 "Check compiletest suite={} mode={} compare_mode={} ({} -> {})",
2395 suite, mode, compare_mode, &test_compiler.host, target
2396 ));
2397 let _time = helpers::timeit(builder);
2398 try_run_tests(builder, &mut cmd, false);
2399 }
2400 }
2401
2402 fn metadata(&self) -> Option<StepMetadata> {
2403 Some(
2404 StepMetadata::test(&format!("compiletest-{}", self.suite), self.target)
2405 .stage(self.test_compiler.stage),
2406 )
2407 }
2408}
2409
2410#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2412struct BookTest {
2413 test_compiler: Compiler,
2414 path: PathBuf,
2415 name: &'static str,
2416 is_ext_doc: bool,
2417 dependencies: Vec<&'static str>,
2418}
2419
2420impl Step for BookTest {
2421 type Output = ();
2422 const IS_HOST: bool = true;
2423
2424 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2425 run.never()
2426 }
2427
2428 fn run(self, builder: &Builder<'_>) {
2429 if self.is_ext_doc {
2439 self.run_ext_doc(builder);
2440 } else {
2441 self.run_local_doc(builder);
2442 }
2443 }
2444}
2445
2446impl BookTest {
2447 fn run_ext_doc(self, builder: &Builder<'_>) {
2450 let test_compiler = self.test_compiler;
2451
2452 builder.std(test_compiler, test_compiler.host);
2453
2454 let mut rustdoc_path = builder.rustdoc_for_compiler(test_compiler);
2457 rustdoc_path.pop();
2458 let old_path = env::var_os("PATH").unwrap_or_default();
2459 let new_path = env::join_paths(iter::once(rustdoc_path).chain(env::split_paths(&old_path)))
2460 .expect("could not add rustdoc to PATH");
2461
2462 let mut rustbook_cmd = builder.tool_cmd(Tool::Rustbook);
2463 let path = builder.src.join(&self.path);
2464 rustbook_cmd.env("RUSTC_BOOTSTRAP", "1");
2466 rustbook_cmd.env("PATH", new_path).arg("test").arg(path);
2467
2468 let libs = if !self.dependencies.is_empty() {
2473 let mut lib_paths = vec![];
2474 for dep in self.dependencies {
2475 let mode = Mode::ToolRustcPrivate;
2476 let target = builder.config.host_target;
2477 let cargo = tool::prepare_tool_cargo(
2478 builder,
2479 test_compiler,
2480 mode,
2481 target,
2482 Kind::Build,
2483 dep,
2484 SourceType::Submodule,
2485 &[],
2486 );
2487
2488 let stamp = BuildStamp::new(&builder.cargo_out(test_compiler, mode, target))
2489 .with_prefix(PathBuf::from(dep).file_name().and_then(|v| v.to_str()).unwrap());
2490
2491 let output_paths = run_cargo(builder, cargo, vec![], &stamp, vec![], false, false);
2492 let directories = output_paths
2493 .into_iter()
2494 .filter_map(|p| p.parent().map(ToOwned::to_owned))
2495 .fold(HashSet::new(), |mut set, dir| {
2496 set.insert(dir);
2497 set
2498 });
2499
2500 lib_paths.extend(directories);
2501 }
2502 lib_paths
2503 } else {
2504 vec![]
2505 };
2506
2507 if !libs.is_empty() {
2508 let paths = libs
2509 .into_iter()
2510 .map(|path| path.into_os_string())
2511 .collect::<Vec<OsString>>()
2512 .join(OsStr::new(","));
2513 rustbook_cmd.args([OsString::from("--library-path"), paths]);
2514 }
2515
2516 builder.add_rust_test_threads(&mut rustbook_cmd);
2517 let _guard = builder.msg_test(
2518 format_args!("mdbook {}", self.path.display()),
2519 test_compiler.host,
2520 test_compiler.stage,
2521 );
2522 let _time = helpers::timeit(builder);
2523 let toolstate = if rustbook_cmd.delay_failure().run(builder) {
2524 ToolState::TestPass
2525 } else {
2526 ToolState::TestFail
2527 };
2528 builder.save_toolstate(self.name, toolstate);
2529 }
2530
2531 fn run_local_doc(self, builder: &Builder<'_>) {
2533 let test_compiler = self.test_compiler;
2534 let host = self.test_compiler.host;
2535
2536 builder.std(test_compiler, host);
2537
2538 let _guard = builder.msg_test(
2539 format!("book {}", self.name),
2540 test_compiler.host,
2541 test_compiler.stage,
2542 );
2543
2544 let mut stack = vec![builder.src.join(self.path)];
2547 let _time = helpers::timeit(builder);
2548 let mut files = Vec::new();
2549 while let Some(p) = stack.pop() {
2550 if p.is_dir() {
2551 stack.extend(t!(p.read_dir()).map(|p| t!(p).path()));
2552 continue;
2553 }
2554
2555 if p.extension().and_then(|s| s.to_str()) != Some("md") {
2556 continue;
2557 }
2558
2559 files.push(p);
2560 }
2561
2562 files.sort();
2563
2564 for file in files {
2565 markdown_test(builder, test_compiler, &file);
2566 }
2567 }
2568}
2569
2570macro_rules! test_book {
2571 ($(
2572 $name:ident, $path:expr, $book_name:expr,
2573 default=$default:expr
2574 $(,submodules = $submodules:expr)?
2575 $(,dependencies=$dependencies:expr)?
2576 ;
2577 )+) => {
2578 $(
2579 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
2580 pub struct $name {
2581 test_compiler: Compiler,
2582 }
2583
2584 impl Step for $name {
2585 type Output = ();
2586 const DEFAULT: bool = $default;
2587 const IS_HOST: bool = true;
2588
2589 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2590 run.path($path)
2591 }
2592
2593 fn make_run(run: RunConfig<'_>) {
2594 run.builder.ensure($name {
2595 test_compiler: run.builder.compiler(run.builder.top_stage, run.target),
2596 });
2597 }
2598
2599 fn run(self, builder: &Builder<'_>) {
2600 $(
2601 for submodule in $submodules {
2602 builder.require_submodule(submodule, None);
2603 }
2604 )*
2605
2606 let dependencies = vec![];
2607 $(
2608 let mut dependencies = dependencies;
2609 for dep in $dependencies {
2610 dependencies.push(dep);
2611 }
2612 )?
2613
2614 builder.ensure(BookTest {
2615 test_compiler: self.test_compiler,
2616 path: PathBuf::from($path),
2617 name: $book_name,
2618 is_ext_doc: !$default,
2619 dependencies,
2620 });
2621 }
2622 }
2623 )+
2624 }
2625}
2626
2627test_book!(
2628 Nomicon, "src/doc/nomicon", "nomicon", default=false, submodules=["src/doc/nomicon"];
2629 Reference, "src/doc/reference", "reference", default=false, submodules=["src/doc/reference"];
2630 RustdocBook, "src/doc/rustdoc", "rustdoc", default=true;
2631 RustcBook, "src/doc/rustc", "rustc", default=true;
2632 RustByExample, "src/doc/rust-by-example", "rust-by-example", default=false, submodules=["src/doc/rust-by-example"];
2633 EmbeddedBook, "src/doc/embedded-book", "embedded-book", default=false, submodules=["src/doc/embedded-book"];
2634 TheBook, "src/doc/book", "book", default=false, submodules=["src/doc/book"], dependencies=["src/doc/book/packages/trpl"];
2635 UnstableBook, "src/doc/unstable-book", "unstable-book", default=true;
2636 EditionGuide, "src/doc/edition-guide", "edition-guide", default=false, submodules=["src/doc/edition-guide"];
2637);
2638
2639#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2640pub struct ErrorIndex {
2641 compilers: RustcPrivateCompilers,
2642}
2643
2644impl Step for ErrorIndex {
2645 type Output = ();
2646 const DEFAULT: bool = true;
2647 const IS_HOST: bool = true;
2648
2649 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2650 run.path("src/tools/error_index_generator").alias("error-index")
2653 }
2654
2655 fn make_run(run: RunConfig<'_>) {
2656 let compilers = RustcPrivateCompilers::new(
2660 run.builder,
2661 run.builder.top_stage,
2662 run.builder.config.host_target,
2663 );
2664 run.builder.ensure(ErrorIndex { compilers });
2665 }
2666
2667 fn run(self, builder: &Builder<'_>) {
2674 let target_compiler = self.compilers.target_compiler();
2676
2677 let dir = testdir(builder, target_compiler.host);
2678 t!(fs::create_dir_all(&dir));
2679 let output = dir.join("error-index.md");
2680
2681 let mut tool = tool::ErrorIndex::command(builder, self.compilers);
2682 tool.arg("markdown").arg(&output);
2683
2684 let guard = builder.msg_test("error-index", target_compiler.host, target_compiler.stage);
2685 let _time = helpers::timeit(builder);
2686 tool.run_capture(builder);
2687 drop(guard);
2688 builder.std(target_compiler, target_compiler.host);
2691 markdown_test(builder, target_compiler, &output);
2692 }
2693}
2694
2695fn markdown_test(builder: &Builder<'_>, compiler: Compiler, markdown: &Path) -> bool {
2696 if let Ok(contents) = fs::read_to_string(markdown)
2697 && !contents.contains("```")
2698 {
2699 return true;
2700 }
2701
2702 builder.do_if_verbose(|| println!("doc tests for: {}", markdown.display()));
2703 let mut cmd = builder.rustdoc_cmd(compiler);
2704 builder.add_rust_test_threads(&mut cmd);
2705 cmd.arg("-Z");
2707 cmd.arg("unstable-options");
2708 cmd.arg("--test");
2709 cmd.arg(markdown);
2710 cmd.env("RUSTC_BOOTSTRAP", "1");
2711
2712 let test_args = builder.config.test_args().join(" ");
2713 cmd.arg("--test-args").arg(test_args);
2714
2715 cmd = cmd.delay_failure();
2716 if !builder.config.verbose_tests {
2717 cmd.run_capture(builder).is_success()
2718 } else {
2719 cmd.run(builder)
2720 }
2721}
2722
2723#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2728pub struct CrateLibrustc {
2729 build_compiler: Compiler,
2731 target: TargetSelection,
2732 crates: Vec<String>,
2733}
2734
2735impl Step for CrateLibrustc {
2736 type Output = ();
2737 const DEFAULT: bool = true;
2738 const IS_HOST: bool = true;
2739
2740 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2741 run.crate_or_deps("rustc-main").path("compiler")
2742 }
2743
2744 fn make_run(run: RunConfig<'_>) {
2745 let builder = run.builder;
2746 let host = run.build_triple();
2747 let build_compiler = builder.compiler(builder.top_stage - 1, host);
2748 let crates = run.make_run_crates(Alias::Compiler);
2749
2750 builder.ensure(CrateLibrustc { build_compiler, target: run.target, crates });
2751 }
2752
2753 fn run(self, builder: &Builder<'_>) {
2754 builder.std(self.build_compiler, self.target);
2755
2756 builder.ensure(Crate {
2758 build_compiler: self.build_compiler,
2759 target: self.target,
2760 mode: Mode::Rustc,
2761 crates: self.crates,
2762 });
2763 }
2764
2765 fn metadata(&self) -> Option<StepMetadata> {
2766 Some(StepMetadata::test("CrateLibrustc", self.target).built_by(self.build_compiler))
2767 }
2768}
2769
2770fn run_cargo_test<'a>(
2774 cargo: builder::Cargo,
2775 libtest_args: &[&str],
2776 crates: &[String],
2777 description: impl Into<Option<&'a str>>,
2778 target: TargetSelection,
2779 builder: &Builder<'_>,
2780) -> bool {
2781 let compiler = cargo.compiler();
2782 let mut cargo = prepare_cargo_test(cargo, libtest_args, crates, target, builder);
2783 let _time = helpers::timeit(builder);
2784 let _group =
2785 description.into().and_then(|what| builder.msg_test(what, target, compiler.stage + 1));
2786
2787 #[cfg(feature = "build-metrics")]
2788 builder.metrics.begin_test_suite(
2789 build_helper::metrics::TestSuiteMetadata::CargoPackage {
2790 crates: crates.iter().map(|c| c.to_string()).collect(),
2791 target: target.triple.to_string(),
2792 host: compiler.host.triple.to_string(),
2793 stage: compiler.stage,
2794 },
2795 builder,
2796 );
2797 add_flags_and_try_run_tests(builder, &mut cargo)
2798}
2799
2800fn prepare_cargo_test(
2802 cargo: builder::Cargo,
2803 libtest_args: &[&str],
2804 crates: &[String],
2805 target: TargetSelection,
2806 builder: &Builder<'_>,
2807) -> BootstrapCommand {
2808 let compiler = cargo.compiler();
2809 let mut cargo: BootstrapCommand = cargo.into();
2810
2811 if builder.config.cmd.bless() && !cargo.get_envs().any(|v| v.0 == "RUSTC_BLESS") {
2815 cargo.env("RUSTC_BLESS", "Gesundheit");
2816 }
2817
2818 if builder.kind == Kind::Test && !builder.fail_fast {
2822 cargo.arg("--no-fail-fast");
2823 }
2824
2825 if builder.config.json_output {
2826 cargo.arg("--message-format=json");
2827 }
2828
2829 match builder.doc_tests {
2830 DocTests::Only => {
2831 cargo.arg("--doc");
2832 }
2833 DocTests::No => {
2834 cargo.args(["--bins", "--examples", "--tests", "--benches"]);
2835 }
2836 DocTests::Yes => {}
2837 }
2838
2839 for krate in crates {
2840 cargo.arg("-p").arg(krate);
2841 }
2842
2843 cargo.arg("--").args(builder.config.test_args()).args(libtest_args);
2844 if !builder.config.verbose_tests {
2845 cargo.arg("--quiet");
2846 }
2847
2848 if builder.kind != Kind::Miri {
2857 let mut dylib_paths = builder.rustc_lib_paths(compiler);
2858 dylib_paths.push(builder.sysroot_target_libdir(compiler, target));
2859 helpers::add_dylib_path(dylib_paths, &mut cargo);
2860 }
2861
2862 if builder.remote_tested(target) {
2863 cargo.env(
2864 format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)),
2865 format!("{} run 0", builder.tool_exe(Tool::RemoteTestClient).display()),
2866 );
2867 } else if let Some(tool) = builder.runner(target) {
2868 cargo.env(format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)), tool);
2869 }
2870
2871 cargo
2872}
2873
2874#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2882pub struct Crate {
2883 build_compiler: Compiler,
2885 target: TargetSelection,
2886 mode: Mode,
2887 crates: Vec<String>,
2888}
2889
2890impl Step for Crate {
2891 type Output = ();
2892 const DEFAULT: bool = true;
2893
2894 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2895 run.crate_or_deps("sysroot").crate_or_deps("coretests").crate_or_deps("alloctests")
2896 }
2897
2898 fn make_run(run: RunConfig<'_>) {
2899 let builder = run.builder;
2900 let host = run.build_triple();
2901 let build_compiler = builder.compiler(builder.top_stage, host);
2902 let crates = run
2903 .paths
2904 .iter()
2905 .map(|p| builder.crate_paths[&p.assert_single_path().path].clone())
2906 .collect();
2907
2908 builder.ensure(Crate { build_compiler, target: run.target, mode: Mode::Std, crates });
2909 }
2910
2911 fn run(self, builder: &Builder<'_>) {
2920 let build_compiler = self.build_compiler;
2921 let target = self.target;
2922 let mode = self.mode;
2923
2924 builder.ensure(Std::new(build_compiler, build_compiler.host).force_recompile(true));
2927
2928 let mut cargo = if builder.kind == Kind::Miri {
2929 if builder.top_stage == 0 {
2930 eprintln!("ERROR: `x.py miri` requires stage 1 or higher");
2931 std::process::exit(1);
2932 }
2933
2934 let mut cargo = builder::Cargo::new(
2937 builder,
2938 build_compiler,
2939 mode,
2940 SourceType::InTree,
2941 target,
2942 Kind::MiriTest,
2943 );
2944 cargo.env("MIRI_REPLACE_LIBRS_IF_NOT_TEST", "1");
2956 cargo.rustflag("-Zforce-unstable-if-unmarked");
2960 cargo
2961 } else {
2962 if !builder.config.is_host_target(target) {
2964 builder.ensure(compile::Std::new(build_compiler, target).force_recompile(true));
2965 builder.ensure(RemoteCopyLibs { build_compiler, target });
2966 }
2967
2968 builder::Cargo::new(
2970 builder,
2971 build_compiler,
2972 mode,
2973 SourceType::InTree,
2974 target,
2975 builder.kind,
2976 )
2977 };
2978
2979 match mode {
2980 Mode::Std => {
2981 if builder.kind == Kind::Miri {
2982 cargo
2988 .arg("--manifest-path")
2989 .arg(builder.src.join("library/sysroot/Cargo.toml"));
2990 } else {
2991 compile::std_cargo(builder, target, &mut cargo, &[]);
2992 }
2993 }
2994 Mode::Rustc => {
2995 compile::rustc_cargo(builder, &mut cargo, target, &build_compiler, &self.crates);
2996 }
2997 _ => panic!("can only test libraries"),
2998 };
2999
3000 let mut crates = self.crates.clone();
3001 if crates.iter().any(|crate_| crate_ == "core") {
3006 crates.push("coretests".to_owned());
3007 }
3008 if crates.iter().any(|crate_| crate_ == "alloc") {
3009 crates.push("alloctests".to_owned());
3010 }
3011
3012 run_cargo_test(cargo, &[], &crates, &*crate_description(&self.crates), target, builder);
3013 }
3014}
3015
3016#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3019pub struct CrateRustdoc {
3020 host: TargetSelection,
3021}
3022
3023impl Step for CrateRustdoc {
3024 type Output = ();
3025 const DEFAULT: bool = true;
3026 const IS_HOST: bool = true;
3027
3028 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3029 run.paths(&["src/librustdoc", "src/tools/rustdoc"])
3030 }
3031
3032 fn make_run(run: RunConfig<'_>) {
3033 let builder = run.builder;
3034
3035 builder.ensure(CrateRustdoc { host: run.target });
3036 }
3037
3038 fn run(self, builder: &Builder<'_>) {
3039 let target = self.host;
3040
3041 let compiler = if builder.download_rustc() {
3042 builder.compiler(builder.top_stage, target)
3043 } else {
3044 builder.compiler_for(builder.top_stage, target, target)
3049 };
3050 builder.std(compiler, target);
3055 builder.ensure(compile::Rustc::new(compiler, target));
3056
3057 let mut cargo = tool::prepare_tool_cargo(
3058 builder,
3059 compiler,
3060 Mode::ToolRustcPrivate,
3061 target,
3062 builder.kind,
3063 "src/tools/rustdoc",
3064 SourceType::InTree,
3065 &[],
3066 );
3067 if self.host.contains("musl") {
3068 cargo.arg("'-Ctarget-feature=-crt-static'");
3069 }
3070
3071 let libdir = if builder.download_rustc() {
3098 builder.rustc_libdir(compiler)
3099 } else {
3100 builder.sysroot_target_libdir(compiler, target).to_path_buf()
3101 };
3102 let mut dylib_path = dylib_path();
3103 dylib_path.insert(0, PathBuf::from(&*libdir));
3104 cargo.env(dylib_path_var(), env::join_paths(&dylib_path).unwrap());
3105
3106 run_cargo_test(cargo, &[], &["rustdoc:0.0.0".to_string()], "rustdoc", target, builder);
3107 }
3108}
3109
3110#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3111pub struct CrateRustdocJsonTypes {
3112 build_compiler: Compiler,
3113 target: TargetSelection,
3114}
3115
3116impl Step for CrateRustdocJsonTypes {
3117 type Output = ();
3118 const DEFAULT: bool = true;
3119 const IS_HOST: bool = true;
3120
3121 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3122 run.path("src/rustdoc-json-types")
3123 }
3124
3125 fn make_run(run: RunConfig<'_>) {
3126 let builder = run.builder;
3127
3128 builder.ensure(CrateRustdocJsonTypes {
3129 build_compiler: get_tool_target_compiler(
3130 builder,
3131 ToolTargetBuildMode::Build(run.target),
3132 ),
3133 target: run.target,
3134 });
3135 }
3136
3137 fn run(self, builder: &Builder<'_>) {
3138 let target = self.target;
3139
3140 let cargo = tool::prepare_tool_cargo(
3141 builder,
3142 self.build_compiler,
3143 Mode::ToolTarget,
3144 target,
3145 builder.kind,
3146 "src/rustdoc-json-types",
3147 SourceType::InTree,
3148 &[],
3149 );
3150
3151 let libtest_args = if target.contains("musl") {
3153 ["'-Ctarget-feature=-crt-static'"].as_slice()
3154 } else {
3155 &[]
3156 };
3157
3158 run_cargo_test(
3159 cargo,
3160 libtest_args,
3161 &["rustdoc-json-types".to_string()],
3162 "rustdoc-json-types",
3163 target,
3164 builder,
3165 );
3166 }
3167}
3168
3169#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3179pub struct RemoteCopyLibs {
3180 build_compiler: Compiler,
3181 target: TargetSelection,
3182}
3183
3184impl Step for RemoteCopyLibs {
3185 type Output = ();
3186
3187 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3188 run.never()
3189 }
3190
3191 fn run(self, builder: &Builder<'_>) {
3192 let build_compiler = self.build_compiler;
3193 let target = self.target;
3194 if !builder.remote_tested(target) {
3195 return;
3196 }
3197
3198 builder.std(build_compiler, target);
3199
3200 builder.info(&format!("REMOTE copy libs to emulator ({target})"));
3201
3202 let remote_test_server = builder.ensure(tool::RemoteTestServer { build_compiler, target });
3203
3204 let tool = builder.tool_exe(Tool::RemoteTestClient);
3206 let mut cmd = command(&tool);
3207 cmd.arg("spawn-emulator")
3208 .arg(target.triple)
3209 .arg(&remote_test_server.tool_path)
3210 .arg(builder.tempdir());
3211 if let Some(rootfs) = builder.qemu_rootfs(target) {
3212 cmd.arg(rootfs);
3213 }
3214 cmd.run(builder);
3215
3216 for f in t!(builder.sysroot_target_libdir(build_compiler, target).read_dir()) {
3218 let f = t!(f);
3219 if helpers::is_dylib(&f.path()) {
3220 command(&tool).arg("push").arg(f.path()).run(builder);
3221 }
3222 }
3223 }
3224}
3225
3226#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3227pub struct Distcheck;
3228
3229impl Step for Distcheck {
3230 type Output = ();
3231
3232 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3233 run.alias("distcheck")
3234 }
3235
3236 fn make_run(run: RunConfig<'_>) {
3237 run.builder.ensure(Distcheck);
3238 }
3239
3240 fn run(self, builder: &Builder<'_>) {
3250 let root_dir = std::env::temp_dir().join("distcheck");
3253
3254 distcheck_plain_source_tarball(builder, &root_dir.join("distcheck-rustc-src"));
3255 distcheck_rust_src(builder, &root_dir.join("distcheck-rust-src"));
3256 distcheck_rustc_dev(builder, &root_dir.join("distcheck-rustc-dev"));
3257 }
3258}
3259
3260fn distcheck_plain_source_tarball(builder: &Builder<'_>, plain_src_dir: &Path) {
3262 builder.info("Distcheck plain source tarball");
3263 let plain_src_tarball = builder.ensure(dist::PlainSourceTarball);
3264 builder.clear_dir(plain_src_dir);
3265
3266 let configure_args: Vec<String> = std::env::var("DISTCHECK_CONFIGURE_ARGS")
3267 .map(|args| args.split(" ").map(|s| s.to_string()).collect::<Vec<String>>())
3268 .unwrap_or_default();
3269
3270 command("tar")
3271 .arg("-xf")
3272 .arg(plain_src_tarball.tarball())
3273 .arg("--strip-components=1")
3274 .current_dir(plain_src_dir)
3275 .run(builder);
3276 command("./configure")
3277 .arg("--set")
3278 .arg("rust.omit-git-hash=false")
3279 .args(&configure_args)
3280 .arg("--enable-vendor")
3281 .current_dir(plain_src_dir)
3282 .run(builder);
3283 command(helpers::make(&builder.config.host_target.triple))
3284 .arg("check")
3285 .env("GITHUB_ACTIONS", "0")
3288 .current_dir(plain_src_dir)
3289 .run(builder);
3290 builder.remove_dir(plain_src_dir);
3292}
3293
3294fn distcheck_rust_src(builder: &Builder<'_>, src_dir: &Path) {
3296 builder.info("Distcheck rust-src");
3297 let src_tarball = builder.ensure(dist::Src);
3298 builder.clear_dir(src_dir);
3299
3300 command("tar")
3301 .arg("-xf")
3302 .arg(src_tarball.tarball())
3303 .arg("--strip-components=1")
3304 .current_dir(src_dir)
3305 .run(builder);
3306
3307 let toml = src_dir.join("rust-src/lib/rustlib/src/rust/library/std/Cargo.toml");
3308 command(&builder.initial_cargo)
3309 .env("RUSTC_BOOTSTRAP", "1")
3312 .arg("generate-lockfile")
3313 .arg("--manifest-path")
3314 .arg(&toml)
3315 .current_dir(src_dir)
3316 .run(builder);
3317 builder.remove_dir(src_dir);
3319}
3320
3321fn distcheck_rustc_dev(builder: &Builder<'_>, dir: &Path) {
3323 builder.info("Distcheck rustc-dev");
3324 let tarball = builder.ensure(dist::RustcDev::new(builder, builder.host_target)).unwrap();
3325 builder.clear_dir(dir);
3326
3327 command("tar")
3328 .arg("-xf")
3329 .arg(tarball.tarball())
3330 .arg("--strip-components=1")
3331 .current_dir(dir)
3332 .run(builder);
3333
3334 command(&builder.initial_cargo)
3335 .arg("metadata")
3336 .arg("--manifest-path")
3337 .arg("rustc-dev/lib/rustlib/rustc-src/rust/compiler/rustc/Cargo.toml")
3338 .env("RUSTC_BOOTSTRAP", "1")
3339 .env("RUSTC", &builder.initial_rustc)
3341 .current_dir(dir)
3342 .run(builder);
3343 builder.remove_dir(dir);
3345}
3346
3347#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3348pub struct Bootstrap;
3349
3350impl Step for Bootstrap {
3351 type Output = ();
3352 const DEFAULT: bool = true;
3353 const IS_HOST: bool = true;
3354
3355 fn run(self, builder: &Builder<'_>) {
3357 let host = builder.config.host_target;
3358 let build_compiler = builder.compiler(0, host);
3359
3360 builder.build.require_submodule("src/tools/cargo", None);
3362
3363 let mut check_bootstrap = command(builder.python());
3364 check_bootstrap
3365 .args(["-m", "unittest", "bootstrap_test.py"])
3366 .env("BUILD_DIR", &builder.out)
3367 .env("BUILD_PLATFORM", builder.build.host_target.triple)
3368 .env("BOOTSTRAP_TEST_RUSTC_BIN", &builder.initial_rustc)
3369 .env("BOOTSTRAP_TEST_CARGO_BIN", &builder.initial_cargo)
3370 .current_dir(builder.src.join("src/bootstrap/"));
3371 check_bootstrap.delay_failure().run(builder);
3374
3375 let mut cargo = tool::prepare_tool_cargo(
3376 builder,
3377 build_compiler,
3378 Mode::ToolBootstrap,
3379 host,
3380 Kind::Test,
3381 "src/bootstrap",
3382 SourceType::InTree,
3383 &[],
3384 );
3385
3386 cargo.release_build(false);
3387
3388 cargo
3389 .rustflag("-Cdebuginfo=2")
3390 .env("CARGO_TARGET_DIR", builder.out.join("bootstrap"))
3391 .env("INSTA_WORKSPACE_ROOT", &builder.src)
3393 .env("RUSTC_BOOTSTRAP", "1");
3394
3395 run_cargo_test(cargo, &[], &[], None, host, builder);
3396 }
3397
3398 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3399 let runs_on_ci = run.builder.config.is_running_on_ci;
3403 run.path("src/bootstrap").default_condition(runs_on_ci)
3404 }
3405
3406 fn make_run(run: RunConfig<'_>) {
3407 run.builder.ensure(Bootstrap);
3408 }
3409}
3410
3411fn get_compiler_to_test(builder: &Builder<'_>, target: TargetSelection) -> Compiler {
3412 builder.compiler(builder.top_stage, target)
3413}
3414
3415#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3418pub struct TierCheck {
3419 test_compiler: Compiler,
3420}
3421
3422impl Step for TierCheck {
3423 type Output = ();
3424 const DEFAULT: bool = true;
3425 const IS_HOST: bool = true;
3426
3427 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3428 run.path("src/tools/tier-check")
3429 }
3430
3431 fn make_run(run: RunConfig<'_>) {
3432 run.builder
3433 .ensure(TierCheck { test_compiler: get_compiler_to_test(run.builder, run.target) });
3434 }
3435
3436 fn run(self, builder: &Builder<'_>) {
3437 let tool_build_compiler = builder.compiler(0, builder.host_target);
3438
3439 let mut cargo = tool::prepare_tool_cargo(
3440 builder,
3441 tool_build_compiler,
3442 Mode::ToolBootstrap,
3443 tool_build_compiler.host,
3444 Kind::Run,
3445 "src/tools/tier-check",
3446 SourceType::InTree,
3447 &[],
3448 );
3449 cargo.arg(builder.src.join("src/doc/rustc/src/platform-support.md"));
3450 cargo.arg(builder.rustc(self.test_compiler));
3451
3452 let _guard = builder.msg_test(
3453 "platform support check",
3454 self.test_compiler.host,
3455 self.test_compiler.stage,
3456 );
3457 BootstrapCommand::from(cargo).delay_failure().run(builder);
3458 }
3459
3460 fn metadata(&self) -> Option<StepMetadata> {
3461 Some(StepMetadata::test("tier-check", self.test_compiler.host))
3462 }
3463}
3464
3465#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3466pub struct LintDocs {
3467 build_compiler: Compiler,
3468 target: TargetSelection,
3469}
3470
3471impl Step for LintDocs {
3472 type Output = ();
3473 const DEFAULT: bool = true;
3474 const IS_HOST: bool = true;
3475
3476 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3477 let stage = run.builder.top_stage;
3478 run.path("src/tools/lint-docs").default_condition(stage > 1)
3481 }
3482
3483 fn make_run(run: RunConfig<'_>) {
3484 if run.builder.top_stage < 2 {
3485 eprintln!("WARNING: lint-docs tests might not work below stage 2");
3486 }
3487
3488 run.builder.ensure(LintDocs {
3489 build_compiler: prepare_doc_compiler(
3490 run.builder,
3491 run.builder.config.host_target,
3492 run.builder.top_stage,
3493 ),
3494 target: run.target,
3495 });
3496 }
3497
3498 fn run(self, builder: &Builder<'_>) {
3501 builder.ensure(crate::core::build_steps::doc::RustcBook::validate(
3502 self.build_compiler,
3503 self.target,
3504 ));
3505 }
3506
3507 fn metadata(&self) -> Option<StepMetadata> {
3508 Some(StepMetadata::test("lint-docs", self.target).built_by(self.build_compiler))
3509 }
3510}
3511
3512#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3513pub struct RustInstaller;
3514
3515impl Step for RustInstaller {
3516 type Output = ();
3517 const IS_HOST: bool = true;
3518 const DEFAULT: bool = true;
3519
3520 fn run(self, builder: &Builder<'_>) {
3522 let bootstrap_host = builder.config.host_target;
3523 let build_compiler = builder.compiler(0, bootstrap_host);
3524 let cargo = tool::prepare_tool_cargo(
3525 builder,
3526 build_compiler,
3527 Mode::ToolBootstrap,
3528 bootstrap_host,
3529 Kind::Test,
3530 "src/tools/rust-installer",
3531 SourceType::InTree,
3532 &[],
3533 );
3534
3535 let _guard = builder.msg_test("rust-installer", bootstrap_host, 1);
3536 run_cargo_test(cargo, &[], &[], None, bootstrap_host, builder);
3537
3538 if bootstrap_host != "x86_64-unknown-linux-gnu" {
3542 return;
3543 }
3544
3545 let mut cmd = command(builder.src.join("src/tools/rust-installer/test.sh"));
3546 let tmpdir = testdir(builder, build_compiler.host).join("rust-installer");
3547 let _ = std::fs::remove_dir_all(&tmpdir);
3548 let _ = std::fs::create_dir_all(&tmpdir);
3549 cmd.current_dir(&tmpdir);
3550 cmd.env("CARGO_TARGET_DIR", tmpdir.join("cargo-target"));
3551 cmd.env("CARGO", &builder.initial_cargo);
3552 cmd.env("RUSTC", &builder.initial_rustc);
3553 cmd.env("TMP_DIR", &tmpdir);
3554 cmd.delay_failure().run(builder);
3555 }
3556
3557 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3558 run.path("src/tools/rust-installer")
3559 }
3560
3561 fn make_run(run: RunConfig<'_>) {
3562 run.builder.ensure(Self);
3563 }
3564}
3565
3566#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3567pub struct TestHelpers {
3568 pub target: TargetSelection,
3569}
3570
3571impl Step for TestHelpers {
3572 type Output = ();
3573
3574 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3575 run.path("tests/auxiliary/rust_test_helpers.c")
3576 }
3577
3578 fn make_run(run: RunConfig<'_>) {
3579 run.builder.ensure(TestHelpers { target: run.target })
3580 }
3581
3582 fn run(self, builder: &Builder<'_>) {
3585 if builder.config.dry_run() {
3586 return;
3587 }
3588 let target = if self.target == "x86_64-fortanix-unknown-sgx" {
3592 TargetSelection::from_user("x86_64-unknown-linux-gnu")
3593 } else {
3594 self.target
3595 };
3596 let dst = builder.test_helpers_out(target);
3597 let src = builder.src.join("tests/auxiliary/rust_test_helpers.c");
3598 if up_to_date(&src, &dst.join("librust_test_helpers.a")) {
3599 return;
3600 }
3601
3602 let _guard = builder.msg_unstaged(Kind::Build, "test helpers", target);
3603 t!(fs::create_dir_all(&dst));
3604 let mut cfg = cc::Build::new();
3605
3606 if !target.is_msvc() {
3610 if let Some(ar) = builder.ar(target) {
3611 cfg.archiver(ar);
3612 }
3613 cfg.compiler(builder.cc(target));
3614 }
3615 cfg.cargo_metadata(false)
3616 .out_dir(&dst)
3617 .target(&target.triple)
3618 .host(&builder.config.host_target.triple)
3619 .opt_level(0)
3620 .warnings(false)
3621 .debug(false)
3622 .file(builder.src.join("tests/auxiliary/rust_test_helpers.c"))
3623 .compile("rust_test_helpers");
3624 }
3625}
3626
3627#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3628pub struct CodegenCranelift {
3629 compilers: RustcPrivateCompilers,
3630 target: TargetSelection,
3631}
3632
3633impl Step for CodegenCranelift {
3634 type Output = ();
3635 const DEFAULT: bool = true;
3636 const IS_HOST: bool = true;
3637
3638 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3639 run.paths(&["compiler/rustc_codegen_cranelift"])
3640 }
3641
3642 fn make_run(run: RunConfig<'_>) {
3643 let builder = run.builder;
3644 let host = run.build_triple();
3645 let compilers = RustcPrivateCompilers::new(run.builder, run.builder.top_stage, host);
3646
3647 if builder.doc_tests == DocTests::Only {
3648 return;
3649 }
3650
3651 if builder.download_rustc() {
3652 builder.info("CI rustc uses the default codegen backend. skipping");
3653 return;
3654 }
3655
3656 if !target_supports_cranelift_backend(run.target) {
3657 builder.info("target not supported by rustc_codegen_cranelift. skipping");
3658 return;
3659 }
3660
3661 if builder.remote_tested(run.target) {
3662 builder.info("remote testing is not supported by rustc_codegen_cranelift. skipping");
3663 return;
3664 }
3665
3666 if !builder
3667 .config
3668 .enabled_codegen_backends(run.target)
3669 .contains(&CodegenBackendKind::Cranelift)
3670 {
3671 builder.info("cranelift not in rust.codegen-backends. skipping");
3672 return;
3673 }
3674
3675 builder.ensure(CodegenCranelift { compilers, target: run.target });
3676 }
3677
3678 fn run(self, builder: &Builder<'_>) {
3679 let compilers = self.compilers;
3680 let build_compiler = compilers.build_compiler();
3681
3682 let target_compiler = compilers.target_compiler();
3685 let target = self.target;
3686
3687 builder.std(target_compiler, target);
3688
3689 let mut cargo = builder::Cargo::new(
3690 builder,
3691 target_compiler,
3692 Mode::Codegen, SourceType::InTree,
3694 target,
3695 Kind::Run,
3696 );
3697
3698 cargo.current_dir(&builder.src.join("compiler/rustc_codegen_cranelift"));
3699 cargo
3700 .arg("--manifest-path")
3701 .arg(builder.src.join("compiler/rustc_codegen_cranelift/build_system/Cargo.toml"));
3702 compile::rustc_cargo_env(builder, &mut cargo, target);
3703
3704 cargo.env("CARGO_BUILD_INCREMENTAL", "false");
3706
3707 let _guard = builder.msg_test(
3708 "rustc_codegen_cranelift",
3709 target_compiler.host,
3710 target_compiler.stage,
3711 );
3712
3713 let download_dir = builder.out.join("cg_clif_download");
3715
3716 cargo
3717 .arg("--")
3718 .arg("test")
3719 .arg("--download-dir")
3720 .arg(&download_dir)
3721 .arg("--out-dir")
3722 .arg(builder.stage_out(build_compiler, Mode::Codegen).join("cg_clif"))
3723 .arg("--no-unstable-features")
3724 .arg("--use-backend")
3725 .arg("cranelift")
3726 .arg("--sysroot")
3728 .arg("llvm")
3729 .arg("--skip-test")
3732 .arg("testsuite.extended_sysroot");
3733
3734 cargo.into_cmd().run(builder);
3735 }
3736
3737 fn metadata(&self) -> Option<StepMetadata> {
3738 Some(
3739 StepMetadata::test("rustc_codegen_cranelift", self.target)
3740 .built_by(self.compilers.build_compiler()),
3741 )
3742 }
3743}
3744
3745#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3746pub struct CodegenGCC {
3747 compilers: RustcPrivateCompilers,
3748 target: TargetSelection,
3749}
3750
3751impl Step for CodegenGCC {
3752 type Output = ();
3753 const DEFAULT: bool = true;
3754 const IS_HOST: bool = true;
3755
3756 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3757 run.paths(&["compiler/rustc_codegen_gcc"])
3758 }
3759
3760 fn make_run(run: RunConfig<'_>) {
3761 let builder = run.builder;
3762 let host = run.build_triple();
3763 let compilers = RustcPrivateCompilers::new(run.builder, run.builder.top_stage, host);
3764
3765 if builder.doc_tests == DocTests::Only {
3766 return;
3767 }
3768
3769 if builder.download_rustc() {
3770 builder.info("CI rustc uses the default codegen backend. skipping");
3771 return;
3772 }
3773
3774 let triple = run.target.triple;
3775 let target_supported =
3776 if triple.contains("linux") { triple.contains("x86_64") } else { false };
3777 if !target_supported {
3778 builder.info("target not supported by rustc_codegen_gcc. skipping");
3779 return;
3780 }
3781
3782 if builder.remote_tested(run.target) {
3783 builder.info("remote testing is not supported by rustc_codegen_gcc. skipping");
3784 return;
3785 }
3786
3787 if !builder.config.enabled_codegen_backends(run.target).contains(&CodegenBackendKind::Gcc) {
3788 builder.info("gcc not in rust.codegen-backends. skipping");
3789 return;
3790 }
3791
3792 builder.ensure(CodegenGCC { compilers, target: run.target });
3793 }
3794
3795 fn run(self, builder: &Builder<'_>) {
3796 let compilers = self.compilers;
3797 let target = self.target;
3798
3799 let gcc = builder.ensure(Gcc { target });
3800
3801 builder.ensure(
3802 compile::Std::new(compilers.build_compiler(), target)
3803 .extra_rust_args(&["-Csymbol-mangling-version=v0", "-Cpanic=abort"]),
3804 );
3805
3806 let _guard = builder.msg_test(
3807 "rustc_codegen_gcc",
3808 compilers.target(),
3809 compilers.target_compiler().stage,
3810 );
3811
3812 let mut cargo = builder::Cargo::new(
3813 builder,
3814 compilers.build_compiler(),
3815 Mode::Codegen, SourceType::InTree,
3817 target,
3818 Kind::Run,
3819 );
3820
3821 cargo.current_dir(&builder.src.join("compiler/rustc_codegen_gcc"));
3822 cargo
3823 .arg("--manifest-path")
3824 .arg(builder.src.join("compiler/rustc_codegen_gcc/build_system/Cargo.toml"));
3825 compile::rustc_cargo_env(builder, &mut cargo, target);
3826 add_cg_gcc_cargo_flags(&mut cargo, &gcc);
3827
3828 cargo.env("CARGO_BUILD_INCREMENTAL", "false");
3830 cargo.rustflag("-Cpanic=abort");
3831
3832 cargo
3833 .env("CG_RUSTFLAGS", "-Alinker-messages")
3835 .arg("--")
3836 .arg("test")
3837 .arg("--use-backend")
3838 .arg("gcc")
3839 .arg("--gcc-path")
3840 .arg(gcc.libgccjit.parent().unwrap())
3841 .arg("--out-dir")
3842 .arg(builder.stage_out(compilers.build_compiler(), Mode::Codegen).join("cg_gcc"))
3843 .arg("--release")
3844 .arg("--mini-tests")
3845 .arg("--std-tests");
3846 cargo.args(builder.config.test_args());
3847
3848 cargo.into_cmd().run(builder);
3849 }
3850
3851 fn metadata(&self) -> Option<StepMetadata> {
3852 Some(
3853 StepMetadata::test("rustc_codegen_gcc", self.target)
3854 .built_by(self.compilers.build_compiler()),
3855 )
3856 }
3857}
3858
3859#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3864pub struct TestFloatParse {
3865 build_compiler: Compiler,
3874 target: TargetSelection,
3876}
3877
3878impl Step for TestFloatParse {
3879 type Output = ();
3880 const IS_HOST: bool = true;
3881 const DEFAULT: bool = true;
3882
3883 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3884 run.path("src/tools/test-float-parse")
3885 }
3886
3887 fn make_run(run: RunConfig<'_>) {
3888 run.builder.ensure(Self {
3889 build_compiler: get_compiler_to_test(run.builder, run.target),
3890 target: run.target,
3891 });
3892 }
3893
3894 fn run(self, builder: &Builder<'_>) {
3895 let build_compiler = self.build_compiler;
3896 let target = self.target;
3897
3898 builder.std(build_compiler, target);
3900 builder.std(build_compiler, builder.host_target);
3901
3902 let mut cargo_test = tool::prepare_tool_cargo(
3904 builder,
3905 build_compiler,
3906 Mode::ToolStd,
3907 target,
3908 Kind::Test,
3909 "src/tools/test-float-parse",
3910 SourceType::InTree,
3911 &[],
3912 );
3913 cargo_test.allow_features(TEST_FLOAT_PARSE_ALLOW_FEATURES);
3914
3915 run_cargo_test(cargo_test, &[], &[], "test-float-parse", target, builder);
3916
3917 let mut cargo_run = tool::prepare_tool_cargo(
3919 builder,
3920 build_compiler,
3921 Mode::ToolStd,
3922 target,
3923 Kind::Run,
3924 "src/tools/test-float-parse",
3925 SourceType::InTree,
3926 &[],
3927 );
3928 cargo_run.allow_features(TEST_FLOAT_PARSE_ALLOW_FEATURES);
3929
3930 if !matches!(env::var("FLOAT_PARSE_TESTS_NO_SKIP_HUGE").as_deref(), Ok("1") | Ok("true")) {
3931 cargo_run.args(["--", "--skip-huge"]);
3932 }
3933
3934 cargo_run.into_cmd().run(builder);
3935 }
3936}
3937
3938#[derive(Debug, Clone, Hash, PartialEq, Eq)]
3942pub struct CollectLicenseMetadata;
3943
3944impl Step for CollectLicenseMetadata {
3945 type Output = PathBuf;
3946 const IS_HOST: bool = true;
3947
3948 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3949 run.path("src/tools/collect-license-metadata")
3950 }
3951
3952 fn make_run(run: RunConfig<'_>) {
3953 run.builder.ensure(CollectLicenseMetadata);
3954 }
3955
3956 fn run(self, builder: &Builder<'_>) -> Self::Output {
3957 let Some(reuse) = &builder.config.reuse else {
3958 panic!("REUSE is required to collect the license metadata");
3959 };
3960
3961 let dest = builder.src.join("license-metadata.json");
3962
3963 let mut cmd = builder.tool_cmd(Tool::CollectLicenseMetadata);
3964 cmd.env("REUSE_EXE", reuse);
3965 cmd.env("DEST", &dest);
3966 cmd.env("ONLY_CHECK", "1");
3967 cmd.run(builder);
3968
3969 dest
3970 }
3971}