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