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::ToolRustc,
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::ToolRustc,
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 = builder.msg(Kind::Build, "miri sysroot", Mode::ToolRustc, compiler, target);
575 cargo.run(builder);
576
577 cargo.arg("--print-sysroot");
583
584 builder.verbose(|| println!("running: {cargo:?}"));
585 let stdout = cargo.run_capture_stdout(builder).stdout();
586 let sysroot = stdout.trim_end();
588 builder.verbose(|| println!("`cargo miri setup --print-sysroot` said: {sysroot:?}"));
589 PathBuf::from(sysroot)
590 }
591}
592
593impl Step for Miri {
594 type Output = ();
595
596 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
597 run.path("src/tools/miri")
598 }
599
600 fn make_run(run: RunConfig<'_>) {
601 run.builder.ensure(Miri { target: run.target });
602 }
603
604 fn run(self, builder: &Builder<'_>) {
606 let host = builder.build.host_target;
607 let target = self.target;
608 let stage = builder.top_stage;
609 if stage == 0 {
610 eprintln!("miri cannot be tested at stage 0");
611 std::process::exit(1);
612 }
613
614 let compilers = RustcPrivateCompilers::new(builder, stage, host);
616
617 let miri = builder.ensure(tool::Miri::from_compilers(compilers));
619 builder.ensure(tool::CargoMiri::from_compilers(compilers));
621
622 let target_compiler = compilers.target_compiler();
623
624 let miri_sysroot = Miri::build_miri_sysroot(builder, target_compiler, target);
627 builder.std(target_compiler, host);
628 let host_sysroot = builder.sysroot(target_compiler);
629
630 if !builder.config.dry_run() {
633 let ui_test_dep_dir = builder
636 .stage_out(miri.build_compiler, Mode::ToolStd)
637 .join(host)
638 .join("tmp")
639 .join("miri_ui");
640 build_stamp::clear_if_dirty(builder, &ui_test_dep_dir, &miri_sysroot);
644 }
645
646 let mut cargo = tool::prepare_tool_cargo(
649 builder,
650 miri.build_compiler,
651 Mode::ToolRustc,
652 host,
653 Kind::Test,
654 "src/tools/miri",
655 SourceType::InTree,
656 &[],
657 );
658
659 cargo.add_rustc_lib_path(builder);
660
661 let mut cargo = prepare_cargo_test(cargo, &[], &[], host, builder);
664
665 cargo.env("MIRI_SYSROOT", &miri_sysroot);
667 cargo.env("MIRI_HOST_SYSROOT", &host_sysroot);
668 cargo.env("MIRI", &miri.tool_path);
669
670 cargo.env("MIRI_TEST_TARGET", target.rustc_target_arg());
672
673 {
674 let _guard = builder.msg_test("miri", target, target_compiler.stage);
675 let _time = helpers::timeit(builder);
676 cargo.run(builder);
677 }
678
679 if builder.config.test_args().is_empty() {
681 cargo.env("MIRIFLAGS", "-O -Zmir-opt-level=4 -Cdebug-assertions=yes");
682 cargo.env("MIRI_SKIP_UI_CHECKS", "1");
684 cargo.env_remove("RUSTC_BLESS");
686 cargo.args(["tests/pass", "tests/panic"]);
688
689 {
690 let _guard =
691 builder.msg_test("miri (mir-opt-level 4)", target, target_compiler.stage);
692 let _time = helpers::timeit(builder);
693 cargo.run(builder);
694 }
695 }
696 }
697}
698
699#[derive(Debug, Clone, PartialEq, Eq, Hash)]
702pub struct CargoMiri {
703 target: TargetSelection,
704}
705
706impl Step for CargoMiri {
707 type Output = ();
708
709 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
710 run.path("src/tools/miri/cargo-miri")
711 }
712
713 fn make_run(run: RunConfig<'_>) {
714 run.builder.ensure(CargoMiri { target: run.target });
715 }
716
717 fn run(self, builder: &Builder<'_>) {
719 let host = builder.build.host_target;
720 let target = self.target;
721 let stage = builder.top_stage;
722 if stage == 0 {
723 eprintln!("cargo-miri cannot be tested at stage 0");
724 std::process::exit(1);
725 }
726
727 let build_compiler = builder.compiler(stage, host);
729
730 let mut cargo = tool::prepare_tool_cargo(
735 builder,
736 build_compiler,
737 Mode::ToolStd, target,
739 Kind::MiriTest,
740 "src/tools/miri/test-cargo-miri",
741 SourceType::Submodule,
742 &[],
743 );
744
745 match builder.doc_tests {
748 DocTests::Yes => {}
749 DocTests::No => {
750 cargo.args(["--lib", "--bins", "--examples", "--tests", "--benches"]);
751 }
752 DocTests::Only => {
753 cargo.arg("--doc");
754 }
755 }
756 cargo.arg("--").args(builder.config.test_args());
757
758 let mut cargo = BootstrapCommand::from(cargo);
760 {
761 let _guard = builder.msg_test("cargo-miri", target, stage);
762 let _time = helpers::timeit(builder);
763 cargo.run(builder);
764 }
765 }
766}
767
768#[derive(Debug, Clone, PartialEq, Eq, Hash)]
769pub struct CompiletestTest {
770 host: TargetSelection,
771}
772
773impl Step for CompiletestTest {
774 type Output = ();
775
776 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
777 run.path("src/tools/compiletest")
778 }
779
780 fn make_run(run: RunConfig<'_>) {
781 run.builder.ensure(CompiletestTest { host: run.target });
782 }
783
784 fn run(self, builder: &Builder<'_>) {
786 let host = self.host;
787
788 if builder.top_stage == 0 && !builder.config.compiletest_allow_stage0 {
789 eprintln!("\
790ERROR: `--stage 0` runs compiletest self-tests against the stage0 (precompiled) compiler, not the in-tree compiler, and will almost always cause tests to fail
791NOTE: 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`."
792 );
793 crate::exit!(1);
794 }
795
796 let compiler = builder.compiler(builder.top_stage, host);
797 debug!(?compiler);
798
799 builder.std(compiler, host);
802 let mut cargo = tool::prepare_tool_cargo(
803 builder,
804 compiler,
805 Mode::ToolStd,
808 host,
809 Kind::Test,
810 "src/tools/compiletest",
811 SourceType::InTree,
812 &[],
813 );
814
815 cargo.env("TEST_RUSTC", builder.rustc(compiler));
819
820 cargo.allow_features(COMPILETEST_ALLOW_FEATURES);
821 run_cargo_test(cargo, &[], &[], "compiletest self test", host, builder);
822 }
823}
824
825#[derive(Debug, Clone, PartialEq, Eq, Hash)]
826pub struct Clippy {
827 compilers: RustcPrivateCompilers,
828}
829
830impl Step for Clippy {
831 type Output = ();
832 const IS_HOST: bool = true;
833 const DEFAULT: bool = false;
834
835 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
836 run.suite_path("src/tools/clippy/tests").path("src/tools/clippy")
837 }
838
839 fn make_run(run: RunConfig<'_>) {
840 run.builder.ensure(Clippy {
841 compilers: RustcPrivateCompilers::new(
842 run.builder,
843 run.builder.top_stage,
844 run.builder.host_target,
845 ),
846 });
847 }
848
849 fn run(self, builder: &Builder<'_>) {
851 let target = self.compilers.target();
852
853 let compilers = self.compilers;
857 let target_compiler = compilers.target_compiler();
858
859 let tool_result = builder.ensure(tool::Clippy::from_compilers(compilers));
860 let build_compiler = tool_result.build_compiler;
861 let mut cargo = tool::prepare_tool_cargo(
862 builder,
863 build_compiler,
864 Mode::ToolRustc,
865 target,
866 Kind::Test,
867 "src/tools/clippy",
868 SourceType::InTree,
869 &[],
870 );
871
872 cargo.env("RUSTC_TEST_SUITE", builder.rustc(build_compiler));
873 cargo.env("RUSTC_LIB_PATH", builder.rustc_libdir(build_compiler));
874 let host_libs =
875 builder.stage_out(build_compiler, Mode::ToolRustc).join(builder.cargo_dir());
876 cargo.env("HOST_LIBS", host_libs);
877
878 builder.std(target_compiler, target);
880 cargo.env("TEST_SYSROOT", builder.sysroot(target_compiler));
881 cargo.env("TEST_RUSTC", builder.rustc(target_compiler));
882 cargo.env("TEST_RUSTC_LIB", builder.rustc_libdir(target_compiler));
883
884 'partially_test: {
886 let paths = &builder.config.paths[..];
887 let mut test_names = Vec::new();
888 for path in paths {
889 if let Some(path) =
890 helpers::is_valid_test_suite_arg(path, "src/tools/clippy/tests", builder)
891 {
892 test_names.push(path);
893 } else if path.ends_with("src/tools/clippy") {
894 break 'partially_test;
896 }
897 }
898 cargo.env("TESTNAME", test_names.join(","));
899 }
900
901 cargo.add_rustc_lib_path(builder);
902 let cargo = prepare_cargo_test(cargo, &[], &[], target, builder);
903
904 let _guard = builder.msg_test("clippy", target, target_compiler.stage);
905
906 if cargo.allow_failure().run(builder) {
908 return;
910 }
911
912 if !builder.config.cmd.bless() {
913 crate::exit!(1);
914 }
915 }
916
917 fn metadata(&self) -> Option<StepMetadata> {
918 Some(
919 StepMetadata::test("clippy", self.compilers.target())
920 .built_by(self.compilers.build_compiler()),
921 )
922 }
923}
924
925fn bin_path_for_cargo(builder: &Builder<'_>, compiler: Compiler) -> OsString {
926 let path = builder.sysroot(compiler).join("bin");
927 let old_path = env::var_os("PATH").unwrap_or_default();
928 env::join_paths(iter::once(path).chain(env::split_paths(&old_path))).expect("")
929}
930
931#[derive(Debug, Clone, Hash, PartialEq, Eq)]
933pub struct RustdocTheme {
934 test_compiler: Compiler,
936}
937
938impl Step for RustdocTheme {
939 type Output = ();
940 const DEFAULT: bool = true;
941 const IS_HOST: bool = true;
942
943 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
944 run.path("src/tools/rustdoc-themes")
945 }
946
947 fn make_run(run: RunConfig<'_>) {
948 let test_compiler = run.builder.compiler(run.builder.top_stage, run.target);
949
950 run.builder.ensure(RustdocTheme { test_compiler });
951 }
952
953 fn run(self, builder: &Builder<'_>) {
954 let rustdoc = builder.bootstrap_out.join("rustdoc");
955 let mut cmd = builder.tool_cmd(Tool::RustdocTheme);
956 cmd.arg(rustdoc.to_str().unwrap())
957 .arg(builder.src.join("src/librustdoc/html/static/css/rustdoc.css").to_str().unwrap())
958 .env("RUSTC_STAGE", self.test_compiler.stage.to_string())
959 .env("RUSTC_SYSROOT", builder.sysroot(self.test_compiler))
960 .env(
961 "RUSTDOC_LIBDIR",
962 builder.sysroot_target_libdir(self.test_compiler, self.test_compiler.host),
963 )
964 .env("CFG_RELEASE_CHANNEL", &builder.config.channel)
965 .env("RUSTDOC_REAL", builder.rustdoc_for_compiler(self.test_compiler))
966 .env("RUSTC_BOOTSTRAP", "1");
967 cmd.args(linker_args(builder, self.test_compiler.host, LldThreads::No));
968
969 cmd.delay_failure().run(builder);
970 }
971
972 fn metadata(&self) -> Option<StepMetadata> {
973 Some(
974 StepMetadata::test("rustdoc-theme", self.test_compiler.host)
975 .stage(self.test_compiler.stage),
976 )
977 }
978}
979
980#[derive(Debug, Clone, Hash, PartialEq, Eq)]
982pub struct RustdocJSStd {
983 build_compiler: Compiler,
985 target: TargetSelection,
986}
987
988impl Step for RustdocJSStd {
989 type Output = ();
990 const DEFAULT: bool = true;
991 const IS_HOST: bool = true;
992
993 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
994 let default = run.builder.config.nodejs.is_some();
995 run.suite_path("tests/rustdoc-js-std").default_condition(default)
996 }
997
998 fn make_run(run: RunConfig<'_>) {
999 run.builder.ensure(RustdocJSStd {
1000 build_compiler: run.builder.compiler(run.builder.top_stage, run.builder.host_target),
1001 target: run.target,
1002 });
1003 }
1004
1005 fn run(self, builder: &Builder<'_>) {
1006 let nodejs =
1007 builder.config.nodejs.as_ref().expect("need nodejs to run rustdoc-js-std tests");
1008 let mut command = command(nodejs);
1009 command
1010 .arg(builder.src.join("src/tools/rustdoc-js/tester.js"))
1011 .arg("--crate-name")
1012 .arg("std")
1013 .arg("--resource-suffix")
1014 .arg(&builder.version)
1015 .arg("--doc-folder")
1016 .arg(builder.doc_out(self.target))
1017 .arg("--test-folder")
1018 .arg(builder.src.join("tests/rustdoc-js-std"));
1019 for path in &builder.paths {
1020 if let Some(p) = helpers::is_valid_test_suite_arg(path, "tests/rustdoc-js-std", builder)
1021 {
1022 if !p.ends_with(".js") {
1023 eprintln!("A non-js file was given: `{}`", path.display());
1024 panic!("Cannot run rustdoc-js-std tests");
1025 }
1026 command.arg("--test-file").arg(path);
1027 }
1028 }
1029 builder.ensure(crate::core::build_steps::doc::Std::from_build_compiler(
1030 self.build_compiler,
1031 self.target,
1032 DocumentationFormat::Html,
1033 ));
1034 let _guard = builder.msg_test("rustdoc-js-std", self.target, self.build_compiler.stage);
1035 command.run(builder);
1036 }
1037
1038 fn metadata(&self) -> Option<StepMetadata> {
1039 Some(StepMetadata::test("rustdoc-js-std", self.target).stage(self.build_compiler.stage))
1040 }
1041}
1042
1043#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1044pub struct RustdocJSNotStd {
1045 pub target: TargetSelection,
1046 pub compiler: Compiler,
1047}
1048
1049impl Step for RustdocJSNotStd {
1050 type Output = ();
1051 const DEFAULT: bool = true;
1052 const IS_HOST: bool = true;
1053
1054 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1055 let default = run.builder.config.nodejs.is_some();
1056 run.suite_path("tests/rustdoc-js").default_condition(default)
1057 }
1058
1059 fn make_run(run: RunConfig<'_>) {
1060 let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1061 run.builder.ensure(RustdocJSNotStd { target: run.target, compiler });
1062 }
1063
1064 fn run(self, builder: &Builder<'_>) {
1065 builder.ensure(Compiletest {
1066 test_compiler: self.compiler,
1067 target: self.target,
1068 mode: "rustdoc-js",
1069 suite: "rustdoc-js",
1070 path: "tests/rustdoc-js",
1071 compare_mode: None,
1072 });
1073 }
1074}
1075
1076fn get_browser_ui_test_version_inner(
1077 builder: &Builder<'_>,
1078 npm: &Path,
1079 global: bool,
1080) -> Option<String> {
1081 let mut command = command(npm);
1082 command.arg("list").arg("--parseable").arg("--long").arg("--depth=0");
1083 if global {
1084 command.arg("--global");
1085 }
1086 let lines = command.allow_failure().run_capture(builder).stdout();
1087 lines
1088 .lines()
1089 .find_map(|l| l.split(':').nth(1)?.strip_prefix("browser-ui-test@"))
1090 .map(|v| v.to_owned())
1091}
1092
1093fn get_browser_ui_test_version(builder: &Builder<'_>, npm: &Path) -> Option<String> {
1094 get_browser_ui_test_version_inner(builder, npm, false)
1095 .or_else(|| get_browser_ui_test_version_inner(builder, npm, true))
1096}
1097
1098#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1100pub struct RustdocGUI {
1101 test_compiler: Compiler,
1103 target: TargetSelection,
1104}
1105
1106impl Step for RustdocGUI {
1107 type Output = ();
1108 const DEFAULT: bool = true;
1109 const IS_HOST: bool = true;
1110
1111 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1112 let builder = run.builder;
1113 let run = run.suite_path("tests/rustdoc-gui");
1114 run.lazy_default_condition(Box::new(move || {
1115 builder.config.nodejs.is_some()
1116 && builder.doc_tests != DocTests::Only
1117 && builder
1118 .config
1119 .npm
1120 .as_ref()
1121 .map(|p| get_browser_ui_test_version(builder, p).is_some())
1122 .unwrap_or(false)
1123 }))
1124 }
1125
1126 fn make_run(run: RunConfig<'_>) {
1127 let test_compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1128 run.builder.ensure(RustdocGUI { test_compiler, target: run.target });
1129 }
1130
1131 fn run(self, builder: &Builder<'_>) {
1132 builder.std(self.test_compiler, self.target);
1133
1134 let mut cmd = builder.tool_cmd(Tool::RustdocGUITest);
1135
1136 let out_dir = builder.test_out(self.target).join("rustdoc-gui");
1137 build_stamp::clear_if_dirty(
1138 builder,
1139 &out_dir,
1140 &builder.rustdoc_for_compiler(self.test_compiler),
1141 );
1142
1143 if let Some(src) = builder.config.src.to_str() {
1144 cmd.arg("--rust-src").arg(src);
1145 }
1146
1147 if let Some(out_dir) = out_dir.to_str() {
1148 cmd.arg("--out-dir").arg(out_dir);
1149 }
1150
1151 if let Some(initial_cargo) = builder.config.initial_cargo.to_str() {
1152 cmd.arg("--initial-cargo").arg(initial_cargo);
1153 }
1154
1155 cmd.arg("--jobs").arg(builder.jobs().to_string());
1156
1157 cmd.env("RUSTDOC", builder.rustdoc_for_compiler(self.test_compiler))
1158 .env("RUSTC", builder.rustc(self.test_compiler));
1159
1160 add_rustdoc_cargo_linker_args(&mut cmd, builder, self.test_compiler.host, LldThreads::No);
1161
1162 for path in &builder.paths {
1163 if let Some(p) = helpers::is_valid_test_suite_arg(path, "tests/rustdoc-gui", builder) {
1164 if !p.ends_with(".goml") {
1165 eprintln!("A non-goml file was given: `{}`", path.display());
1166 panic!("Cannot run rustdoc-gui tests");
1167 }
1168 if let Some(name) = path.file_name().and_then(|f| f.to_str()) {
1169 cmd.arg("--goml-file").arg(name);
1170 }
1171 }
1172 }
1173
1174 for test_arg in builder.config.test_args() {
1175 cmd.arg("--test-arg").arg(test_arg);
1176 }
1177
1178 if let Some(ref nodejs) = builder.config.nodejs {
1179 cmd.arg("--nodejs").arg(nodejs);
1180 }
1181
1182 if let Some(ref npm) = builder.config.npm {
1183 cmd.arg("--npm").arg(npm);
1184 }
1185
1186 let _time = helpers::timeit(builder);
1187 let _guard = builder.msg_test("rustdoc-gui", self.target, self.test_compiler.stage);
1188 try_run_tests(builder, &mut cmd, true);
1189 }
1190
1191 fn metadata(&self) -> Option<StepMetadata> {
1192 Some(StepMetadata::test("rustdoc-gui", self.target).stage(self.test_compiler.stage))
1193 }
1194}
1195
1196#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1201pub struct Tidy;
1202
1203impl Step for Tidy {
1204 type Output = ();
1205 const DEFAULT: bool = true;
1206 const IS_HOST: bool = true;
1207
1208 fn run(self, builder: &Builder<'_>) {
1217 let mut cmd = builder.tool_cmd(Tool::Tidy);
1218 cmd.arg(&builder.src);
1219 cmd.arg(&builder.initial_cargo);
1220 cmd.arg(&builder.out);
1221 let jobs = builder.config.jobs.unwrap_or_else(|| {
1223 8 * std::thread::available_parallelism().map_or(1, std::num::NonZeroUsize::get) as u32
1224 });
1225 cmd.arg(jobs.to_string());
1226 if let Some(npm) = &builder.config.npm {
1228 cmd.arg(npm);
1229 } else {
1230 cmd.arg("npm");
1231 }
1232 if builder.is_verbose() {
1233 cmd.arg("--verbose");
1234 }
1235 if builder.config.cmd.bless() {
1236 cmd.arg("--bless");
1237 }
1238 if let Some(s) =
1239 builder.config.cmd.extra_checks().or(builder.config.tidy_extra_checks.as_deref())
1240 {
1241 cmd.arg(format!("--extra-checks={s}"));
1242 }
1243 let mut args = std::env::args_os();
1244 if args.any(|arg| arg == OsStr::new("--")) {
1245 cmd.arg("--");
1246 cmd.args(args);
1247 }
1248
1249 if builder.config.channel == "dev" || builder.config.channel == "nightly" {
1250 if !builder.config.json_output {
1251 builder.info("fmt check");
1252 if builder.config.initial_rustfmt.is_none() {
1253 let inferred_rustfmt_dir = builder.initial_sysroot.join("bin");
1254 eprintln!(
1255 "\
1256ERROR: no `rustfmt` binary found in {PATH}
1257INFO: `rust.channel` is currently set to \"{CHAN}\"
1258HELP: if you are testing a beta branch, set `rust.channel` to \"beta\" in the `bootstrap.toml` file
1259HELP: to skip test's attempt to check tidiness, pass `--skip src/tools/tidy` to `x.py test`",
1260 PATH = inferred_rustfmt_dir.display(),
1261 CHAN = builder.config.channel,
1262 );
1263 crate::exit!(1);
1264 }
1265 let all = false;
1266 crate::core::build_steps::format::format(
1267 builder,
1268 !builder.config.cmd.bless(),
1269 all,
1270 &[],
1271 );
1272 } else {
1273 eprintln!(
1274 "WARNING: `--json-output` is not supported on rustfmt, formatting will be skipped"
1275 );
1276 }
1277 }
1278
1279 builder.info("tidy check");
1280 cmd.delay_failure().run(builder);
1281
1282 builder.info("x.py completions check");
1283 let completion_paths = get_completion_paths(builder);
1284 if builder.config.cmd.bless() {
1285 builder.ensure(crate::core::build_steps::run::GenerateCompletions);
1286 } else if completion_paths
1287 .into_iter()
1288 .any(|(shell, path)| get_completion(shell, &path).is_some())
1289 {
1290 eprintln!(
1291 "x.py completions were changed; run `x.py run generate-completions` to update them"
1292 );
1293 crate::exit!(1);
1294 }
1295 }
1296
1297 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1298 let default = run.builder.doc_tests != DocTests::Only;
1299 run.path("src/tools/tidy").default_condition(default)
1300 }
1301
1302 fn make_run(run: RunConfig<'_>) {
1303 run.builder.ensure(Tidy);
1304 }
1305
1306 fn metadata(&self) -> Option<StepMetadata> {
1307 Some(StepMetadata::test("tidy", TargetSelection::default()))
1308 }
1309}
1310
1311#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1314pub struct CrateRunMakeSupport {
1315 host: TargetSelection,
1316}
1317
1318impl Step for CrateRunMakeSupport {
1319 type Output = ();
1320 const IS_HOST: bool = true;
1321
1322 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1323 run.path("src/tools/run-make-support")
1324 }
1325
1326 fn make_run(run: RunConfig<'_>) {
1327 run.builder.ensure(CrateRunMakeSupport { host: run.target });
1328 }
1329
1330 fn run(self, builder: &Builder<'_>) {
1332 let host = self.host;
1333 let compiler = builder.compiler(0, host);
1334
1335 let mut cargo = tool::prepare_tool_cargo(
1336 builder,
1337 compiler,
1338 Mode::ToolBootstrap,
1339 host,
1340 Kind::Test,
1341 "src/tools/run-make-support",
1342 SourceType::InTree,
1343 &[],
1344 );
1345 cargo.allow_features("test");
1346 run_cargo_test(cargo, &[], &[], "run-make-support self test", host, builder);
1347 }
1348}
1349
1350#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1351pub struct CrateBuildHelper {
1352 host: TargetSelection,
1353}
1354
1355impl Step for CrateBuildHelper {
1356 type Output = ();
1357 const IS_HOST: bool = true;
1358
1359 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1360 run.path("src/build_helper")
1361 }
1362
1363 fn make_run(run: RunConfig<'_>) {
1364 run.builder.ensure(CrateBuildHelper { host: run.target });
1365 }
1366
1367 fn run(self, builder: &Builder<'_>) {
1369 let host = self.host;
1370 let compiler = builder.compiler(0, host);
1371
1372 let mut cargo = tool::prepare_tool_cargo(
1373 builder,
1374 compiler,
1375 Mode::ToolBootstrap,
1376 host,
1377 Kind::Test,
1378 "src/build_helper",
1379 SourceType::InTree,
1380 &[],
1381 );
1382 cargo.allow_features("test");
1383 run_cargo_test(cargo, &[], &[], "build_helper self test", host, builder);
1384 }
1385}
1386
1387fn testdir(builder: &Builder<'_>, host: TargetSelection) -> PathBuf {
1388 builder.out.join(host).join("test")
1389}
1390
1391macro_rules! test {
1393 (
1394 $( #[$attr:meta] )* $name:ident {
1396 path: $path:expr,
1397 mode: $mode:expr,
1398 suite: $suite:expr,
1399 default: $default:expr
1400 $( , IS_HOST: $IS_HOST:expr )? $( , compare_mode: $compare_mode:expr )? $( , )? }
1404 ) => {
1405 $( #[$attr] )*
1406 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
1407 pub struct $name {
1408 test_compiler: Compiler,
1409 target: TargetSelection,
1410 }
1411
1412 impl Step for $name {
1413 type Output = ();
1414 const DEFAULT: bool = $default;
1415 const IS_HOST: bool = (const {
1416 #[allow(unused_assignments, unused_mut)]
1417 let mut value = false;
1418 $( value = $IS_HOST; )?
1419 value
1420 });
1421
1422 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1423 run.suite_path($path)
1424 }
1425
1426 fn make_run(run: RunConfig<'_>) {
1427 let test_compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1428
1429 run.builder.ensure($name { test_compiler, target: run.target });
1430 }
1431
1432 fn run(self, builder: &Builder<'_>) {
1433 builder.ensure(Compiletest {
1434 test_compiler: self.test_compiler,
1435 target: self.target,
1436 mode: $mode,
1437 suite: $suite,
1438 path: $path,
1439 compare_mode: (const {
1440 #[allow(unused_assignments, unused_mut)]
1441 let mut value = None;
1442 $( value = $compare_mode; )?
1443 value
1444 }),
1445 })
1446 }
1447 }
1448 };
1449}
1450
1451test!(Ui { path: "tests/ui", mode: "ui", suite: "ui", default: true });
1452
1453test!(Crashes { path: "tests/crashes", mode: "crashes", suite: "crashes", default: true });
1454
1455test!(CodegenLlvm {
1456 path: "tests/codegen-llvm",
1457 mode: "codegen",
1458 suite: "codegen-llvm",
1459 default: true
1460});
1461
1462test!(CodegenUnits {
1463 path: "tests/codegen-units",
1464 mode: "codegen-units",
1465 suite: "codegen-units",
1466 default: true,
1467});
1468
1469test!(Incremental {
1470 path: "tests/incremental",
1471 mode: "incremental",
1472 suite: "incremental",
1473 default: true,
1474});
1475
1476test!(Debuginfo {
1477 path: "tests/debuginfo",
1478 mode: "debuginfo",
1479 suite: "debuginfo",
1480 default: true,
1481 compare_mode: Some("split-dwarf"),
1482});
1483
1484test!(UiFullDeps {
1485 path: "tests/ui-fulldeps",
1486 mode: "ui",
1487 suite: "ui-fulldeps",
1488 default: true,
1489 IS_HOST: true,
1490});
1491
1492test!(Rustdoc {
1493 path: "tests/rustdoc",
1494 mode: "rustdoc",
1495 suite: "rustdoc",
1496 default: true,
1497 IS_HOST: true,
1498});
1499test!(RustdocUi {
1500 path: "tests/rustdoc-ui",
1501 mode: "ui",
1502 suite: "rustdoc-ui",
1503 default: true,
1504 IS_HOST: true,
1505});
1506
1507test!(RustdocJson {
1508 path: "tests/rustdoc-json",
1509 mode: "rustdoc-json",
1510 suite: "rustdoc-json",
1511 default: true,
1512 IS_HOST: true,
1513});
1514
1515test!(Pretty {
1516 path: "tests/pretty",
1517 mode: "pretty",
1518 suite: "pretty",
1519 default: true,
1520 IS_HOST: true,
1521});
1522
1523test!(RunMake { path: "tests/run-make", mode: "run-make", suite: "run-make", default: true });
1524
1525test!(AssemblyLlvm {
1526 path: "tests/assembly-llvm",
1527 mode: "assembly",
1528 suite: "assembly-llvm",
1529 default: true
1530});
1531
1532#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
1535pub struct Coverage {
1536 pub compiler: Compiler,
1537 pub target: TargetSelection,
1538 pub mode: &'static str,
1539}
1540
1541impl Coverage {
1542 const PATH: &'static str = "tests/coverage";
1543 const SUITE: &'static str = "coverage";
1544 const ALL_MODES: &[&str] = &["coverage-map", "coverage-run"];
1545}
1546
1547impl Step for Coverage {
1548 type Output = ();
1549 const DEFAULT: bool = true;
1550 const IS_HOST: bool = false;
1552
1553 fn should_run(mut run: ShouldRun<'_>) -> ShouldRun<'_> {
1554 run = run.suite_path(Self::PATH);
1560 for mode in Self::ALL_MODES {
1561 run = run.alias(mode);
1562 }
1563 run
1564 }
1565
1566 fn make_run(run: RunConfig<'_>) {
1567 let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1568 let target = run.target;
1569
1570 let mut modes = vec![];
1574
1575 for path in &run.paths {
1578 match path {
1579 PathSet::Set(_) => {
1580 for mode in Self::ALL_MODES {
1581 if path.assert_single_path().path == Path::new(mode) {
1582 modes.push(mode);
1583 break;
1584 }
1585 }
1586 }
1587 PathSet::Suite(_) => {
1588 modes.extend(Self::ALL_MODES);
1589 break;
1590 }
1591 }
1592 }
1593
1594 modes.retain(|mode| !run.builder.config.skip.iter().any(|skip| skip == Path::new(mode)));
1597
1598 for mode in modes {
1606 run.builder.ensure(Coverage { compiler, target, mode });
1607 }
1608 }
1609
1610 fn run(self, builder: &Builder<'_>) {
1611 let Self { compiler, target, mode } = self;
1612 builder.ensure(Compiletest {
1615 test_compiler: compiler,
1616 target,
1617 mode,
1618 suite: Self::SUITE,
1619 path: Self::PATH,
1620 compare_mode: None,
1621 });
1622 }
1623}
1624
1625test!(CoverageRunRustdoc {
1626 path: "tests/coverage-run-rustdoc",
1627 mode: "coverage-run",
1628 suite: "coverage-run-rustdoc",
1629 default: true,
1630 IS_HOST: true,
1631});
1632
1633#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1635pub struct MirOpt {
1636 pub compiler: Compiler,
1637 pub target: TargetSelection,
1638}
1639
1640impl Step for MirOpt {
1641 type Output = ();
1642 const DEFAULT: bool = true;
1643
1644 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1645 run.suite_path("tests/mir-opt")
1646 }
1647
1648 fn make_run(run: RunConfig<'_>) {
1649 let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1650 run.builder.ensure(MirOpt { compiler, target: run.target });
1651 }
1652
1653 fn run(self, builder: &Builder<'_>) {
1654 let run = |target| {
1655 builder.ensure(Compiletest {
1656 test_compiler: self.compiler,
1657 target,
1658 mode: "mir-opt",
1659 suite: "mir-opt",
1660 path: "tests/mir-opt",
1661 compare_mode: None,
1662 })
1663 };
1664
1665 run(self.target);
1666
1667 if builder.config.cmd.bless() {
1670 for target in ["aarch64-unknown-linux-gnu", "i686-pc-windows-msvc"] {
1676 run(TargetSelection::from_user(target));
1677 }
1678
1679 for target in ["x86_64-apple-darwin", "i686-unknown-linux-musl"] {
1680 let target = TargetSelection::from_user(target);
1681 let panic_abort_target = builder.ensure(MirOptPanicAbortSyntheticTarget {
1682 compiler: self.compiler,
1683 base: target,
1684 });
1685 run(panic_abort_target);
1686 }
1687 }
1688 }
1689}
1690
1691#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1697struct Compiletest {
1698 test_compiler: Compiler,
1700 target: TargetSelection,
1701 mode: &'static str,
1702 suite: &'static str,
1703 path: &'static str,
1704 compare_mode: Option<&'static str>,
1705}
1706
1707impl Step for Compiletest {
1708 type Output = ();
1709
1710 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1711 run.never()
1712 }
1713
1714 fn run(self, builder: &Builder<'_>) {
1715 if builder.doc_tests == DocTests::Only {
1716 return;
1717 }
1718
1719 if builder.top_stage == 0 && !builder.config.compiletest_allow_stage0 {
1720 eprintln!("\
1721ERROR: `--stage 0` runs compiletest on the stage0 (precompiled) compiler, not your local changes, and will almost always cause tests to fail
1722HELP: to test the compiler or standard library, omit the stage or explicitly use `--stage 1` instead
1723NOTE: 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`."
1724 );
1725 crate::exit!(1);
1726 }
1727
1728 let mut test_compiler = self.test_compiler;
1729 let target = self.target;
1730 let mode = self.mode;
1731 let suite = self.suite;
1732
1733 let suite_path = self.path;
1735
1736 if !builder.config.codegen_tests && mode == "codegen" {
1738 return;
1739 }
1740
1741 let query_compiler;
1748 let (stage, stage_id) = if suite == "ui-fulldeps" && test_compiler.stage == 1 {
1749 query_compiler = Some(test_compiler);
1752 let build = builder.build.host_target;
1756 test_compiler = builder.compiler(test_compiler.stage - 1, build);
1757 let test_stage = test_compiler.stage + 1;
1758 (test_stage, format!("stage{test_stage}-{build}"))
1759 } else {
1760 query_compiler = None;
1761 let stage = test_compiler.stage;
1762 (stage, format!("stage{stage}-{target}"))
1763 };
1764
1765 if suite.ends_with("fulldeps") {
1766 builder.ensure(compile::Rustc::new(test_compiler, target));
1767 }
1768
1769 if suite == "debuginfo" {
1770 builder.ensure(dist::DebuggerScripts {
1771 sysroot: builder.sysroot(test_compiler).to_path_buf(),
1772 target,
1773 });
1774 }
1775 if suite == "run-make" {
1776 builder.tool_exe(Tool::RunMakeSupport);
1777 }
1778
1779 if suite == "mir-opt" {
1781 builder.ensure(
1782 compile::Std::new(test_compiler, test_compiler.host).is_for_mir_opt_tests(true),
1783 );
1784 } else {
1785 builder.std(test_compiler, test_compiler.host);
1786 }
1787
1788 let mut cmd = builder.tool_cmd(Tool::Compiletest);
1789
1790 if suite == "mir-opt" {
1791 builder.ensure(compile::Std::new(test_compiler, target).is_for_mir_opt_tests(true));
1792 } else {
1793 builder.std(test_compiler, target);
1794 }
1795
1796 builder.ensure(RemoteCopyLibs { build_compiler: test_compiler, target });
1797
1798 cmd.arg("--stage").arg(stage.to_string());
1802 cmd.arg("--stage-id").arg(stage_id);
1803
1804 cmd.arg("--compile-lib-path").arg(builder.rustc_libdir(test_compiler));
1805 cmd.arg("--run-lib-path").arg(builder.sysroot_target_libdir(test_compiler, target));
1806 cmd.arg("--rustc-path").arg(builder.rustc(test_compiler));
1807 if let Some(query_compiler) = query_compiler {
1808 cmd.arg("--query-rustc-path").arg(builder.rustc(query_compiler));
1809 }
1810
1811 cmd.arg("--minicore-path")
1814 .arg(builder.src.join("tests").join("auxiliary").join("minicore.rs"));
1815
1816 let is_rustdoc = suite == "rustdoc-ui" || suite == "rustdoc-js";
1817
1818 if mode == "run-make" {
1819 let cargo_path = if test_compiler.stage == 0 {
1820 builder.initial_cargo.clone()
1822 } else {
1823 builder
1824 .ensure(tool::Cargo::from_build_compiler(
1825 builder.compiler(test_compiler.stage - 1, test_compiler.host),
1826 test_compiler.host,
1827 ))
1828 .tool_path
1829 };
1830
1831 cmd.arg("--cargo-path").arg(cargo_path);
1832
1833 let stage0_rustc_path = builder.compiler(0, test_compiler.host);
1836 cmd.arg("--stage0-rustc-path").arg(builder.rustc(stage0_rustc_path));
1837 }
1838
1839 if mode == "rustdoc"
1841 || mode == "run-make"
1842 || (mode == "ui" && is_rustdoc)
1843 || mode == "rustdoc-js"
1844 || mode == "rustdoc-json"
1845 || suite == "coverage-run-rustdoc"
1846 {
1847 cmd.arg("--rustdoc-path").arg(builder.rustdoc_for_compiler(test_compiler));
1848 }
1849
1850 if mode == "rustdoc-json" {
1851 let json_compiler = builder.compiler(0, builder.host_target);
1853 cmd.arg("--jsondocck-path")
1854 .arg(builder.ensure(tool::JsonDocCk { compiler: json_compiler, target }).tool_path);
1855 cmd.arg("--jsondoclint-path").arg(
1856 builder.ensure(tool::JsonDocLint { compiler: json_compiler, target }).tool_path,
1857 );
1858 }
1859
1860 if matches!(mode, "coverage-map" | "coverage-run") {
1861 let coverage_dump = builder.tool_exe(Tool::CoverageDump);
1862 cmd.arg("--coverage-dump-path").arg(coverage_dump);
1863 }
1864
1865 cmd.arg("--src-root").arg(&builder.src);
1866 cmd.arg("--src-test-suite-root").arg(builder.src.join("tests").join(suite));
1867
1868 cmd.arg("--build-root").arg(&builder.out);
1872 cmd.arg("--build-test-suite-root").arg(testdir(builder, test_compiler.host).join(suite));
1873
1874 let sysroot = if builder.top_stage == 0 {
1879 builder.initial_sysroot.clone()
1880 } else {
1881 builder.sysroot(test_compiler)
1882 };
1883
1884 cmd.arg("--sysroot-base").arg(sysroot);
1885
1886 cmd.arg("--suite").arg(suite);
1887 cmd.arg("--mode").arg(mode);
1888 cmd.arg("--target").arg(target.rustc_target_arg());
1889 cmd.arg("--host").arg(&*test_compiler.host.triple);
1890 cmd.arg("--llvm-filecheck").arg(builder.llvm_filecheck(builder.config.host_target));
1891
1892 if let Some(codegen_backend) = builder.config.cmd.test_codegen_backend() {
1893 if !builder
1894 .config
1895 .enabled_codegen_backends(test_compiler.host)
1896 .contains(codegen_backend)
1897 {
1898 eprintln!(
1899 "\
1900ERROR: No configured backend named `{name}`
1901HELP: You can add it into `bootstrap.toml` in `rust.codegen-backends = [{name:?}]`",
1902 name = codegen_backend.name(),
1903 );
1904 crate::exit!(1);
1905 }
1906 cmd.arg("--override-codegen-backend").arg(codegen_backend.name());
1909 cmd.arg("--default-codegen-backend").arg(codegen_backend.name());
1912 } else {
1913 cmd.arg("--default-codegen-backend")
1916 .arg(builder.config.default_codegen_backend(test_compiler.host).name());
1917 }
1918
1919 if builder.build.config.llvm_enzyme {
1920 cmd.arg("--has-enzyme");
1921 }
1922
1923 if builder.config.cmd.bless() {
1924 cmd.arg("--bless");
1925 }
1926
1927 if builder.config.cmd.force_rerun() {
1928 cmd.arg("--force-rerun");
1929 }
1930
1931 if builder.config.cmd.no_capture() {
1932 cmd.arg("--no-capture");
1933 }
1934
1935 let compare_mode =
1936 builder.config.cmd.compare_mode().or_else(|| {
1937 if builder.config.test_compare_mode { self.compare_mode } else { None }
1938 });
1939
1940 if let Some(ref pass) = builder.config.cmd.pass() {
1941 cmd.arg("--pass");
1942 cmd.arg(pass);
1943 }
1944
1945 if let Some(ref run) = builder.config.cmd.run() {
1946 cmd.arg("--run");
1947 cmd.arg(run);
1948 }
1949
1950 if let Some(ref nodejs) = builder.config.nodejs {
1951 cmd.arg("--nodejs").arg(nodejs);
1952 } else if mode == "rustdoc-js" {
1953 panic!("need nodejs to run rustdoc-js suite");
1954 }
1955 if let Some(ref npm) = builder.config.npm {
1956 cmd.arg("--npm").arg(npm);
1957 }
1958 if builder.config.rust_optimize_tests {
1959 cmd.arg("--optimize-tests");
1960 }
1961 if builder.config.rust_randomize_layout {
1962 cmd.arg("--rust-randomized-layout");
1963 }
1964 if builder.config.cmd.only_modified() {
1965 cmd.arg("--only-modified");
1966 }
1967 if let Some(compiletest_diff_tool) = &builder.config.compiletest_diff_tool {
1968 cmd.arg("--compiletest-diff-tool").arg(compiletest_diff_tool);
1969 }
1970
1971 let mut flags = if is_rustdoc { Vec::new() } else { vec!["-Crpath".to_string()] };
1972 flags.push(format!(
1973 "-Cdebuginfo={}",
1974 if mode == "codegen" {
1975 if builder.config.rust_debuginfo_level_tests
1978 != crate::core::config::DebuginfoLevel::None
1979 {
1980 println!(
1981 "NOTE: ignoring `rust.debuginfo-level-tests={}` for codegen tests",
1982 builder.config.rust_debuginfo_level_tests
1983 );
1984 }
1985 crate::core::config::DebuginfoLevel::None
1986 } else {
1987 builder.config.rust_debuginfo_level_tests
1988 }
1989 ));
1990 flags.extend(builder.config.cmd.compiletest_rustc_args().iter().map(|s| s.to_string()));
1991
1992 if suite != "mir-opt" {
1993 if let Some(linker) = builder.linker(target) {
1994 cmd.arg("--target-linker").arg(linker);
1995 }
1996 if let Some(linker) = builder.linker(test_compiler.host) {
1997 cmd.arg("--host-linker").arg(linker);
1998 }
1999 }
2000
2001 if suite == "ui-fulldeps" && target.ends_with("darwin") {
2003 flags.push("-Alinker_messages".into());
2004 }
2005
2006 let mut hostflags = flags.clone();
2007 hostflags.extend(linker_flags(builder, test_compiler.host, LldThreads::No));
2008
2009 let mut targetflags = flags;
2010
2011 if suite == "ui" || suite == "incremental" {
2013 builder.ensure(TestHelpers { target: test_compiler.host });
2014 builder.ensure(TestHelpers { target });
2015 hostflags.push(format!(
2016 "-Lnative={}",
2017 builder.test_helpers_out(test_compiler.host).display()
2018 ));
2019 targetflags.push(format!("-Lnative={}", builder.test_helpers_out(target).display()));
2020 }
2021
2022 for flag in hostflags {
2023 cmd.arg("--host-rustcflags").arg(flag);
2024 }
2025 for flag in targetflags {
2026 cmd.arg("--target-rustcflags").arg(flag);
2027 }
2028
2029 cmd.arg("--python").arg(builder.python());
2030
2031 if let Some(ref gdb) = builder.config.gdb {
2032 cmd.arg("--gdb").arg(gdb);
2033 }
2034
2035 let lldb_exe = builder.config.lldb.clone().unwrap_or_else(|| PathBuf::from("lldb"));
2036 let lldb_version = command(&lldb_exe)
2037 .allow_failure()
2038 .arg("--version")
2039 .run_capture(builder)
2040 .stdout_if_ok()
2041 .and_then(|v| if v.trim().is_empty() { None } else { Some(v) });
2042 if let Some(ref vers) = lldb_version {
2043 cmd.arg("--lldb-version").arg(vers);
2044 let lldb_python_dir = command(&lldb_exe)
2045 .allow_failure()
2046 .arg("-P")
2047 .run_capture_stdout(builder)
2048 .stdout_if_ok()
2049 .map(|p| p.lines().next().expect("lldb Python dir not found").to_string());
2050 if let Some(ref dir) = lldb_python_dir {
2051 cmd.arg("--lldb-python-dir").arg(dir);
2052 }
2053 }
2054
2055 if helpers::forcing_clang_based_tests() {
2056 let clang_exe = builder.llvm_out(target).join("bin").join("clang");
2057 cmd.arg("--run-clang-based-tests-with").arg(clang_exe);
2058 }
2059
2060 for exclude in &builder.config.skip {
2061 cmd.arg("--skip");
2062 cmd.arg(exclude);
2063 }
2064
2065 let paths = match &builder.config.cmd {
2067 Subcommand::Test { .. } => &builder.config.paths[..],
2068 _ => &[],
2069 };
2070
2071 let mut test_args: Vec<&str> = paths
2073 .iter()
2074 .filter_map(|p| helpers::is_valid_test_suite_arg(p, suite_path, builder))
2075 .collect();
2076
2077 test_args.append(&mut builder.config.test_args());
2078
2079 if cfg!(windows) {
2082 let test_args_win: Vec<String> =
2083 test_args.iter().map(|s| s.replace('/', "\\")).collect();
2084 cmd.args(&test_args_win);
2085 } else {
2086 cmd.args(&test_args);
2087 }
2088
2089 if builder.is_verbose() {
2090 cmd.arg("--verbose");
2091 }
2092
2093 if builder.config.rustc_debug_assertions {
2094 cmd.arg("--with-rustc-debug-assertions");
2095 }
2096
2097 if builder.config.std_debug_assertions {
2098 cmd.arg("--with-std-debug-assertions");
2099 }
2100
2101 let mut llvm_components_passed = false;
2102 let mut copts_passed = false;
2103 if builder.config.llvm_enabled(test_compiler.host) {
2104 let llvm::LlvmResult { host_llvm_config, .. } =
2105 builder.ensure(llvm::Llvm { target: builder.config.host_target });
2106 if !builder.config.dry_run() {
2107 let llvm_version = get_llvm_version(builder, &host_llvm_config);
2108 let llvm_components = command(&host_llvm_config)
2109 .cached()
2110 .arg("--components")
2111 .run_capture_stdout(builder)
2112 .stdout();
2113 cmd.arg("--llvm-version")
2115 .arg(llvm_version.trim())
2116 .arg("--llvm-components")
2117 .arg(llvm_components.trim());
2118 llvm_components_passed = true;
2119 }
2120 if !builder.config.is_rust_llvm(target) {
2121 cmd.arg("--system-llvm");
2122 }
2123
2124 if !builder.config.dry_run() && suite.ends_with("fulldeps") {
2129 let llvm_libdir = command(&host_llvm_config)
2130 .cached()
2131 .arg("--libdir")
2132 .run_capture_stdout(builder)
2133 .stdout();
2134 let link_llvm = if target.is_msvc() {
2135 format!("-Clink-arg=-LIBPATH:{llvm_libdir}")
2136 } else {
2137 format!("-Clink-arg=-L{llvm_libdir}")
2138 };
2139 cmd.arg("--host-rustcflags").arg(link_llvm);
2140 }
2141
2142 if !builder.config.dry_run() && matches!(mode, "run-make" | "coverage-run") {
2143 let llvm_bin_path = host_llvm_config
2148 .parent()
2149 .expect("Expected llvm-config to be contained in directory");
2150 assert!(llvm_bin_path.is_dir());
2151 cmd.arg("--llvm-bin-dir").arg(llvm_bin_path);
2152 }
2153
2154 if !builder.config.dry_run() && mode == "run-make" {
2155 if builder.config.lld_enabled {
2157 let lld_install_root =
2158 builder.ensure(llvm::Lld { target: builder.config.host_target });
2159
2160 let lld_bin_path = lld_install_root.join("bin");
2161
2162 let old_path = env::var_os("PATH").unwrap_or_default();
2163 let new_path = env::join_paths(
2164 std::iter::once(lld_bin_path).chain(env::split_paths(&old_path)),
2165 )
2166 .expect("Could not add LLD bin path to PATH");
2167 cmd.env("PATH", new_path);
2168 }
2169 }
2170 }
2171
2172 if !builder.config.dry_run() && mode == "run-make" {
2175 let mut cflags = builder.cc_handled_clags(target, CLang::C);
2176 cflags.extend(builder.cc_unhandled_cflags(target, GitRepo::Rustc, CLang::C));
2177 let mut cxxflags = builder.cc_handled_clags(target, CLang::Cxx);
2178 cxxflags.extend(builder.cc_unhandled_cflags(target, GitRepo::Rustc, CLang::Cxx));
2179 cmd.arg("--cc")
2180 .arg(builder.cc(target))
2181 .arg("--cxx")
2182 .arg(builder.cxx(target).unwrap())
2183 .arg("--cflags")
2184 .arg(cflags.join(" "))
2185 .arg("--cxxflags")
2186 .arg(cxxflags.join(" "));
2187 copts_passed = true;
2188 if let Some(ar) = builder.ar(target) {
2189 cmd.arg("--ar").arg(ar);
2190 }
2191 }
2192
2193 if !llvm_components_passed {
2194 cmd.arg("--llvm-components").arg("");
2195 }
2196 if !copts_passed {
2197 cmd.arg("--cc")
2198 .arg("")
2199 .arg("--cxx")
2200 .arg("")
2201 .arg("--cflags")
2202 .arg("")
2203 .arg("--cxxflags")
2204 .arg("");
2205 }
2206
2207 if builder.remote_tested(target) {
2208 cmd.arg("--remote-test-client").arg(builder.tool_exe(Tool::RemoteTestClient));
2209 } else if let Some(tool) = builder.runner(target) {
2210 cmd.arg("--runner").arg(tool);
2211 }
2212
2213 if suite != "mir-opt" {
2214 if !builder.config.dry_run() && target.is_msvc() {
2220 for (k, v) in builder.cc[&target].env() {
2221 if k != "PATH" {
2222 cmd.env(k, v);
2223 }
2224 }
2225 }
2226 }
2227
2228 if !builder.config.dry_run()
2230 && target.contains("msvc")
2231 && builder.config.sanitizers_enabled(target)
2232 {
2233 cmd.env("ASAN_WIN_CONTINUE_ON_INTERCEPTION_FAILURE", "1");
2236 let asan_runtime_path = builder.cc[&target].path().parent().unwrap().to_path_buf();
2238 let old_path = cmd
2239 .get_envs()
2240 .find_map(|(k, v)| (k == "PATH").then_some(v))
2241 .flatten()
2242 .map_or_else(|| env::var_os("PATH").unwrap_or_default(), |v| v.to_owned());
2243 let new_path = env::join_paths(
2244 env::split_paths(&old_path).chain(std::iter::once(asan_runtime_path)),
2245 )
2246 .expect("Could not add ASAN runtime path to PATH");
2247 cmd.env("PATH", new_path);
2248 }
2249
2250 cmd.env_remove("CARGO");
2253
2254 cmd.env("RUSTC_BOOTSTRAP", "1");
2255 cmd.env("RUSTC_FORCE_RUSTC_VERSION", "compiletest");
2258 cmd.env("DOC_RUST_LANG_ORG_CHANNEL", builder.doc_rust_lang_org_channel());
2259 builder.add_rust_test_threads(&mut cmd);
2260
2261 if builder.config.sanitizers_enabled(target) {
2262 cmd.env("RUSTC_SANITIZER_SUPPORT", "1");
2263 }
2264
2265 if builder.config.profiler_enabled(target) {
2266 cmd.arg("--profiler-runtime");
2267 }
2268
2269 cmd.env("RUST_TEST_TMPDIR", builder.tempdir());
2270
2271 cmd.arg("--adb-path").arg("adb");
2272 cmd.arg("--adb-test-dir").arg(ADB_TEST_DIR);
2273 if target.contains("android") && !builder.config.dry_run() {
2274 cmd.arg("--android-cross-path")
2276 .arg(builder.cc(target).parent().unwrap().parent().unwrap());
2277 } else {
2278 cmd.arg("--android-cross-path").arg("");
2279 }
2280
2281 if builder.config.cmd.rustfix_coverage() {
2282 cmd.arg("--rustfix-coverage");
2283 }
2284
2285 cmd.arg("--channel").arg(&builder.config.channel);
2286
2287 if !builder.config.omit_git_hash {
2288 cmd.arg("--git-hash");
2289 }
2290
2291 let git_config = builder.config.git_config();
2292 cmd.arg("--nightly-branch").arg(git_config.nightly_branch);
2293 cmd.arg("--git-merge-commit-email").arg(git_config.git_merge_commit_email);
2294 cmd.force_coloring_in_ci();
2295
2296 #[cfg(feature = "build-metrics")]
2297 builder.metrics.begin_test_suite(
2298 build_helper::metrics::TestSuiteMetadata::Compiletest {
2299 suite: suite.into(),
2300 mode: mode.into(),
2301 compare_mode: None,
2302 target: self.target.triple.to_string(),
2303 host: self.test_compiler.host.triple.to_string(),
2304 stage: self.test_compiler.stage,
2305 },
2306 builder,
2307 );
2308
2309 let _group = builder.msg_test(
2310 format!("with compiletest suite={suite} mode={mode}"),
2311 target,
2312 test_compiler.stage,
2313 );
2314 try_run_tests(builder, &mut cmd, false);
2315
2316 if let Some(compare_mode) = compare_mode {
2317 cmd.arg("--compare-mode").arg(compare_mode);
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: Some(compare_mode.into()),
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 builder.info(&format!(
2333 "Check compiletest suite={} mode={} compare_mode={} ({} -> {})",
2334 suite, mode, compare_mode, &test_compiler.host, target
2335 ));
2336 let _time = helpers::timeit(builder);
2337 try_run_tests(builder, &mut cmd, false);
2338 }
2339 }
2340
2341 fn metadata(&self) -> Option<StepMetadata> {
2342 Some(
2343 StepMetadata::test(&format!("compiletest-{}", self.suite), self.target)
2344 .stage(self.test_compiler.stage),
2345 )
2346 }
2347}
2348
2349#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2351struct BookTest {
2352 test_compiler: Compiler,
2353 path: PathBuf,
2354 name: &'static str,
2355 is_ext_doc: bool,
2356 dependencies: Vec<&'static str>,
2357}
2358
2359impl Step for BookTest {
2360 type Output = ();
2361 const IS_HOST: bool = true;
2362
2363 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2364 run.never()
2365 }
2366
2367 fn run(self, builder: &Builder<'_>) {
2368 if self.is_ext_doc {
2378 self.run_ext_doc(builder);
2379 } else {
2380 self.run_local_doc(builder);
2381 }
2382 }
2383}
2384
2385impl BookTest {
2386 fn run_ext_doc(self, builder: &Builder<'_>) {
2389 let test_compiler = self.test_compiler;
2390
2391 builder.std(test_compiler, test_compiler.host);
2392
2393 let mut rustdoc_path = builder.rustdoc_for_compiler(test_compiler);
2396 rustdoc_path.pop();
2397 let old_path = env::var_os("PATH").unwrap_or_default();
2398 let new_path = env::join_paths(iter::once(rustdoc_path).chain(env::split_paths(&old_path)))
2399 .expect("could not add rustdoc to PATH");
2400
2401 let mut rustbook_cmd = builder.tool_cmd(Tool::Rustbook);
2402 let path = builder.src.join(&self.path);
2403 rustbook_cmd.env("RUSTC_BOOTSTRAP", "1");
2405 rustbook_cmd.env("PATH", new_path).arg("test").arg(path);
2406
2407 let libs = if !self.dependencies.is_empty() {
2412 let mut lib_paths = vec![];
2413 for dep in self.dependencies {
2414 let mode = Mode::ToolRustc;
2415 let target = builder.config.host_target;
2416 let cargo = tool::prepare_tool_cargo(
2417 builder,
2418 test_compiler,
2419 mode,
2420 target,
2421 Kind::Build,
2422 dep,
2423 SourceType::Submodule,
2424 &[],
2425 );
2426
2427 let stamp = BuildStamp::new(&builder.cargo_out(test_compiler, mode, target))
2428 .with_prefix(PathBuf::from(dep).file_name().and_then(|v| v.to_str()).unwrap());
2429
2430 let output_paths = run_cargo(builder, cargo, vec![], &stamp, vec![], false, false);
2431 let directories = output_paths
2432 .into_iter()
2433 .filter_map(|p| p.parent().map(ToOwned::to_owned))
2434 .fold(HashSet::new(), |mut set, dir| {
2435 set.insert(dir);
2436 set
2437 });
2438
2439 lib_paths.extend(directories);
2440 }
2441 lib_paths
2442 } else {
2443 vec![]
2444 };
2445
2446 if !libs.is_empty() {
2447 let paths = libs
2448 .into_iter()
2449 .map(|path| path.into_os_string())
2450 .collect::<Vec<OsString>>()
2451 .join(OsStr::new(","));
2452 rustbook_cmd.args([OsString::from("--library-path"), paths]);
2453 }
2454
2455 builder.add_rust_test_threads(&mut rustbook_cmd);
2456 let _guard = builder.msg_test(
2457 format_args!("mdbook {}", self.path.display()),
2458 test_compiler.host,
2459 test_compiler.stage,
2460 );
2461 let _time = helpers::timeit(builder);
2462 let toolstate = if rustbook_cmd.delay_failure().run(builder) {
2463 ToolState::TestPass
2464 } else {
2465 ToolState::TestFail
2466 };
2467 builder.save_toolstate(self.name, toolstate);
2468 }
2469
2470 fn run_local_doc(self, builder: &Builder<'_>) {
2472 let test_compiler = self.test_compiler;
2473 let host = self.test_compiler.host;
2474
2475 builder.std(test_compiler, host);
2476
2477 let _guard = builder.msg_test(
2478 format!("book {}", self.name),
2479 test_compiler.host,
2480 test_compiler.stage,
2481 );
2482
2483 let mut stack = vec![builder.src.join(self.path)];
2486 let _time = helpers::timeit(builder);
2487 let mut files = Vec::new();
2488 while let Some(p) = stack.pop() {
2489 if p.is_dir() {
2490 stack.extend(t!(p.read_dir()).map(|p| t!(p).path()));
2491 continue;
2492 }
2493
2494 if p.extension().and_then(|s| s.to_str()) != Some("md") {
2495 continue;
2496 }
2497
2498 files.push(p);
2499 }
2500
2501 files.sort();
2502
2503 for file in files {
2504 markdown_test(builder, test_compiler, &file);
2505 }
2506 }
2507}
2508
2509macro_rules! test_book {
2510 ($(
2511 $name:ident, $path:expr, $book_name:expr,
2512 default=$default:expr
2513 $(,submodules = $submodules:expr)?
2514 $(,dependencies=$dependencies:expr)?
2515 ;
2516 )+) => {
2517 $(
2518 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
2519 pub struct $name {
2520 test_compiler: Compiler,
2521 }
2522
2523 impl Step for $name {
2524 type Output = ();
2525 const DEFAULT: bool = $default;
2526 const IS_HOST: bool = true;
2527
2528 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2529 run.path($path)
2530 }
2531
2532 fn make_run(run: RunConfig<'_>) {
2533 run.builder.ensure($name {
2534 test_compiler: run.builder.compiler(run.builder.top_stage, run.target),
2535 });
2536 }
2537
2538 fn run(self, builder: &Builder<'_>) {
2539 $(
2540 for submodule in $submodules {
2541 builder.require_submodule(submodule, None);
2542 }
2543 )*
2544
2545 let dependencies = vec![];
2546 $(
2547 let mut dependencies = dependencies;
2548 for dep in $dependencies {
2549 dependencies.push(dep);
2550 }
2551 )?
2552
2553 builder.ensure(BookTest {
2554 test_compiler: self.test_compiler,
2555 path: PathBuf::from($path),
2556 name: $book_name,
2557 is_ext_doc: !$default,
2558 dependencies,
2559 });
2560 }
2561 }
2562 )+
2563 }
2564}
2565
2566test_book!(
2567 Nomicon, "src/doc/nomicon", "nomicon", default=false, submodules=["src/doc/nomicon"];
2568 Reference, "src/doc/reference", "reference", default=false, submodules=["src/doc/reference"];
2569 RustdocBook, "src/doc/rustdoc", "rustdoc", default=true;
2570 RustcBook, "src/doc/rustc", "rustc", default=true;
2571 RustByExample, "src/doc/rust-by-example", "rust-by-example", default=false, submodules=["src/doc/rust-by-example"];
2572 EmbeddedBook, "src/doc/embedded-book", "embedded-book", default=false, submodules=["src/doc/embedded-book"];
2573 TheBook, "src/doc/book", "book", default=false, submodules=["src/doc/book"], dependencies=["src/doc/book/packages/trpl"];
2574 UnstableBook, "src/doc/unstable-book", "unstable-book", default=true;
2575 EditionGuide, "src/doc/edition-guide", "edition-guide", default=false, submodules=["src/doc/edition-guide"];
2576);
2577
2578#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2579pub struct ErrorIndex {
2580 compilers: RustcPrivateCompilers,
2581}
2582
2583impl Step for ErrorIndex {
2584 type Output = ();
2585 const DEFAULT: bool = true;
2586 const IS_HOST: bool = true;
2587
2588 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2589 run.path("src/tools/error_index_generator").alias("error-index")
2592 }
2593
2594 fn make_run(run: RunConfig<'_>) {
2595 let compilers = RustcPrivateCompilers::new(
2599 run.builder,
2600 run.builder.top_stage,
2601 run.builder.config.host_target,
2602 );
2603 run.builder.ensure(ErrorIndex { compilers });
2604 }
2605
2606 fn run(self, builder: &Builder<'_>) {
2613 let target_compiler = self.compilers.target_compiler();
2615
2616 let dir = testdir(builder, target_compiler.host);
2617 t!(fs::create_dir_all(&dir));
2618 let output = dir.join("error-index.md");
2619
2620 let mut tool = tool::ErrorIndex::command(builder, self.compilers);
2621 tool.arg("markdown").arg(&output);
2622
2623 let guard = builder.msg_test("error-index", target_compiler.host, target_compiler.stage);
2624 let _time = helpers::timeit(builder);
2625 tool.run_capture(builder);
2626 drop(guard);
2627 builder.std(target_compiler, target_compiler.host);
2630 markdown_test(builder, target_compiler, &output);
2631 }
2632}
2633
2634fn markdown_test(builder: &Builder<'_>, compiler: Compiler, markdown: &Path) -> bool {
2635 if let Ok(contents) = fs::read_to_string(markdown)
2636 && !contents.contains("```")
2637 {
2638 return true;
2639 }
2640
2641 builder.verbose(|| println!("doc tests for: {}", markdown.display()));
2642 let mut cmd = builder.rustdoc_cmd(compiler);
2643 builder.add_rust_test_threads(&mut cmd);
2644 cmd.arg("-Z");
2646 cmd.arg("unstable-options");
2647 cmd.arg("--test");
2648 cmd.arg(markdown);
2649 cmd.env("RUSTC_BOOTSTRAP", "1");
2650
2651 let test_args = builder.config.test_args().join(" ");
2652 cmd.arg("--test-args").arg(test_args);
2653
2654 cmd = cmd.delay_failure();
2655 if !builder.config.verbose_tests {
2656 cmd.run_capture(builder).is_success()
2657 } else {
2658 cmd.run(builder)
2659 }
2660}
2661
2662#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2667pub struct CrateLibrustc {
2668 build_compiler: Compiler,
2670 target: TargetSelection,
2671 crates: Vec<String>,
2672}
2673
2674impl Step for CrateLibrustc {
2675 type Output = ();
2676 const DEFAULT: bool = true;
2677 const IS_HOST: bool = true;
2678
2679 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2680 run.crate_or_deps("rustc-main").path("compiler")
2681 }
2682
2683 fn make_run(run: RunConfig<'_>) {
2684 let builder = run.builder;
2685 let host = run.build_triple();
2686 let build_compiler = builder.compiler(builder.top_stage - 1, host);
2687 let crates = run.make_run_crates(Alias::Compiler);
2688
2689 builder.ensure(CrateLibrustc { build_compiler, target: run.target, crates });
2690 }
2691
2692 fn run(self, builder: &Builder<'_>) {
2693 builder.std(self.build_compiler, self.target);
2694
2695 builder.ensure(Crate {
2697 build_compiler: self.build_compiler,
2698 target: self.target,
2699 mode: Mode::Rustc,
2700 crates: self.crates,
2701 });
2702 }
2703
2704 fn metadata(&self) -> Option<StepMetadata> {
2705 Some(StepMetadata::test("CrateLibrustc", self.target).built_by(self.build_compiler))
2706 }
2707}
2708
2709fn run_cargo_test<'a>(
2713 cargo: builder::Cargo,
2714 libtest_args: &[&str],
2715 crates: &[String],
2716 description: impl Into<Option<&'a str>>,
2717 target: TargetSelection,
2718 builder: &Builder<'_>,
2719) -> bool {
2720 let compiler = cargo.compiler();
2721 let mut cargo = prepare_cargo_test(cargo, libtest_args, crates, target, builder);
2722 let _time = helpers::timeit(builder);
2723 let _group =
2724 description.into().and_then(|what| builder.msg_test(what, target, compiler.stage + 1));
2725
2726 #[cfg(feature = "build-metrics")]
2727 builder.metrics.begin_test_suite(
2728 build_helper::metrics::TestSuiteMetadata::CargoPackage {
2729 crates: crates.iter().map(|c| c.to_string()).collect(),
2730 target: target.triple.to_string(),
2731 host: compiler.host.triple.to_string(),
2732 stage: compiler.stage,
2733 },
2734 builder,
2735 );
2736 add_flags_and_try_run_tests(builder, &mut cargo)
2737}
2738
2739fn prepare_cargo_test(
2741 cargo: builder::Cargo,
2742 libtest_args: &[&str],
2743 crates: &[String],
2744 target: TargetSelection,
2745 builder: &Builder<'_>,
2746) -> BootstrapCommand {
2747 let compiler = cargo.compiler();
2748 let mut cargo: BootstrapCommand = cargo.into();
2749
2750 if builder.config.cmd.bless() && !cargo.get_envs().any(|v| v.0 == "RUSTC_BLESS") {
2754 cargo.env("RUSTC_BLESS", "Gesundheit");
2755 }
2756
2757 if builder.kind == Kind::Test && !builder.fail_fast {
2761 cargo.arg("--no-fail-fast");
2762 }
2763
2764 if builder.config.json_output {
2765 cargo.arg("--message-format=json");
2766 }
2767
2768 match builder.doc_tests {
2769 DocTests::Only => {
2770 cargo.arg("--doc");
2771 }
2772 DocTests::No => {
2773 cargo.args(["--bins", "--examples", "--tests", "--benches"]);
2774 }
2775 DocTests::Yes => {}
2776 }
2777
2778 for krate in crates {
2779 cargo.arg("-p").arg(krate);
2780 }
2781
2782 cargo.arg("--").args(builder.config.test_args()).args(libtest_args);
2783 if !builder.config.verbose_tests {
2784 cargo.arg("--quiet");
2785 }
2786
2787 if builder.kind != Kind::Miri {
2796 let mut dylib_paths = builder.rustc_lib_paths(compiler);
2797 dylib_paths.push(builder.sysroot_target_libdir(compiler, target));
2798 helpers::add_dylib_path(dylib_paths, &mut cargo);
2799 }
2800
2801 if builder.remote_tested(target) {
2802 cargo.env(
2803 format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)),
2804 format!("{} run 0", builder.tool_exe(Tool::RemoteTestClient).display()),
2805 );
2806 } else if let Some(tool) = builder.runner(target) {
2807 cargo.env(format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)), tool);
2808 }
2809
2810 cargo
2811}
2812
2813#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2821pub struct Crate {
2822 build_compiler: Compiler,
2824 target: TargetSelection,
2825 mode: Mode,
2826 crates: Vec<String>,
2827}
2828
2829impl Step for Crate {
2830 type Output = ();
2831 const DEFAULT: bool = true;
2832
2833 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2834 run.crate_or_deps("sysroot").crate_or_deps("coretests").crate_or_deps("alloctests")
2835 }
2836
2837 fn make_run(run: RunConfig<'_>) {
2838 let builder = run.builder;
2839 let host = run.build_triple();
2840 let build_compiler = builder.compiler(builder.top_stage, host);
2841 let crates = run
2842 .paths
2843 .iter()
2844 .map(|p| builder.crate_paths[&p.assert_single_path().path].clone())
2845 .collect();
2846
2847 builder.ensure(Crate { build_compiler, target: run.target, mode: Mode::Std, crates });
2848 }
2849
2850 fn run(self, builder: &Builder<'_>) {
2859 let build_compiler = self.build_compiler;
2860 let target = self.target;
2861 let mode = self.mode;
2862
2863 builder.ensure(Std::new(build_compiler, build_compiler.host).force_recompile(true));
2866
2867 let mut cargo = if builder.kind == Kind::Miri {
2868 if builder.top_stage == 0 {
2869 eprintln!("ERROR: `x.py miri` requires stage 1 or higher");
2870 std::process::exit(1);
2871 }
2872
2873 let mut cargo = builder::Cargo::new(
2876 builder,
2877 build_compiler,
2878 mode,
2879 SourceType::InTree,
2880 target,
2881 Kind::MiriTest,
2882 );
2883 cargo.env("MIRI_REPLACE_LIBRS_IF_NOT_TEST", "1");
2895 cargo.rustflag("-Zforce-unstable-if-unmarked");
2899 cargo
2900 } else {
2901 if !builder.config.is_host_target(target) {
2903 builder.ensure(compile::Std::new(build_compiler, target).force_recompile(true));
2904 builder.ensure(RemoteCopyLibs { build_compiler, target });
2905 }
2906
2907 builder::Cargo::new(
2909 builder,
2910 build_compiler,
2911 mode,
2912 SourceType::InTree,
2913 target,
2914 builder.kind,
2915 )
2916 };
2917
2918 match mode {
2919 Mode::Std => {
2920 if builder.kind == Kind::Miri {
2921 cargo
2927 .arg("--manifest-path")
2928 .arg(builder.src.join("library/sysroot/Cargo.toml"));
2929 } else {
2930 compile::std_cargo(builder, target, &mut cargo);
2931 }
2932 }
2933 Mode::Rustc => {
2934 compile::rustc_cargo(builder, &mut cargo, target, &build_compiler, &self.crates);
2935 }
2936 _ => panic!("can only test libraries"),
2937 };
2938
2939 let mut crates = self.crates.clone();
2940 if crates.iter().any(|crate_| crate_ == "core") {
2945 crates.push("coretests".to_owned());
2946 }
2947 if crates.iter().any(|crate_| crate_ == "alloc") {
2948 crates.push("alloctests".to_owned());
2949 }
2950
2951 run_cargo_test(cargo, &[], &crates, &*crate_description(&self.crates), target, builder);
2952 }
2953}
2954
2955#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2958pub struct CrateRustdoc {
2959 host: TargetSelection,
2960}
2961
2962impl Step for CrateRustdoc {
2963 type Output = ();
2964 const DEFAULT: bool = true;
2965 const IS_HOST: bool = true;
2966
2967 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2968 run.paths(&["src/librustdoc", "src/tools/rustdoc"])
2969 }
2970
2971 fn make_run(run: RunConfig<'_>) {
2972 let builder = run.builder;
2973
2974 builder.ensure(CrateRustdoc { host: run.target });
2975 }
2976
2977 fn run(self, builder: &Builder<'_>) {
2978 let target = self.host;
2979
2980 let compiler = if builder.download_rustc() {
2981 builder.compiler(builder.top_stage, target)
2982 } else {
2983 builder.compiler_for(builder.top_stage, target, target)
2988 };
2989 builder.std(compiler, target);
2994 builder.ensure(compile::Rustc::new(compiler, target));
2995
2996 let mut cargo = tool::prepare_tool_cargo(
2997 builder,
2998 compiler,
2999 Mode::ToolRustc,
3000 target,
3001 builder.kind,
3002 "src/tools/rustdoc",
3003 SourceType::InTree,
3004 &[],
3005 );
3006 if self.host.contains("musl") {
3007 cargo.arg("'-Ctarget-feature=-crt-static'");
3008 }
3009
3010 let libdir = if builder.download_rustc() {
3037 builder.rustc_libdir(compiler)
3038 } else {
3039 builder.sysroot_target_libdir(compiler, target).to_path_buf()
3040 };
3041 let mut dylib_path = dylib_path();
3042 dylib_path.insert(0, PathBuf::from(&*libdir));
3043 cargo.env(dylib_path_var(), env::join_paths(&dylib_path).unwrap());
3044
3045 run_cargo_test(cargo, &[], &["rustdoc:0.0.0".to_string()], "rustdoc", target, builder);
3046 }
3047}
3048
3049#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3050pub struct CrateRustdocJsonTypes {
3051 build_compiler: Compiler,
3052 target: TargetSelection,
3053}
3054
3055impl Step for CrateRustdocJsonTypes {
3056 type Output = ();
3057 const DEFAULT: bool = true;
3058 const IS_HOST: bool = true;
3059
3060 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3061 run.path("src/rustdoc-json-types")
3062 }
3063
3064 fn make_run(run: RunConfig<'_>) {
3065 let builder = run.builder;
3066
3067 builder.ensure(CrateRustdocJsonTypes {
3068 build_compiler: get_tool_target_compiler(
3069 builder,
3070 ToolTargetBuildMode::Build(run.target),
3071 ),
3072 target: run.target,
3073 });
3074 }
3075
3076 fn run(self, builder: &Builder<'_>) {
3077 let target = self.target;
3078
3079 let cargo = tool::prepare_tool_cargo(
3080 builder,
3081 self.build_compiler,
3082 Mode::ToolTarget,
3083 target,
3084 builder.kind,
3085 "src/rustdoc-json-types",
3086 SourceType::InTree,
3087 &[],
3088 );
3089
3090 let libtest_args = if target.contains("musl") {
3092 ["'-Ctarget-feature=-crt-static'"].as_slice()
3093 } else {
3094 &[]
3095 };
3096
3097 run_cargo_test(
3098 cargo,
3099 libtest_args,
3100 &["rustdoc-json-types".to_string()],
3101 "rustdoc-json-types",
3102 target,
3103 builder,
3104 );
3105 }
3106}
3107
3108#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3118pub struct RemoteCopyLibs {
3119 build_compiler: Compiler,
3120 target: TargetSelection,
3121}
3122
3123impl Step for RemoteCopyLibs {
3124 type Output = ();
3125
3126 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3127 run.never()
3128 }
3129
3130 fn run(self, builder: &Builder<'_>) {
3131 let build_compiler = self.build_compiler;
3132 let target = self.target;
3133 if !builder.remote_tested(target) {
3134 return;
3135 }
3136
3137 builder.std(build_compiler, target);
3138
3139 builder.info(&format!("REMOTE copy libs to emulator ({target})"));
3140
3141 let remote_test_server = builder.ensure(tool::RemoteTestServer { build_compiler, target });
3142
3143 let tool = builder.tool_exe(Tool::RemoteTestClient);
3145 let mut cmd = command(&tool);
3146 cmd.arg("spawn-emulator")
3147 .arg(target.triple)
3148 .arg(&remote_test_server.tool_path)
3149 .arg(builder.tempdir());
3150 if let Some(rootfs) = builder.qemu_rootfs(target) {
3151 cmd.arg(rootfs);
3152 }
3153 cmd.run(builder);
3154
3155 for f in t!(builder.sysroot_target_libdir(build_compiler, target).read_dir()) {
3157 let f = t!(f);
3158 if helpers::is_dylib(&f.path()) {
3159 command(&tool).arg("push").arg(f.path()).run(builder);
3160 }
3161 }
3162 }
3163}
3164
3165#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3166pub struct Distcheck;
3167
3168impl Step for Distcheck {
3169 type Output = ();
3170
3171 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3172 run.alias("distcheck")
3173 }
3174
3175 fn make_run(run: RunConfig<'_>) {
3176 run.builder.ensure(Distcheck);
3177 }
3178
3179 fn run(self, builder: &Builder<'_>) {
3188 let root_dir = std::env::temp_dir().join("distcheck");
3191
3192 builder.info("Distcheck plain source tarball");
3194 let plain_src_tarball = builder.ensure(dist::PlainSourceTarball);
3195 let plain_src_dir = root_dir.join("distcheck-plain-src");
3196 builder.clear_dir(&plain_src_dir);
3197
3198 let configure_args: Vec<String> = std::env::var("DISTCHECK_CONFIGURE_ARGS")
3199 .map(|args| args.split(" ").map(|s| s.to_string()).collect::<Vec<String>>())
3200 .unwrap_or_default();
3201
3202 command("tar")
3203 .arg("-xf")
3204 .arg(plain_src_tarball.tarball())
3205 .arg("--strip-components=1")
3206 .current_dir(&plain_src_dir)
3207 .run(builder);
3208 command("./configure")
3209 .arg("--set")
3210 .arg("rust.omit-git-hash=false")
3211 .args(&configure_args)
3212 .arg("--enable-vendor")
3213 .current_dir(&plain_src_dir)
3214 .run(builder);
3215 command(helpers::make(&builder.config.host_target.triple))
3216 .arg("check")
3217 .env("GITHUB_ACTIONS", "0")
3220 .current_dir(&plain_src_dir)
3221 .run(builder);
3222
3223 builder.info("Distcheck rust-src");
3225 let src_tarball = builder.ensure(dist::Src);
3226 let src_dir = root_dir.join("distcheck-src");
3227 builder.clear_dir(&src_dir);
3228
3229 command("tar")
3230 .arg("-xf")
3231 .arg(src_tarball.tarball())
3232 .arg("--strip-components=1")
3233 .current_dir(&src_dir)
3234 .run(builder);
3235
3236 let toml = src_dir.join("rust-src/lib/rustlib/src/rust/library/std/Cargo.toml");
3237 command(&builder.initial_cargo)
3238 .env("RUSTC_BOOTSTRAP", "1")
3241 .arg("generate-lockfile")
3242 .arg("--manifest-path")
3243 .arg(&toml)
3244 .current_dir(&src_dir)
3245 .run(builder);
3246 }
3247}
3248
3249#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3250pub struct Bootstrap;
3251
3252impl Step for Bootstrap {
3253 type Output = ();
3254 const DEFAULT: bool = true;
3255 const IS_HOST: bool = true;
3256
3257 fn run(self, builder: &Builder<'_>) {
3259 let host = builder.config.host_target;
3260 let build_compiler = builder.compiler(0, host);
3261
3262 builder.build.require_submodule("src/tools/cargo", None);
3264
3265 let mut check_bootstrap = command(builder.python());
3266 check_bootstrap
3267 .args(["-m", "unittest", "bootstrap_test.py"])
3268 .env("BUILD_DIR", &builder.out)
3269 .env("BUILD_PLATFORM", builder.build.host_target.triple)
3270 .env("BOOTSTRAP_TEST_RUSTC_BIN", &builder.initial_rustc)
3271 .env("BOOTSTRAP_TEST_CARGO_BIN", &builder.initial_cargo)
3272 .current_dir(builder.src.join("src/bootstrap/"));
3273 check_bootstrap.delay_failure().run(builder);
3276
3277 let mut cargo = tool::prepare_tool_cargo(
3278 builder,
3279 build_compiler,
3280 Mode::ToolBootstrap,
3281 host,
3282 Kind::Test,
3283 "src/bootstrap",
3284 SourceType::InTree,
3285 &[],
3286 );
3287
3288 cargo.release_build(false);
3289
3290 cargo
3291 .rustflag("-Cdebuginfo=2")
3292 .env("CARGO_TARGET_DIR", builder.out.join("bootstrap"))
3293 .env("INSTA_WORKSPACE_ROOT", &builder.src)
3295 .env("RUSTC_BOOTSTRAP", "1");
3296
3297 run_cargo_test(cargo, &["--test-threads=1"], &[], None, host, builder);
3300 }
3301
3302 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3303 let runs_on_ci = run.builder.config.is_running_on_ci;
3307 run.path("src/bootstrap").default_condition(runs_on_ci)
3308 }
3309
3310 fn make_run(run: RunConfig<'_>) {
3311 run.builder.ensure(Bootstrap);
3312 }
3313}
3314
3315fn get_compiler_to_test(builder: &Builder<'_>, target: TargetSelection) -> Compiler {
3316 builder.compiler(builder.top_stage, target)
3317}
3318
3319#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3322pub struct TierCheck {
3323 test_compiler: Compiler,
3324}
3325
3326impl Step for TierCheck {
3327 type Output = ();
3328 const DEFAULT: bool = true;
3329 const IS_HOST: bool = true;
3330
3331 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3332 run.path("src/tools/tier-check")
3333 }
3334
3335 fn make_run(run: RunConfig<'_>) {
3336 run.builder
3337 .ensure(TierCheck { test_compiler: get_compiler_to_test(run.builder, run.target) });
3338 }
3339
3340 fn run(self, builder: &Builder<'_>) {
3341 let tool_build_compiler = builder.compiler(0, builder.host_target);
3342
3343 let mut cargo = tool::prepare_tool_cargo(
3344 builder,
3345 tool_build_compiler,
3346 Mode::ToolBootstrap,
3347 tool_build_compiler.host,
3348 Kind::Run,
3349 "src/tools/tier-check",
3350 SourceType::InTree,
3351 &[],
3352 );
3353 cargo.arg(builder.src.join("src/doc/rustc/src/platform-support.md"));
3354 cargo.arg(builder.rustc(self.test_compiler));
3355 if builder.is_verbose() {
3356 cargo.arg("--verbose");
3357 }
3358
3359 let _guard = builder.msg_test(
3360 "platform support check",
3361 self.test_compiler.host,
3362 self.test_compiler.stage,
3363 );
3364 BootstrapCommand::from(cargo).delay_failure().run(builder);
3365 }
3366
3367 fn metadata(&self) -> Option<StepMetadata> {
3368 Some(StepMetadata::test("tier-check", self.test_compiler.host))
3369 }
3370}
3371
3372#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3373pub struct LintDocs {
3374 build_compiler: Compiler,
3375 target: TargetSelection,
3376}
3377
3378impl Step for LintDocs {
3379 type Output = ();
3380 const DEFAULT: bool = true;
3381 const IS_HOST: bool = true;
3382
3383 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3384 let stage = run.builder.top_stage;
3385 run.path("src/tools/lint-docs").default_condition(stage > 1)
3388 }
3389
3390 fn make_run(run: RunConfig<'_>) {
3391 if run.builder.top_stage < 2 {
3392 eprintln!("WARNING: lint-docs tests might not work below stage 2");
3393 }
3394
3395 run.builder.ensure(LintDocs {
3396 build_compiler: prepare_doc_compiler(
3397 run.builder,
3398 run.builder.config.host_target,
3399 run.builder.top_stage,
3400 ),
3401 target: run.target,
3402 });
3403 }
3404
3405 fn run(self, builder: &Builder<'_>) {
3408 builder.ensure(crate::core::build_steps::doc::RustcBook::validate(
3409 self.build_compiler,
3410 self.target,
3411 ));
3412 }
3413
3414 fn metadata(&self) -> Option<StepMetadata> {
3415 Some(StepMetadata::test("lint-docs", self.target).built_by(self.build_compiler))
3416 }
3417}
3418
3419#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3420pub struct RustInstaller;
3421
3422impl Step for RustInstaller {
3423 type Output = ();
3424 const IS_HOST: bool = true;
3425 const DEFAULT: bool = true;
3426
3427 fn run(self, builder: &Builder<'_>) {
3429 let bootstrap_host = builder.config.host_target;
3430 let build_compiler = builder.compiler(0, bootstrap_host);
3431 let cargo = tool::prepare_tool_cargo(
3432 builder,
3433 build_compiler,
3434 Mode::ToolBootstrap,
3435 bootstrap_host,
3436 Kind::Test,
3437 "src/tools/rust-installer",
3438 SourceType::InTree,
3439 &[],
3440 );
3441
3442 let _guard = builder.msg_test("rust-installer", bootstrap_host, 1);
3443 run_cargo_test(cargo, &[], &[], None, bootstrap_host, builder);
3444
3445 if bootstrap_host != "x86_64-unknown-linux-gnu" {
3449 return;
3450 }
3451
3452 let mut cmd = command(builder.src.join("src/tools/rust-installer/test.sh"));
3453 let tmpdir = testdir(builder, build_compiler.host).join("rust-installer");
3454 let _ = std::fs::remove_dir_all(&tmpdir);
3455 let _ = std::fs::create_dir_all(&tmpdir);
3456 cmd.current_dir(&tmpdir);
3457 cmd.env("CARGO_TARGET_DIR", tmpdir.join("cargo-target"));
3458 cmd.env("CARGO", &builder.initial_cargo);
3459 cmd.env("RUSTC", &builder.initial_rustc);
3460 cmd.env("TMP_DIR", &tmpdir);
3461 cmd.delay_failure().run(builder);
3462 }
3463
3464 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3465 run.path("src/tools/rust-installer")
3466 }
3467
3468 fn make_run(run: RunConfig<'_>) {
3469 run.builder.ensure(Self);
3470 }
3471}
3472
3473#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3474pub struct TestHelpers {
3475 pub target: TargetSelection,
3476}
3477
3478impl Step for TestHelpers {
3479 type Output = ();
3480
3481 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3482 run.path("tests/auxiliary/rust_test_helpers.c")
3483 }
3484
3485 fn make_run(run: RunConfig<'_>) {
3486 run.builder.ensure(TestHelpers { target: run.target })
3487 }
3488
3489 fn run(self, builder: &Builder<'_>) {
3492 if builder.config.dry_run() {
3493 return;
3494 }
3495 let target = if self.target == "x86_64-fortanix-unknown-sgx" {
3499 TargetSelection::from_user("x86_64-unknown-linux-gnu")
3500 } else {
3501 self.target
3502 };
3503 let dst = builder.test_helpers_out(target);
3504 let src = builder.src.join("tests/auxiliary/rust_test_helpers.c");
3505 if up_to_date(&src, &dst.join("librust_test_helpers.a")) {
3506 return;
3507 }
3508
3509 let _guard = builder.msg_unstaged(Kind::Build, "test helpers", target);
3510 t!(fs::create_dir_all(&dst));
3511 let mut cfg = cc::Build::new();
3512
3513 if !target.is_msvc() {
3517 if let Some(ar) = builder.ar(target) {
3518 cfg.archiver(ar);
3519 }
3520 cfg.compiler(builder.cc(target));
3521 }
3522 cfg.cargo_metadata(false)
3523 .out_dir(&dst)
3524 .target(&target.triple)
3525 .host(&builder.config.host_target.triple)
3526 .opt_level(0)
3527 .warnings(false)
3528 .debug(false)
3529 .file(builder.src.join("tests/auxiliary/rust_test_helpers.c"))
3530 .compile("rust_test_helpers");
3531 }
3532}
3533
3534#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3535pub struct CodegenCranelift {
3536 compilers: RustcPrivateCompilers,
3537 target: TargetSelection,
3538}
3539
3540impl Step for CodegenCranelift {
3541 type Output = ();
3542 const DEFAULT: bool = true;
3543 const IS_HOST: bool = true;
3544
3545 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3546 run.paths(&["compiler/rustc_codegen_cranelift"])
3547 }
3548
3549 fn make_run(run: RunConfig<'_>) {
3550 let builder = run.builder;
3551 let host = run.build_triple();
3552 let compilers = RustcPrivateCompilers::new(run.builder, run.builder.top_stage, host);
3553
3554 if builder.doc_tests == DocTests::Only {
3555 return;
3556 }
3557
3558 if builder.download_rustc() {
3559 builder.info("CI rustc uses the default codegen backend. skipping");
3560 return;
3561 }
3562
3563 if !target_supports_cranelift_backend(run.target) {
3564 builder.info("target not supported by rustc_codegen_cranelift. skipping");
3565 return;
3566 }
3567
3568 if builder.remote_tested(run.target) {
3569 builder.info("remote testing is not supported by rustc_codegen_cranelift. skipping");
3570 return;
3571 }
3572
3573 if !builder
3574 .config
3575 .enabled_codegen_backends(run.target)
3576 .contains(&CodegenBackendKind::Cranelift)
3577 {
3578 builder.info("cranelift not in rust.codegen-backends. skipping");
3579 return;
3580 }
3581
3582 builder.ensure(CodegenCranelift { compilers, target: run.target });
3583 }
3584
3585 fn run(self, builder: &Builder<'_>) {
3586 let compilers = self.compilers;
3587 let build_compiler = compilers.build_compiler();
3588
3589 let target_compiler = compilers.target_compiler();
3592 let target = self.target;
3593
3594 builder.std(target_compiler, target);
3595
3596 let mut cargo = builder::Cargo::new(
3597 builder,
3598 target_compiler,
3599 Mode::Codegen, SourceType::InTree,
3601 target,
3602 Kind::Run,
3603 );
3604
3605 cargo.current_dir(&builder.src.join("compiler/rustc_codegen_cranelift"));
3606 cargo
3607 .arg("--manifest-path")
3608 .arg(builder.src.join("compiler/rustc_codegen_cranelift/build_system/Cargo.toml"));
3609 compile::rustc_cargo_env(builder, &mut cargo, target);
3610
3611 cargo.env("CARGO_BUILD_INCREMENTAL", "false");
3613
3614 let _guard = builder.msg_test(
3615 "rustc_codegen_cranelift",
3616 target_compiler.host,
3617 target_compiler.stage,
3618 );
3619
3620 let download_dir = builder.out.join("cg_clif_download");
3622
3623 cargo
3624 .arg("--")
3625 .arg("test")
3626 .arg("--download-dir")
3627 .arg(&download_dir)
3628 .arg("--out-dir")
3629 .arg(builder.stage_out(build_compiler, Mode::Codegen).join("cg_clif"))
3630 .arg("--no-unstable-features")
3631 .arg("--use-backend")
3632 .arg("cranelift")
3633 .arg("--sysroot")
3635 .arg("llvm")
3636 .arg("--skip-test")
3639 .arg("testsuite.extended_sysroot");
3640
3641 cargo.into_cmd().run(builder);
3642 }
3643
3644 fn metadata(&self) -> Option<StepMetadata> {
3645 Some(
3646 StepMetadata::test("rustc_codegen_cranelift", self.target)
3647 .built_by(self.compilers.build_compiler()),
3648 )
3649 }
3650}
3651
3652#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3653pub struct CodegenGCC {
3654 compilers: RustcPrivateCompilers,
3655 target: TargetSelection,
3656}
3657
3658impl Step for CodegenGCC {
3659 type Output = ();
3660 const DEFAULT: bool = true;
3661 const IS_HOST: bool = true;
3662
3663 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3664 run.paths(&["compiler/rustc_codegen_gcc"])
3665 }
3666
3667 fn make_run(run: RunConfig<'_>) {
3668 let builder = run.builder;
3669 let host = run.build_triple();
3670 let compilers = RustcPrivateCompilers::new(run.builder, run.builder.top_stage, host);
3671
3672 if builder.doc_tests == DocTests::Only {
3673 return;
3674 }
3675
3676 if builder.download_rustc() {
3677 builder.info("CI rustc uses the default codegen backend. skipping");
3678 return;
3679 }
3680
3681 let triple = run.target.triple;
3682 let target_supported =
3683 if triple.contains("linux") { triple.contains("x86_64") } else { false };
3684 if !target_supported {
3685 builder.info("target not supported by rustc_codegen_gcc. skipping");
3686 return;
3687 }
3688
3689 if builder.remote_tested(run.target) {
3690 builder.info("remote testing is not supported by rustc_codegen_gcc. skipping");
3691 return;
3692 }
3693
3694 if !builder.config.enabled_codegen_backends(run.target).contains(&CodegenBackendKind::Gcc) {
3695 builder.info("gcc not in rust.codegen-backends. skipping");
3696 return;
3697 }
3698
3699 builder.ensure(CodegenGCC { compilers, target: run.target });
3700 }
3701
3702 fn run(self, builder: &Builder<'_>) {
3703 let compilers = self.compilers;
3704 let target = self.target;
3705
3706 let gcc = builder.ensure(Gcc { target });
3707
3708 builder.ensure(
3709 compile::Std::new(compilers.build_compiler(), target)
3710 .extra_rust_args(&["-Csymbol-mangling-version=v0", "-Cpanic=abort"]),
3711 );
3712
3713 let _guard = builder.msg_test(
3714 "rustc_codegen_gcc",
3715 compilers.target(),
3716 compilers.target_compiler().stage,
3717 );
3718
3719 let mut cargo = builder::Cargo::new(
3720 builder,
3721 compilers.build_compiler(),
3722 Mode::Codegen, SourceType::InTree,
3724 target,
3725 Kind::Run,
3726 );
3727
3728 cargo.current_dir(&builder.src.join("compiler/rustc_codegen_gcc"));
3729 cargo
3730 .arg("--manifest-path")
3731 .arg(builder.src.join("compiler/rustc_codegen_gcc/build_system/Cargo.toml"));
3732 compile::rustc_cargo_env(builder, &mut cargo, target);
3733 add_cg_gcc_cargo_flags(&mut cargo, &gcc);
3734
3735 cargo.env("CARGO_BUILD_INCREMENTAL", "false");
3737 cargo.rustflag("-Cpanic=abort");
3738
3739 cargo
3740 .env("CG_RUSTFLAGS", "-Alinker-messages")
3742 .arg("--")
3743 .arg("test")
3744 .arg("--use-backend")
3745 .arg("gcc")
3746 .arg("--gcc-path")
3747 .arg(gcc.libgccjit.parent().unwrap())
3748 .arg("--out-dir")
3749 .arg(builder.stage_out(compilers.build_compiler(), Mode::Codegen).join("cg_gcc"))
3750 .arg("--release")
3751 .arg("--mini-tests")
3752 .arg("--std-tests");
3753 cargo.args(builder.config.test_args());
3754
3755 cargo.into_cmd().run(builder);
3756 }
3757
3758 fn metadata(&self) -> Option<StepMetadata> {
3759 Some(
3760 StepMetadata::test("rustc_codegen_gcc", self.target)
3761 .built_by(self.compilers.build_compiler()),
3762 )
3763 }
3764}
3765
3766#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3771pub struct TestFloatParse {
3772 build_compiler: Compiler,
3781 target: TargetSelection,
3783}
3784
3785impl Step for TestFloatParse {
3786 type Output = ();
3787 const IS_HOST: bool = true;
3788 const DEFAULT: bool = true;
3789
3790 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3791 run.path("src/tools/test-float-parse")
3792 }
3793
3794 fn make_run(run: RunConfig<'_>) {
3795 run.builder.ensure(Self {
3796 build_compiler: get_compiler_to_test(run.builder, run.target),
3797 target: run.target,
3798 });
3799 }
3800
3801 fn run(self, builder: &Builder<'_>) {
3802 let build_compiler = self.build_compiler;
3803 let target = self.target;
3804
3805 builder.std(build_compiler, target);
3807 builder.std(build_compiler, builder.host_target);
3808
3809 let mut cargo_test = tool::prepare_tool_cargo(
3811 builder,
3812 build_compiler,
3813 Mode::ToolStd,
3814 target,
3815 Kind::Test,
3816 "src/tools/test-float-parse",
3817 SourceType::InTree,
3818 &[],
3819 );
3820 cargo_test.allow_features(TEST_FLOAT_PARSE_ALLOW_FEATURES);
3821
3822 run_cargo_test(cargo_test, &[], &[], "test-float-parse", target, builder);
3823
3824 let mut cargo_run = tool::prepare_tool_cargo(
3826 builder,
3827 build_compiler,
3828 Mode::ToolStd,
3829 target,
3830 Kind::Run,
3831 "src/tools/test-float-parse",
3832 SourceType::InTree,
3833 &[],
3834 );
3835 cargo_run.allow_features(TEST_FLOAT_PARSE_ALLOW_FEATURES);
3836
3837 if !matches!(env::var("FLOAT_PARSE_TESTS_NO_SKIP_HUGE").as_deref(), Ok("1") | Ok("true")) {
3838 cargo_run.args(["--", "--skip-huge"]);
3839 }
3840
3841 cargo_run.into_cmd().run(builder);
3842 }
3843}
3844
3845#[derive(Debug, Clone, Hash, PartialEq, Eq)]
3849pub struct CollectLicenseMetadata;
3850
3851impl Step for CollectLicenseMetadata {
3852 type Output = PathBuf;
3853 const IS_HOST: bool = true;
3854
3855 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3856 run.path("src/tools/collect-license-metadata")
3857 }
3858
3859 fn make_run(run: RunConfig<'_>) {
3860 run.builder.ensure(CollectLicenseMetadata);
3861 }
3862
3863 fn run(self, builder: &Builder<'_>) -> Self::Output {
3864 let Some(reuse) = &builder.config.reuse else {
3865 panic!("REUSE is required to collect the license metadata");
3866 };
3867
3868 let dest = builder.src.join("license-metadata.json");
3869
3870 let mut cmd = builder.tool_cmd(Tool::CollectLicenseMetadata);
3871 cmd.env("REUSE_EXE", reuse);
3872 cmd.env("DEST", &dest);
3873 cmd.env("ONLY_CHECK", "1");
3874 cmd.run(builder);
3875
3876 dest
3877 }
3878}