1use std::collections::HashSet;
7use std::env::split_paths;
8use std::ffi::{OsStr, OsString};
9use std::path::{Path, PathBuf};
10use std::{env, fs, iter};
11
12use build_helper::exit;
13
14use crate::core::build_steps::compile::{Std, run_cargo};
15use crate::core::build_steps::doc::{DocumentationFormat, prepare_doc_compiler};
16use crate::core::build_steps::gcc::{Gcc, add_cg_gcc_cargo_flags};
17use crate::core::build_steps::llvm::get_llvm_version;
18use crate::core::build_steps::run::get_completion_paths;
19use crate::core::build_steps::synthetic_targets::MirOptPanicAbortSyntheticTarget;
20use crate::core::build_steps::tool::{
21 self, COMPILETEST_ALLOW_FEATURES, RustcPrivateCompilers, SourceType,
22 TEST_FLOAT_PARSE_ALLOW_FEATURES, Tool, ToolTargetBuildMode, get_tool_target_compiler,
23};
24use crate::core::build_steps::toolstate::ToolState;
25use crate::core::build_steps::{compile, dist, llvm};
26use crate::core::builder::{
27 self, Alias, Builder, Compiler, Kind, RunConfig, ShouldRun, Step, StepMetadata,
28 crate_description,
29};
30use crate::core::config::TargetSelection;
31use crate::core::config::flags::{Subcommand, get_completion};
32use crate::utils::build_stamp::{self, BuildStamp};
33use crate::utils::exec::{BootstrapCommand, command};
34use crate::utils::helpers::{
35 self, LldThreads, add_dylib_path, add_rustdoc_cargo_linker_args, dylib_path, dylib_path_var,
36 linker_args, linker_flags, t, target_supports_cranelift_backend, up_to_date,
37};
38use crate::utils::render_tests::{add_flags_and_try_run_tests, try_run_tests};
39use crate::{CLang, CodegenBackendKind, DocTests, GitRepo, Mode, PathSet, debug, 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.verbose(|| println!("running: {cargo:?}"));
586 let stdout = cargo.run_capture_stdout(builder).stdout();
587 let sysroot = stdout.trim_end();
589 builder.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 {
790 eprintln!("\
791ERROR: `--stage 0` runs compiletest self-tests against the stage0 (precompiled) compiler, not the in-tree compiler, and will almost always cause tests to fail
792NOTE: 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`."
793 );
794 crate::exit!(1);
795 }
796
797 let compiler = builder.compiler(builder.top_stage, host);
798 debug!(?compiler);
799
800 builder.std(compiler, host);
803 let mut cargo = tool::prepare_tool_cargo(
804 builder,
805 compiler,
806 Mode::ToolStd,
809 host,
810 Kind::Test,
811 "src/tools/compiletest",
812 SourceType::InTree,
813 &[],
814 );
815
816 cargo.env("TEST_RUSTC", builder.rustc(compiler));
820
821 cargo.allow_features(COMPILETEST_ALLOW_FEATURES);
822 run_cargo_test(cargo, &[], &[], "compiletest self test", host, builder);
823 }
824}
825
826#[derive(Debug, Clone, PartialEq, Eq, Hash)]
827pub struct Clippy {
828 compilers: RustcPrivateCompilers,
829}
830
831impl Step for Clippy {
832 type Output = ();
833 const IS_HOST: bool = true;
834 const DEFAULT: bool = false;
835
836 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
837 run.suite_path("src/tools/clippy/tests").path("src/tools/clippy")
838 }
839
840 fn make_run(run: RunConfig<'_>) {
841 run.builder.ensure(Clippy {
842 compilers: RustcPrivateCompilers::new(
843 run.builder,
844 run.builder.top_stage,
845 run.builder.host_target,
846 ),
847 });
848 }
849
850 fn run(self, builder: &Builder<'_>) {
852 let target = self.compilers.target();
853
854 let compilers = self.compilers;
858 let target_compiler = compilers.target_compiler();
859
860 let tool_result = builder.ensure(tool::Clippy::from_compilers(compilers));
861 let build_compiler = tool_result.build_compiler;
862 let mut cargo = tool::prepare_tool_cargo(
863 builder,
864 build_compiler,
865 Mode::ToolRustcPrivate,
866 target,
867 Kind::Test,
868 "src/tools/clippy",
869 SourceType::InTree,
870 &[],
871 );
872
873 cargo.env("RUSTC_TEST_SUITE", builder.rustc(build_compiler));
874 cargo.env("RUSTC_LIB_PATH", builder.rustc_libdir(build_compiler));
875 let host_libs =
876 builder.stage_out(build_compiler, Mode::ToolRustcPrivate).join(builder.cargo_dir());
877 cargo.env("HOST_LIBS", host_libs);
878
879 builder.std(target_compiler, target);
881 cargo.env("TEST_SYSROOT", builder.sysroot(target_compiler));
882 cargo.env("TEST_RUSTC", builder.rustc(target_compiler));
883 cargo.env("TEST_RUSTC_LIB", builder.rustc_libdir(target_compiler));
884
885 'partially_test: {
887 let paths = &builder.config.paths[..];
888 let mut test_names = Vec::new();
889 for path in paths {
890 if let Some(path) =
891 helpers::is_valid_test_suite_arg(path, "src/tools/clippy/tests", builder)
892 {
893 test_names.push(path);
894 } else if path.ends_with("src/tools/clippy") {
895 break 'partially_test;
897 }
898 }
899 cargo.env("TESTNAME", test_names.join(","));
900 }
901
902 cargo.add_rustc_lib_path(builder);
903 let cargo = prepare_cargo_test(cargo, &[], &[], target, builder);
904
905 let _guard = builder.msg_test("clippy", target, target_compiler.stage);
906
907 if cargo.allow_failure().run(builder) {
909 return;
911 }
912
913 if !builder.config.cmd.bless() {
914 crate::exit!(1);
915 }
916 }
917
918 fn metadata(&self) -> Option<StepMetadata> {
919 Some(
920 StepMetadata::test("clippy", self.compilers.target())
921 .built_by(self.compilers.build_compiler()),
922 )
923 }
924}
925
926fn bin_path_for_cargo(builder: &Builder<'_>, compiler: Compiler) -> OsString {
927 let path = builder.sysroot(compiler).join("bin");
928 let old_path = env::var_os("PATH").unwrap_or_default();
929 env::join_paths(iter::once(path).chain(env::split_paths(&old_path))).expect("")
930}
931
932#[derive(Debug, Clone, Hash, PartialEq, Eq)]
934pub struct RustdocTheme {
935 test_compiler: Compiler,
937}
938
939impl Step for RustdocTheme {
940 type Output = ();
941 const DEFAULT: bool = true;
942 const IS_HOST: bool = true;
943
944 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
945 run.path("src/tools/rustdoc-themes")
946 }
947
948 fn make_run(run: RunConfig<'_>) {
949 let test_compiler = run.builder.compiler(run.builder.top_stage, run.target);
950
951 run.builder.ensure(RustdocTheme { test_compiler });
952 }
953
954 fn run(self, builder: &Builder<'_>) {
955 let rustdoc = builder.bootstrap_out.join("rustdoc");
956 let mut cmd = builder.tool_cmd(Tool::RustdocTheme);
957 cmd.arg(rustdoc.to_str().unwrap())
958 .arg(builder.src.join("src/librustdoc/html/static/css/rustdoc.css").to_str().unwrap())
959 .env("RUSTC_STAGE", self.test_compiler.stage.to_string())
960 .env("RUSTC_SYSROOT", builder.sysroot(self.test_compiler))
961 .env(
962 "RUSTDOC_LIBDIR",
963 builder.sysroot_target_libdir(self.test_compiler, self.test_compiler.host),
964 )
965 .env("CFG_RELEASE_CHANNEL", &builder.config.channel)
966 .env("RUSTDOC_REAL", builder.rustdoc_for_compiler(self.test_compiler))
967 .env("RUSTC_BOOTSTRAP", "1");
968 cmd.args(linker_args(builder, self.test_compiler.host, LldThreads::No));
969
970 cmd.delay_failure().run(builder);
971 }
972
973 fn metadata(&self) -> Option<StepMetadata> {
974 Some(
975 StepMetadata::test("rustdoc-theme", self.test_compiler.host)
976 .stage(self.test_compiler.stage),
977 )
978 }
979}
980
981#[derive(Debug, Clone, Hash, PartialEq, Eq)]
983pub struct RustdocJSStd {
984 build_compiler: Compiler,
986 target: TargetSelection,
987}
988
989impl Step for RustdocJSStd {
990 type Output = ();
991 const DEFAULT: bool = true;
992 const IS_HOST: bool = true;
993
994 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
995 let default = run.builder.config.nodejs.is_some();
996 run.suite_path("tests/rustdoc-js-std").default_condition(default)
997 }
998
999 fn make_run(run: RunConfig<'_>) {
1000 run.builder.ensure(RustdocJSStd {
1001 build_compiler: run.builder.compiler(run.builder.top_stage, run.builder.host_target),
1002 target: run.target,
1003 });
1004 }
1005
1006 fn run(self, builder: &Builder<'_>) {
1007 let nodejs =
1008 builder.config.nodejs.as_ref().expect("need nodejs to run rustdoc-js-std tests");
1009 let mut command = command(nodejs);
1010 command
1011 .arg(builder.src.join("src/tools/rustdoc-js/tester.js"))
1012 .arg("--crate-name")
1013 .arg("std")
1014 .arg("--resource-suffix")
1015 .arg(&builder.version)
1016 .arg("--doc-folder")
1017 .arg(builder.doc_out(self.target))
1018 .arg("--test-folder")
1019 .arg(builder.src.join("tests/rustdoc-js-std"));
1020 for path in &builder.paths {
1021 if let Some(p) = helpers::is_valid_test_suite_arg(path, "tests/rustdoc-js-std", builder)
1022 {
1023 if !p.ends_with(".js") {
1024 eprintln!("A non-js file was given: `{}`", path.display());
1025 panic!("Cannot run rustdoc-js-std tests");
1026 }
1027 command.arg("--test-file").arg(path);
1028 }
1029 }
1030 builder.ensure(crate::core::build_steps::doc::Std::from_build_compiler(
1031 self.build_compiler,
1032 self.target,
1033 DocumentationFormat::Html,
1034 ));
1035 let _guard = builder.msg_test("rustdoc-js-std", self.target, self.build_compiler.stage);
1036 command.run(builder);
1037 }
1038
1039 fn metadata(&self) -> Option<StepMetadata> {
1040 Some(StepMetadata::test("rustdoc-js-std", self.target).stage(self.build_compiler.stage))
1041 }
1042}
1043
1044#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1045pub struct RustdocJSNotStd {
1046 pub target: TargetSelection,
1047 pub compiler: Compiler,
1048}
1049
1050impl Step for RustdocJSNotStd {
1051 type Output = ();
1052 const DEFAULT: bool = true;
1053 const IS_HOST: bool = true;
1054
1055 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1056 let default = run.builder.config.nodejs.is_some();
1057 run.suite_path("tests/rustdoc-js").default_condition(default)
1058 }
1059
1060 fn make_run(run: RunConfig<'_>) {
1061 let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1062 run.builder.ensure(RustdocJSNotStd { target: run.target, compiler });
1063 }
1064
1065 fn run(self, builder: &Builder<'_>) {
1066 builder.ensure(Compiletest {
1067 test_compiler: self.compiler,
1068 target: self.target,
1069 mode: "rustdoc-js",
1070 suite: "rustdoc-js",
1071 path: "tests/rustdoc-js",
1072 compare_mode: None,
1073 });
1074 }
1075}
1076
1077fn get_browser_ui_test_version_inner(
1078 builder: &Builder<'_>,
1079 npm: &Path,
1080 global: bool,
1081) -> Option<String> {
1082 let mut command = command(npm);
1083 command.arg("list").arg("--parseable").arg("--long").arg("--depth=0");
1084 if global {
1085 command.arg("--global");
1086 }
1087 let lines = command.allow_failure().run_capture(builder).stdout();
1088 lines
1089 .lines()
1090 .find_map(|l| l.split(':').nth(1)?.strip_prefix("browser-ui-test@"))
1091 .map(|v| v.to_owned())
1092}
1093
1094fn get_browser_ui_test_version(builder: &Builder<'_>, npm: &Path) -> Option<String> {
1095 get_browser_ui_test_version_inner(builder, npm, false)
1096 .or_else(|| get_browser_ui_test_version_inner(builder, npm, true))
1097}
1098
1099#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1101pub struct RustdocGUI {
1102 test_compiler: Compiler,
1104 target: TargetSelection,
1105}
1106
1107impl Step for RustdocGUI {
1108 type Output = ();
1109 const DEFAULT: bool = true;
1110 const IS_HOST: bool = true;
1111
1112 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1113 let builder = run.builder;
1114 let run = run.suite_path("tests/rustdoc-gui");
1115 run.lazy_default_condition(Box::new(move || {
1116 builder.config.nodejs.is_some()
1117 && builder.doc_tests != DocTests::Only
1118 && builder
1119 .config
1120 .npm
1121 .as_ref()
1122 .map(|p| get_browser_ui_test_version(builder, p).is_some())
1123 .unwrap_or(false)
1124 }))
1125 }
1126
1127 fn make_run(run: RunConfig<'_>) {
1128 let test_compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1129 run.builder.ensure(RustdocGUI { test_compiler, target: run.target });
1130 }
1131
1132 fn run(self, builder: &Builder<'_>) {
1133 builder.std(self.test_compiler, self.target);
1134
1135 let mut cmd = builder.tool_cmd(Tool::RustdocGUITest);
1136
1137 let out_dir = builder.test_out(self.target).join("rustdoc-gui");
1138 build_stamp::clear_if_dirty(
1139 builder,
1140 &out_dir,
1141 &builder.rustdoc_for_compiler(self.test_compiler),
1142 );
1143
1144 if let Some(src) = builder.config.src.to_str() {
1145 cmd.arg("--rust-src").arg(src);
1146 }
1147
1148 if let Some(out_dir) = out_dir.to_str() {
1149 cmd.arg("--out-dir").arg(out_dir);
1150 }
1151
1152 if let Some(initial_cargo) = builder.config.initial_cargo.to_str() {
1153 cmd.arg("--initial-cargo").arg(initial_cargo);
1154 }
1155
1156 cmd.arg("--jobs").arg(builder.jobs().to_string());
1157
1158 cmd.env("RUSTDOC", builder.rustdoc_for_compiler(self.test_compiler))
1159 .env("RUSTC", builder.rustc(self.test_compiler));
1160
1161 add_rustdoc_cargo_linker_args(&mut cmd, builder, self.test_compiler.host, LldThreads::No);
1162
1163 for path in &builder.paths {
1164 if let Some(p) = helpers::is_valid_test_suite_arg(path, "tests/rustdoc-gui", builder) {
1165 if !p.ends_with(".goml") {
1166 eprintln!("A non-goml file was given: `{}`", path.display());
1167 panic!("Cannot run rustdoc-gui tests");
1168 }
1169 if let Some(name) = path.file_name().and_then(|f| f.to_str()) {
1170 cmd.arg("--goml-file").arg(name);
1171 }
1172 }
1173 }
1174
1175 for test_arg in builder.config.test_args() {
1176 cmd.arg("--test-arg").arg(test_arg);
1177 }
1178
1179 if let Some(ref nodejs) = builder.config.nodejs {
1180 cmd.arg("--nodejs").arg(nodejs);
1181 }
1182
1183 if let Some(ref npm) = builder.config.npm {
1184 cmd.arg("--npm").arg(npm);
1185 }
1186
1187 let _time = helpers::timeit(builder);
1188 let _guard = builder.msg_test("rustdoc-gui", self.target, self.test_compiler.stage);
1189 try_run_tests(builder, &mut cmd, true);
1190 }
1191
1192 fn metadata(&self) -> Option<StepMetadata> {
1193 Some(StepMetadata::test("rustdoc-gui", self.target).stage(self.test_compiler.stage))
1194 }
1195}
1196
1197#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1202pub struct Tidy;
1203
1204impl Step for Tidy {
1205 type Output = ();
1206 const DEFAULT: bool = true;
1207 const IS_HOST: bool = true;
1208
1209 fn run(self, builder: &Builder<'_>) {
1218 let mut cmd = builder.tool_cmd(Tool::Tidy);
1219 cmd.arg(&builder.src);
1220 cmd.arg(&builder.initial_cargo);
1221 cmd.arg(&builder.out);
1222 let jobs = builder.config.jobs.unwrap_or_else(|| {
1224 8 * std::thread::available_parallelism().map_or(1, std::num::NonZeroUsize::get) as u32
1225 });
1226 cmd.arg(jobs.to_string());
1227 if let Some(npm) = &builder.config.npm {
1229 cmd.arg(npm);
1230 } else {
1231 cmd.arg("npm");
1232 }
1233 if builder.is_verbose() {
1234 cmd.arg("--verbose");
1235 }
1236 if builder.config.cmd.bless() {
1237 cmd.arg("--bless");
1238 }
1239 if let Some(s) =
1240 builder.config.cmd.extra_checks().or(builder.config.tidy_extra_checks.as_deref())
1241 {
1242 cmd.arg(format!("--extra-checks={s}"));
1243 }
1244 let mut args = std::env::args_os();
1245 if args.any(|arg| arg == OsStr::new("--")) {
1246 cmd.arg("--");
1247 cmd.args(args);
1248 }
1249
1250 if builder.config.channel == "dev" || builder.config.channel == "nightly" {
1251 if !builder.config.json_output {
1252 builder.info("fmt check");
1253 if builder.config.initial_rustfmt.is_none() {
1254 let inferred_rustfmt_dir = builder.initial_sysroot.join("bin");
1255 eprintln!(
1256 "\
1257ERROR: no `rustfmt` binary found in {PATH}
1258INFO: `rust.channel` is currently set to \"{CHAN}\"
1259HELP: if you are testing a beta branch, set `rust.channel` to \"beta\" in the `bootstrap.toml` file
1260HELP: to skip test's attempt to check tidiness, pass `--skip src/tools/tidy` to `x.py test`",
1261 PATH = inferred_rustfmt_dir.display(),
1262 CHAN = builder.config.channel,
1263 );
1264 crate::exit!(1);
1265 }
1266 let all = false;
1267 crate::core::build_steps::format::format(
1268 builder,
1269 !builder.config.cmd.bless(),
1270 all,
1271 &[],
1272 );
1273 } else {
1274 eprintln!(
1275 "WARNING: `--json-output` is not supported on rustfmt, formatting will be skipped"
1276 );
1277 }
1278 }
1279
1280 builder.info("tidy check");
1281 cmd.delay_failure().run(builder);
1282
1283 builder.info("x.py completions check");
1284 let completion_paths = get_completion_paths(builder);
1285 if builder.config.cmd.bless() {
1286 builder.ensure(crate::core::build_steps::run::GenerateCompletions);
1287 } else if completion_paths
1288 .into_iter()
1289 .any(|(shell, path)| get_completion(shell, &path).is_some())
1290 {
1291 eprintln!(
1292 "x.py completions were changed; run `x.py run generate-completions` to update them"
1293 );
1294 crate::exit!(1);
1295 }
1296 }
1297
1298 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1299 let default = run.builder.doc_tests != DocTests::Only;
1300 run.path("src/tools/tidy").default_condition(default)
1301 }
1302
1303 fn make_run(run: RunConfig<'_>) {
1304 run.builder.ensure(Tidy);
1305 }
1306
1307 fn metadata(&self) -> Option<StepMetadata> {
1308 Some(StepMetadata::test("tidy", TargetSelection::default()))
1309 }
1310}
1311
1312#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1315pub struct CrateRunMakeSupport {
1316 host: TargetSelection,
1317}
1318
1319impl Step for CrateRunMakeSupport {
1320 type Output = ();
1321 const IS_HOST: bool = true;
1322
1323 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1324 run.path("src/tools/run-make-support")
1325 }
1326
1327 fn make_run(run: RunConfig<'_>) {
1328 run.builder.ensure(CrateRunMakeSupport { host: run.target });
1329 }
1330
1331 fn run(self, builder: &Builder<'_>) {
1333 let host = self.host;
1334 let compiler = builder.compiler(0, host);
1335
1336 let mut cargo = tool::prepare_tool_cargo(
1337 builder,
1338 compiler,
1339 Mode::ToolBootstrap,
1340 host,
1341 Kind::Test,
1342 "src/tools/run-make-support",
1343 SourceType::InTree,
1344 &[],
1345 );
1346 cargo.allow_features("test");
1347 run_cargo_test(cargo, &[], &[], "run-make-support self test", host, builder);
1348 }
1349}
1350
1351#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1352pub struct CrateBuildHelper {
1353 host: TargetSelection,
1354}
1355
1356impl Step for CrateBuildHelper {
1357 type Output = ();
1358 const IS_HOST: bool = true;
1359
1360 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1361 run.path("src/build_helper")
1362 }
1363
1364 fn make_run(run: RunConfig<'_>) {
1365 run.builder.ensure(CrateBuildHelper { host: run.target });
1366 }
1367
1368 fn run(self, builder: &Builder<'_>) {
1370 let host = self.host;
1371 let compiler = builder.compiler(0, host);
1372
1373 let mut cargo = tool::prepare_tool_cargo(
1374 builder,
1375 compiler,
1376 Mode::ToolBootstrap,
1377 host,
1378 Kind::Test,
1379 "src/build_helper",
1380 SourceType::InTree,
1381 &[],
1382 );
1383 cargo.allow_features("test");
1384 run_cargo_test(cargo, &[], &[], "build_helper self test", host, builder);
1385 }
1386}
1387
1388fn testdir(builder: &Builder<'_>, host: TargetSelection) -> PathBuf {
1389 builder.out.join(host).join("test")
1390}
1391
1392macro_rules! test {
1394 (
1395 $( #[$attr:meta] )* $name:ident {
1397 path: $path:expr,
1398 mode: $mode:expr,
1399 suite: $suite:expr,
1400 default: $default:expr
1401 $( , IS_HOST: $IS_HOST:expr )? $( , compare_mode: $compare_mode:expr )? $( , )? }
1405 ) => {
1406 $( #[$attr] )*
1407 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
1408 pub struct $name {
1409 test_compiler: Compiler,
1410 target: TargetSelection,
1411 }
1412
1413 impl Step for $name {
1414 type Output = ();
1415 const DEFAULT: bool = $default;
1416 const IS_HOST: bool = (const {
1417 #[allow(unused_assignments, unused_mut)]
1418 let mut value = false;
1419 $( value = $IS_HOST; )?
1420 value
1421 });
1422
1423 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1424 run.suite_path($path)
1425 }
1426
1427 fn make_run(run: RunConfig<'_>) {
1428 let test_compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1429
1430 run.builder.ensure($name { test_compiler, target: run.target });
1431 }
1432
1433 fn run(self, builder: &Builder<'_>) {
1434 builder.ensure(Compiletest {
1435 test_compiler: self.test_compiler,
1436 target: self.target,
1437 mode: $mode,
1438 suite: $suite,
1439 path: $path,
1440 compare_mode: (const {
1441 #[allow(unused_assignments, unused_mut)]
1442 let mut value = None;
1443 $( value = $compare_mode; )?
1444 value
1445 }),
1446 })
1447 }
1448 }
1449 };
1450}
1451
1452test!(Ui { path: "tests/ui", mode: "ui", suite: "ui", default: true });
1453
1454test!(Crashes { path: "tests/crashes", mode: "crashes", suite: "crashes", default: true });
1455
1456test!(CodegenLlvm {
1457 path: "tests/codegen-llvm",
1458 mode: "codegen",
1459 suite: "codegen-llvm",
1460 default: true
1461});
1462
1463test!(CodegenUnits {
1464 path: "tests/codegen-units",
1465 mode: "codegen-units",
1466 suite: "codegen-units",
1467 default: true,
1468});
1469
1470test!(Incremental {
1471 path: "tests/incremental",
1472 mode: "incremental",
1473 suite: "incremental",
1474 default: true,
1475});
1476
1477test!(Debuginfo {
1478 path: "tests/debuginfo",
1479 mode: "debuginfo",
1480 suite: "debuginfo",
1481 default: true,
1482 compare_mode: Some("split-dwarf"),
1483});
1484
1485test!(UiFullDeps {
1486 path: "tests/ui-fulldeps",
1487 mode: "ui",
1488 suite: "ui-fulldeps",
1489 default: true,
1490 IS_HOST: true,
1491});
1492
1493test!(Rustdoc {
1494 path: "tests/rustdoc",
1495 mode: "rustdoc",
1496 suite: "rustdoc",
1497 default: true,
1498 IS_HOST: true,
1499});
1500test!(RustdocUi {
1501 path: "tests/rustdoc-ui",
1502 mode: "ui",
1503 suite: "rustdoc-ui",
1504 default: true,
1505 IS_HOST: true,
1506});
1507
1508test!(RustdocJson {
1509 path: "tests/rustdoc-json",
1510 mode: "rustdoc-json",
1511 suite: "rustdoc-json",
1512 default: true,
1513 IS_HOST: true,
1514});
1515
1516test!(Pretty {
1517 path: "tests/pretty",
1518 mode: "pretty",
1519 suite: "pretty",
1520 default: true,
1521 IS_HOST: true,
1522});
1523
1524test!(RunMake { path: "tests/run-make", mode: "run-make", suite: "run-make", default: true });
1525test!(RunMakeCargo {
1526 path: "tests/run-make-cargo",
1527 mode: "run-make",
1528 suite: "run-make-cargo",
1529 default: true
1530});
1531
1532test!(AssemblyLlvm {
1533 path: "tests/assembly-llvm",
1534 mode: "assembly",
1535 suite: "assembly-llvm",
1536 default: true
1537});
1538
1539#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
1542pub struct Coverage {
1543 pub compiler: Compiler,
1544 pub target: TargetSelection,
1545 pub mode: &'static str,
1546}
1547
1548impl Coverage {
1549 const PATH: &'static str = "tests/coverage";
1550 const SUITE: &'static str = "coverage";
1551 const ALL_MODES: &[&str] = &["coverage-map", "coverage-run"];
1552}
1553
1554impl Step for Coverage {
1555 type Output = ();
1556 const DEFAULT: bool = true;
1557 const IS_HOST: bool = false;
1559
1560 fn should_run(mut run: ShouldRun<'_>) -> ShouldRun<'_> {
1561 run = run.suite_path(Self::PATH);
1567 for mode in Self::ALL_MODES {
1568 run = run.alias(mode);
1569 }
1570 run
1571 }
1572
1573 fn make_run(run: RunConfig<'_>) {
1574 let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1575 let target = run.target;
1576
1577 let mut modes = vec![];
1581
1582 for path in &run.paths {
1585 match path {
1586 PathSet::Set(_) => {
1587 for mode in Self::ALL_MODES {
1588 if path.assert_single_path().path == Path::new(mode) {
1589 modes.push(mode);
1590 break;
1591 }
1592 }
1593 }
1594 PathSet::Suite(_) => {
1595 modes.extend(Self::ALL_MODES);
1596 break;
1597 }
1598 }
1599 }
1600
1601 modes.retain(|mode| !run.builder.config.skip.iter().any(|skip| skip == Path::new(mode)));
1604
1605 for mode in modes {
1613 run.builder.ensure(Coverage { compiler, target, mode });
1614 }
1615 }
1616
1617 fn run(self, builder: &Builder<'_>) {
1618 let Self { compiler, target, mode } = self;
1619 builder.ensure(Compiletest {
1622 test_compiler: compiler,
1623 target,
1624 mode,
1625 suite: Self::SUITE,
1626 path: Self::PATH,
1627 compare_mode: None,
1628 });
1629 }
1630}
1631
1632test!(CoverageRunRustdoc {
1633 path: "tests/coverage-run-rustdoc",
1634 mode: "coverage-run",
1635 suite: "coverage-run-rustdoc",
1636 default: true,
1637 IS_HOST: true,
1638});
1639
1640#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1642pub struct MirOpt {
1643 pub compiler: Compiler,
1644 pub target: TargetSelection,
1645}
1646
1647impl Step for MirOpt {
1648 type Output = ();
1649 const DEFAULT: bool = true;
1650
1651 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1652 run.suite_path("tests/mir-opt")
1653 }
1654
1655 fn make_run(run: RunConfig<'_>) {
1656 let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1657 run.builder.ensure(MirOpt { compiler, target: run.target });
1658 }
1659
1660 fn run(self, builder: &Builder<'_>) {
1661 let run = |target| {
1662 builder.ensure(Compiletest {
1663 test_compiler: self.compiler,
1664 target,
1665 mode: "mir-opt",
1666 suite: "mir-opt",
1667 path: "tests/mir-opt",
1668 compare_mode: None,
1669 })
1670 };
1671
1672 run(self.target);
1673
1674 if builder.config.cmd.bless() {
1677 for target in ["aarch64-unknown-linux-gnu", "i686-pc-windows-msvc"] {
1683 run(TargetSelection::from_user(target));
1684 }
1685
1686 for target in ["x86_64-apple-darwin", "i686-unknown-linux-musl"] {
1687 let target = TargetSelection::from_user(target);
1688 let panic_abort_target = builder.ensure(MirOptPanicAbortSyntheticTarget {
1689 compiler: self.compiler,
1690 base: target,
1691 });
1692 run(panic_abort_target);
1693 }
1694 }
1695 }
1696}
1697
1698#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1704struct Compiletest {
1705 test_compiler: Compiler,
1707 target: TargetSelection,
1708 mode: &'static str,
1709 suite: &'static str,
1710 path: &'static str,
1711 compare_mode: Option<&'static str>,
1712}
1713
1714impl Step for Compiletest {
1715 type Output = ();
1716
1717 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1718 run.never()
1719 }
1720
1721 fn run(self, builder: &Builder<'_>) {
1722 if builder.doc_tests == DocTests::Only {
1723 return;
1724 }
1725
1726 if builder.top_stage == 0 && !builder.config.compiletest_allow_stage0 {
1727 eprintln!("\
1728ERROR: `--stage 0` runs compiletest on the stage0 (precompiled) compiler, not your local changes, and will almost always cause tests to fail
1729HELP: to test the compiler or standard library, omit the stage or explicitly use `--stage 1` instead
1730NOTE: 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`."
1731 );
1732 crate::exit!(1);
1733 }
1734
1735 let mut test_compiler = self.test_compiler;
1736 let target = self.target;
1737 let mode = self.mode;
1738 let suite = self.suite;
1739
1740 let suite_path = self.path;
1742
1743 if !builder.config.codegen_tests && mode == "codegen" {
1745 return;
1746 }
1747
1748 let query_compiler;
1755 let (stage, stage_id) = if suite == "ui-fulldeps" && test_compiler.stage == 1 {
1756 query_compiler = Some(test_compiler);
1759 let build = builder.build.host_target;
1763 test_compiler = builder.compiler(test_compiler.stage - 1, build);
1764 let test_stage = test_compiler.stage + 1;
1765 (test_stage, format!("stage{test_stage}-{build}"))
1766 } else {
1767 query_compiler = None;
1768 let stage = test_compiler.stage;
1769 (stage, format!("stage{stage}-{target}"))
1770 };
1771
1772 if suite.ends_with("fulldeps") {
1773 builder.ensure(compile::Rustc::new(test_compiler, target));
1774 }
1775
1776 if suite == "debuginfo" {
1777 builder.ensure(dist::DebuggerScripts {
1778 sysroot: builder.sysroot(test_compiler).to_path_buf(),
1779 target,
1780 });
1781 }
1782 if mode == "run-make" {
1783 builder.tool_exe(Tool::RunMakeSupport);
1784 }
1785
1786 if suite == "mir-opt" {
1788 builder.ensure(
1789 compile::Std::new(test_compiler, test_compiler.host).is_for_mir_opt_tests(true),
1790 );
1791 } else {
1792 builder.std(test_compiler, test_compiler.host);
1793 }
1794
1795 let mut cmd = builder.tool_cmd(Tool::Compiletest);
1796
1797 if suite == "mir-opt" {
1798 builder.ensure(compile::Std::new(test_compiler, target).is_for_mir_opt_tests(true));
1799 } else {
1800 builder.std(test_compiler, target);
1801 }
1802
1803 builder.ensure(RemoteCopyLibs { build_compiler: test_compiler, target });
1804
1805 cmd.arg("--stage").arg(stage.to_string());
1809 cmd.arg("--stage-id").arg(stage_id);
1810
1811 cmd.arg("--compile-lib-path").arg(builder.rustc_libdir(test_compiler));
1812 cmd.arg("--run-lib-path").arg(builder.sysroot_target_libdir(test_compiler, target));
1813 cmd.arg("--rustc-path").arg(builder.rustc(test_compiler));
1814 if let Some(query_compiler) = query_compiler {
1815 cmd.arg("--query-rustc-path").arg(builder.rustc(query_compiler));
1816 }
1817
1818 cmd.arg("--minicore-path")
1821 .arg(builder.src.join("tests").join("auxiliary").join("minicore.rs"));
1822
1823 let is_rustdoc = suite == "rustdoc-ui" || suite == "rustdoc-js";
1824
1825 if mode == "run-make" {
1840 let stage0_rustc_path = builder.compiler(0, test_compiler.host);
1843 cmd.arg("--stage0-rustc-path").arg(builder.rustc(stage0_rustc_path));
1844
1845 if suite == "run-make-cargo" {
1846 let cargo_path = if test_compiler.stage == 0 {
1847 builder.initial_cargo.clone()
1849 } else {
1850 builder
1851 .ensure(tool::Cargo::from_build_compiler(
1852 builder.compiler(test_compiler.stage - 1, test_compiler.host),
1853 test_compiler.host,
1854 ))
1855 .tool_path
1856 };
1857
1858 cmd.arg("--cargo-path").arg(cargo_path);
1859 }
1860 }
1861
1862 if mode == "rustdoc"
1864 || mode == "run-make"
1865 || (mode == "ui" && is_rustdoc)
1866 || mode == "rustdoc-js"
1867 || mode == "rustdoc-json"
1868 || suite == "coverage-run-rustdoc"
1869 {
1870 cmd.arg("--rustdoc-path").arg(builder.rustdoc_for_compiler(test_compiler));
1871 }
1872
1873 if mode == "rustdoc-json" {
1874 let json_compiler = builder.compiler(0, builder.host_target);
1876 cmd.arg("--jsondocck-path")
1877 .arg(builder.ensure(tool::JsonDocCk { compiler: json_compiler, target }).tool_path);
1878 cmd.arg("--jsondoclint-path").arg(
1879 builder.ensure(tool::JsonDocLint { compiler: json_compiler, target }).tool_path,
1880 );
1881 }
1882
1883 if matches!(mode, "coverage-map" | "coverage-run") {
1884 let coverage_dump = builder.tool_exe(Tool::CoverageDump);
1885 cmd.arg("--coverage-dump-path").arg(coverage_dump);
1886 }
1887
1888 cmd.arg("--src-root").arg(&builder.src);
1889 cmd.arg("--src-test-suite-root").arg(builder.src.join("tests").join(suite));
1890
1891 cmd.arg("--build-root").arg(&builder.out);
1895 cmd.arg("--build-test-suite-root").arg(testdir(builder, test_compiler.host).join(suite));
1896
1897 let sysroot = if builder.top_stage == 0 {
1902 builder.initial_sysroot.clone()
1903 } else {
1904 builder.sysroot(test_compiler)
1905 };
1906
1907 cmd.arg("--sysroot-base").arg(sysroot);
1908
1909 cmd.arg("--suite").arg(suite);
1910 cmd.arg("--mode").arg(mode);
1911 cmd.arg("--target").arg(target.rustc_target_arg());
1912 cmd.arg("--host").arg(&*test_compiler.host.triple);
1913 cmd.arg("--llvm-filecheck").arg(builder.llvm_filecheck(builder.config.host_target));
1914
1915 if let Some(codegen_backend) = builder.config.cmd.test_codegen_backend() {
1916 if !builder
1917 .config
1918 .enabled_codegen_backends(test_compiler.host)
1919 .contains(codegen_backend)
1920 {
1921 eprintln!(
1922 "\
1923ERROR: No configured backend named `{name}`
1924HELP: You can add it into `bootstrap.toml` in `rust.codegen-backends = [{name:?}]`",
1925 name = codegen_backend.name(),
1926 );
1927 crate::exit!(1);
1928 }
1929 cmd.arg("--override-codegen-backend").arg(codegen_backend.name());
1932 cmd.arg("--default-codegen-backend").arg(codegen_backend.name());
1935 } else {
1936 cmd.arg("--default-codegen-backend")
1939 .arg(builder.config.default_codegen_backend(test_compiler.host).name());
1940 }
1941
1942 if builder.build.config.llvm_enzyme {
1943 cmd.arg("--has-enzyme");
1944 }
1945
1946 if builder.config.cmd.bless() {
1947 cmd.arg("--bless");
1948 }
1949
1950 if builder.config.cmd.force_rerun() {
1951 cmd.arg("--force-rerun");
1952 }
1953
1954 if builder.config.cmd.no_capture() {
1955 cmd.arg("--no-capture");
1956 }
1957
1958 let compare_mode =
1959 builder.config.cmd.compare_mode().or_else(|| {
1960 if builder.config.test_compare_mode { self.compare_mode } else { None }
1961 });
1962
1963 if let Some(ref pass) = builder.config.cmd.pass() {
1964 cmd.arg("--pass");
1965 cmd.arg(pass);
1966 }
1967
1968 if let Some(ref run) = builder.config.cmd.run() {
1969 cmd.arg("--run");
1970 cmd.arg(run);
1971 }
1972
1973 if let Some(ref nodejs) = builder.config.nodejs {
1974 cmd.arg("--nodejs").arg(nodejs);
1975 } else if mode == "rustdoc-js" {
1976 panic!("need nodejs to run rustdoc-js suite");
1977 }
1978 if let Some(ref npm) = builder.config.npm {
1979 cmd.arg("--npm").arg(npm);
1980 }
1981 if builder.config.rust_optimize_tests {
1982 cmd.arg("--optimize-tests");
1983 }
1984 if builder.config.rust_randomize_layout {
1985 cmd.arg("--rust-randomized-layout");
1986 }
1987 if builder.config.cmd.only_modified() {
1988 cmd.arg("--only-modified");
1989 }
1990 if let Some(compiletest_diff_tool) = &builder.config.compiletest_diff_tool {
1991 cmd.arg("--compiletest-diff-tool").arg(compiletest_diff_tool);
1992 }
1993
1994 let mut flags = if is_rustdoc { Vec::new() } else { vec!["-Crpath".to_string()] };
1995 flags.push(format!(
1996 "-Cdebuginfo={}",
1997 if mode == "codegen" {
1998 if builder.config.rust_debuginfo_level_tests
2001 != crate::core::config::DebuginfoLevel::None
2002 {
2003 println!(
2004 "NOTE: ignoring `rust.debuginfo-level-tests={}` for codegen tests",
2005 builder.config.rust_debuginfo_level_tests
2006 );
2007 }
2008 crate::core::config::DebuginfoLevel::None
2009 } else {
2010 builder.config.rust_debuginfo_level_tests
2011 }
2012 ));
2013 flags.extend(builder.config.cmd.compiletest_rustc_args().iter().map(|s| s.to_string()));
2014
2015 if suite != "mir-opt" {
2016 if let Some(linker) = builder.linker(target) {
2017 cmd.arg("--target-linker").arg(linker);
2018 }
2019 if let Some(linker) = builder.linker(test_compiler.host) {
2020 cmd.arg("--host-linker").arg(linker);
2021 }
2022 }
2023
2024 if suite == "ui-fulldeps" && target.ends_with("darwin") {
2026 flags.push("-Alinker_messages".into());
2027 }
2028
2029 let mut hostflags = flags.clone();
2030 hostflags.extend(linker_flags(builder, test_compiler.host, LldThreads::No));
2031
2032 let mut targetflags = flags;
2033
2034 if suite == "ui" || suite == "incremental" {
2036 builder.ensure(TestHelpers { target: test_compiler.host });
2037 builder.ensure(TestHelpers { target });
2038 hostflags.push(format!(
2039 "-Lnative={}",
2040 builder.test_helpers_out(test_compiler.host).display()
2041 ));
2042 targetflags.push(format!("-Lnative={}", builder.test_helpers_out(target).display()));
2043 }
2044
2045 for flag in hostflags {
2046 cmd.arg("--host-rustcflags").arg(flag);
2047 }
2048 for flag in targetflags {
2049 cmd.arg("--target-rustcflags").arg(flag);
2050 }
2051
2052 cmd.arg("--python").arg(builder.python());
2053
2054 if let Some(ref gdb) = builder.config.gdb {
2055 cmd.arg("--gdb").arg(gdb);
2056 }
2057
2058 let lldb_exe = builder.config.lldb.clone().unwrap_or_else(|| PathBuf::from("lldb"));
2059 let lldb_version = command(&lldb_exe)
2060 .allow_failure()
2061 .arg("--version")
2062 .run_capture(builder)
2063 .stdout_if_ok()
2064 .and_then(|v| if v.trim().is_empty() { None } else { Some(v) });
2065 if let Some(ref vers) = lldb_version {
2066 cmd.arg("--lldb-version").arg(vers);
2067 let lldb_python_dir = command(&lldb_exe)
2068 .allow_failure()
2069 .arg("-P")
2070 .run_capture_stdout(builder)
2071 .stdout_if_ok()
2072 .map(|p| p.lines().next().expect("lldb Python dir not found").to_string());
2073 if let Some(ref dir) = lldb_python_dir {
2074 cmd.arg("--lldb-python-dir").arg(dir);
2075 }
2076 }
2077
2078 if helpers::forcing_clang_based_tests() {
2079 let clang_exe = builder.llvm_out(target).join("bin").join("clang");
2080 cmd.arg("--run-clang-based-tests-with").arg(clang_exe);
2081 }
2082
2083 for exclude in &builder.config.skip {
2084 cmd.arg("--skip");
2085 cmd.arg(exclude);
2086 }
2087
2088 let paths = match &builder.config.cmd {
2090 Subcommand::Test { .. } => &builder.config.paths[..],
2091 _ => &[],
2092 };
2093
2094 let mut test_args: Vec<&str> = paths
2096 .iter()
2097 .filter_map(|p| helpers::is_valid_test_suite_arg(p, suite_path, builder))
2098 .collect();
2099
2100 test_args.append(&mut builder.config.test_args());
2101
2102 if cfg!(windows) {
2105 let test_args_win: Vec<String> =
2106 test_args.iter().map(|s| s.replace('/', "\\")).collect();
2107 cmd.args(&test_args_win);
2108 } else {
2109 cmd.args(&test_args);
2110 }
2111
2112 if builder.is_verbose() {
2113 cmd.arg("--verbose");
2114 }
2115
2116 if builder.config.rustc_debug_assertions {
2117 cmd.arg("--with-rustc-debug-assertions");
2118 }
2119
2120 if builder.config.std_debug_assertions {
2121 cmd.arg("--with-std-debug-assertions");
2122 }
2123
2124 let mut llvm_components_passed = false;
2125 let mut copts_passed = false;
2126 if builder.config.llvm_enabled(test_compiler.host) {
2127 let llvm::LlvmResult { host_llvm_config, .. } =
2128 builder.ensure(llvm::Llvm { target: builder.config.host_target });
2129 if !builder.config.dry_run() {
2130 let llvm_version = get_llvm_version(builder, &host_llvm_config);
2131 let llvm_components = command(&host_llvm_config)
2132 .cached()
2133 .arg("--components")
2134 .run_capture_stdout(builder)
2135 .stdout();
2136 cmd.arg("--llvm-version")
2138 .arg(llvm_version.trim())
2139 .arg("--llvm-components")
2140 .arg(llvm_components.trim());
2141 llvm_components_passed = true;
2142 }
2143 if !builder.config.is_rust_llvm(target) {
2144 cmd.arg("--system-llvm");
2145 }
2146
2147 if !builder.config.dry_run() && suite.ends_with("fulldeps") {
2152 let llvm_libdir = command(&host_llvm_config)
2153 .cached()
2154 .arg("--libdir")
2155 .run_capture_stdout(builder)
2156 .stdout();
2157 let link_llvm = if target.is_msvc() {
2158 format!("-Clink-arg=-LIBPATH:{llvm_libdir}")
2159 } else {
2160 format!("-Clink-arg=-L{llvm_libdir}")
2161 };
2162 cmd.arg("--host-rustcflags").arg(link_llvm);
2163 }
2164
2165 if !builder.config.dry_run() && matches!(mode, "run-make" | "coverage-run") {
2166 let llvm_bin_path = host_llvm_config
2171 .parent()
2172 .expect("Expected llvm-config to be contained in directory");
2173 assert!(llvm_bin_path.is_dir());
2174 cmd.arg("--llvm-bin-dir").arg(llvm_bin_path);
2175 }
2176
2177 if !builder.config.dry_run() && mode == "run-make" {
2178 if builder.config.lld_enabled {
2180 let lld_install_root =
2181 builder.ensure(llvm::Lld { target: builder.config.host_target });
2182
2183 let lld_bin_path = lld_install_root.join("bin");
2184
2185 let old_path = env::var_os("PATH").unwrap_or_default();
2186 let new_path = env::join_paths(
2187 std::iter::once(lld_bin_path).chain(env::split_paths(&old_path)),
2188 )
2189 .expect("Could not add LLD bin path to PATH");
2190 cmd.env("PATH", new_path);
2191 }
2192 }
2193 }
2194
2195 if !builder.config.dry_run() && mode == "run-make" {
2198 let mut cflags = builder.cc_handled_clags(target, CLang::C);
2199 cflags.extend(builder.cc_unhandled_cflags(target, GitRepo::Rustc, CLang::C));
2200 let mut cxxflags = builder.cc_handled_clags(target, CLang::Cxx);
2201 cxxflags.extend(builder.cc_unhandled_cflags(target, GitRepo::Rustc, CLang::Cxx));
2202 cmd.arg("--cc")
2203 .arg(builder.cc(target))
2204 .arg("--cxx")
2205 .arg(builder.cxx(target).unwrap())
2206 .arg("--cflags")
2207 .arg(cflags.join(" "))
2208 .arg("--cxxflags")
2209 .arg(cxxflags.join(" "));
2210 copts_passed = true;
2211 if let Some(ar) = builder.ar(target) {
2212 cmd.arg("--ar").arg(ar);
2213 }
2214 }
2215
2216 if !llvm_components_passed {
2217 cmd.arg("--llvm-components").arg("");
2218 }
2219 if !copts_passed {
2220 cmd.arg("--cc")
2221 .arg("")
2222 .arg("--cxx")
2223 .arg("")
2224 .arg("--cflags")
2225 .arg("")
2226 .arg("--cxxflags")
2227 .arg("");
2228 }
2229
2230 if builder.remote_tested(target) {
2231 cmd.arg("--remote-test-client").arg(builder.tool_exe(Tool::RemoteTestClient));
2232 } else if let Some(tool) = builder.runner(target) {
2233 cmd.arg("--runner").arg(tool);
2234 }
2235
2236 if suite != "mir-opt" {
2237 if !builder.config.dry_run() && target.is_msvc() {
2243 for (k, v) in builder.cc[&target].env() {
2244 if k != "PATH" {
2245 cmd.env(k, v);
2246 }
2247 }
2248 }
2249 }
2250
2251 if !builder.config.dry_run()
2253 && target.contains("msvc")
2254 && builder.config.sanitizers_enabled(target)
2255 {
2256 cmd.env("ASAN_WIN_CONTINUE_ON_INTERCEPTION_FAILURE", "1");
2259 let asan_runtime_path = builder.cc[&target].path().parent().unwrap().to_path_buf();
2261 let old_path = cmd
2262 .get_envs()
2263 .find_map(|(k, v)| (k == "PATH").then_some(v))
2264 .flatten()
2265 .map_or_else(|| env::var_os("PATH").unwrap_or_default(), |v| v.to_owned());
2266 let new_path = env::join_paths(
2267 env::split_paths(&old_path).chain(std::iter::once(asan_runtime_path)),
2268 )
2269 .expect("Could not add ASAN runtime path to PATH");
2270 cmd.env("PATH", new_path);
2271 }
2272
2273 cmd.env_remove("CARGO");
2276
2277 cmd.env("RUSTC_BOOTSTRAP", "1");
2278 cmd.env("RUSTC_FORCE_RUSTC_VERSION", "compiletest");
2281 cmd.env("DOC_RUST_LANG_ORG_CHANNEL", builder.doc_rust_lang_org_channel());
2282 builder.add_rust_test_threads(&mut cmd);
2283
2284 if builder.config.sanitizers_enabled(target) {
2285 cmd.env("RUSTC_SANITIZER_SUPPORT", "1");
2286 }
2287
2288 if builder.config.profiler_enabled(target) {
2289 cmd.arg("--profiler-runtime");
2290 }
2291
2292 cmd.env("RUST_TEST_TMPDIR", builder.tempdir());
2293
2294 cmd.arg("--adb-path").arg("adb");
2295 cmd.arg("--adb-test-dir").arg(ADB_TEST_DIR);
2296 if target.contains("android") && !builder.config.dry_run() {
2297 cmd.arg("--android-cross-path")
2299 .arg(builder.cc(target).parent().unwrap().parent().unwrap());
2300 } else {
2301 cmd.arg("--android-cross-path").arg("");
2302 }
2303
2304 if builder.config.cmd.rustfix_coverage() {
2305 cmd.arg("--rustfix-coverage");
2306 }
2307
2308 cmd.arg("--channel").arg(&builder.config.channel);
2309
2310 if !builder.config.omit_git_hash {
2311 cmd.arg("--git-hash");
2312 }
2313
2314 let git_config = builder.config.git_config();
2315 cmd.arg("--nightly-branch").arg(git_config.nightly_branch);
2316 cmd.arg("--git-merge-commit-email").arg(git_config.git_merge_commit_email);
2317 cmd.force_coloring_in_ci();
2318
2319 #[cfg(feature = "build-metrics")]
2320 builder.metrics.begin_test_suite(
2321 build_helper::metrics::TestSuiteMetadata::Compiletest {
2322 suite: suite.into(),
2323 mode: mode.into(),
2324 compare_mode: None,
2325 target: self.target.triple.to_string(),
2326 host: self.test_compiler.host.triple.to_string(),
2327 stage: self.test_compiler.stage,
2328 },
2329 builder,
2330 );
2331
2332 let _group = builder.msg_test(
2333 format!("with compiletest suite={suite} mode={mode}"),
2334 target,
2335 test_compiler.stage,
2336 );
2337 try_run_tests(builder, &mut cmd, false);
2338
2339 if let Some(compare_mode) = compare_mode {
2340 cmd.arg("--compare-mode").arg(compare_mode);
2341
2342 #[cfg(feature = "build-metrics")]
2343 builder.metrics.begin_test_suite(
2344 build_helper::metrics::TestSuiteMetadata::Compiletest {
2345 suite: suite.into(),
2346 mode: mode.into(),
2347 compare_mode: Some(compare_mode.into()),
2348 target: self.target.triple.to_string(),
2349 host: self.test_compiler.host.triple.to_string(),
2350 stage: self.test_compiler.stage,
2351 },
2352 builder,
2353 );
2354
2355 builder.info(&format!(
2356 "Check compiletest suite={} mode={} compare_mode={} ({} -> {})",
2357 suite, mode, compare_mode, &test_compiler.host, target
2358 ));
2359 let _time = helpers::timeit(builder);
2360 try_run_tests(builder, &mut cmd, false);
2361 }
2362 }
2363
2364 fn metadata(&self) -> Option<StepMetadata> {
2365 Some(
2366 StepMetadata::test(&format!("compiletest-{}", self.suite), self.target)
2367 .stage(self.test_compiler.stage),
2368 )
2369 }
2370}
2371
2372#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2374struct BookTest {
2375 test_compiler: Compiler,
2376 path: PathBuf,
2377 name: &'static str,
2378 is_ext_doc: bool,
2379 dependencies: Vec<&'static str>,
2380}
2381
2382impl Step for BookTest {
2383 type Output = ();
2384 const IS_HOST: bool = true;
2385
2386 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2387 run.never()
2388 }
2389
2390 fn run(self, builder: &Builder<'_>) {
2391 if self.is_ext_doc {
2401 self.run_ext_doc(builder);
2402 } else {
2403 self.run_local_doc(builder);
2404 }
2405 }
2406}
2407
2408impl BookTest {
2409 fn run_ext_doc(self, builder: &Builder<'_>) {
2412 let test_compiler = self.test_compiler;
2413
2414 builder.std(test_compiler, test_compiler.host);
2415
2416 let mut rustdoc_path = builder.rustdoc_for_compiler(test_compiler);
2419 rustdoc_path.pop();
2420 let old_path = env::var_os("PATH").unwrap_or_default();
2421 let new_path = env::join_paths(iter::once(rustdoc_path).chain(env::split_paths(&old_path)))
2422 .expect("could not add rustdoc to PATH");
2423
2424 let mut rustbook_cmd = builder.tool_cmd(Tool::Rustbook);
2425 let path = builder.src.join(&self.path);
2426 rustbook_cmd.env("RUSTC_BOOTSTRAP", "1");
2428 rustbook_cmd.env("PATH", new_path).arg("test").arg(path);
2429
2430 let libs = if !self.dependencies.is_empty() {
2435 let mut lib_paths = vec![];
2436 for dep in self.dependencies {
2437 let mode = Mode::ToolRustcPrivate;
2438 let target = builder.config.host_target;
2439 let cargo = tool::prepare_tool_cargo(
2440 builder,
2441 test_compiler,
2442 mode,
2443 target,
2444 Kind::Build,
2445 dep,
2446 SourceType::Submodule,
2447 &[],
2448 );
2449
2450 let stamp = BuildStamp::new(&builder.cargo_out(test_compiler, mode, target))
2451 .with_prefix(PathBuf::from(dep).file_name().and_then(|v| v.to_str()).unwrap());
2452
2453 let output_paths = run_cargo(builder, cargo, vec![], &stamp, vec![], false, false);
2454 let directories = output_paths
2455 .into_iter()
2456 .filter_map(|p| p.parent().map(ToOwned::to_owned))
2457 .fold(HashSet::new(), |mut set, dir| {
2458 set.insert(dir);
2459 set
2460 });
2461
2462 lib_paths.extend(directories);
2463 }
2464 lib_paths
2465 } else {
2466 vec![]
2467 };
2468
2469 if !libs.is_empty() {
2470 let paths = libs
2471 .into_iter()
2472 .map(|path| path.into_os_string())
2473 .collect::<Vec<OsString>>()
2474 .join(OsStr::new(","));
2475 rustbook_cmd.args([OsString::from("--library-path"), paths]);
2476 }
2477
2478 builder.add_rust_test_threads(&mut rustbook_cmd);
2479 let _guard = builder.msg_test(
2480 format_args!("mdbook {}", self.path.display()),
2481 test_compiler.host,
2482 test_compiler.stage,
2483 );
2484 let _time = helpers::timeit(builder);
2485 let toolstate = if rustbook_cmd.delay_failure().run(builder) {
2486 ToolState::TestPass
2487 } else {
2488 ToolState::TestFail
2489 };
2490 builder.save_toolstate(self.name, toolstate);
2491 }
2492
2493 fn run_local_doc(self, builder: &Builder<'_>) {
2495 let test_compiler = self.test_compiler;
2496 let host = self.test_compiler.host;
2497
2498 builder.std(test_compiler, host);
2499
2500 let _guard = builder.msg_test(
2501 format!("book {}", self.name),
2502 test_compiler.host,
2503 test_compiler.stage,
2504 );
2505
2506 let mut stack = vec![builder.src.join(self.path)];
2509 let _time = helpers::timeit(builder);
2510 let mut files = Vec::new();
2511 while let Some(p) = stack.pop() {
2512 if p.is_dir() {
2513 stack.extend(t!(p.read_dir()).map(|p| t!(p).path()));
2514 continue;
2515 }
2516
2517 if p.extension().and_then(|s| s.to_str()) != Some("md") {
2518 continue;
2519 }
2520
2521 files.push(p);
2522 }
2523
2524 files.sort();
2525
2526 for file in files {
2527 markdown_test(builder, test_compiler, &file);
2528 }
2529 }
2530}
2531
2532macro_rules! test_book {
2533 ($(
2534 $name:ident, $path:expr, $book_name:expr,
2535 default=$default:expr
2536 $(,submodules = $submodules:expr)?
2537 $(,dependencies=$dependencies:expr)?
2538 ;
2539 )+) => {
2540 $(
2541 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
2542 pub struct $name {
2543 test_compiler: Compiler,
2544 }
2545
2546 impl Step for $name {
2547 type Output = ();
2548 const DEFAULT: bool = $default;
2549 const IS_HOST: bool = true;
2550
2551 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2552 run.path($path)
2553 }
2554
2555 fn make_run(run: RunConfig<'_>) {
2556 run.builder.ensure($name {
2557 test_compiler: run.builder.compiler(run.builder.top_stage, run.target),
2558 });
2559 }
2560
2561 fn run(self, builder: &Builder<'_>) {
2562 $(
2563 for submodule in $submodules {
2564 builder.require_submodule(submodule, None);
2565 }
2566 )*
2567
2568 let dependencies = vec![];
2569 $(
2570 let mut dependencies = dependencies;
2571 for dep in $dependencies {
2572 dependencies.push(dep);
2573 }
2574 )?
2575
2576 builder.ensure(BookTest {
2577 test_compiler: self.test_compiler,
2578 path: PathBuf::from($path),
2579 name: $book_name,
2580 is_ext_doc: !$default,
2581 dependencies,
2582 });
2583 }
2584 }
2585 )+
2586 }
2587}
2588
2589test_book!(
2590 Nomicon, "src/doc/nomicon", "nomicon", default=false, submodules=["src/doc/nomicon"];
2591 Reference, "src/doc/reference", "reference", default=false, submodules=["src/doc/reference"];
2592 RustdocBook, "src/doc/rustdoc", "rustdoc", default=true;
2593 RustcBook, "src/doc/rustc", "rustc", default=true;
2594 RustByExample, "src/doc/rust-by-example", "rust-by-example", default=false, submodules=["src/doc/rust-by-example"];
2595 EmbeddedBook, "src/doc/embedded-book", "embedded-book", default=false, submodules=["src/doc/embedded-book"];
2596 TheBook, "src/doc/book", "book", default=false, submodules=["src/doc/book"], dependencies=["src/doc/book/packages/trpl"];
2597 UnstableBook, "src/doc/unstable-book", "unstable-book", default=true;
2598 EditionGuide, "src/doc/edition-guide", "edition-guide", default=false, submodules=["src/doc/edition-guide"];
2599);
2600
2601#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2602pub struct ErrorIndex {
2603 compilers: RustcPrivateCompilers,
2604}
2605
2606impl Step for ErrorIndex {
2607 type Output = ();
2608 const DEFAULT: bool = true;
2609 const IS_HOST: bool = true;
2610
2611 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2612 run.path("src/tools/error_index_generator").alias("error-index")
2615 }
2616
2617 fn make_run(run: RunConfig<'_>) {
2618 let compilers = RustcPrivateCompilers::new(
2622 run.builder,
2623 run.builder.top_stage,
2624 run.builder.config.host_target,
2625 );
2626 run.builder.ensure(ErrorIndex { compilers });
2627 }
2628
2629 fn run(self, builder: &Builder<'_>) {
2636 let target_compiler = self.compilers.target_compiler();
2638
2639 let dir = testdir(builder, target_compiler.host);
2640 t!(fs::create_dir_all(&dir));
2641 let output = dir.join("error-index.md");
2642
2643 let mut tool = tool::ErrorIndex::command(builder, self.compilers);
2644 tool.arg("markdown").arg(&output);
2645
2646 let guard = builder.msg_test("error-index", target_compiler.host, target_compiler.stage);
2647 let _time = helpers::timeit(builder);
2648 tool.run_capture(builder);
2649 drop(guard);
2650 builder.std(target_compiler, target_compiler.host);
2653 markdown_test(builder, target_compiler, &output);
2654 }
2655}
2656
2657fn markdown_test(builder: &Builder<'_>, compiler: Compiler, markdown: &Path) -> bool {
2658 if let Ok(contents) = fs::read_to_string(markdown)
2659 && !contents.contains("```")
2660 {
2661 return true;
2662 }
2663
2664 builder.verbose(|| println!("doc tests for: {}", markdown.display()));
2665 let mut cmd = builder.rustdoc_cmd(compiler);
2666 builder.add_rust_test_threads(&mut cmd);
2667 cmd.arg("-Z");
2669 cmd.arg("unstable-options");
2670 cmd.arg("--test");
2671 cmd.arg(markdown);
2672 cmd.env("RUSTC_BOOTSTRAP", "1");
2673
2674 let test_args = builder.config.test_args().join(" ");
2675 cmd.arg("--test-args").arg(test_args);
2676
2677 cmd = cmd.delay_failure();
2678 if !builder.config.verbose_tests {
2679 cmd.run_capture(builder).is_success()
2680 } else {
2681 cmd.run(builder)
2682 }
2683}
2684
2685#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2690pub struct CrateLibrustc {
2691 build_compiler: Compiler,
2693 target: TargetSelection,
2694 crates: Vec<String>,
2695}
2696
2697impl Step for CrateLibrustc {
2698 type Output = ();
2699 const DEFAULT: bool = true;
2700 const IS_HOST: bool = true;
2701
2702 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2703 run.crate_or_deps("rustc-main").path("compiler")
2704 }
2705
2706 fn make_run(run: RunConfig<'_>) {
2707 let builder = run.builder;
2708 let host = run.build_triple();
2709 let build_compiler = builder.compiler(builder.top_stage - 1, host);
2710 let crates = run.make_run_crates(Alias::Compiler);
2711
2712 builder.ensure(CrateLibrustc { build_compiler, target: run.target, crates });
2713 }
2714
2715 fn run(self, builder: &Builder<'_>) {
2716 builder.std(self.build_compiler, self.target);
2717
2718 builder.ensure(Crate {
2720 build_compiler: self.build_compiler,
2721 target: self.target,
2722 mode: Mode::Rustc,
2723 crates: self.crates,
2724 });
2725 }
2726
2727 fn metadata(&self) -> Option<StepMetadata> {
2728 Some(StepMetadata::test("CrateLibrustc", self.target).built_by(self.build_compiler))
2729 }
2730}
2731
2732fn run_cargo_test<'a>(
2736 cargo: builder::Cargo,
2737 libtest_args: &[&str],
2738 crates: &[String],
2739 description: impl Into<Option<&'a str>>,
2740 target: TargetSelection,
2741 builder: &Builder<'_>,
2742) -> bool {
2743 let compiler = cargo.compiler();
2744 let mut cargo = prepare_cargo_test(cargo, libtest_args, crates, target, builder);
2745 let _time = helpers::timeit(builder);
2746 let _group =
2747 description.into().and_then(|what| builder.msg_test(what, target, compiler.stage + 1));
2748
2749 #[cfg(feature = "build-metrics")]
2750 builder.metrics.begin_test_suite(
2751 build_helper::metrics::TestSuiteMetadata::CargoPackage {
2752 crates: crates.iter().map(|c| c.to_string()).collect(),
2753 target: target.triple.to_string(),
2754 host: compiler.host.triple.to_string(),
2755 stage: compiler.stage,
2756 },
2757 builder,
2758 );
2759 add_flags_and_try_run_tests(builder, &mut cargo)
2760}
2761
2762fn prepare_cargo_test(
2764 cargo: builder::Cargo,
2765 libtest_args: &[&str],
2766 crates: &[String],
2767 target: TargetSelection,
2768 builder: &Builder<'_>,
2769) -> BootstrapCommand {
2770 let compiler = cargo.compiler();
2771 let mut cargo: BootstrapCommand = cargo.into();
2772
2773 if builder.config.cmd.bless() && !cargo.get_envs().any(|v| v.0 == "RUSTC_BLESS") {
2777 cargo.env("RUSTC_BLESS", "Gesundheit");
2778 }
2779
2780 if builder.kind == Kind::Test && !builder.fail_fast {
2784 cargo.arg("--no-fail-fast");
2785 }
2786
2787 if builder.config.json_output {
2788 cargo.arg("--message-format=json");
2789 }
2790
2791 match builder.doc_tests {
2792 DocTests::Only => {
2793 cargo.arg("--doc");
2794 }
2795 DocTests::No => {
2796 cargo.args(["--bins", "--examples", "--tests", "--benches"]);
2797 }
2798 DocTests::Yes => {}
2799 }
2800
2801 for krate in crates {
2802 cargo.arg("-p").arg(krate);
2803 }
2804
2805 cargo.arg("--").args(builder.config.test_args()).args(libtest_args);
2806 if !builder.config.verbose_tests {
2807 cargo.arg("--quiet");
2808 }
2809
2810 if builder.kind != Kind::Miri {
2819 let mut dylib_paths = builder.rustc_lib_paths(compiler);
2820 dylib_paths.push(builder.sysroot_target_libdir(compiler, target));
2821 helpers::add_dylib_path(dylib_paths, &mut cargo);
2822 }
2823
2824 if builder.remote_tested(target) {
2825 cargo.env(
2826 format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)),
2827 format!("{} run 0", builder.tool_exe(Tool::RemoteTestClient).display()),
2828 );
2829 } else if let Some(tool) = builder.runner(target) {
2830 cargo.env(format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)), tool);
2831 }
2832
2833 cargo
2834}
2835
2836#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2844pub struct Crate {
2845 build_compiler: Compiler,
2847 target: TargetSelection,
2848 mode: Mode,
2849 crates: Vec<String>,
2850}
2851
2852impl Step for Crate {
2853 type Output = ();
2854 const DEFAULT: bool = true;
2855
2856 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2857 run.crate_or_deps("sysroot").crate_or_deps("coretests").crate_or_deps("alloctests")
2858 }
2859
2860 fn make_run(run: RunConfig<'_>) {
2861 let builder = run.builder;
2862 let host = run.build_triple();
2863 let build_compiler = builder.compiler(builder.top_stage, host);
2864 let crates = run
2865 .paths
2866 .iter()
2867 .map(|p| builder.crate_paths[&p.assert_single_path().path].clone())
2868 .collect();
2869
2870 builder.ensure(Crate { build_compiler, target: run.target, mode: Mode::Std, crates });
2871 }
2872
2873 fn run(self, builder: &Builder<'_>) {
2882 let build_compiler = self.build_compiler;
2883 let target = self.target;
2884 let mode = self.mode;
2885
2886 builder.ensure(Std::new(build_compiler, build_compiler.host).force_recompile(true));
2889
2890 let mut cargo = if builder.kind == Kind::Miri {
2891 if builder.top_stage == 0 {
2892 eprintln!("ERROR: `x.py miri` requires stage 1 or higher");
2893 std::process::exit(1);
2894 }
2895
2896 let mut cargo = builder::Cargo::new(
2899 builder,
2900 build_compiler,
2901 mode,
2902 SourceType::InTree,
2903 target,
2904 Kind::MiriTest,
2905 );
2906 cargo.env("MIRI_REPLACE_LIBRS_IF_NOT_TEST", "1");
2918 cargo.rustflag("-Zforce-unstable-if-unmarked");
2922 cargo
2923 } else {
2924 if !builder.config.is_host_target(target) {
2926 builder.ensure(compile::Std::new(build_compiler, target).force_recompile(true));
2927 builder.ensure(RemoteCopyLibs { build_compiler, target });
2928 }
2929
2930 builder::Cargo::new(
2932 builder,
2933 build_compiler,
2934 mode,
2935 SourceType::InTree,
2936 target,
2937 builder.kind,
2938 )
2939 };
2940
2941 match mode {
2942 Mode::Std => {
2943 if builder.kind == Kind::Miri {
2944 cargo
2950 .arg("--manifest-path")
2951 .arg(builder.src.join("library/sysroot/Cargo.toml"));
2952 } else {
2953 compile::std_cargo(builder, target, &mut cargo);
2954 }
2955 }
2956 Mode::Rustc => {
2957 compile::rustc_cargo(builder, &mut cargo, target, &build_compiler, &self.crates);
2958 }
2959 _ => panic!("can only test libraries"),
2960 };
2961
2962 let mut crates = self.crates.clone();
2963 if crates.iter().any(|crate_| crate_ == "core") {
2968 crates.push("coretests".to_owned());
2969 }
2970 if crates.iter().any(|crate_| crate_ == "alloc") {
2971 crates.push("alloctests".to_owned());
2972 }
2973
2974 run_cargo_test(cargo, &[], &crates, &*crate_description(&self.crates), target, builder);
2975 }
2976}
2977
2978#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2981pub struct CrateRustdoc {
2982 host: TargetSelection,
2983}
2984
2985impl Step for CrateRustdoc {
2986 type Output = ();
2987 const DEFAULT: bool = true;
2988 const IS_HOST: bool = true;
2989
2990 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2991 run.paths(&["src/librustdoc", "src/tools/rustdoc"])
2992 }
2993
2994 fn make_run(run: RunConfig<'_>) {
2995 let builder = run.builder;
2996
2997 builder.ensure(CrateRustdoc { host: run.target });
2998 }
2999
3000 fn run(self, builder: &Builder<'_>) {
3001 let target = self.host;
3002
3003 let compiler = if builder.download_rustc() {
3004 builder.compiler(builder.top_stage, target)
3005 } else {
3006 builder.compiler_for(builder.top_stage, target, target)
3011 };
3012 builder.std(compiler, target);
3017 builder.ensure(compile::Rustc::new(compiler, target));
3018
3019 let mut cargo = tool::prepare_tool_cargo(
3020 builder,
3021 compiler,
3022 Mode::ToolRustcPrivate,
3023 target,
3024 builder.kind,
3025 "src/tools/rustdoc",
3026 SourceType::InTree,
3027 &[],
3028 );
3029 if self.host.contains("musl") {
3030 cargo.arg("'-Ctarget-feature=-crt-static'");
3031 }
3032
3033 let libdir = if builder.download_rustc() {
3060 builder.rustc_libdir(compiler)
3061 } else {
3062 builder.sysroot_target_libdir(compiler, target).to_path_buf()
3063 };
3064 let mut dylib_path = dylib_path();
3065 dylib_path.insert(0, PathBuf::from(&*libdir));
3066 cargo.env(dylib_path_var(), env::join_paths(&dylib_path).unwrap());
3067
3068 run_cargo_test(cargo, &[], &["rustdoc:0.0.0".to_string()], "rustdoc", target, builder);
3069 }
3070}
3071
3072#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3073pub struct CrateRustdocJsonTypes {
3074 build_compiler: Compiler,
3075 target: TargetSelection,
3076}
3077
3078impl Step for CrateRustdocJsonTypes {
3079 type Output = ();
3080 const DEFAULT: bool = true;
3081 const IS_HOST: bool = true;
3082
3083 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3084 run.path("src/rustdoc-json-types")
3085 }
3086
3087 fn make_run(run: RunConfig<'_>) {
3088 let builder = run.builder;
3089
3090 builder.ensure(CrateRustdocJsonTypes {
3091 build_compiler: get_tool_target_compiler(
3092 builder,
3093 ToolTargetBuildMode::Build(run.target),
3094 ),
3095 target: run.target,
3096 });
3097 }
3098
3099 fn run(self, builder: &Builder<'_>) {
3100 let target = self.target;
3101
3102 let cargo = tool::prepare_tool_cargo(
3103 builder,
3104 self.build_compiler,
3105 Mode::ToolTarget,
3106 target,
3107 builder.kind,
3108 "src/rustdoc-json-types",
3109 SourceType::InTree,
3110 &[],
3111 );
3112
3113 let libtest_args = if target.contains("musl") {
3115 ["'-Ctarget-feature=-crt-static'"].as_slice()
3116 } else {
3117 &[]
3118 };
3119
3120 run_cargo_test(
3121 cargo,
3122 libtest_args,
3123 &["rustdoc-json-types".to_string()],
3124 "rustdoc-json-types",
3125 target,
3126 builder,
3127 );
3128 }
3129}
3130
3131#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3141pub struct RemoteCopyLibs {
3142 build_compiler: Compiler,
3143 target: TargetSelection,
3144}
3145
3146impl Step for RemoteCopyLibs {
3147 type Output = ();
3148
3149 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3150 run.never()
3151 }
3152
3153 fn run(self, builder: &Builder<'_>) {
3154 let build_compiler = self.build_compiler;
3155 let target = self.target;
3156 if !builder.remote_tested(target) {
3157 return;
3158 }
3159
3160 builder.std(build_compiler, target);
3161
3162 builder.info(&format!("REMOTE copy libs to emulator ({target})"));
3163
3164 let remote_test_server = builder.ensure(tool::RemoteTestServer { build_compiler, target });
3165
3166 let tool = builder.tool_exe(Tool::RemoteTestClient);
3168 let mut cmd = command(&tool);
3169 cmd.arg("spawn-emulator")
3170 .arg(target.triple)
3171 .arg(&remote_test_server.tool_path)
3172 .arg(builder.tempdir());
3173 if let Some(rootfs) = builder.qemu_rootfs(target) {
3174 cmd.arg(rootfs);
3175 }
3176 cmd.run(builder);
3177
3178 for f in t!(builder.sysroot_target_libdir(build_compiler, target).read_dir()) {
3180 let f = t!(f);
3181 if helpers::is_dylib(&f.path()) {
3182 command(&tool).arg("push").arg(f.path()).run(builder);
3183 }
3184 }
3185 }
3186}
3187
3188#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3189pub struct Distcheck;
3190
3191impl Step for Distcheck {
3192 type Output = ();
3193
3194 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3195 run.alias("distcheck")
3196 }
3197
3198 fn make_run(run: RunConfig<'_>) {
3199 run.builder.ensure(Distcheck);
3200 }
3201
3202 fn run(self, builder: &Builder<'_>) {
3212 let root_dir = std::env::temp_dir().join("distcheck");
3215
3216 distcheck_plain_source_tarball(builder, &root_dir.join("distcheck-rustc-src"));
3217 distcheck_rust_src(builder, &root_dir.join("distcheck-rust-src"));
3218 distcheck_rustc_dev(builder, &root_dir.join("distcheck-rustc-dev"));
3219 }
3220}
3221
3222fn distcheck_plain_source_tarball(builder: &Builder<'_>, plain_src_dir: &Path) {
3224 builder.info("Distcheck plain source tarball");
3225 let plain_src_tarball = builder.ensure(dist::PlainSourceTarball);
3226 builder.clear_dir(plain_src_dir);
3227
3228 let configure_args: Vec<String> = std::env::var("DISTCHECK_CONFIGURE_ARGS")
3229 .map(|args| args.split(" ").map(|s| s.to_string()).collect::<Vec<String>>())
3230 .unwrap_or_default();
3231
3232 command("tar")
3233 .arg("-xf")
3234 .arg(plain_src_tarball.tarball())
3235 .arg("--strip-components=1")
3236 .current_dir(plain_src_dir)
3237 .run(builder);
3238 command("./configure")
3239 .arg("--set")
3240 .arg("rust.omit-git-hash=false")
3241 .args(&configure_args)
3242 .arg("--enable-vendor")
3243 .current_dir(plain_src_dir)
3244 .run(builder);
3245 command(helpers::make(&builder.config.host_target.triple))
3246 .arg("check")
3247 .env("GITHUB_ACTIONS", "0")
3250 .current_dir(plain_src_dir)
3251 .run(builder);
3252}
3253
3254fn distcheck_rust_src(builder: &Builder<'_>, src_dir: &Path) {
3256 builder.info("Distcheck rust-src");
3257 let src_tarball = builder.ensure(dist::Src);
3258 builder.clear_dir(src_dir);
3259
3260 command("tar")
3261 .arg("-xf")
3262 .arg(src_tarball.tarball())
3263 .arg("--strip-components=1")
3264 .current_dir(src_dir)
3265 .run(builder);
3266
3267 let toml = src_dir.join("rust-src/lib/rustlib/src/rust/library/std/Cargo.toml");
3268 command(&builder.initial_cargo)
3269 .env("RUSTC_BOOTSTRAP", "1")
3272 .arg("generate-lockfile")
3273 .arg("--manifest-path")
3274 .arg(&toml)
3275 .current_dir(src_dir)
3276 .run(builder);
3277}
3278
3279fn distcheck_rustc_dev(builder: &Builder<'_>, dir: &Path) {
3281 builder.info("Distcheck rustc-dev");
3282 let tarball = builder.ensure(dist::RustcDev::new(builder, builder.host_target)).unwrap();
3283 builder.clear_dir(dir);
3284
3285 command("tar")
3286 .arg("-xf")
3287 .arg(tarball.tarball())
3288 .arg("--strip-components=1")
3289 .current_dir(dir)
3290 .run(builder);
3291
3292 command(&builder.initial_cargo)
3293 .arg("metadata")
3294 .arg("--manifest-path")
3295 .arg("rustc-dev/lib/rustlib/rustc-src/rust/compiler/rustc/Cargo.toml")
3296 .env("RUSTC_BOOTSTRAP", "1")
3297 .env("RUSTC", &builder.initial_rustc)
3299 .current_dir(dir)
3300 .run(builder);
3301}
3302
3303#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3304pub struct Bootstrap;
3305
3306impl Step for Bootstrap {
3307 type Output = ();
3308 const DEFAULT: bool = true;
3309 const IS_HOST: bool = true;
3310
3311 fn run(self, builder: &Builder<'_>) {
3313 let host = builder.config.host_target;
3314 let build_compiler = builder.compiler(0, host);
3315
3316 builder.build.require_submodule("src/tools/cargo", None);
3318
3319 let mut check_bootstrap = command(builder.python());
3320 check_bootstrap
3321 .args(["-m", "unittest", "bootstrap_test.py"])
3322 .env("BUILD_DIR", &builder.out)
3323 .env("BUILD_PLATFORM", builder.build.host_target.triple)
3324 .env("BOOTSTRAP_TEST_RUSTC_BIN", &builder.initial_rustc)
3325 .env("BOOTSTRAP_TEST_CARGO_BIN", &builder.initial_cargo)
3326 .current_dir(builder.src.join("src/bootstrap/"));
3327 check_bootstrap.delay_failure().run(builder);
3330
3331 let mut cargo = tool::prepare_tool_cargo(
3332 builder,
3333 build_compiler,
3334 Mode::ToolBootstrap,
3335 host,
3336 Kind::Test,
3337 "src/bootstrap",
3338 SourceType::InTree,
3339 &[],
3340 );
3341
3342 cargo.release_build(false);
3343
3344 cargo
3345 .rustflag("-Cdebuginfo=2")
3346 .env("CARGO_TARGET_DIR", builder.out.join("bootstrap"))
3347 .env("INSTA_WORKSPACE_ROOT", &builder.src)
3349 .env("RUSTC_BOOTSTRAP", "1");
3350
3351 run_cargo_test(cargo, &[], &[], None, host, builder);
3352 }
3353
3354 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3355 let runs_on_ci = run.builder.config.is_running_on_ci;
3359 run.path("src/bootstrap").default_condition(runs_on_ci)
3360 }
3361
3362 fn make_run(run: RunConfig<'_>) {
3363 run.builder.ensure(Bootstrap);
3364 }
3365}
3366
3367fn get_compiler_to_test(builder: &Builder<'_>, target: TargetSelection) -> Compiler {
3368 builder.compiler(builder.top_stage, target)
3369}
3370
3371#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3374pub struct TierCheck {
3375 test_compiler: Compiler,
3376}
3377
3378impl Step for TierCheck {
3379 type Output = ();
3380 const DEFAULT: bool = true;
3381 const IS_HOST: bool = true;
3382
3383 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3384 run.path("src/tools/tier-check")
3385 }
3386
3387 fn make_run(run: RunConfig<'_>) {
3388 run.builder
3389 .ensure(TierCheck { test_compiler: get_compiler_to_test(run.builder, run.target) });
3390 }
3391
3392 fn run(self, builder: &Builder<'_>) {
3393 let tool_build_compiler = builder.compiler(0, builder.host_target);
3394
3395 let mut cargo = tool::prepare_tool_cargo(
3396 builder,
3397 tool_build_compiler,
3398 Mode::ToolBootstrap,
3399 tool_build_compiler.host,
3400 Kind::Run,
3401 "src/tools/tier-check",
3402 SourceType::InTree,
3403 &[],
3404 );
3405 cargo.arg(builder.src.join("src/doc/rustc/src/platform-support.md"));
3406 cargo.arg(builder.rustc(self.test_compiler));
3407 if builder.is_verbose() {
3408 cargo.arg("--verbose");
3409 }
3410
3411 let _guard = builder.msg_test(
3412 "platform support check",
3413 self.test_compiler.host,
3414 self.test_compiler.stage,
3415 );
3416 BootstrapCommand::from(cargo).delay_failure().run(builder);
3417 }
3418
3419 fn metadata(&self) -> Option<StepMetadata> {
3420 Some(StepMetadata::test("tier-check", self.test_compiler.host))
3421 }
3422}
3423
3424#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3425pub struct LintDocs {
3426 build_compiler: Compiler,
3427 target: TargetSelection,
3428}
3429
3430impl Step for LintDocs {
3431 type Output = ();
3432 const DEFAULT: bool = true;
3433 const IS_HOST: bool = true;
3434
3435 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3436 let stage = run.builder.top_stage;
3437 run.path("src/tools/lint-docs").default_condition(stage > 1)
3440 }
3441
3442 fn make_run(run: RunConfig<'_>) {
3443 if run.builder.top_stage < 2 {
3444 eprintln!("WARNING: lint-docs tests might not work below stage 2");
3445 }
3446
3447 run.builder.ensure(LintDocs {
3448 build_compiler: prepare_doc_compiler(
3449 run.builder,
3450 run.builder.config.host_target,
3451 run.builder.top_stage,
3452 ),
3453 target: run.target,
3454 });
3455 }
3456
3457 fn run(self, builder: &Builder<'_>) {
3460 builder.ensure(crate::core::build_steps::doc::RustcBook::validate(
3461 self.build_compiler,
3462 self.target,
3463 ));
3464 }
3465
3466 fn metadata(&self) -> Option<StepMetadata> {
3467 Some(StepMetadata::test("lint-docs", self.target).built_by(self.build_compiler))
3468 }
3469}
3470
3471#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3472pub struct RustInstaller;
3473
3474impl Step for RustInstaller {
3475 type Output = ();
3476 const IS_HOST: bool = true;
3477 const DEFAULT: bool = true;
3478
3479 fn run(self, builder: &Builder<'_>) {
3481 let bootstrap_host = builder.config.host_target;
3482 let build_compiler = builder.compiler(0, bootstrap_host);
3483 let cargo = tool::prepare_tool_cargo(
3484 builder,
3485 build_compiler,
3486 Mode::ToolBootstrap,
3487 bootstrap_host,
3488 Kind::Test,
3489 "src/tools/rust-installer",
3490 SourceType::InTree,
3491 &[],
3492 );
3493
3494 let _guard = builder.msg_test("rust-installer", bootstrap_host, 1);
3495 run_cargo_test(cargo, &[], &[], None, bootstrap_host, builder);
3496
3497 if bootstrap_host != "x86_64-unknown-linux-gnu" {
3501 return;
3502 }
3503
3504 let mut cmd = command(builder.src.join("src/tools/rust-installer/test.sh"));
3505 let tmpdir = testdir(builder, build_compiler.host).join("rust-installer");
3506 let _ = std::fs::remove_dir_all(&tmpdir);
3507 let _ = std::fs::create_dir_all(&tmpdir);
3508 cmd.current_dir(&tmpdir);
3509 cmd.env("CARGO_TARGET_DIR", tmpdir.join("cargo-target"));
3510 cmd.env("CARGO", &builder.initial_cargo);
3511 cmd.env("RUSTC", &builder.initial_rustc);
3512 cmd.env("TMP_DIR", &tmpdir);
3513 cmd.delay_failure().run(builder);
3514 }
3515
3516 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3517 run.path("src/tools/rust-installer")
3518 }
3519
3520 fn make_run(run: RunConfig<'_>) {
3521 run.builder.ensure(Self);
3522 }
3523}
3524
3525#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3526pub struct TestHelpers {
3527 pub target: TargetSelection,
3528}
3529
3530impl Step for TestHelpers {
3531 type Output = ();
3532
3533 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3534 run.path("tests/auxiliary/rust_test_helpers.c")
3535 }
3536
3537 fn make_run(run: RunConfig<'_>) {
3538 run.builder.ensure(TestHelpers { target: run.target })
3539 }
3540
3541 fn run(self, builder: &Builder<'_>) {
3544 if builder.config.dry_run() {
3545 return;
3546 }
3547 let target = if self.target == "x86_64-fortanix-unknown-sgx" {
3551 TargetSelection::from_user("x86_64-unknown-linux-gnu")
3552 } else {
3553 self.target
3554 };
3555 let dst = builder.test_helpers_out(target);
3556 let src = builder.src.join("tests/auxiliary/rust_test_helpers.c");
3557 if up_to_date(&src, &dst.join("librust_test_helpers.a")) {
3558 return;
3559 }
3560
3561 let _guard = builder.msg_unstaged(Kind::Build, "test helpers", target);
3562 t!(fs::create_dir_all(&dst));
3563 let mut cfg = cc::Build::new();
3564
3565 if !target.is_msvc() {
3569 if let Some(ar) = builder.ar(target) {
3570 cfg.archiver(ar);
3571 }
3572 cfg.compiler(builder.cc(target));
3573 }
3574 cfg.cargo_metadata(false)
3575 .out_dir(&dst)
3576 .target(&target.triple)
3577 .host(&builder.config.host_target.triple)
3578 .opt_level(0)
3579 .warnings(false)
3580 .debug(false)
3581 .file(builder.src.join("tests/auxiliary/rust_test_helpers.c"))
3582 .compile("rust_test_helpers");
3583 }
3584}
3585
3586#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3587pub struct CodegenCranelift {
3588 compilers: RustcPrivateCompilers,
3589 target: TargetSelection,
3590}
3591
3592impl Step for CodegenCranelift {
3593 type Output = ();
3594 const DEFAULT: bool = true;
3595 const IS_HOST: bool = true;
3596
3597 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3598 run.paths(&["compiler/rustc_codegen_cranelift"])
3599 }
3600
3601 fn make_run(run: RunConfig<'_>) {
3602 let builder = run.builder;
3603 let host = run.build_triple();
3604 let compilers = RustcPrivateCompilers::new(run.builder, run.builder.top_stage, host);
3605
3606 if builder.doc_tests == DocTests::Only {
3607 return;
3608 }
3609
3610 if builder.download_rustc() {
3611 builder.info("CI rustc uses the default codegen backend. skipping");
3612 return;
3613 }
3614
3615 if !target_supports_cranelift_backend(run.target) {
3616 builder.info("target not supported by rustc_codegen_cranelift. skipping");
3617 return;
3618 }
3619
3620 if builder.remote_tested(run.target) {
3621 builder.info("remote testing is not supported by rustc_codegen_cranelift. skipping");
3622 return;
3623 }
3624
3625 if !builder
3626 .config
3627 .enabled_codegen_backends(run.target)
3628 .contains(&CodegenBackendKind::Cranelift)
3629 {
3630 builder.info("cranelift not in rust.codegen-backends. skipping");
3631 return;
3632 }
3633
3634 builder.ensure(CodegenCranelift { compilers, target: run.target });
3635 }
3636
3637 fn run(self, builder: &Builder<'_>) {
3638 let compilers = self.compilers;
3639 let build_compiler = compilers.build_compiler();
3640
3641 let target_compiler = compilers.target_compiler();
3644 let target = self.target;
3645
3646 builder.std(target_compiler, target);
3647
3648 let mut cargo = builder::Cargo::new(
3649 builder,
3650 target_compiler,
3651 Mode::Codegen, SourceType::InTree,
3653 target,
3654 Kind::Run,
3655 );
3656
3657 cargo.current_dir(&builder.src.join("compiler/rustc_codegen_cranelift"));
3658 cargo
3659 .arg("--manifest-path")
3660 .arg(builder.src.join("compiler/rustc_codegen_cranelift/build_system/Cargo.toml"));
3661 compile::rustc_cargo_env(builder, &mut cargo, target);
3662
3663 cargo.env("CARGO_BUILD_INCREMENTAL", "false");
3665
3666 let _guard = builder.msg_test(
3667 "rustc_codegen_cranelift",
3668 target_compiler.host,
3669 target_compiler.stage,
3670 );
3671
3672 let download_dir = builder.out.join("cg_clif_download");
3674
3675 cargo
3676 .arg("--")
3677 .arg("test")
3678 .arg("--download-dir")
3679 .arg(&download_dir)
3680 .arg("--out-dir")
3681 .arg(builder.stage_out(build_compiler, Mode::Codegen).join("cg_clif"))
3682 .arg("--no-unstable-features")
3683 .arg("--use-backend")
3684 .arg("cranelift")
3685 .arg("--sysroot")
3687 .arg("llvm")
3688 .arg("--skip-test")
3691 .arg("testsuite.extended_sysroot");
3692
3693 cargo.into_cmd().run(builder);
3694 }
3695
3696 fn metadata(&self) -> Option<StepMetadata> {
3697 Some(
3698 StepMetadata::test("rustc_codegen_cranelift", self.target)
3699 .built_by(self.compilers.build_compiler()),
3700 )
3701 }
3702}
3703
3704#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3705pub struct CodegenGCC {
3706 compilers: RustcPrivateCompilers,
3707 target: TargetSelection,
3708}
3709
3710impl Step for CodegenGCC {
3711 type Output = ();
3712 const DEFAULT: bool = true;
3713 const IS_HOST: bool = true;
3714
3715 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3716 run.paths(&["compiler/rustc_codegen_gcc"])
3717 }
3718
3719 fn make_run(run: RunConfig<'_>) {
3720 let builder = run.builder;
3721 let host = run.build_triple();
3722 let compilers = RustcPrivateCompilers::new(run.builder, run.builder.top_stage, host);
3723
3724 if builder.doc_tests == DocTests::Only {
3725 return;
3726 }
3727
3728 if builder.download_rustc() {
3729 builder.info("CI rustc uses the default codegen backend. skipping");
3730 return;
3731 }
3732
3733 let triple = run.target.triple;
3734 let target_supported =
3735 if triple.contains("linux") { triple.contains("x86_64") } else { false };
3736 if !target_supported {
3737 builder.info("target not supported by rustc_codegen_gcc. skipping");
3738 return;
3739 }
3740
3741 if builder.remote_tested(run.target) {
3742 builder.info("remote testing is not supported by rustc_codegen_gcc. skipping");
3743 return;
3744 }
3745
3746 if !builder.config.enabled_codegen_backends(run.target).contains(&CodegenBackendKind::Gcc) {
3747 builder.info("gcc not in rust.codegen-backends. skipping");
3748 return;
3749 }
3750
3751 builder.ensure(CodegenGCC { compilers, target: run.target });
3752 }
3753
3754 fn run(self, builder: &Builder<'_>) {
3755 let compilers = self.compilers;
3756 let target = self.target;
3757
3758 let gcc = builder.ensure(Gcc { target });
3759
3760 builder.ensure(
3761 compile::Std::new(compilers.build_compiler(), target)
3762 .extra_rust_args(&["-Csymbol-mangling-version=v0", "-Cpanic=abort"]),
3763 );
3764
3765 let _guard = builder.msg_test(
3766 "rustc_codegen_gcc",
3767 compilers.target(),
3768 compilers.target_compiler().stage,
3769 );
3770
3771 let mut cargo = builder::Cargo::new(
3772 builder,
3773 compilers.build_compiler(),
3774 Mode::Codegen, SourceType::InTree,
3776 target,
3777 Kind::Run,
3778 );
3779
3780 cargo.current_dir(&builder.src.join("compiler/rustc_codegen_gcc"));
3781 cargo
3782 .arg("--manifest-path")
3783 .arg(builder.src.join("compiler/rustc_codegen_gcc/build_system/Cargo.toml"));
3784 compile::rustc_cargo_env(builder, &mut cargo, target);
3785 add_cg_gcc_cargo_flags(&mut cargo, &gcc);
3786
3787 cargo.env("CARGO_BUILD_INCREMENTAL", "false");
3789 cargo.rustflag("-Cpanic=abort");
3790
3791 cargo
3792 .env("CG_RUSTFLAGS", "-Alinker-messages")
3794 .arg("--")
3795 .arg("test")
3796 .arg("--use-backend")
3797 .arg("gcc")
3798 .arg("--gcc-path")
3799 .arg(gcc.libgccjit.parent().unwrap())
3800 .arg("--out-dir")
3801 .arg(builder.stage_out(compilers.build_compiler(), Mode::Codegen).join("cg_gcc"))
3802 .arg("--release")
3803 .arg("--mini-tests")
3804 .arg("--std-tests");
3805 cargo.args(builder.config.test_args());
3806
3807 cargo.into_cmd().run(builder);
3808 }
3809
3810 fn metadata(&self) -> Option<StepMetadata> {
3811 Some(
3812 StepMetadata::test("rustc_codegen_gcc", self.target)
3813 .built_by(self.compilers.build_compiler()),
3814 )
3815 }
3816}
3817
3818#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3823pub struct TestFloatParse {
3824 build_compiler: Compiler,
3833 target: TargetSelection,
3835}
3836
3837impl Step for TestFloatParse {
3838 type Output = ();
3839 const IS_HOST: bool = true;
3840 const DEFAULT: bool = true;
3841
3842 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3843 run.path("src/tools/test-float-parse")
3844 }
3845
3846 fn make_run(run: RunConfig<'_>) {
3847 run.builder.ensure(Self {
3848 build_compiler: get_compiler_to_test(run.builder, run.target),
3849 target: run.target,
3850 });
3851 }
3852
3853 fn run(self, builder: &Builder<'_>) {
3854 let build_compiler = self.build_compiler;
3855 let target = self.target;
3856
3857 builder.std(build_compiler, target);
3859 builder.std(build_compiler, builder.host_target);
3860
3861 let mut cargo_test = tool::prepare_tool_cargo(
3863 builder,
3864 build_compiler,
3865 Mode::ToolStd,
3866 target,
3867 Kind::Test,
3868 "src/tools/test-float-parse",
3869 SourceType::InTree,
3870 &[],
3871 );
3872 cargo_test.allow_features(TEST_FLOAT_PARSE_ALLOW_FEATURES);
3873
3874 run_cargo_test(cargo_test, &[], &[], "test-float-parse", target, builder);
3875
3876 let mut cargo_run = tool::prepare_tool_cargo(
3878 builder,
3879 build_compiler,
3880 Mode::ToolStd,
3881 target,
3882 Kind::Run,
3883 "src/tools/test-float-parse",
3884 SourceType::InTree,
3885 &[],
3886 );
3887 cargo_run.allow_features(TEST_FLOAT_PARSE_ALLOW_FEATURES);
3888
3889 if !matches!(env::var("FLOAT_PARSE_TESTS_NO_SKIP_HUGE").as_deref(), Ok("1") | Ok("true")) {
3890 cargo_run.args(["--", "--skip-huge"]);
3891 }
3892
3893 cargo_run.into_cmd().run(builder);
3894 }
3895}
3896
3897#[derive(Debug, Clone, Hash, PartialEq, Eq)]
3901pub struct CollectLicenseMetadata;
3902
3903impl Step for CollectLicenseMetadata {
3904 type Output = PathBuf;
3905 const IS_HOST: bool = true;
3906
3907 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3908 run.path("src/tools/collect-license-metadata")
3909 }
3910
3911 fn make_run(run: RunConfig<'_>) {
3912 run.builder.ensure(CollectLicenseMetadata);
3913 }
3914
3915 fn run(self, builder: &Builder<'_>) -> Self::Output {
3916 let Some(reuse) = &builder.config.reuse else {
3917 panic!("REUSE is required to collect the license metadata");
3918 };
3919
3920 let dest = builder.src.join("license-metadata.json");
3921
3922 let mut cmd = builder.tool_cmd(Tool::CollectLicenseMetadata);
3923 cmd.env("REUSE_EXE", reuse);
3924 cmd.env("DEST", &dest);
3925 cmd.env("ONLY_CHECK", "1");
3926 cmd.run(builder);
3927
3928 dest
3929 }
3930}