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;
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, Tool, ToolTargetBuildMode,
22 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
103#[derive(Debug, Clone, PartialEq, Eq, Hash)]
104pub struct Linkcheck {
105 host: TargetSelection,
106}
107
108impl Step for Linkcheck {
109 type Output = ();
110 const IS_HOST: bool = true;
111 const DEFAULT: bool = true;
112
113 fn run(self, builder: &Builder<'_>) {
118 let host = self.host;
119 let hosts = &builder.hosts;
120 let targets = &builder.targets;
121
122 if (hosts != targets) && !hosts.is_empty() && !targets.is_empty() {
127 panic!(
128 "Linkcheck currently does not support builds with different hosts and targets.
129You can skip linkcheck with --skip src/tools/linkchecker"
130 );
131 }
132
133 builder.info(&format!("Linkcheck ({host})"));
134
135 let bootstrap_host = builder.config.host_target;
137 let compiler = builder.compiler(0, bootstrap_host);
138
139 let cargo = tool::prepare_tool_cargo(
140 builder,
141 compiler,
142 Mode::ToolBootstrap,
143 bootstrap_host,
144 Kind::Test,
145 "src/tools/linkchecker",
146 SourceType::InTree,
147 &[],
148 );
149 run_cargo_test(cargo, &[], &[], "linkchecker self tests", bootstrap_host, builder);
150
151 if builder.doc_tests == DocTests::No {
152 return;
153 }
154
155 builder.run_default_doc_steps();
157
158 let linkchecker = builder.tool_cmd(Tool::Linkchecker);
160
161 let _guard = builder.msg(Kind::Test, "Linkcheck", None, compiler, bootstrap_host);
163 let _time = helpers::timeit(builder);
164 linkchecker.delay_failure().arg(builder.out.join(host).join("doc")).run(builder);
165 }
166
167 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
168 let builder = run.builder;
169 let run = run.path("src/tools/linkchecker");
170 run.default_condition(builder.config.docs)
171 }
172
173 fn make_run(run: RunConfig<'_>) {
174 run.builder.ensure(Linkcheck { host: run.target });
175 }
176}
177
178fn check_if_tidy_is_installed(builder: &Builder<'_>) -> bool {
179 command("tidy").allow_failure().arg("--version").run_capture_stdout(builder).is_success()
180}
181
182#[derive(Debug, Clone, PartialEq, Eq, Hash)]
183pub struct HtmlCheck {
184 target: TargetSelection,
185}
186
187impl Step for HtmlCheck {
188 type Output = ();
189 const DEFAULT: bool = true;
190 const IS_HOST: bool = true;
191
192 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
193 let builder = run.builder;
194 let run = run.path("src/tools/html-checker");
195 run.lazy_default_condition(Box::new(|| check_if_tidy_is_installed(builder)))
196 }
197
198 fn make_run(run: RunConfig<'_>) {
199 run.builder.ensure(HtmlCheck { target: run.target });
200 }
201
202 fn run(self, builder: &Builder<'_>) {
203 if !check_if_tidy_is_installed(builder) {
204 eprintln!("not running HTML-check tool because `tidy` is missing");
205 eprintln!(
206 "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."
207 );
208 panic!("Cannot run html-check tests");
209 }
210 builder.run_default_doc_steps();
212 builder.ensure(crate::core::build_steps::doc::Rustc::for_stage(
213 builder,
214 builder.top_stage,
215 self.target,
216 ));
217
218 builder
219 .tool_cmd(Tool::HtmlChecker)
220 .delay_failure()
221 .arg(builder.doc_out(self.target))
222 .run(builder);
223 }
224}
225
226#[derive(Debug, Clone, PartialEq, Eq, Hash)]
230pub struct Cargotest {
231 build_compiler: Compiler,
232 host: TargetSelection,
233}
234
235impl Step for Cargotest {
236 type Output = ();
237 const IS_HOST: bool = true;
238
239 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
240 run.path("src/tools/cargotest")
241 }
242
243 fn make_run(run: RunConfig<'_>) {
244 if run.builder.top_stage == 0 {
245 eprintln!(
246 "ERROR: running cargotest with stage 0 is currently unsupported. Use at least stage 1."
247 );
248 exit!(1);
249 }
250 run.builder.ensure(Cargotest {
254 build_compiler: run.builder.compiler(run.builder.top_stage - 1, run.target),
255 host: run.target,
256 });
257 }
258
259 fn run(self, builder: &Builder<'_>) {
264 let cargo =
274 builder.ensure(tool::Cargo::from_build_compiler(self.build_compiler, self.host));
275 let tested_compiler = builder.compiler(self.build_compiler.stage + 1, self.host);
276 builder.std(tested_compiler, self.host);
277
278 let out_dir = builder.out.join("ct");
282 t!(fs::create_dir_all(&out_dir));
283
284 let _time = helpers::timeit(builder);
285 let mut cmd = builder.tool_cmd(Tool::CargoTest);
286 cmd.arg(&cargo.tool_path)
287 .arg(&out_dir)
288 .args(builder.config.test_args())
289 .env("RUSTC", builder.rustc(tested_compiler))
290 .env("RUSTDOC", builder.rustdoc_for_compiler(tested_compiler));
291 add_rustdoc_cargo_linker_args(&mut cmd, builder, tested_compiler.host, LldThreads::No);
292 cmd.delay_failure().run(builder);
293 }
294
295 fn metadata(&self) -> Option<StepMetadata> {
296 Some(StepMetadata::test("cargotest", self.host).stage(self.build_compiler.stage + 1))
297 }
298}
299
300#[derive(Debug, Clone, PartialEq, Eq, Hash)]
303pub struct Cargo {
304 build_compiler: Compiler,
305 host: TargetSelection,
306}
307
308impl Cargo {
309 const CRATE_PATH: &str = "src/tools/cargo";
310}
311
312impl Step for Cargo {
313 type Output = ();
314 const IS_HOST: bool = true;
315
316 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
317 run.path(Self::CRATE_PATH)
318 }
319
320 fn make_run(run: RunConfig<'_>) {
321 run.builder.ensure(Cargo {
322 build_compiler: get_tool_target_compiler(
323 run.builder,
324 ToolTargetBuildMode::Build(run.target),
325 ),
326 host: run.target,
327 });
328 }
329
330 fn run(self, builder: &Builder<'_>) {
332 builder.ensure(tool::Cargo::from_build_compiler(self.build_compiler, self.host));
336
337 let tested_compiler = builder.compiler(self.build_compiler.stage + 1, self.host);
338 builder.std(tested_compiler, self.host);
339 builder.rustdoc_for_compiler(tested_compiler);
343
344 let cargo = tool::prepare_tool_cargo(
345 builder,
346 self.build_compiler,
347 Mode::ToolTarget,
348 self.host,
349 Kind::Test,
350 Self::CRATE_PATH,
351 SourceType::Submodule,
352 &[],
353 );
354
355 let mut cargo = prepare_cargo_test(cargo, &[], &[], self.host, builder);
357
358 cargo.env("CFG_DISABLE_CROSS_TESTS", "1");
361 cargo.env("CARGO_TEST_DISABLE_NIGHTLY", "1");
364
365 cargo.env("PATH", bin_path_for_cargo(builder, tested_compiler));
369
370 let mut existing_dylib_paths = cargo
375 .get_envs()
376 .find(|(k, _)| *k == OsStr::new(dylib_path_var()))
377 .and_then(|(_, v)| v)
378 .map(|value| split_paths(value).collect::<Vec<PathBuf>>())
379 .unwrap_or_default();
380 existing_dylib_paths.insert(0, builder.rustc_libdir(tested_compiler));
381 add_dylib_path(existing_dylib_paths, &mut cargo);
382
383 cargo.env("CARGO_RUSTC_CURRENT_DIR", builder.src.display().to_string());
387
388 #[cfg(feature = "build-metrics")]
389 builder.metrics.begin_test_suite(
390 build_helper::metrics::TestSuiteMetadata::CargoPackage {
391 crates: vec!["cargo".into()],
392 target: self.host.triple.to_string(),
393 host: self.host.triple.to_string(),
394 stage: self.build_compiler.stage + 1,
395 },
396 builder,
397 );
398
399 let _time = helpers::timeit(builder);
400 add_flags_and_try_run_tests(builder, &mut cargo);
401 }
402}
403
404#[derive(Debug, Clone, PartialEq, Eq, Hash)]
405pub struct RustAnalyzer {
406 compilers: RustcPrivateCompilers,
407}
408
409impl Step for RustAnalyzer {
410 type Output = ();
411 const IS_HOST: bool = true;
412 const DEFAULT: bool = true;
413
414 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
415 run.path("src/tools/rust-analyzer")
416 }
417
418 fn make_run(run: RunConfig<'_>) {
419 run.builder.ensure(Self {
420 compilers: RustcPrivateCompilers::new(
421 run.builder,
422 run.builder.top_stage,
423 run.builder.host_target,
424 ),
425 });
426 }
427
428 fn run(self, builder: &Builder<'_>) {
430 let host = self.compilers.target();
431
432 let workspace_path = "src/tools/rust-analyzer";
433 let crate_path = "src/tools/rust-analyzer/crates/proc-macro-srv";
436 let mut cargo = tool::prepare_tool_cargo(
437 builder,
438 self.compilers.build_compiler(),
439 Mode::ToolRustc,
440 host,
441 Kind::Test,
442 crate_path,
443 SourceType::InTree,
444 &["in-rust-tree".to_owned()],
445 );
446 cargo.allow_features(tool::RustAnalyzer::ALLOW_FEATURES);
447
448 let dir = builder.src.join(workspace_path);
449 cargo.env("CARGO_WORKSPACE_DIR", &dir);
452
453 cargo.env("SKIP_SLOW_TESTS", "1");
456
457 cargo.add_rustc_lib_path(builder);
458 run_cargo_test(cargo, &[], &[], "rust-analyzer", host, builder);
459 }
460}
461
462#[derive(Debug, Clone, PartialEq, Eq, Hash)]
464pub struct Rustfmt {
465 compilers: RustcPrivateCompilers,
466}
467
468impl Step for Rustfmt {
469 type Output = ();
470 const IS_HOST: bool = true;
471
472 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
473 run.path("src/tools/rustfmt")
474 }
475
476 fn make_run(run: RunConfig<'_>) {
477 run.builder.ensure(Rustfmt {
478 compilers: RustcPrivateCompilers::new(
479 run.builder,
480 run.builder.top_stage,
481 run.builder.host_target,
482 ),
483 });
484 }
485
486 fn run(self, builder: &Builder<'_>) {
488 let tool_result = builder.ensure(tool::Rustfmt::from_compilers(self.compilers));
489 let build_compiler = tool_result.build_compiler;
490 let target = self.compilers.target();
491
492 let mut cargo = tool::prepare_tool_cargo(
493 builder,
494 build_compiler,
495 Mode::ToolRustc,
496 target,
497 Kind::Test,
498 "src/tools/rustfmt",
499 SourceType::InTree,
500 &[],
501 );
502
503 let dir = testdir(builder, target);
504 t!(fs::create_dir_all(&dir));
505 cargo.env("RUSTFMT_TEST_DIR", dir);
506
507 cargo.add_rustc_lib_path(builder);
508
509 run_cargo_test(cargo, &[], &[], "rustfmt", target, builder);
510 }
511}
512
513#[derive(Debug, Clone, PartialEq, Eq, Hash)]
514pub struct Miri {
515 target: TargetSelection,
516}
517
518impl Miri {
519 pub fn build_miri_sysroot(
521 builder: &Builder<'_>,
522 compiler: Compiler,
523 target: TargetSelection,
524 ) -> PathBuf {
525 let miri_sysroot = builder.out.join(compiler.host).join("miri-sysroot");
526 let mut cargo = builder::Cargo::new(
527 builder,
528 compiler,
529 Mode::Std,
530 SourceType::Submodule,
531 target,
532 Kind::MiriSetup,
533 );
534
535 cargo.env("MIRI_LIB_SRC", builder.src.join("library"));
537 cargo.env("MIRI_SYSROOT", &miri_sysroot);
539
540 let mut cargo = BootstrapCommand::from(cargo);
541 let _guard = builder.msg(Kind::Build, "miri sysroot", Mode::ToolRustc, compiler, target);
542 cargo.run(builder);
543
544 cargo.arg("--print-sysroot");
550
551 builder.verbose(|| println!("running: {cargo:?}"));
552 let stdout = cargo.run_capture_stdout(builder).stdout();
553 let sysroot = stdout.trim_end();
555 builder.verbose(|| println!("`cargo miri setup --print-sysroot` said: {sysroot:?}"));
556 PathBuf::from(sysroot)
557 }
558}
559
560impl Step for Miri {
561 type Output = ();
562
563 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
564 run.path("src/tools/miri")
565 }
566
567 fn make_run(run: RunConfig<'_>) {
568 run.builder.ensure(Miri { target: run.target });
569 }
570
571 fn run(self, builder: &Builder<'_>) {
573 let host = builder.build.host_target;
574 let target = self.target;
575 let stage = builder.top_stage;
576 if stage == 0 {
577 eprintln!("miri cannot be tested at stage 0");
578 std::process::exit(1);
579 }
580
581 let compilers = RustcPrivateCompilers::new(builder, stage, host);
583
584 let miri = builder.ensure(tool::Miri::from_compilers(compilers));
586 builder.ensure(tool::CargoMiri::from_compilers(compilers));
588
589 let target_compiler = compilers.target_compiler();
590
591 let miri_sysroot = Miri::build_miri_sysroot(builder, target_compiler, target);
594 builder.std(target_compiler, host);
595 let host_sysroot = builder.sysroot(target_compiler);
596
597 if !builder.config.dry_run() {
600 let ui_test_dep_dir = builder
603 .stage_out(miri.build_compiler, Mode::ToolStd)
604 .join(host)
605 .join("tmp")
606 .join("miri_ui");
607 build_stamp::clear_if_dirty(builder, &ui_test_dep_dir, &miri_sysroot);
611 }
612
613 let mut cargo = tool::prepare_tool_cargo(
616 builder,
617 miri.build_compiler,
618 Mode::ToolRustc,
619 host,
620 Kind::Test,
621 "src/tools/miri",
622 SourceType::InTree,
623 &[],
624 );
625
626 cargo.add_rustc_lib_path(builder);
627
628 let mut cargo = prepare_cargo_test(cargo, &[], &[], host, builder);
631
632 cargo.env("MIRI_SYSROOT", &miri_sysroot);
634 cargo.env("MIRI_HOST_SYSROOT", &host_sysroot);
635 cargo.env("MIRI", &miri.tool_path);
636
637 cargo.env("MIRI_TEST_TARGET", target.rustc_target_arg());
639
640 {
641 let _guard =
642 builder.msg(Kind::Test, "miri", Mode::ToolRustc, miri.build_compiler, target);
643 let _time = helpers::timeit(builder);
644 cargo.run(builder);
645 }
646
647 if builder.config.test_args().is_empty() {
649 cargo.env("MIRIFLAGS", "-O -Zmir-opt-level=4 -Cdebug-assertions=yes");
650 cargo.env("MIRI_SKIP_UI_CHECKS", "1");
652 cargo.env_remove("RUSTC_BLESS");
654 cargo.args(["tests/pass", "tests/panic"]);
656
657 {
658 let _guard = builder.msg(
659 Kind::Test,
660 "miri (mir-opt-level 4)",
661 Mode::ToolRustc,
662 miri.build_compiler,
663 target,
664 );
665 let _time = helpers::timeit(builder);
666 cargo.run(builder);
667 }
668 }
669 }
670}
671
672#[derive(Debug, Clone, PartialEq, Eq, Hash)]
675pub struct CargoMiri {
676 target: TargetSelection,
677}
678
679impl Step for CargoMiri {
680 type Output = ();
681
682 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
683 run.path("src/tools/miri/cargo-miri")
684 }
685
686 fn make_run(run: RunConfig<'_>) {
687 run.builder.ensure(CargoMiri { target: run.target });
688 }
689
690 fn run(self, builder: &Builder<'_>) {
692 let host = builder.build.host_target;
693 let target = self.target;
694 let stage = builder.top_stage;
695 if stage == 0 {
696 eprintln!("cargo-miri cannot be tested at stage 0");
697 std::process::exit(1);
698 }
699
700 let build_compiler = builder.compiler(stage, host);
702
703 let mut cargo = tool::prepare_tool_cargo(
708 builder,
709 build_compiler,
710 Mode::ToolStd, target,
712 Kind::MiriTest,
713 "src/tools/miri/test-cargo-miri",
714 SourceType::Submodule,
715 &[],
716 );
717
718 match builder.doc_tests {
721 DocTests::Yes => {}
722 DocTests::No => {
723 cargo.args(["--lib", "--bins", "--examples", "--tests", "--benches"]);
724 }
725 DocTests::Only => {
726 cargo.arg("--doc");
727 }
728 }
729 cargo.arg("--").args(builder.config.test_args());
730
731 let mut cargo = BootstrapCommand::from(cargo);
733 {
734 let _guard =
735 builder.msg(Kind::Test, "cargo-miri", Mode::ToolRustc, (host, stage), target);
736 let _time = helpers::timeit(builder);
737 cargo.run(builder);
738 }
739 }
740}
741
742#[derive(Debug, Clone, PartialEq, Eq, Hash)]
743pub struct CompiletestTest {
744 host: TargetSelection,
745}
746
747impl Step for CompiletestTest {
748 type Output = ();
749
750 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
751 run.path("src/tools/compiletest")
752 }
753
754 fn make_run(run: RunConfig<'_>) {
755 run.builder.ensure(CompiletestTest { host: run.target });
756 }
757
758 fn run(self, builder: &Builder<'_>) {
760 let host = self.host;
761
762 if builder.top_stage == 0 && !builder.config.compiletest_allow_stage0 {
763 eprintln!("\
764ERROR: `--stage 0` runs compiletest self-tests against the stage0 (precompiled) compiler, not the in-tree compiler, and will almost always cause tests to fail
765NOTE: 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`."
766 );
767 crate::exit!(1);
768 }
769
770 let compiler = builder.compiler(builder.top_stage, host);
771 debug!(?compiler);
772
773 builder.std(compiler, host);
776 let mut cargo = tool::prepare_tool_cargo(
777 builder,
778 compiler,
779 Mode::ToolStd,
782 host,
783 Kind::Test,
784 "src/tools/compiletest",
785 SourceType::InTree,
786 &[],
787 );
788
789 cargo.env("TEST_RUSTC", builder.rustc(compiler));
793
794 cargo.allow_features(COMPILETEST_ALLOW_FEATURES);
795 run_cargo_test(cargo, &[], &[], "compiletest self test", host, builder);
796 }
797}
798
799#[derive(Debug, Clone, PartialEq, Eq, Hash)]
800pub struct Clippy {
801 compilers: RustcPrivateCompilers,
802}
803
804impl Step for Clippy {
805 type Output = ();
806 const IS_HOST: bool = true;
807 const DEFAULT: bool = false;
808
809 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
810 run.suite_path("src/tools/clippy/tests").path("src/tools/clippy")
811 }
812
813 fn make_run(run: RunConfig<'_>) {
814 run.builder.ensure(Clippy {
815 compilers: RustcPrivateCompilers::new(
816 run.builder,
817 run.builder.top_stage,
818 run.builder.host_target,
819 ),
820 });
821 }
822
823 fn run(self, builder: &Builder<'_>) {
825 let target = self.compilers.target();
826
827 let compilers = self.compilers;
831 let target_compiler = compilers.target_compiler();
832
833 let tool_result = builder.ensure(tool::Clippy::from_compilers(compilers));
834 let build_compiler = tool_result.build_compiler;
835 let mut cargo = tool::prepare_tool_cargo(
836 builder,
837 build_compiler,
838 Mode::ToolRustc,
839 target,
840 Kind::Test,
841 "src/tools/clippy",
842 SourceType::InTree,
843 &[],
844 );
845
846 cargo.env("RUSTC_TEST_SUITE", builder.rustc(build_compiler));
847 cargo.env("RUSTC_LIB_PATH", builder.rustc_libdir(build_compiler));
848 let host_libs =
849 builder.stage_out(build_compiler, Mode::ToolRustc).join(builder.cargo_dir());
850 cargo.env("HOST_LIBS", host_libs);
851
852 builder.std(target_compiler, target);
854 cargo.env("TEST_SYSROOT", builder.sysroot(target_compiler));
855 cargo.env("TEST_RUSTC", builder.rustc(target_compiler));
856 cargo.env("TEST_RUSTC_LIB", builder.rustc_libdir(target_compiler));
857
858 'partially_test: {
860 let paths = &builder.config.paths[..];
861 let mut test_names = Vec::new();
862 for path in paths {
863 if let Some(path) =
864 helpers::is_valid_test_suite_arg(path, "src/tools/clippy/tests", builder)
865 {
866 test_names.push(path);
867 } else if path.ends_with("src/tools/clippy") {
868 break 'partially_test;
870 }
871 }
872 cargo.env("TESTNAME", test_names.join(","));
873 }
874
875 cargo.add_rustc_lib_path(builder);
876 let cargo = prepare_cargo_test(cargo, &[], &[], target, builder);
877
878 let _guard = builder.msg(Kind::Test, "clippy", Mode::ToolRustc, build_compiler, target);
879
880 if cargo.allow_failure().run(builder) {
882 return;
884 }
885
886 if !builder.config.cmd.bless() {
887 crate::exit!(1);
888 }
889 }
890}
891
892fn bin_path_for_cargo(builder: &Builder<'_>, compiler: Compiler) -> OsString {
893 let path = builder.sysroot(compiler).join("bin");
894 let old_path = env::var_os("PATH").unwrap_or_default();
895 env::join_paths(iter::once(path).chain(env::split_paths(&old_path))).expect("")
896}
897
898#[derive(Debug, Clone, Hash, PartialEq, Eq)]
899pub struct RustdocTheme {
900 pub compiler: Compiler,
901}
902
903impl Step for RustdocTheme {
904 type Output = ();
905 const DEFAULT: bool = true;
906 const IS_HOST: bool = true;
907
908 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
909 run.path("src/tools/rustdoc-themes")
910 }
911
912 fn make_run(run: RunConfig<'_>) {
913 let compiler = run.builder.compiler(run.builder.top_stage, run.target);
914
915 run.builder.ensure(RustdocTheme { compiler });
916 }
917
918 fn run(self, builder: &Builder<'_>) {
919 let rustdoc = builder.bootstrap_out.join("rustdoc");
920 let mut cmd = builder.tool_cmd(Tool::RustdocTheme);
921 cmd.arg(rustdoc.to_str().unwrap())
922 .arg(builder.src.join("src/librustdoc/html/static/css/rustdoc.css").to_str().unwrap())
923 .env("RUSTC_STAGE", self.compiler.stage.to_string())
924 .env("RUSTC_SYSROOT", builder.sysroot(self.compiler))
925 .env("RUSTDOC_LIBDIR", builder.sysroot_target_libdir(self.compiler, self.compiler.host))
926 .env("CFG_RELEASE_CHANNEL", &builder.config.channel)
927 .env("RUSTDOC_REAL", builder.rustdoc_for_compiler(self.compiler))
928 .env("RUSTC_BOOTSTRAP", "1");
929 cmd.args(linker_args(builder, self.compiler.host, LldThreads::No));
930
931 cmd.delay_failure().run(builder);
932 }
933}
934
935#[derive(Debug, Clone, Hash, PartialEq, Eq)]
936pub struct RustdocJSStd {
937 pub target: TargetSelection,
938}
939
940impl Step for RustdocJSStd {
941 type Output = ();
942 const DEFAULT: bool = true;
943 const IS_HOST: bool = true;
944
945 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
946 let default = run.builder.config.nodejs.is_some();
947 run.suite_path("tests/rustdoc-js-std").default_condition(default)
948 }
949
950 fn make_run(run: RunConfig<'_>) {
951 run.builder.ensure(RustdocJSStd { target: run.target });
952 }
953
954 fn run(self, builder: &Builder<'_>) {
955 let nodejs =
956 builder.config.nodejs.as_ref().expect("need nodejs to run rustdoc-js-std tests");
957 let mut command = command(nodejs);
958 command
959 .arg(builder.src.join("src/tools/rustdoc-js/tester.js"))
960 .arg("--crate-name")
961 .arg("std")
962 .arg("--resource-suffix")
963 .arg(&builder.version)
964 .arg("--doc-folder")
965 .arg(builder.doc_out(self.target))
966 .arg("--test-folder")
967 .arg(builder.src.join("tests/rustdoc-js-std"));
968 for path in &builder.paths {
969 if let Some(p) = helpers::is_valid_test_suite_arg(path, "tests/rustdoc-js-std", builder)
970 {
971 if !p.ends_with(".js") {
972 eprintln!("A non-js file was given: `{}`", path.display());
973 panic!("Cannot run rustdoc-js-std tests");
974 }
975 command.arg("--test-file").arg(path);
976 }
977 }
978 builder.ensure(crate::core::build_steps::doc::Std::from_build_compiler(
979 builder.compiler(builder.top_stage, builder.host_target),
980 self.target,
981 DocumentationFormat::Html,
982 ));
983 let _guard = builder.msg(
984 Kind::Test,
985 "rustdoc-js-std",
986 None,
987 (builder.config.host_target, builder.top_stage),
988 self.target,
989 );
990 command.run(builder);
991 }
992}
993
994#[derive(Debug, Clone, Hash, PartialEq, Eq)]
995pub struct RustdocJSNotStd {
996 pub target: TargetSelection,
997 pub compiler: Compiler,
998}
999
1000impl Step for RustdocJSNotStd {
1001 type Output = ();
1002 const DEFAULT: bool = true;
1003 const IS_HOST: bool = true;
1004
1005 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1006 let default = run.builder.config.nodejs.is_some();
1007 run.suite_path("tests/rustdoc-js").default_condition(default)
1008 }
1009
1010 fn make_run(run: RunConfig<'_>) {
1011 let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1012 run.builder.ensure(RustdocJSNotStd { target: run.target, compiler });
1013 }
1014
1015 fn run(self, builder: &Builder<'_>) {
1016 builder.ensure(Compiletest {
1017 compiler: self.compiler,
1018 target: self.target,
1019 mode: "rustdoc-js",
1020 suite: "rustdoc-js",
1021 path: "tests/rustdoc-js",
1022 compare_mode: None,
1023 });
1024 }
1025}
1026
1027fn get_browser_ui_test_version_inner(
1028 builder: &Builder<'_>,
1029 npm: &Path,
1030 global: bool,
1031) -> Option<String> {
1032 let mut command = command(npm);
1033 command.arg("list").arg("--parseable").arg("--long").arg("--depth=0");
1034 if global {
1035 command.arg("--global");
1036 }
1037 let lines = command.allow_failure().run_capture(builder).stdout();
1038 lines
1039 .lines()
1040 .find_map(|l| l.split(':').nth(1)?.strip_prefix("browser-ui-test@"))
1041 .map(|v| v.to_owned())
1042}
1043
1044fn get_browser_ui_test_version(builder: &Builder<'_>, npm: &Path) -> Option<String> {
1045 get_browser_ui_test_version_inner(builder, npm, false)
1046 .or_else(|| get_browser_ui_test_version_inner(builder, npm, true))
1047}
1048
1049#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1050pub struct RustdocGUI {
1051 pub target: TargetSelection,
1052 pub compiler: Compiler,
1053}
1054
1055impl Step for RustdocGUI {
1056 type Output = ();
1057 const DEFAULT: bool = true;
1058 const IS_HOST: bool = true;
1059
1060 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1061 let builder = run.builder;
1062 let run = run.suite_path("tests/rustdoc-gui");
1063 run.lazy_default_condition(Box::new(move || {
1064 builder.config.nodejs.is_some()
1065 && builder.doc_tests != DocTests::Only
1066 && builder
1067 .config
1068 .npm
1069 .as_ref()
1070 .map(|p| get_browser_ui_test_version(builder, p).is_some())
1071 .unwrap_or(false)
1072 }))
1073 }
1074
1075 fn make_run(run: RunConfig<'_>) {
1076 let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1077 run.builder.ensure(RustdocGUI { target: run.target, compiler });
1078 }
1079
1080 fn run(self, builder: &Builder<'_>) {
1081 builder.std(self.compiler, self.target);
1082
1083 let mut cmd = builder.tool_cmd(Tool::RustdocGUITest);
1084
1085 let out_dir = builder.test_out(self.target).join("rustdoc-gui");
1086 build_stamp::clear_if_dirty(
1087 builder,
1088 &out_dir,
1089 &builder.rustdoc_for_compiler(self.compiler),
1090 );
1091
1092 if let Some(src) = builder.config.src.to_str() {
1093 cmd.arg("--rust-src").arg(src);
1094 }
1095
1096 if let Some(out_dir) = out_dir.to_str() {
1097 cmd.arg("--out-dir").arg(out_dir);
1098 }
1099
1100 if let Some(initial_cargo) = builder.config.initial_cargo.to_str() {
1101 cmd.arg("--initial-cargo").arg(initial_cargo);
1102 }
1103
1104 cmd.arg("--jobs").arg(builder.jobs().to_string());
1105
1106 cmd.env("RUSTDOC", builder.rustdoc_for_compiler(self.compiler))
1107 .env("RUSTC", builder.rustc(self.compiler));
1108
1109 add_rustdoc_cargo_linker_args(&mut cmd, builder, self.compiler.host, LldThreads::No);
1110
1111 for path in &builder.paths {
1112 if let Some(p) = helpers::is_valid_test_suite_arg(path, "tests/rustdoc-gui", builder) {
1113 if !p.ends_with(".goml") {
1114 eprintln!("A non-goml file was given: `{}`", path.display());
1115 panic!("Cannot run rustdoc-gui tests");
1116 }
1117 if let Some(name) = path.file_name().and_then(|f| f.to_str()) {
1118 cmd.arg("--goml-file").arg(name);
1119 }
1120 }
1121 }
1122
1123 for test_arg in builder.config.test_args() {
1124 cmd.arg("--test-arg").arg(test_arg);
1125 }
1126
1127 if let Some(ref nodejs) = builder.config.nodejs {
1128 cmd.arg("--nodejs").arg(nodejs);
1129 }
1130
1131 if let Some(ref npm) = builder.config.npm {
1132 cmd.arg("--npm").arg(npm);
1133 }
1134
1135 let _time = helpers::timeit(builder);
1136 let _guard = builder.msg(Kind::Test, "rustdoc-gui", None, self.compiler, self.target);
1137 try_run_tests(builder, &mut cmd, true);
1138 }
1139}
1140
1141#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1146pub struct Tidy;
1147
1148impl Step for Tidy {
1149 type Output = ();
1150 const DEFAULT: bool = true;
1151 const IS_HOST: bool = true;
1152
1153 fn run(self, builder: &Builder<'_>) {
1162 let mut cmd = builder.tool_cmd(Tool::Tidy);
1163 cmd.arg(&builder.src);
1164 cmd.arg(&builder.initial_cargo);
1165 cmd.arg(&builder.out);
1166 let jobs = builder.config.jobs.unwrap_or_else(|| {
1168 8 * std::thread::available_parallelism().map_or(1, std::num::NonZeroUsize::get) as u32
1169 });
1170 cmd.arg(jobs.to_string());
1171 if let Some(npm) = &builder.config.npm {
1173 cmd.arg(npm);
1174 } else {
1175 cmd.arg("npm");
1176 }
1177 if builder.is_verbose() {
1178 cmd.arg("--verbose");
1179 }
1180 if builder.config.cmd.bless() {
1181 cmd.arg("--bless");
1182 }
1183 if let Some(s) =
1184 builder.config.cmd.extra_checks().or(builder.config.tidy_extra_checks.as_deref())
1185 {
1186 cmd.arg(format!("--extra-checks={s}"));
1187 }
1188 let mut args = std::env::args_os();
1189 if args.any(|arg| arg == OsStr::new("--")) {
1190 cmd.arg("--");
1191 cmd.args(args);
1192 }
1193
1194 if builder.config.channel == "dev" || builder.config.channel == "nightly" {
1195 if !builder.config.json_output {
1196 builder.info("fmt check");
1197 if builder.config.initial_rustfmt.is_none() {
1198 let inferred_rustfmt_dir = builder.initial_sysroot.join("bin");
1199 eprintln!(
1200 "\
1201ERROR: no `rustfmt` binary found in {PATH}
1202INFO: `rust.channel` is currently set to \"{CHAN}\"
1203HELP: if you are testing a beta branch, set `rust.channel` to \"beta\" in the `bootstrap.toml` file
1204HELP: to skip test's attempt to check tidiness, pass `--skip src/tools/tidy` to `x.py test`",
1205 PATH = inferred_rustfmt_dir.display(),
1206 CHAN = builder.config.channel,
1207 );
1208 crate::exit!(1);
1209 }
1210 let all = false;
1211 crate::core::build_steps::format::format(
1212 builder,
1213 !builder.config.cmd.bless(),
1214 all,
1215 &[],
1216 );
1217 } else {
1218 eprintln!(
1219 "WARNING: `--json-output` is not supported on rustfmt, formatting will be skipped"
1220 );
1221 }
1222 }
1223
1224 builder.info("tidy check");
1225 cmd.delay_failure().run(builder);
1226
1227 builder.info("x.py completions check");
1228 let completion_paths = get_completion_paths(builder);
1229 if builder.config.cmd.bless() {
1230 builder.ensure(crate::core::build_steps::run::GenerateCompletions);
1231 } else if completion_paths
1232 .into_iter()
1233 .any(|(shell, path)| get_completion(shell, &path).is_some())
1234 {
1235 eprintln!(
1236 "x.py completions were changed; run `x.py run generate-completions` to update them"
1237 );
1238 crate::exit!(1);
1239 }
1240 }
1241
1242 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1243 let default = run.builder.doc_tests != DocTests::Only;
1244 run.path("src/tools/tidy").default_condition(default)
1245 }
1246
1247 fn make_run(run: RunConfig<'_>) {
1248 run.builder.ensure(Tidy);
1249 }
1250
1251 fn metadata(&self) -> Option<StepMetadata> {
1252 Some(StepMetadata::test("tidy", TargetSelection::default()))
1253 }
1254}
1255
1256fn testdir(builder: &Builder<'_>, host: TargetSelection) -> PathBuf {
1257 builder.out.join(host).join("test")
1258}
1259
1260macro_rules! test {
1262 (
1263 $( #[$attr:meta] )* $name:ident {
1265 path: $path:expr,
1266 mode: $mode:expr,
1267 suite: $suite:expr,
1268 default: $default:expr
1269 $( , IS_HOST: $IS_HOST:expr )? $( , compare_mode: $compare_mode:expr )? $( , )? }
1273 ) => {
1274 $( #[$attr] )*
1275 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
1276 pub struct $name {
1277 pub compiler: Compiler,
1278 pub target: TargetSelection,
1279 }
1280
1281 impl Step for $name {
1282 type Output = ();
1283 const DEFAULT: bool = $default;
1284 const IS_HOST: bool = (const {
1285 #[allow(unused_assignments, unused_mut)]
1286 let mut value = false;
1287 $( value = $IS_HOST; )?
1288 value
1289 });
1290
1291 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1292 run.suite_path($path)
1293 }
1294
1295 fn make_run(run: RunConfig<'_>) {
1296 let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1297
1298 run.builder.ensure($name { compiler, target: run.target });
1299 }
1300
1301 fn run(self, builder: &Builder<'_>) {
1302 builder.ensure(Compiletest {
1303 compiler: self.compiler,
1304 target: self.target,
1305 mode: $mode,
1306 suite: $suite,
1307 path: $path,
1308 compare_mode: (const {
1309 #[allow(unused_assignments, unused_mut)]
1310 let mut value = None;
1311 $( value = $compare_mode; )?
1312 value
1313 }),
1314 })
1315 }
1316
1317 fn metadata(&self) -> Option<StepMetadata> {
1318 Some(
1319 StepMetadata::test(stringify!($name), self.target)
1320 )
1321 }
1322 }
1323 };
1324}
1325
1326#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1329pub struct CrateRunMakeSupport {
1330 host: TargetSelection,
1331}
1332
1333impl Step for CrateRunMakeSupport {
1334 type Output = ();
1335 const IS_HOST: bool = true;
1336
1337 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1338 run.path("src/tools/run-make-support")
1339 }
1340
1341 fn make_run(run: RunConfig<'_>) {
1342 run.builder.ensure(CrateRunMakeSupport { host: run.target });
1343 }
1344
1345 fn run(self, builder: &Builder<'_>) {
1347 let host = self.host;
1348 let compiler = builder.compiler(0, host);
1349
1350 let mut cargo = tool::prepare_tool_cargo(
1351 builder,
1352 compiler,
1353 Mode::ToolBootstrap,
1354 host,
1355 Kind::Test,
1356 "src/tools/run-make-support",
1357 SourceType::InTree,
1358 &[],
1359 );
1360 cargo.allow_features("test");
1361 run_cargo_test(cargo, &[], &[], "run-make-support self test", host, builder);
1362 }
1363}
1364
1365#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1366pub struct CrateBuildHelper {
1367 host: TargetSelection,
1368}
1369
1370impl Step for CrateBuildHelper {
1371 type Output = ();
1372 const IS_HOST: bool = true;
1373
1374 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1375 run.path("src/build_helper")
1376 }
1377
1378 fn make_run(run: RunConfig<'_>) {
1379 run.builder.ensure(CrateBuildHelper { host: run.target });
1380 }
1381
1382 fn run(self, builder: &Builder<'_>) {
1384 let host = self.host;
1385 let compiler = builder.compiler(0, host);
1386
1387 let mut cargo = tool::prepare_tool_cargo(
1388 builder,
1389 compiler,
1390 Mode::ToolBootstrap,
1391 host,
1392 Kind::Test,
1393 "src/build_helper",
1394 SourceType::InTree,
1395 &[],
1396 );
1397 cargo.allow_features("test");
1398 run_cargo_test(cargo, &[], &[], "build_helper self test", host, builder);
1399 }
1400}
1401
1402test!(Ui { path: "tests/ui", mode: "ui", suite: "ui", default: true });
1403
1404test!(Crashes { path: "tests/crashes", mode: "crashes", suite: "crashes", default: true });
1405
1406test!(CodegenLlvm {
1407 path: "tests/codegen-llvm",
1408 mode: "codegen",
1409 suite: "codegen-llvm",
1410 default: true
1411});
1412
1413test!(CodegenUnits {
1414 path: "tests/codegen-units",
1415 mode: "codegen-units",
1416 suite: "codegen-units",
1417 default: true,
1418});
1419
1420test!(Incremental {
1421 path: "tests/incremental",
1422 mode: "incremental",
1423 suite: "incremental",
1424 default: true,
1425});
1426
1427test!(Debuginfo {
1428 path: "tests/debuginfo",
1429 mode: "debuginfo",
1430 suite: "debuginfo",
1431 default: true,
1432 compare_mode: Some("split-dwarf"),
1433});
1434
1435test!(UiFullDeps {
1436 path: "tests/ui-fulldeps",
1437 mode: "ui",
1438 suite: "ui-fulldeps",
1439 default: true,
1440 IS_HOST: true,
1441});
1442
1443test!(Rustdoc {
1444 path: "tests/rustdoc",
1445 mode: "rustdoc",
1446 suite: "rustdoc",
1447 default: true,
1448 IS_HOST: true,
1449});
1450test!(RustdocUi {
1451 path: "tests/rustdoc-ui",
1452 mode: "ui",
1453 suite: "rustdoc-ui",
1454 default: true,
1455 IS_HOST: true,
1456});
1457
1458test!(RustdocJson {
1459 path: "tests/rustdoc-json",
1460 mode: "rustdoc-json",
1461 suite: "rustdoc-json",
1462 default: true,
1463 IS_HOST: true,
1464});
1465
1466test!(Pretty {
1467 path: "tests/pretty",
1468 mode: "pretty",
1469 suite: "pretty",
1470 default: true,
1471 IS_HOST: true,
1472});
1473
1474test!(RunMake { path: "tests/run-make", mode: "run-make", suite: "run-make", default: true });
1475
1476test!(AssemblyLlvm {
1477 path: "tests/assembly-llvm",
1478 mode: "assembly",
1479 suite: "assembly-llvm",
1480 default: true
1481});
1482
1483#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
1486pub struct Coverage {
1487 pub compiler: Compiler,
1488 pub target: TargetSelection,
1489 pub mode: &'static str,
1490}
1491
1492impl Coverage {
1493 const PATH: &'static str = "tests/coverage";
1494 const SUITE: &'static str = "coverage";
1495 const ALL_MODES: &[&str] = &["coverage-map", "coverage-run"];
1496}
1497
1498impl Step for Coverage {
1499 type Output = ();
1500 const DEFAULT: bool = true;
1501 const IS_HOST: bool = false;
1503
1504 fn should_run(mut run: ShouldRun<'_>) -> ShouldRun<'_> {
1505 run = run.suite_path(Self::PATH);
1511 for mode in Self::ALL_MODES {
1512 run = run.alias(mode);
1513 }
1514 run
1515 }
1516
1517 fn make_run(run: RunConfig<'_>) {
1518 let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1519 let target = run.target;
1520
1521 let mut modes = vec![];
1525
1526 for path in &run.paths {
1529 match path {
1530 PathSet::Set(_) => {
1531 for mode in Self::ALL_MODES {
1532 if path.assert_single_path().path == Path::new(mode) {
1533 modes.push(mode);
1534 break;
1535 }
1536 }
1537 }
1538 PathSet::Suite(_) => {
1539 modes.extend(Self::ALL_MODES);
1540 break;
1541 }
1542 }
1543 }
1544
1545 modes.retain(|mode| !run.builder.config.skip.iter().any(|skip| skip == Path::new(mode)));
1548
1549 for mode in modes {
1557 run.builder.ensure(Coverage { compiler, target, mode });
1558 }
1559 }
1560
1561 fn run(self, builder: &Builder<'_>) {
1562 let Self { compiler, target, mode } = self;
1563 builder.ensure(Compiletest {
1566 compiler,
1567 target,
1568 mode,
1569 suite: Self::SUITE,
1570 path: Self::PATH,
1571 compare_mode: None,
1572 });
1573 }
1574}
1575
1576test!(CoverageRunRustdoc {
1577 path: "tests/coverage-run-rustdoc",
1578 mode: "coverage-run",
1579 suite: "coverage-run-rustdoc",
1580 default: true,
1581 IS_HOST: true,
1582});
1583
1584#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1586pub struct MirOpt {
1587 pub compiler: Compiler,
1588 pub target: TargetSelection,
1589}
1590
1591impl Step for MirOpt {
1592 type Output = ();
1593 const DEFAULT: bool = true;
1594
1595 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1596 run.suite_path("tests/mir-opt")
1597 }
1598
1599 fn make_run(run: RunConfig<'_>) {
1600 let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1601 run.builder.ensure(MirOpt { compiler, target: run.target });
1602 }
1603
1604 fn run(self, builder: &Builder<'_>) {
1605 let run = |target| {
1606 builder.ensure(Compiletest {
1607 compiler: self.compiler,
1608 target,
1609 mode: "mir-opt",
1610 suite: "mir-opt",
1611 path: "tests/mir-opt",
1612 compare_mode: None,
1613 })
1614 };
1615
1616 run(self.target);
1617
1618 if builder.config.cmd.bless() {
1621 for target in ["aarch64-unknown-linux-gnu", "i686-pc-windows-msvc"] {
1627 run(TargetSelection::from_user(target));
1628 }
1629
1630 for target in ["x86_64-apple-darwin", "i686-unknown-linux-musl"] {
1631 let target = TargetSelection::from_user(target);
1632 let panic_abort_target = builder.ensure(MirOptPanicAbortSyntheticTarget {
1633 compiler: self.compiler,
1634 base: target,
1635 });
1636 run(panic_abort_target);
1637 }
1638 }
1639 }
1640}
1641
1642#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1643struct Compiletest {
1644 compiler: Compiler,
1645 target: TargetSelection,
1646 mode: &'static str,
1647 suite: &'static str,
1648 path: &'static str,
1649 compare_mode: Option<&'static str>,
1650}
1651
1652impl Step for Compiletest {
1653 type Output = ();
1654
1655 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1656 run.never()
1657 }
1658
1659 fn run(self, builder: &Builder<'_>) {
1665 if builder.doc_tests == DocTests::Only {
1666 return;
1667 }
1668
1669 if builder.top_stage == 0 && !builder.config.compiletest_allow_stage0 {
1670 eprintln!("\
1671ERROR: `--stage 0` runs compiletest on the stage0 (precompiled) compiler, not your local changes, and will almost always cause tests to fail
1672HELP: to test the compiler or standard library, omit the stage or explicitly use `--stage 1` instead
1673NOTE: 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`."
1674 );
1675 crate::exit!(1);
1676 }
1677
1678 let mut compiler = self.compiler;
1679 let target = self.target;
1680 let mode = self.mode;
1681 let suite = self.suite;
1682
1683 let suite_path = self.path;
1685
1686 if !builder.config.codegen_tests && mode == "codegen" {
1688 return;
1689 }
1690
1691 let query_compiler;
1698 let (stage, stage_id) = if suite == "ui-fulldeps" && compiler.stage == 1 {
1699 query_compiler = Some(compiler);
1702 let build = builder.build.host_target;
1706 compiler = builder.compiler(compiler.stage - 1, build);
1707 let test_stage = compiler.stage + 1;
1708 (test_stage, format!("stage{test_stage}-{build}"))
1709 } else {
1710 query_compiler = None;
1711 let stage = compiler.stage;
1712 (stage, format!("stage{stage}-{target}"))
1713 };
1714
1715 if suite.ends_with("fulldeps") {
1716 builder.ensure(compile::Rustc::new(compiler, target));
1717 }
1718
1719 if suite == "debuginfo" {
1720 builder.ensure(dist::DebuggerScripts {
1721 sysroot: builder.sysroot(compiler).to_path_buf(),
1722 target,
1723 });
1724 }
1725 if suite == "run-make" {
1726 builder.tool_exe(Tool::RunMakeSupport);
1727 }
1728
1729 if suite == "mir-opt" {
1731 builder.ensure(compile::Std::new(compiler, compiler.host).is_for_mir_opt_tests(true));
1732 } else {
1733 builder.std(compiler, compiler.host);
1734 }
1735
1736 let mut cmd = builder.tool_cmd(Tool::Compiletest);
1737
1738 if suite == "mir-opt" {
1739 builder.ensure(compile::Std::new(compiler, target).is_for_mir_opt_tests(true));
1740 } else {
1741 builder.std(compiler, target);
1742 }
1743
1744 builder.ensure(RemoteCopyLibs { compiler, target });
1745
1746 cmd.arg("--stage").arg(stage.to_string());
1750 cmd.arg("--stage-id").arg(stage_id);
1751
1752 cmd.arg("--compile-lib-path").arg(builder.rustc_libdir(compiler));
1753 cmd.arg("--run-lib-path").arg(builder.sysroot_target_libdir(compiler, target));
1754 cmd.arg("--rustc-path").arg(builder.rustc(compiler));
1755 if let Some(query_compiler) = query_compiler {
1756 cmd.arg("--query-rustc-path").arg(builder.rustc(query_compiler));
1757 }
1758
1759 cmd.arg("--minicore-path")
1762 .arg(builder.src.join("tests").join("auxiliary").join("minicore.rs"));
1763
1764 let is_rustdoc = suite == "rustdoc-ui" || suite == "rustdoc-js";
1765
1766 if mode == "run-make" {
1767 let cargo_path = if builder.top_stage == 0 {
1768 builder.initial_cargo.clone()
1770 } else {
1771 builder.ensure(tool::Cargo::from_build_compiler(compiler, compiler.host)).tool_path
1772 };
1773
1774 cmd.arg("--cargo-path").arg(cargo_path);
1775
1776 let stage0_rustc_path = builder.compiler(0, compiler.host);
1779 cmd.arg("--stage0-rustc-path").arg(builder.rustc(stage0_rustc_path));
1780 }
1781
1782 if mode == "rustdoc"
1784 || mode == "run-make"
1785 || (mode == "ui" && is_rustdoc)
1786 || mode == "rustdoc-js"
1787 || mode == "rustdoc-json"
1788 || suite == "coverage-run-rustdoc"
1789 {
1790 cmd.arg("--rustdoc-path").arg(builder.rustdoc_for_compiler(compiler));
1791 }
1792
1793 if mode == "rustdoc-json" {
1794 let json_compiler = compiler.with_stage(0);
1796 cmd.arg("--jsondocck-path")
1797 .arg(builder.ensure(tool::JsonDocCk { compiler: json_compiler, target }).tool_path);
1798 cmd.arg("--jsondoclint-path").arg(
1799 builder.ensure(tool::JsonDocLint { compiler: json_compiler, target }).tool_path,
1800 );
1801 }
1802
1803 if matches!(mode, "coverage-map" | "coverage-run") {
1804 let coverage_dump = builder.tool_exe(Tool::CoverageDump);
1805 cmd.arg("--coverage-dump-path").arg(coverage_dump);
1806 }
1807
1808 cmd.arg("--src-root").arg(&builder.src);
1809 cmd.arg("--src-test-suite-root").arg(builder.src.join("tests").join(suite));
1810
1811 cmd.arg("--build-root").arg(&builder.out);
1815 cmd.arg("--build-test-suite-root").arg(testdir(builder, compiler.host).join(suite));
1816
1817 let sysroot = if builder.top_stage == 0 {
1820 builder.initial_sysroot.clone()
1821 } else {
1822 builder.sysroot(compiler)
1823 };
1824
1825 cmd.arg("--sysroot-base").arg(sysroot);
1826
1827 cmd.arg("--suite").arg(suite);
1828 cmd.arg("--mode").arg(mode);
1829 cmd.arg("--target").arg(target.rustc_target_arg());
1830 cmd.arg("--host").arg(&*compiler.host.triple);
1831 cmd.arg("--llvm-filecheck").arg(builder.llvm_filecheck(builder.config.host_target));
1832
1833 if let Some(codegen_backend) = builder.config.cmd.test_codegen_backend() {
1834 if !builder.config.enabled_codegen_backends(compiler.host).contains(codegen_backend) {
1835 eprintln!(
1836 "\
1837ERROR: No configured backend named `{name}`
1838HELP: You can add it into `bootstrap.toml` in `rust.codegen-backends = [{name:?}]`",
1839 name = codegen_backend.name(),
1840 );
1841 crate::exit!(1);
1842 }
1843 cmd.arg("--override-codegen-backend").arg(codegen_backend.name());
1846 cmd.arg("--default-codegen-backend").arg(codegen_backend.name());
1849 } else {
1850 cmd.arg("--default-codegen-backend")
1853 .arg(builder.config.default_codegen_backend(compiler.host).name());
1854 }
1855
1856 if builder.build.config.llvm_enzyme {
1857 cmd.arg("--has-enzyme");
1858 }
1859
1860 if builder.config.cmd.bless() {
1861 cmd.arg("--bless");
1862 }
1863
1864 if builder.config.cmd.force_rerun() {
1865 cmd.arg("--force-rerun");
1866 }
1867
1868 if builder.config.cmd.no_capture() {
1869 cmd.arg("--no-capture");
1870 }
1871
1872 let compare_mode =
1873 builder.config.cmd.compare_mode().or_else(|| {
1874 if builder.config.test_compare_mode { self.compare_mode } else { None }
1875 });
1876
1877 if let Some(ref pass) = builder.config.cmd.pass() {
1878 cmd.arg("--pass");
1879 cmd.arg(pass);
1880 }
1881
1882 if let Some(ref run) = builder.config.cmd.run() {
1883 cmd.arg("--run");
1884 cmd.arg(run);
1885 }
1886
1887 if let Some(ref nodejs) = builder.config.nodejs {
1888 cmd.arg("--nodejs").arg(nodejs);
1889 } else if mode == "rustdoc-js" {
1890 panic!("need nodejs to run rustdoc-js suite");
1891 }
1892 if let Some(ref npm) = builder.config.npm {
1893 cmd.arg("--npm").arg(npm);
1894 }
1895 if builder.config.rust_optimize_tests {
1896 cmd.arg("--optimize-tests");
1897 }
1898 if builder.config.rust_randomize_layout {
1899 cmd.arg("--rust-randomized-layout");
1900 }
1901 if builder.config.cmd.only_modified() {
1902 cmd.arg("--only-modified");
1903 }
1904 if let Some(compiletest_diff_tool) = &builder.config.compiletest_diff_tool {
1905 cmd.arg("--compiletest-diff-tool").arg(compiletest_diff_tool);
1906 }
1907
1908 let mut flags = if is_rustdoc { Vec::new() } else { vec!["-Crpath".to_string()] };
1909 flags.push(format!(
1910 "-Cdebuginfo={}",
1911 if mode == "codegen" {
1912 if builder.config.rust_debuginfo_level_tests
1915 != crate::core::config::DebuginfoLevel::None
1916 {
1917 println!(
1918 "NOTE: ignoring `rust.debuginfo-level-tests={}` for codegen tests",
1919 builder.config.rust_debuginfo_level_tests
1920 );
1921 }
1922 crate::core::config::DebuginfoLevel::None
1923 } else {
1924 builder.config.rust_debuginfo_level_tests
1925 }
1926 ));
1927 flags.extend(builder.config.cmd.compiletest_rustc_args().iter().map(|s| s.to_string()));
1928
1929 if suite != "mir-opt" {
1930 if let Some(linker) = builder.linker(target) {
1931 cmd.arg("--target-linker").arg(linker);
1932 }
1933 if let Some(linker) = builder.linker(compiler.host) {
1934 cmd.arg("--host-linker").arg(linker);
1935 }
1936 }
1937
1938 if suite == "ui-fulldeps" && target.ends_with("darwin") {
1940 flags.push("-Alinker_messages".into());
1941 }
1942
1943 let mut hostflags = flags.clone();
1944 hostflags.extend(linker_flags(builder, compiler.host, LldThreads::No));
1945
1946 let mut targetflags = flags;
1947
1948 if suite == "ui" || suite == "incremental" {
1950 builder.ensure(TestHelpers { target: compiler.host });
1951 builder.ensure(TestHelpers { target });
1952 hostflags
1953 .push(format!("-Lnative={}", builder.test_helpers_out(compiler.host).display()));
1954 targetflags.push(format!("-Lnative={}", builder.test_helpers_out(target).display()));
1955 }
1956
1957 for flag in hostflags {
1958 cmd.arg("--host-rustcflags").arg(flag);
1959 }
1960 for flag in targetflags {
1961 cmd.arg("--target-rustcflags").arg(flag);
1962 }
1963
1964 cmd.arg("--python").arg(builder.python());
1965
1966 if let Some(ref gdb) = builder.config.gdb {
1967 cmd.arg("--gdb").arg(gdb);
1968 }
1969
1970 let lldb_exe = builder.config.lldb.clone().unwrap_or_else(|| PathBuf::from("lldb"));
1971 let lldb_version = command(&lldb_exe)
1972 .allow_failure()
1973 .arg("--version")
1974 .run_capture(builder)
1975 .stdout_if_ok()
1976 .and_then(|v| if v.trim().is_empty() { None } else { Some(v) });
1977 if let Some(ref vers) = lldb_version {
1978 cmd.arg("--lldb-version").arg(vers);
1979 let lldb_python_dir = command(&lldb_exe)
1980 .allow_failure()
1981 .arg("-P")
1982 .run_capture_stdout(builder)
1983 .stdout_if_ok()
1984 .map(|p| p.lines().next().expect("lldb Python dir not found").to_string());
1985 if let Some(ref dir) = lldb_python_dir {
1986 cmd.arg("--lldb-python-dir").arg(dir);
1987 }
1988 }
1989
1990 if helpers::forcing_clang_based_tests() {
1991 let clang_exe = builder.llvm_out(target).join("bin").join("clang");
1992 cmd.arg("--run-clang-based-tests-with").arg(clang_exe);
1993 }
1994
1995 for exclude in &builder.config.skip {
1996 cmd.arg("--skip");
1997 cmd.arg(exclude);
1998 }
1999
2000 let paths = match &builder.config.cmd {
2002 Subcommand::Test { .. } => &builder.config.paths[..],
2003 _ => &[],
2004 };
2005
2006 let mut test_args: Vec<&str> = paths
2008 .iter()
2009 .filter_map(|p| helpers::is_valid_test_suite_arg(p, suite_path, builder))
2010 .collect();
2011
2012 test_args.append(&mut builder.config.test_args());
2013
2014 if cfg!(windows) {
2017 let test_args_win: Vec<String> =
2018 test_args.iter().map(|s| s.replace('/', "\\")).collect();
2019 cmd.args(&test_args_win);
2020 } else {
2021 cmd.args(&test_args);
2022 }
2023
2024 if builder.is_verbose() {
2025 cmd.arg("--verbose");
2026 }
2027
2028 cmd.arg("--json");
2029
2030 if builder.config.rustc_debug_assertions {
2031 cmd.arg("--with-rustc-debug-assertions");
2032 }
2033
2034 if builder.config.std_debug_assertions {
2035 cmd.arg("--with-std-debug-assertions");
2036 }
2037
2038 let mut llvm_components_passed = false;
2039 let mut copts_passed = false;
2040 if builder.config.llvm_enabled(compiler.host) {
2041 let llvm::LlvmResult { host_llvm_config, .. } =
2042 builder.ensure(llvm::Llvm { target: builder.config.host_target });
2043 if !builder.config.dry_run() {
2044 let llvm_version = get_llvm_version(builder, &host_llvm_config);
2045 let llvm_components = command(&host_llvm_config)
2046 .cached()
2047 .arg("--components")
2048 .run_capture_stdout(builder)
2049 .stdout();
2050 cmd.arg("--llvm-version")
2052 .arg(llvm_version.trim())
2053 .arg("--llvm-components")
2054 .arg(llvm_components.trim());
2055 llvm_components_passed = true;
2056 }
2057 if !builder.config.is_rust_llvm(target) {
2058 cmd.arg("--system-llvm");
2059 }
2060
2061 if !builder.config.dry_run() && suite.ends_with("fulldeps") {
2066 let llvm_libdir = command(&host_llvm_config)
2067 .cached()
2068 .arg("--libdir")
2069 .run_capture_stdout(builder)
2070 .stdout();
2071 let link_llvm = if target.is_msvc() {
2072 format!("-Clink-arg=-LIBPATH:{llvm_libdir}")
2073 } else {
2074 format!("-Clink-arg=-L{llvm_libdir}")
2075 };
2076 cmd.arg("--host-rustcflags").arg(link_llvm);
2077 }
2078
2079 if !builder.config.dry_run() && matches!(mode, "run-make" | "coverage-run") {
2080 let llvm_bin_path = host_llvm_config
2085 .parent()
2086 .expect("Expected llvm-config to be contained in directory");
2087 assert!(llvm_bin_path.is_dir());
2088 cmd.arg("--llvm-bin-dir").arg(llvm_bin_path);
2089 }
2090
2091 if !builder.config.dry_run() && mode == "run-make" {
2092 if builder.config.lld_enabled {
2094 let lld_install_root =
2095 builder.ensure(llvm::Lld { target: builder.config.host_target });
2096
2097 let lld_bin_path = lld_install_root.join("bin");
2098
2099 let old_path = env::var_os("PATH").unwrap_or_default();
2100 let new_path = env::join_paths(
2101 std::iter::once(lld_bin_path).chain(env::split_paths(&old_path)),
2102 )
2103 .expect("Could not add LLD bin path to PATH");
2104 cmd.env("PATH", new_path);
2105 }
2106 }
2107 }
2108
2109 if !builder.config.dry_run() && mode == "run-make" {
2112 let mut cflags = builder.cc_handled_clags(target, CLang::C);
2113 cflags.extend(builder.cc_unhandled_cflags(target, GitRepo::Rustc, CLang::C));
2114 let mut cxxflags = builder.cc_handled_clags(target, CLang::Cxx);
2115 cxxflags.extend(builder.cc_unhandled_cflags(target, GitRepo::Rustc, CLang::Cxx));
2116 cmd.arg("--cc")
2117 .arg(builder.cc(target))
2118 .arg("--cxx")
2119 .arg(builder.cxx(target).unwrap())
2120 .arg("--cflags")
2121 .arg(cflags.join(" "))
2122 .arg("--cxxflags")
2123 .arg(cxxflags.join(" "));
2124 copts_passed = true;
2125 if let Some(ar) = builder.ar(target) {
2126 cmd.arg("--ar").arg(ar);
2127 }
2128 }
2129
2130 if !llvm_components_passed {
2131 cmd.arg("--llvm-components").arg("");
2132 }
2133 if !copts_passed {
2134 cmd.arg("--cc")
2135 .arg("")
2136 .arg("--cxx")
2137 .arg("")
2138 .arg("--cflags")
2139 .arg("")
2140 .arg("--cxxflags")
2141 .arg("");
2142 }
2143
2144 if builder.remote_tested(target) {
2145 cmd.arg("--remote-test-client").arg(builder.tool_exe(Tool::RemoteTestClient));
2146 } else if let Some(tool) = builder.runner(target) {
2147 cmd.arg("--runner").arg(tool);
2148 }
2149
2150 if suite != "mir-opt" {
2151 if !builder.config.dry_run() && target.is_msvc() {
2157 for (k, v) in builder.cc[&target].env() {
2158 if k != "PATH" {
2159 cmd.env(k, v);
2160 }
2161 }
2162 }
2163 }
2164
2165 if !builder.config.dry_run()
2167 && target.contains("msvc")
2168 && builder.config.sanitizers_enabled(target)
2169 {
2170 cmd.env("ASAN_WIN_CONTINUE_ON_INTERCEPTION_FAILURE", "1");
2173 let asan_runtime_path = builder.cc[&target].path().parent().unwrap().to_path_buf();
2175 let old_path = cmd
2176 .get_envs()
2177 .find_map(|(k, v)| (k == "PATH").then_some(v))
2178 .flatten()
2179 .map_or_else(|| env::var_os("PATH").unwrap_or_default(), |v| v.to_owned());
2180 let new_path = env::join_paths(
2181 env::split_paths(&old_path).chain(std::iter::once(asan_runtime_path)),
2182 )
2183 .expect("Could not add ASAN runtime path to PATH");
2184 cmd.env("PATH", new_path);
2185 }
2186
2187 cmd.env_remove("CARGO");
2190
2191 cmd.env("RUSTC_BOOTSTRAP", "1");
2192 cmd.env("RUSTC_FORCE_RUSTC_VERSION", "compiletest");
2195 cmd.env("DOC_RUST_LANG_ORG_CHANNEL", builder.doc_rust_lang_org_channel());
2196 builder.add_rust_test_threads(&mut cmd);
2197
2198 if builder.config.sanitizers_enabled(target) {
2199 cmd.env("RUSTC_SANITIZER_SUPPORT", "1");
2200 }
2201
2202 if builder.config.profiler_enabled(target) {
2203 cmd.arg("--profiler-runtime");
2204 }
2205
2206 cmd.env("RUST_TEST_TMPDIR", builder.tempdir());
2207
2208 cmd.arg("--adb-path").arg("adb");
2209 cmd.arg("--adb-test-dir").arg(ADB_TEST_DIR);
2210 if target.contains("android") && !builder.config.dry_run() {
2211 cmd.arg("--android-cross-path")
2213 .arg(builder.cc(target).parent().unwrap().parent().unwrap());
2214 } else {
2215 cmd.arg("--android-cross-path").arg("");
2216 }
2217
2218 if builder.config.cmd.rustfix_coverage() {
2219 cmd.arg("--rustfix-coverage");
2220 }
2221
2222 cmd.arg("--channel").arg(&builder.config.channel);
2223
2224 if !builder.config.omit_git_hash {
2225 cmd.arg("--git-hash");
2226 }
2227
2228 let git_config = builder.config.git_config();
2229 cmd.arg("--nightly-branch").arg(git_config.nightly_branch);
2230 cmd.arg("--git-merge-commit-email").arg(git_config.git_merge_commit_email);
2231 cmd.force_coloring_in_ci();
2232
2233 #[cfg(feature = "build-metrics")]
2234 builder.metrics.begin_test_suite(
2235 build_helper::metrics::TestSuiteMetadata::Compiletest {
2236 suite: suite.into(),
2237 mode: mode.into(),
2238 compare_mode: None,
2239 target: self.target.triple.to_string(),
2240 host: self.compiler.host.triple.to_string(),
2241 stage: self.compiler.stage,
2242 },
2243 builder,
2244 );
2245
2246 let _group = builder.msg(
2247 Kind::Test,
2248 format!("compiletest suite={suite} mode={mode}"),
2249 Mode::ToolBootstrap,
2251 compiler,
2252 target,
2253 );
2254 try_run_tests(builder, &mut cmd, false);
2255
2256 if let Some(compare_mode) = compare_mode {
2257 cmd.arg("--compare-mode").arg(compare_mode);
2258
2259 #[cfg(feature = "build-metrics")]
2260 builder.metrics.begin_test_suite(
2261 build_helper::metrics::TestSuiteMetadata::Compiletest {
2262 suite: suite.into(),
2263 mode: mode.into(),
2264 compare_mode: Some(compare_mode.into()),
2265 target: self.target.triple.to_string(),
2266 host: self.compiler.host.triple.to_string(),
2267 stage: self.compiler.stage,
2268 },
2269 builder,
2270 );
2271
2272 builder.info(&format!(
2273 "Check compiletest suite={} mode={} compare_mode={} ({} -> {})",
2274 suite, mode, compare_mode, &compiler.host, target
2275 ));
2276 let _time = helpers::timeit(builder);
2277 try_run_tests(builder, &mut cmd, false);
2278 }
2279 }
2280}
2281
2282#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2283struct BookTest {
2284 compiler: Compiler,
2285 path: PathBuf,
2286 name: &'static str,
2287 is_ext_doc: bool,
2288 dependencies: Vec<&'static str>,
2289}
2290
2291impl Step for BookTest {
2292 type Output = ();
2293 const IS_HOST: bool = true;
2294
2295 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2296 run.never()
2297 }
2298
2299 fn run(self, builder: &Builder<'_>) {
2303 if self.is_ext_doc {
2313 self.run_ext_doc(builder);
2314 } else {
2315 self.run_local_doc(builder);
2316 }
2317 }
2318}
2319
2320impl BookTest {
2321 fn run_ext_doc(self, builder: &Builder<'_>) {
2324 let compiler = self.compiler;
2325
2326 builder.std(compiler, compiler.host);
2327
2328 let mut rustdoc_path = builder.rustdoc_for_compiler(compiler);
2331 rustdoc_path.pop();
2332 let old_path = env::var_os("PATH").unwrap_or_default();
2333 let new_path = env::join_paths(iter::once(rustdoc_path).chain(env::split_paths(&old_path)))
2334 .expect("could not add rustdoc to PATH");
2335
2336 let mut rustbook_cmd = builder.tool_cmd(Tool::Rustbook);
2337 let path = builder.src.join(&self.path);
2338 rustbook_cmd.env("RUSTC_BOOTSTRAP", "1");
2340 rustbook_cmd.env("PATH", new_path).arg("test").arg(path);
2341
2342 let libs = if !self.dependencies.is_empty() {
2347 let mut lib_paths = vec![];
2348 for dep in self.dependencies {
2349 let mode = Mode::ToolRustc;
2350 let target = builder.config.host_target;
2351 let cargo = tool::prepare_tool_cargo(
2352 builder,
2353 compiler,
2354 mode,
2355 target,
2356 Kind::Build,
2357 dep,
2358 SourceType::Submodule,
2359 &[],
2360 );
2361
2362 let stamp = BuildStamp::new(&builder.cargo_out(compiler, mode, target))
2363 .with_prefix(PathBuf::from(dep).file_name().and_then(|v| v.to_str()).unwrap());
2364
2365 let output_paths = run_cargo(builder, cargo, vec![], &stamp, vec![], false, false);
2366 let directories = output_paths
2367 .into_iter()
2368 .filter_map(|p| p.parent().map(ToOwned::to_owned))
2369 .fold(HashSet::new(), |mut set, dir| {
2370 set.insert(dir);
2371 set
2372 });
2373
2374 lib_paths.extend(directories);
2375 }
2376 lib_paths
2377 } else {
2378 vec![]
2379 };
2380
2381 if !libs.is_empty() {
2382 let paths = libs
2383 .into_iter()
2384 .map(|path| path.into_os_string())
2385 .collect::<Vec<OsString>>()
2386 .join(OsStr::new(","));
2387 rustbook_cmd.args([OsString::from("--library-path"), paths]);
2388 }
2389
2390 builder.add_rust_test_threads(&mut rustbook_cmd);
2391 let _guard = builder.msg(
2392 Kind::Test,
2393 format_args!("mdbook {}", self.path.display()),
2394 None,
2395 compiler,
2396 compiler.host,
2397 );
2398 let _time = helpers::timeit(builder);
2399 let toolstate = if rustbook_cmd.delay_failure().run(builder) {
2400 ToolState::TestPass
2401 } else {
2402 ToolState::TestFail
2403 };
2404 builder.save_toolstate(self.name, toolstate);
2405 }
2406
2407 fn run_local_doc(self, builder: &Builder<'_>) {
2409 let compiler = self.compiler;
2410 let host = self.compiler.host;
2411
2412 builder.std(compiler, host);
2413
2414 let _guard = builder.msg(Kind::Test, format!("book {}", self.name), None, compiler, host);
2415
2416 let mut stack = vec![builder.src.join(self.path)];
2419 let _time = helpers::timeit(builder);
2420 let mut files = Vec::new();
2421 while let Some(p) = stack.pop() {
2422 if p.is_dir() {
2423 stack.extend(t!(p.read_dir()).map(|p| t!(p).path()));
2424 continue;
2425 }
2426
2427 if p.extension().and_then(|s| s.to_str()) != Some("md") {
2428 continue;
2429 }
2430
2431 files.push(p);
2432 }
2433
2434 files.sort();
2435
2436 for file in files {
2437 markdown_test(builder, compiler, &file);
2438 }
2439 }
2440}
2441
2442macro_rules! test_book {
2443 ($(
2444 $name:ident, $path:expr, $book_name:expr,
2445 default=$default:expr
2446 $(,submodules = $submodules:expr)?
2447 $(,dependencies=$dependencies:expr)?
2448 ;
2449 )+) => {
2450 $(
2451 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
2452 pub struct $name {
2453 compiler: Compiler,
2454 }
2455
2456 impl Step for $name {
2457 type Output = ();
2458 const DEFAULT: bool = $default;
2459 const IS_HOST: bool = true;
2460
2461 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2462 run.path($path)
2463 }
2464
2465 fn make_run(run: RunConfig<'_>) {
2466 run.builder.ensure($name {
2467 compiler: run.builder.compiler(run.builder.top_stage, run.target),
2468 });
2469 }
2470
2471 fn run(self, builder: &Builder<'_>) {
2472 $(
2473 for submodule in $submodules {
2474 builder.require_submodule(submodule, None);
2475 }
2476 )*
2477
2478 let dependencies = vec![];
2479 $(
2480 let mut dependencies = dependencies;
2481 for dep in $dependencies {
2482 dependencies.push(dep);
2483 }
2484 )?
2485
2486 builder.ensure(BookTest {
2487 compiler: self.compiler,
2488 path: PathBuf::from($path),
2489 name: $book_name,
2490 is_ext_doc: !$default,
2491 dependencies,
2492 });
2493 }
2494 }
2495 )+
2496 }
2497}
2498
2499test_book!(
2500 Nomicon, "src/doc/nomicon", "nomicon", default=false, submodules=["src/doc/nomicon"];
2501 Reference, "src/doc/reference", "reference", default=false, submodules=["src/doc/reference"];
2502 RustdocBook, "src/doc/rustdoc", "rustdoc", default=true;
2503 RustcBook, "src/doc/rustc", "rustc", default=true;
2504 RustByExample, "src/doc/rust-by-example", "rust-by-example", default=false, submodules=["src/doc/rust-by-example"];
2505 EmbeddedBook, "src/doc/embedded-book", "embedded-book", default=false, submodules=["src/doc/embedded-book"];
2506 TheBook, "src/doc/book", "book", default=false, submodules=["src/doc/book"], dependencies=["src/doc/book/packages/trpl"];
2507 UnstableBook, "src/doc/unstable-book", "unstable-book", default=true;
2508 EditionGuide, "src/doc/edition-guide", "edition-guide", default=false, submodules=["src/doc/edition-guide"];
2509);
2510
2511#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2512pub struct ErrorIndex {
2513 compilers: RustcPrivateCompilers,
2514}
2515
2516impl Step for ErrorIndex {
2517 type Output = ();
2518 const DEFAULT: bool = true;
2519 const IS_HOST: bool = true;
2520
2521 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2522 run.path("src/tools/error_index_generator").alias("error-index")
2525 }
2526
2527 fn make_run(run: RunConfig<'_>) {
2528 let compilers = RustcPrivateCompilers::new(
2532 run.builder,
2533 run.builder.top_stage,
2534 run.builder.config.host_target,
2535 );
2536 run.builder.ensure(ErrorIndex { compilers });
2537 }
2538
2539 fn run(self, builder: &Builder<'_>) {
2546 let target_compiler = self.compilers.target_compiler();
2548
2549 let dir = testdir(builder, target_compiler.host);
2550 t!(fs::create_dir_all(&dir));
2551 let output = dir.join("error-index.md");
2552
2553 let mut tool = tool::ErrorIndex::command(builder, self.compilers);
2554 tool.arg("markdown").arg(&output);
2555
2556 let guard = builder.msg(
2557 Kind::Test,
2558 "error-index",
2559 None,
2560 self.compilers.build_compiler(),
2561 target_compiler.host,
2562 );
2563 let _time = helpers::timeit(builder);
2564 tool.run_capture(builder);
2565 drop(guard);
2566 builder.std(target_compiler, target_compiler.host);
2569 markdown_test(builder, target_compiler, &output);
2570 }
2571}
2572
2573fn markdown_test(builder: &Builder<'_>, compiler: Compiler, markdown: &Path) -> bool {
2574 if let Ok(contents) = fs::read_to_string(markdown)
2575 && !contents.contains("```")
2576 {
2577 return true;
2578 }
2579
2580 builder.verbose(|| println!("doc tests for: {}", markdown.display()));
2581 let mut cmd = builder.rustdoc_cmd(compiler);
2582 builder.add_rust_test_threads(&mut cmd);
2583 cmd.arg("-Z");
2585 cmd.arg("unstable-options");
2586 cmd.arg("--test");
2587 cmd.arg(markdown);
2588 cmd.env("RUSTC_BOOTSTRAP", "1");
2589
2590 let test_args = builder.config.test_args().join(" ");
2591 cmd.arg("--test-args").arg(test_args);
2592
2593 cmd = cmd.delay_failure();
2594 if !builder.config.verbose_tests {
2595 cmd.run_capture(builder).is_success()
2596 } else {
2597 cmd.run(builder)
2598 }
2599}
2600
2601#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2606pub struct CrateLibrustc {
2607 compiler: Compiler,
2608 target: TargetSelection,
2609 crates: Vec<String>,
2610}
2611
2612impl Step for CrateLibrustc {
2613 type Output = ();
2614 const DEFAULT: bool = true;
2615 const IS_HOST: bool = true;
2616
2617 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2618 run.crate_or_deps("rustc-main").path("compiler")
2619 }
2620
2621 fn make_run(run: RunConfig<'_>) {
2622 let builder = run.builder;
2623 let host = run.build_triple();
2624 let compiler = builder.compiler_for(builder.top_stage, host, host);
2625 let crates = run.make_run_crates(Alias::Compiler);
2626
2627 builder.ensure(CrateLibrustc { compiler, target: run.target, crates });
2628 }
2629
2630 fn run(self, builder: &Builder<'_>) {
2631 builder.std(self.compiler, self.target);
2632
2633 builder.ensure(Crate {
2635 compiler: self.compiler,
2636 target: self.target,
2637 mode: Mode::Rustc,
2638 crates: self.crates,
2639 });
2640 }
2641
2642 fn metadata(&self) -> Option<StepMetadata> {
2643 Some(StepMetadata::test("CrateLibrustc", self.target))
2644 }
2645}
2646
2647fn run_cargo_test<'a>(
2651 cargo: builder::Cargo,
2652 libtest_args: &[&str],
2653 crates: &[String],
2654 description: impl Into<Option<&'a str>>,
2655 target: TargetSelection,
2656 builder: &Builder<'_>,
2657) -> bool {
2658 let compiler = cargo.compiler();
2659 let mut cargo = prepare_cargo_test(cargo, libtest_args, crates, target, builder);
2660 let _time = helpers::timeit(builder);
2661 let _group =
2662 description.into().and_then(|what| builder.msg(Kind::Test, what, None, compiler, target));
2663
2664 #[cfg(feature = "build-metrics")]
2665 builder.metrics.begin_test_suite(
2666 build_helper::metrics::TestSuiteMetadata::CargoPackage {
2667 crates: crates.iter().map(|c| c.to_string()).collect(),
2668 target: target.triple.to_string(),
2669 host: compiler.host.triple.to_string(),
2670 stage: compiler.stage,
2671 },
2672 builder,
2673 );
2674 add_flags_and_try_run_tests(builder, &mut cargo)
2675}
2676
2677fn prepare_cargo_test(
2679 cargo: builder::Cargo,
2680 libtest_args: &[&str],
2681 crates: &[String],
2682 target: TargetSelection,
2683 builder: &Builder<'_>,
2684) -> BootstrapCommand {
2685 let compiler = cargo.compiler();
2686 let mut cargo: BootstrapCommand = cargo.into();
2687
2688 if builder.config.cmd.bless() && !cargo.get_envs().any(|v| v.0 == "RUSTC_BLESS") {
2692 cargo.env("RUSTC_BLESS", "Gesundheit");
2693 }
2694
2695 if builder.kind == Kind::Test && !builder.fail_fast {
2699 cargo.arg("--no-fail-fast");
2700 }
2701
2702 if builder.config.json_output {
2703 cargo.arg("--message-format=json");
2704 }
2705
2706 match builder.doc_tests {
2707 DocTests::Only => {
2708 cargo.arg("--doc");
2709 }
2710 DocTests::No => {
2711 cargo.args(["--bins", "--examples", "--tests", "--benches"]);
2712 }
2713 DocTests::Yes => {}
2714 }
2715
2716 for krate in crates {
2717 cargo.arg("-p").arg(krate);
2718 }
2719
2720 cargo.arg("--").args(builder.config.test_args()).args(libtest_args);
2721 if !builder.config.verbose_tests {
2722 cargo.arg("--quiet");
2723 }
2724
2725 if builder.kind != Kind::Miri {
2734 let mut dylib_paths = builder.rustc_lib_paths(compiler);
2735 dylib_paths.push(builder.sysroot_target_libdir(compiler, target));
2736 helpers::add_dylib_path(dylib_paths, &mut cargo);
2737 }
2738
2739 if builder.remote_tested(target) {
2740 cargo.env(
2741 format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)),
2742 format!("{} run 0", builder.tool_exe(Tool::RemoteTestClient).display()),
2743 );
2744 } else if let Some(tool) = builder.runner(target) {
2745 cargo.env(format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)), tool);
2746 }
2747
2748 cargo
2749}
2750
2751#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2759pub struct Crate {
2760 pub compiler: Compiler,
2761 pub target: TargetSelection,
2762 pub mode: Mode,
2763 pub crates: Vec<String>,
2764}
2765
2766impl Step for Crate {
2767 type Output = ();
2768 const DEFAULT: bool = true;
2769
2770 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2771 run.crate_or_deps("sysroot").crate_or_deps("coretests").crate_or_deps("alloctests")
2772 }
2773
2774 fn make_run(run: RunConfig<'_>) {
2775 let builder = run.builder;
2776 let host = run.build_triple();
2777 let compiler = builder.compiler_for(builder.top_stage, host, host);
2778 let crates = run
2779 .paths
2780 .iter()
2781 .map(|p| builder.crate_paths[&p.assert_single_path().path].clone())
2782 .collect();
2783
2784 builder.ensure(Crate { compiler, target: run.target, mode: Mode::Std, crates });
2785 }
2786
2787 fn run(self, builder: &Builder<'_>) {
2796 let compiler = self.compiler;
2797 let target = self.target;
2798 let mode = self.mode;
2799
2800 builder.ensure(Std::new(compiler, compiler.host).force_recompile(true));
2803
2804 let compiler = builder.compiler_for(compiler.stage, compiler.host, target);
2809
2810 let mut cargo = if builder.kind == Kind::Miri {
2811 if builder.top_stage == 0 {
2812 eprintln!("ERROR: `x.py miri` requires stage 1 or higher");
2813 std::process::exit(1);
2814 }
2815
2816 let mut cargo = builder::Cargo::new(
2819 builder,
2820 compiler,
2821 mode,
2822 SourceType::InTree,
2823 target,
2824 Kind::MiriTest,
2825 );
2826 cargo.env("MIRI_REPLACE_LIBRS_IF_NOT_TEST", "1");
2838 cargo.rustflag("-Zforce-unstable-if-unmarked");
2842 cargo
2843 } else {
2844 if !builder.config.is_host_target(target) {
2846 builder.ensure(compile::Std::new(compiler, target).force_recompile(true));
2847 builder.ensure(RemoteCopyLibs { compiler, target });
2848 }
2849
2850 builder::Cargo::new(builder, compiler, mode, SourceType::InTree, target, builder.kind)
2852 };
2853
2854 match mode {
2855 Mode::Std => {
2856 if builder.kind == Kind::Miri {
2857 cargo
2863 .arg("--manifest-path")
2864 .arg(builder.src.join("library/sysroot/Cargo.toml"));
2865 } else {
2866 compile::std_cargo(builder, target, &mut cargo);
2867 }
2868 }
2869 Mode::Rustc => {
2870 compile::rustc_cargo(builder, &mut cargo, target, &compiler, &self.crates);
2871 }
2872 _ => panic!("can only test libraries"),
2873 };
2874
2875 let mut crates = self.crates.clone();
2876 if crates.iter().any(|crate_| crate_ == "core") {
2881 crates.push("coretests".to_owned());
2882 }
2883 if crates.iter().any(|crate_| crate_ == "alloc") {
2884 crates.push("alloctests".to_owned());
2885 }
2886
2887 run_cargo_test(cargo, &[], &crates, &*crate_description(&self.crates), target, builder);
2888 }
2889}
2890
2891#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2893pub struct CrateRustdoc {
2894 host: TargetSelection,
2895}
2896
2897impl Step for CrateRustdoc {
2898 type Output = ();
2899 const DEFAULT: bool = true;
2900 const IS_HOST: bool = true;
2901
2902 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2903 run.paths(&["src/librustdoc", "src/tools/rustdoc"])
2904 }
2905
2906 fn make_run(run: RunConfig<'_>) {
2907 let builder = run.builder;
2908
2909 builder.ensure(CrateRustdoc { host: run.target });
2910 }
2911
2912 fn run(self, builder: &Builder<'_>) {
2913 let target = self.host;
2914
2915 let compiler = if builder.download_rustc() {
2916 builder.compiler(builder.top_stage, target)
2917 } else {
2918 builder.compiler_for(builder.top_stage, target, target)
2923 };
2924 builder.std(compiler, target);
2929 builder.ensure(compile::Rustc::new(compiler, target));
2930
2931 let mut cargo = tool::prepare_tool_cargo(
2932 builder,
2933 compiler,
2934 Mode::ToolRustc,
2935 target,
2936 builder.kind,
2937 "src/tools/rustdoc",
2938 SourceType::InTree,
2939 &[],
2940 );
2941 if self.host.contains("musl") {
2942 cargo.arg("'-Ctarget-feature=-crt-static'");
2943 }
2944
2945 let libdir = if builder.download_rustc() {
2972 builder.rustc_libdir(compiler)
2973 } else {
2974 builder.sysroot_target_libdir(compiler, target).to_path_buf()
2975 };
2976 let mut dylib_path = dylib_path();
2977 dylib_path.insert(0, PathBuf::from(&*libdir));
2978 cargo.env(dylib_path_var(), env::join_paths(&dylib_path).unwrap());
2979
2980 run_cargo_test(cargo, &[], &["rustdoc:0.0.0".to_string()], "rustdoc", target, builder);
2981 }
2982}
2983
2984#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2985pub struct CrateRustdocJsonTypes {
2986 host: TargetSelection,
2987}
2988
2989impl Step for CrateRustdocJsonTypes {
2990 type Output = ();
2991 const DEFAULT: bool = true;
2992 const IS_HOST: bool = true;
2993
2994 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2995 run.path("src/rustdoc-json-types")
2996 }
2997
2998 fn make_run(run: RunConfig<'_>) {
2999 let builder = run.builder;
3000
3001 builder.ensure(CrateRustdocJsonTypes { host: run.target });
3002 }
3003
3004 fn run(self, builder: &Builder<'_>) {
3005 let target = self.host;
3006
3007 let compiler = builder.compiler_for(builder.top_stage, target, target);
3012 builder.ensure(compile::Rustc::new(compiler, target));
3013
3014 let cargo = tool::prepare_tool_cargo(
3015 builder,
3016 compiler,
3017 Mode::ToolRustc,
3018 target,
3019 builder.kind,
3020 "src/rustdoc-json-types",
3021 SourceType::InTree,
3022 &[],
3023 );
3024
3025 let libtest_args = if self.host.contains("musl") {
3027 ["'-Ctarget-feature=-crt-static'"].as_slice()
3028 } else {
3029 &[]
3030 };
3031
3032 run_cargo_test(
3033 cargo,
3034 libtest_args,
3035 &["rustdoc-json-types".to_string()],
3036 "rustdoc-json-types",
3037 target,
3038 builder,
3039 );
3040 }
3041}
3042
3043#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3053pub struct RemoteCopyLibs {
3054 compiler: Compiler,
3055 target: TargetSelection,
3056}
3057
3058impl Step for RemoteCopyLibs {
3059 type Output = ();
3060
3061 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3062 run.never()
3063 }
3064
3065 fn run(self, builder: &Builder<'_>) {
3066 let compiler = self.compiler;
3067 let target = self.target;
3068 if !builder.remote_tested(target) {
3069 return;
3070 }
3071
3072 builder.std(compiler, target);
3073
3074 builder.info(&format!("REMOTE copy libs to emulator ({target})"));
3075
3076 let remote_test_server =
3077 builder.ensure(tool::RemoteTestServer { build_compiler: compiler, target });
3078
3079 let tool = builder.tool_exe(Tool::RemoteTestClient);
3081 let mut cmd = command(&tool);
3082 cmd.arg("spawn-emulator")
3083 .arg(target.triple)
3084 .arg(&remote_test_server.tool_path)
3085 .arg(builder.tempdir());
3086 if let Some(rootfs) = builder.qemu_rootfs(target) {
3087 cmd.arg(rootfs);
3088 }
3089 cmd.run(builder);
3090
3091 for f in t!(builder.sysroot_target_libdir(compiler, target).read_dir()) {
3093 let f = t!(f);
3094 if helpers::is_dylib(&f.path()) {
3095 command(&tool).arg("push").arg(f.path()).run(builder);
3096 }
3097 }
3098 }
3099}
3100
3101#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3102pub struct Distcheck;
3103
3104impl Step for Distcheck {
3105 type Output = ();
3106
3107 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3108 run.alias("distcheck")
3109 }
3110
3111 fn make_run(run: RunConfig<'_>) {
3112 run.builder.ensure(Distcheck);
3113 }
3114
3115 fn run(self, builder: &Builder<'_>) {
3124 let root_dir = std::env::temp_dir().join("distcheck");
3127
3128 builder.info("Distcheck plain source tarball");
3130 let plain_src_tarball = builder.ensure(dist::PlainSourceTarball);
3131 let plain_src_dir = root_dir.join("distcheck-plain-src");
3132 builder.clear_dir(&plain_src_dir);
3133
3134 let configure_args: Vec<String> = std::env::var("DISTCHECK_CONFIGURE_ARGS")
3135 .map(|args| args.split(" ").map(|s| s.to_string()).collect::<Vec<String>>())
3136 .unwrap_or_default();
3137
3138 command("tar")
3139 .arg("-xf")
3140 .arg(plain_src_tarball.tarball())
3141 .arg("--strip-components=1")
3142 .current_dir(&plain_src_dir)
3143 .run(builder);
3144 command("./configure")
3145 .arg("--set")
3146 .arg("rust.omit-git-hash=false")
3147 .args(&configure_args)
3148 .arg("--enable-vendor")
3149 .current_dir(&plain_src_dir)
3150 .run(builder);
3151 command(helpers::make(&builder.config.host_target.triple))
3152 .arg("check")
3153 .env("GITHUB_ACTIONS", "0")
3156 .current_dir(&plain_src_dir)
3157 .run(builder);
3158
3159 builder.info("Distcheck rust-src");
3161 let src_tarball = builder.ensure(dist::Src);
3162 let src_dir = root_dir.join("distcheck-src");
3163 builder.clear_dir(&src_dir);
3164
3165 command("tar")
3166 .arg("-xf")
3167 .arg(src_tarball.tarball())
3168 .arg("--strip-components=1")
3169 .current_dir(&src_dir)
3170 .run(builder);
3171
3172 let toml = src_dir.join("rust-src/lib/rustlib/src/rust/library/std/Cargo.toml");
3173 command(&builder.initial_cargo)
3174 .env("RUSTC_BOOTSTRAP", "1")
3177 .arg("generate-lockfile")
3178 .arg("--manifest-path")
3179 .arg(&toml)
3180 .current_dir(&src_dir)
3181 .run(builder);
3182 }
3183}
3184
3185#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3186pub struct Bootstrap;
3187
3188impl Step for Bootstrap {
3189 type Output = ();
3190 const DEFAULT: bool = true;
3191 const IS_HOST: bool = true;
3192
3193 fn run(self, builder: &Builder<'_>) {
3195 let host = builder.config.host_target;
3196 let build_compiler = builder.compiler(0, host);
3197 let _guard =
3198 builder.msg(Kind::Test, "bootstrap", Mode::ToolBootstrap, build_compiler, host);
3199
3200 builder.build.require_submodule("src/tools/cargo", None);
3202
3203 let mut check_bootstrap = command(builder.python());
3204 check_bootstrap
3205 .args(["-m", "unittest", "bootstrap_test.py"])
3206 .env("BUILD_DIR", &builder.out)
3207 .env("BUILD_PLATFORM", builder.build.host_target.triple)
3208 .env("BOOTSTRAP_TEST_RUSTC_BIN", &builder.initial_rustc)
3209 .env("BOOTSTRAP_TEST_CARGO_BIN", &builder.initial_cargo)
3210 .current_dir(builder.src.join("src/bootstrap/"));
3211 check_bootstrap.delay_failure().run(builder);
3214
3215 let mut cargo = tool::prepare_tool_cargo(
3216 builder,
3217 build_compiler,
3218 Mode::ToolBootstrap,
3219 host,
3220 Kind::Test,
3221 "src/bootstrap",
3222 SourceType::InTree,
3223 &[],
3224 );
3225
3226 cargo.release_build(false);
3227
3228 cargo
3229 .rustflag("-Cdebuginfo=2")
3230 .env("CARGO_TARGET_DIR", builder.out.join("bootstrap"))
3231 .env("INSTA_WORKSPACE_ROOT", &builder.src)
3233 .env("RUSTC_BOOTSTRAP", "1");
3234
3235 run_cargo_test(cargo, &["--test-threads=1"], &[], None, host, builder);
3238 }
3239
3240 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3241 let runs_on_ci = run.builder.config.is_running_on_ci;
3245 run.path("src/bootstrap").default_condition(runs_on_ci)
3246 }
3247
3248 fn make_run(run: RunConfig<'_>) {
3249 run.builder.ensure(Bootstrap);
3250 }
3251}
3252
3253#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3254pub struct TierCheck {
3255 pub compiler: Compiler,
3256}
3257
3258impl Step for TierCheck {
3259 type Output = ();
3260 const DEFAULT: bool = true;
3261 const IS_HOST: bool = true;
3262
3263 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3264 run.path("src/tools/tier-check")
3265 }
3266
3267 fn make_run(run: RunConfig<'_>) {
3268 let compiler = run.builder.compiler_for(
3269 run.builder.top_stage,
3270 run.builder.build.host_target,
3271 run.target,
3272 );
3273 run.builder.ensure(TierCheck { compiler });
3274 }
3275
3276 fn run(self, builder: &Builder<'_>) {
3278 builder.std(self.compiler, self.compiler.host);
3279 let mut cargo = tool::prepare_tool_cargo(
3280 builder,
3281 self.compiler,
3282 Mode::ToolStd,
3283 self.compiler.host,
3284 Kind::Run,
3285 "src/tools/tier-check",
3286 SourceType::InTree,
3287 &[],
3288 );
3289 cargo.arg(builder.src.join("src/doc/rustc/src/platform-support.md"));
3290 cargo.arg(builder.rustc(self.compiler));
3291 if builder.is_verbose() {
3292 cargo.arg("--verbose");
3293 }
3294
3295 let _guard = builder.msg(
3296 Kind::Test,
3297 "platform support check",
3298 None,
3299 self.compiler,
3300 self.compiler.host,
3301 );
3302 BootstrapCommand::from(cargo).delay_failure().run(builder);
3303 }
3304}
3305
3306#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3307pub struct LintDocs {
3308 pub compiler: Compiler,
3309 pub target: TargetSelection,
3310}
3311
3312impl Step for LintDocs {
3313 type Output = ();
3314 const DEFAULT: bool = true;
3315 const IS_HOST: bool = true;
3316
3317 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3318 run.path("src/tools/lint-docs")
3319 }
3320
3321 fn make_run(run: RunConfig<'_>) {
3322 run.builder.ensure(LintDocs {
3323 compiler: run.builder.compiler(run.builder.top_stage, run.builder.config.host_target),
3324 target: run.target,
3325 });
3326 }
3327
3328 fn run(self, builder: &Builder<'_>) {
3331 builder
3332 .ensure(crate::core::build_steps::doc::RustcBook::validate(self.compiler, self.target));
3333 }
3334}
3335
3336#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3337pub struct RustInstaller;
3338
3339impl Step for RustInstaller {
3340 type Output = ();
3341 const IS_HOST: bool = true;
3342 const DEFAULT: bool = true;
3343
3344 fn run(self, builder: &Builder<'_>) {
3346 let bootstrap_host = builder.config.host_target;
3347 let build_compiler = builder.compiler(0, bootstrap_host);
3348 let cargo = tool::prepare_tool_cargo(
3349 builder,
3350 build_compiler,
3351 Mode::ToolBootstrap,
3352 bootstrap_host,
3353 Kind::Test,
3354 "src/tools/rust-installer",
3355 SourceType::InTree,
3356 &[],
3357 );
3358
3359 let _guard =
3360 builder.msg(Kind::Test, "rust-installer", None, build_compiler, bootstrap_host);
3361 run_cargo_test(cargo, &[], &[], None, bootstrap_host, builder);
3362
3363 if bootstrap_host != "x86_64-unknown-linux-gnu" {
3367 return;
3368 }
3369
3370 let mut cmd = command(builder.src.join("src/tools/rust-installer/test.sh"));
3371 let tmpdir = testdir(builder, build_compiler.host).join("rust-installer");
3372 let _ = std::fs::remove_dir_all(&tmpdir);
3373 let _ = std::fs::create_dir_all(&tmpdir);
3374 cmd.current_dir(&tmpdir);
3375 cmd.env("CARGO_TARGET_DIR", tmpdir.join("cargo-target"));
3376 cmd.env("CARGO", &builder.initial_cargo);
3377 cmd.env("RUSTC", &builder.initial_rustc);
3378 cmd.env("TMP_DIR", &tmpdir);
3379 cmd.delay_failure().run(builder);
3380 }
3381
3382 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3383 run.path("src/tools/rust-installer")
3384 }
3385
3386 fn make_run(run: RunConfig<'_>) {
3387 run.builder.ensure(Self);
3388 }
3389}
3390
3391#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3392pub struct TestHelpers {
3393 pub target: TargetSelection,
3394}
3395
3396impl Step for TestHelpers {
3397 type Output = ();
3398
3399 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3400 run.path("tests/auxiliary/rust_test_helpers.c")
3401 }
3402
3403 fn make_run(run: RunConfig<'_>) {
3404 run.builder.ensure(TestHelpers { target: run.target })
3405 }
3406
3407 fn run(self, builder: &Builder<'_>) {
3410 if builder.config.dry_run() {
3411 return;
3412 }
3413 let target = if self.target == "x86_64-fortanix-unknown-sgx" {
3417 TargetSelection::from_user("x86_64-unknown-linux-gnu")
3418 } else {
3419 self.target
3420 };
3421 let dst = builder.test_helpers_out(target);
3422 let src = builder.src.join("tests/auxiliary/rust_test_helpers.c");
3423 if up_to_date(&src, &dst.join("librust_test_helpers.a")) {
3424 return;
3425 }
3426
3427 let _guard = builder.msg_unstaged(Kind::Build, "test helpers", target);
3428 t!(fs::create_dir_all(&dst));
3429 let mut cfg = cc::Build::new();
3430
3431 if !target.is_msvc() {
3435 if let Some(ar) = builder.ar(target) {
3436 cfg.archiver(ar);
3437 }
3438 cfg.compiler(builder.cc(target));
3439 }
3440 cfg.cargo_metadata(false)
3441 .out_dir(&dst)
3442 .target(&target.triple)
3443 .host(&builder.config.host_target.triple)
3444 .opt_level(0)
3445 .warnings(false)
3446 .debug(false)
3447 .file(builder.src.join("tests/auxiliary/rust_test_helpers.c"))
3448 .compile("rust_test_helpers");
3449 }
3450}
3451
3452#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3453pub struct CodegenCranelift {
3454 compiler: Compiler,
3455 target: TargetSelection,
3456}
3457
3458impl Step for CodegenCranelift {
3459 type Output = ();
3460 const DEFAULT: bool = true;
3461 const IS_HOST: bool = true;
3462
3463 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3464 run.paths(&["compiler/rustc_codegen_cranelift"])
3465 }
3466
3467 fn make_run(run: RunConfig<'_>) {
3468 let builder = run.builder;
3469 let host = run.build_triple();
3470 let compiler = run.builder.compiler_for(run.builder.top_stage, host, host);
3471
3472 if builder.doc_tests == DocTests::Only {
3473 return;
3474 }
3475
3476 if builder.download_rustc() {
3477 builder.info("CI rustc uses the default codegen backend. skipping");
3478 return;
3479 }
3480
3481 if !target_supports_cranelift_backend(run.target) {
3482 builder.info("target not supported by rustc_codegen_cranelift. skipping");
3483 return;
3484 }
3485
3486 if builder.remote_tested(run.target) {
3487 builder.info("remote testing is not supported by rustc_codegen_cranelift. skipping");
3488 return;
3489 }
3490
3491 if !builder
3492 .config
3493 .enabled_codegen_backends(run.target)
3494 .contains(&CodegenBackendKind::Cranelift)
3495 {
3496 builder.info("cranelift not in rust.codegen-backends. skipping");
3497 return;
3498 }
3499
3500 builder.ensure(CodegenCranelift { compiler, target: run.target });
3501 }
3502
3503 fn run(self, builder: &Builder<'_>) {
3504 let compiler = self.compiler;
3505 let target = self.target;
3506
3507 builder.std(compiler, target);
3508
3509 let compiler = builder.compiler_for(compiler.stage, compiler.host, target);
3514
3515 let build_cargo = || {
3516 let mut cargo = builder::Cargo::new(
3517 builder,
3518 compiler,
3519 Mode::Codegen, SourceType::InTree,
3521 target,
3522 Kind::Run,
3523 );
3524
3525 cargo.current_dir(&builder.src.join("compiler/rustc_codegen_cranelift"));
3526 cargo
3527 .arg("--manifest-path")
3528 .arg(builder.src.join("compiler/rustc_codegen_cranelift/build_system/Cargo.toml"));
3529 compile::rustc_cargo_env(builder, &mut cargo, target);
3530
3531 cargo.env("CARGO_BUILD_INCREMENTAL", "false");
3533
3534 cargo
3535 };
3536
3537 builder.info(&format!(
3538 "{} cranelift stage{} ({} -> {})",
3539 Kind::Test.description(),
3540 compiler.stage,
3541 &compiler.host,
3542 target
3543 ));
3544 let _time = helpers::timeit(builder);
3545
3546 let download_dir = builder.out.join("cg_clif_download");
3548
3549 let mut cargo = build_cargo();
3558 cargo
3559 .arg("--")
3560 .arg("test")
3561 .arg("--download-dir")
3562 .arg(&download_dir)
3563 .arg("--out-dir")
3564 .arg(builder.stage_out(compiler, Mode::ToolRustc).join("cg_clif"))
3565 .arg("--no-unstable-features")
3566 .arg("--use-backend")
3567 .arg("cranelift")
3568 .arg("--sysroot")
3570 .arg("llvm")
3571 .arg("--skip-test")
3574 .arg("testsuite.extended_sysroot");
3575
3576 cargo.into_cmd().run(builder);
3577 }
3578}
3579
3580#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3581pub struct CodegenGCC {
3582 compiler: Compiler,
3583 target: TargetSelection,
3584}
3585
3586impl Step for CodegenGCC {
3587 type Output = ();
3588 const DEFAULT: bool = true;
3589 const IS_HOST: bool = true;
3590
3591 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3592 run.paths(&["compiler/rustc_codegen_gcc"])
3593 }
3594
3595 fn make_run(run: RunConfig<'_>) {
3596 let builder = run.builder;
3597 let host = run.build_triple();
3598 let compiler = run.builder.compiler_for(run.builder.top_stage, host, host);
3599
3600 if builder.doc_tests == DocTests::Only {
3601 return;
3602 }
3603
3604 if builder.download_rustc() {
3605 builder.info("CI rustc uses the default codegen backend. skipping");
3606 return;
3607 }
3608
3609 let triple = run.target.triple;
3610 let target_supported =
3611 if triple.contains("linux") { triple.contains("x86_64") } else { false };
3612 if !target_supported {
3613 builder.info("target not supported by rustc_codegen_gcc. skipping");
3614 return;
3615 }
3616
3617 if builder.remote_tested(run.target) {
3618 builder.info("remote testing is not supported by rustc_codegen_gcc. skipping");
3619 return;
3620 }
3621
3622 if !builder.config.enabled_codegen_backends(run.target).contains(&CodegenBackendKind::Gcc) {
3623 builder.info("gcc not in rust.codegen-backends. skipping");
3624 return;
3625 }
3626
3627 builder.ensure(CodegenGCC { compiler, target: run.target });
3628 }
3629
3630 fn run(self, builder: &Builder<'_>) {
3631 let compiler = self.compiler;
3632 let target = self.target;
3633
3634 let gcc = builder.ensure(Gcc { target });
3635
3636 builder.ensure(
3637 compile::Std::new(compiler, target)
3638 .extra_rust_args(&["-Csymbol-mangling-version=v0", "-Cpanic=abort"]),
3639 );
3640
3641 let compiler = builder.compiler_for(compiler.stage, compiler.host, target);
3646
3647 let build_cargo = || {
3648 let mut cargo = builder::Cargo::new(
3649 builder,
3650 compiler,
3651 Mode::Codegen, SourceType::InTree,
3653 target,
3654 Kind::Run,
3655 );
3656
3657 cargo.current_dir(&builder.src.join("compiler/rustc_codegen_gcc"));
3658 cargo
3659 .arg("--manifest-path")
3660 .arg(builder.src.join("compiler/rustc_codegen_gcc/build_system/Cargo.toml"));
3661 compile::rustc_cargo_env(builder, &mut cargo, target);
3662 add_cg_gcc_cargo_flags(&mut cargo, &gcc);
3663
3664 cargo.env("CARGO_BUILD_INCREMENTAL", "false");
3666 cargo.rustflag("-Cpanic=abort");
3667
3668 cargo
3669 };
3670
3671 builder.info(&format!(
3672 "{} GCC stage{} ({} -> {})",
3673 Kind::Test.description(),
3674 compiler.stage,
3675 &compiler.host,
3676 target
3677 ));
3678 let _time = helpers::timeit(builder);
3679
3680 let mut cargo = build_cargo();
3689
3690 cargo
3691 .env("CG_RUSTFLAGS", "-Alinker-messages")
3693 .arg("--")
3694 .arg("test")
3695 .arg("--use-backend")
3696 .arg("gcc")
3697 .arg("--gcc-path")
3698 .arg(gcc.libgccjit.parent().unwrap())
3699 .arg("--out-dir")
3700 .arg(builder.stage_out(compiler, Mode::ToolRustc).join("cg_gcc"))
3701 .arg("--release")
3702 .arg("--mini-tests")
3703 .arg("--std-tests");
3704 cargo.args(builder.config.test_args());
3705
3706 cargo.into_cmd().run(builder);
3707 }
3708}
3709
3710#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3715pub struct TestFloatParse {
3716 path: PathBuf,
3717 host: TargetSelection,
3718}
3719
3720impl Step for TestFloatParse {
3721 type Output = ();
3722 const IS_HOST: bool = true;
3723 const DEFAULT: bool = true;
3724
3725 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3726 run.path("src/tools/test-float-parse")
3727 }
3728
3729 fn make_run(run: RunConfig<'_>) {
3730 for path in run.paths {
3731 let path = path.assert_single_path().path.clone();
3732 run.builder.ensure(Self { path, host: run.target });
3733 }
3734 }
3735
3736 fn run(self, builder: &Builder<'_>) {
3737 let bootstrap_host = builder.config.host_target;
3738 let compiler = builder.compiler(builder.top_stage, bootstrap_host);
3739 let path = self.path.to_str().unwrap();
3740 let crate_name = self.path.iter().next_back().unwrap().to_str().unwrap();
3741
3742 builder.ensure(tool::TestFloatParse { host: self.host });
3743
3744 let mut cargo_test = tool::prepare_tool_cargo(
3746 builder,
3747 compiler,
3748 Mode::ToolStd,
3749 bootstrap_host,
3750 Kind::Test,
3751 path,
3752 SourceType::InTree,
3753 &[],
3754 );
3755 cargo_test.allow_features(tool::TestFloatParse::ALLOW_FEATURES);
3756
3757 run_cargo_test(cargo_test, &[], &[], crate_name, bootstrap_host, builder);
3758
3759 let mut cargo_run = tool::prepare_tool_cargo(
3761 builder,
3762 compiler,
3763 Mode::ToolStd,
3764 bootstrap_host,
3765 Kind::Run,
3766 path,
3767 SourceType::InTree,
3768 &[],
3769 );
3770 cargo_run.allow_features(tool::TestFloatParse::ALLOW_FEATURES);
3771
3772 if !matches!(env::var("FLOAT_PARSE_TESTS_NO_SKIP_HUGE").as_deref(), Ok("1") | Ok("true")) {
3773 cargo_run.args(["--", "--skip-huge"]);
3774 }
3775
3776 cargo_run.into_cmd().run(builder);
3777 }
3778}
3779
3780#[derive(Debug, Clone, Hash, PartialEq, Eq)]
3784pub struct CollectLicenseMetadata;
3785
3786impl Step for CollectLicenseMetadata {
3787 type Output = PathBuf;
3788 const IS_HOST: bool = true;
3789
3790 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3791 run.path("src/tools/collect-license-metadata")
3792 }
3793
3794 fn make_run(run: RunConfig<'_>) {
3795 run.builder.ensure(CollectLicenseMetadata);
3796 }
3797
3798 fn run(self, builder: &Builder<'_>) -> Self::Output {
3799 let Some(reuse) = &builder.config.reuse else {
3800 panic!("REUSE is required to collect the license metadata");
3801 };
3802
3803 let dest = builder.src.join("license-metadata.json");
3804
3805 let mut cmd = builder.tool_cmd(Tool::CollectLicenseMetadata);
3806 cmd.env("REUSE_EXE", reuse);
3807 cmd.env("DEST", &dest);
3808 cmd.env("ONLY_CHECK", "1");
3809 cmd.run(builder);
3810
3811 dest
3812 }
3813}