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 });
1525
1526test!(AssemblyLlvm {
1527 path: "tests/assembly-llvm",
1528 mode: "assembly",
1529 suite: "assembly-llvm",
1530 default: true
1531});
1532
1533#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
1536pub struct Coverage {
1537 pub compiler: Compiler,
1538 pub target: TargetSelection,
1539 pub mode: &'static str,
1540}
1541
1542impl Coverage {
1543 const PATH: &'static str = "tests/coverage";
1544 const SUITE: &'static str = "coverage";
1545 const ALL_MODES: &[&str] = &["coverage-map", "coverage-run"];
1546}
1547
1548impl Step for Coverage {
1549 type Output = ();
1550 const DEFAULT: bool = true;
1551 const IS_HOST: bool = false;
1553
1554 fn should_run(mut run: ShouldRun<'_>) -> ShouldRun<'_> {
1555 run = run.suite_path(Self::PATH);
1561 for mode in Self::ALL_MODES {
1562 run = run.alias(mode);
1563 }
1564 run
1565 }
1566
1567 fn make_run(run: RunConfig<'_>) {
1568 let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1569 let target = run.target;
1570
1571 let mut modes = vec![];
1575
1576 for path in &run.paths {
1579 match path {
1580 PathSet::Set(_) => {
1581 for mode in Self::ALL_MODES {
1582 if path.assert_single_path().path == Path::new(mode) {
1583 modes.push(mode);
1584 break;
1585 }
1586 }
1587 }
1588 PathSet::Suite(_) => {
1589 modes.extend(Self::ALL_MODES);
1590 break;
1591 }
1592 }
1593 }
1594
1595 modes.retain(|mode| !run.builder.config.skip.iter().any(|skip| skip == Path::new(mode)));
1598
1599 for mode in modes {
1607 run.builder.ensure(Coverage { compiler, target, mode });
1608 }
1609 }
1610
1611 fn run(self, builder: &Builder<'_>) {
1612 let Self { compiler, target, mode } = self;
1613 builder.ensure(Compiletest {
1616 test_compiler: compiler,
1617 target,
1618 mode,
1619 suite: Self::SUITE,
1620 path: Self::PATH,
1621 compare_mode: None,
1622 });
1623 }
1624}
1625
1626test!(CoverageRunRustdoc {
1627 path: "tests/coverage-run-rustdoc",
1628 mode: "coverage-run",
1629 suite: "coverage-run-rustdoc",
1630 default: true,
1631 IS_HOST: true,
1632});
1633
1634#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1636pub struct MirOpt {
1637 pub compiler: Compiler,
1638 pub target: TargetSelection,
1639}
1640
1641impl Step for MirOpt {
1642 type Output = ();
1643 const DEFAULT: bool = true;
1644
1645 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1646 run.suite_path("tests/mir-opt")
1647 }
1648
1649 fn make_run(run: RunConfig<'_>) {
1650 let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1651 run.builder.ensure(MirOpt { compiler, target: run.target });
1652 }
1653
1654 fn run(self, builder: &Builder<'_>) {
1655 let run = |target| {
1656 builder.ensure(Compiletest {
1657 test_compiler: self.compiler,
1658 target,
1659 mode: "mir-opt",
1660 suite: "mir-opt",
1661 path: "tests/mir-opt",
1662 compare_mode: None,
1663 })
1664 };
1665
1666 run(self.target);
1667
1668 if builder.config.cmd.bless() {
1671 for target in ["aarch64-unknown-linux-gnu", "i686-pc-windows-msvc"] {
1677 run(TargetSelection::from_user(target));
1678 }
1679
1680 for target in ["x86_64-apple-darwin", "i686-unknown-linux-musl"] {
1681 let target = TargetSelection::from_user(target);
1682 let panic_abort_target = builder.ensure(MirOptPanicAbortSyntheticTarget {
1683 compiler: self.compiler,
1684 base: target,
1685 });
1686 run(panic_abort_target);
1687 }
1688 }
1689 }
1690}
1691
1692#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1698struct Compiletest {
1699 test_compiler: Compiler,
1701 target: TargetSelection,
1702 mode: &'static str,
1703 suite: &'static str,
1704 path: &'static str,
1705 compare_mode: Option<&'static str>,
1706}
1707
1708impl Step for Compiletest {
1709 type Output = ();
1710
1711 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1712 run.never()
1713 }
1714
1715 fn run(self, builder: &Builder<'_>) {
1716 if builder.doc_tests == DocTests::Only {
1717 return;
1718 }
1719
1720 if builder.top_stage == 0 && !builder.config.compiletest_allow_stage0 {
1721 eprintln!("\
1722ERROR: `--stage 0` runs compiletest on the stage0 (precompiled) compiler, not your local changes, and will almost always cause tests to fail
1723HELP: to test the compiler or standard library, omit the stage or explicitly use `--stage 1` instead
1724NOTE: 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`."
1725 );
1726 crate::exit!(1);
1727 }
1728
1729 let mut test_compiler = self.test_compiler;
1730 let target = self.target;
1731 let mode = self.mode;
1732 let suite = self.suite;
1733
1734 let suite_path = self.path;
1736
1737 if !builder.config.codegen_tests && mode == "codegen" {
1739 return;
1740 }
1741
1742 let query_compiler;
1749 let (stage, stage_id) = if suite == "ui-fulldeps" && test_compiler.stage == 1 {
1750 query_compiler = Some(test_compiler);
1753 let build = builder.build.host_target;
1757 test_compiler = builder.compiler(test_compiler.stage - 1, build);
1758 let test_stage = test_compiler.stage + 1;
1759 (test_stage, format!("stage{test_stage}-{build}"))
1760 } else {
1761 query_compiler = None;
1762 let stage = test_compiler.stage;
1763 (stage, format!("stage{stage}-{target}"))
1764 };
1765
1766 if suite.ends_with("fulldeps") {
1767 builder.ensure(compile::Rustc::new(test_compiler, target));
1768 }
1769
1770 if suite == "debuginfo" {
1771 builder.ensure(dist::DebuggerScripts {
1772 sysroot: builder.sysroot(test_compiler).to_path_buf(),
1773 target,
1774 });
1775 }
1776 if suite == "run-make" {
1777 builder.tool_exe(Tool::RunMakeSupport);
1778 }
1779
1780 if suite == "mir-opt" {
1782 builder.ensure(
1783 compile::Std::new(test_compiler, test_compiler.host).is_for_mir_opt_tests(true),
1784 );
1785 } else {
1786 builder.std(test_compiler, test_compiler.host);
1787 }
1788
1789 let mut cmd = builder.tool_cmd(Tool::Compiletest);
1790
1791 if suite == "mir-opt" {
1792 builder.ensure(compile::Std::new(test_compiler, target).is_for_mir_opt_tests(true));
1793 } else {
1794 builder.std(test_compiler, target);
1795 }
1796
1797 builder.ensure(RemoteCopyLibs { build_compiler: test_compiler, target });
1798
1799 cmd.arg("--stage").arg(stage.to_string());
1803 cmd.arg("--stage-id").arg(stage_id);
1804
1805 cmd.arg("--compile-lib-path").arg(builder.rustc_libdir(test_compiler));
1806 cmd.arg("--run-lib-path").arg(builder.sysroot_target_libdir(test_compiler, target));
1807 cmd.arg("--rustc-path").arg(builder.rustc(test_compiler));
1808 if let Some(query_compiler) = query_compiler {
1809 cmd.arg("--query-rustc-path").arg(builder.rustc(query_compiler));
1810 }
1811
1812 cmd.arg("--minicore-path")
1815 .arg(builder.src.join("tests").join("auxiliary").join("minicore.rs"));
1816
1817 let is_rustdoc = suite == "rustdoc-ui" || suite == "rustdoc-js";
1818
1819 if mode == "run-make" {
1820 let cargo_path = if test_compiler.stage == 0 {
1821 builder.initial_cargo.clone()
1823 } else {
1824 builder
1825 .ensure(tool::Cargo::from_build_compiler(
1826 builder.compiler(test_compiler.stage - 1, test_compiler.host),
1827 test_compiler.host,
1828 ))
1829 .tool_path
1830 };
1831
1832 cmd.arg("--cargo-path").arg(cargo_path);
1833
1834 let stage0_rustc_path = builder.compiler(0, test_compiler.host);
1837 cmd.arg("--stage0-rustc-path").arg(builder.rustc(stage0_rustc_path));
1838 }
1839
1840 if mode == "rustdoc"
1842 || mode == "run-make"
1843 || (mode == "ui" && is_rustdoc)
1844 || mode == "rustdoc-js"
1845 || mode == "rustdoc-json"
1846 || suite == "coverage-run-rustdoc"
1847 {
1848 cmd.arg("--rustdoc-path").arg(builder.rustdoc_for_compiler(test_compiler));
1849 }
1850
1851 if mode == "rustdoc-json" {
1852 let json_compiler = builder.compiler(0, builder.host_target);
1854 cmd.arg("--jsondocck-path")
1855 .arg(builder.ensure(tool::JsonDocCk { compiler: json_compiler, target }).tool_path);
1856 cmd.arg("--jsondoclint-path").arg(
1857 builder.ensure(tool::JsonDocLint { compiler: json_compiler, target }).tool_path,
1858 );
1859 }
1860
1861 if matches!(mode, "coverage-map" | "coverage-run") {
1862 let coverage_dump = builder.tool_exe(Tool::CoverageDump);
1863 cmd.arg("--coverage-dump-path").arg(coverage_dump);
1864 }
1865
1866 cmd.arg("--src-root").arg(&builder.src);
1867 cmd.arg("--src-test-suite-root").arg(builder.src.join("tests").join(suite));
1868
1869 cmd.arg("--build-root").arg(&builder.out);
1873 cmd.arg("--build-test-suite-root").arg(testdir(builder, test_compiler.host).join(suite));
1874
1875 let sysroot = if builder.top_stage == 0 {
1880 builder.initial_sysroot.clone()
1881 } else {
1882 builder.sysroot(test_compiler)
1883 };
1884
1885 cmd.arg("--sysroot-base").arg(sysroot);
1886
1887 cmd.arg("--suite").arg(suite);
1888 cmd.arg("--mode").arg(mode);
1889 cmd.arg("--target").arg(target.rustc_target_arg());
1890 cmd.arg("--host").arg(&*test_compiler.host.triple);
1891 cmd.arg("--llvm-filecheck").arg(builder.llvm_filecheck(builder.config.host_target));
1892
1893 if let Some(codegen_backend) = builder.config.cmd.test_codegen_backend() {
1894 if !builder
1895 .config
1896 .enabled_codegen_backends(test_compiler.host)
1897 .contains(codegen_backend)
1898 {
1899 eprintln!(
1900 "\
1901ERROR: No configured backend named `{name}`
1902HELP: You can add it into `bootstrap.toml` in `rust.codegen-backends = [{name:?}]`",
1903 name = codegen_backend.name(),
1904 );
1905 crate::exit!(1);
1906 }
1907 cmd.arg("--override-codegen-backend").arg(codegen_backend.name());
1910 cmd.arg("--default-codegen-backend").arg(codegen_backend.name());
1913 } else {
1914 cmd.arg("--default-codegen-backend")
1917 .arg(builder.config.default_codegen_backend(test_compiler.host).name());
1918 }
1919
1920 if builder.build.config.llvm_enzyme {
1921 cmd.arg("--has-enzyme");
1922 }
1923
1924 if builder.config.cmd.bless() {
1925 cmd.arg("--bless");
1926 }
1927
1928 if builder.config.cmd.force_rerun() {
1929 cmd.arg("--force-rerun");
1930 }
1931
1932 if builder.config.cmd.no_capture() {
1933 cmd.arg("--no-capture");
1934 }
1935
1936 let compare_mode =
1937 builder.config.cmd.compare_mode().or_else(|| {
1938 if builder.config.test_compare_mode { self.compare_mode } else { None }
1939 });
1940
1941 if let Some(ref pass) = builder.config.cmd.pass() {
1942 cmd.arg("--pass");
1943 cmd.arg(pass);
1944 }
1945
1946 if let Some(ref run) = builder.config.cmd.run() {
1947 cmd.arg("--run");
1948 cmd.arg(run);
1949 }
1950
1951 if let Some(ref nodejs) = builder.config.nodejs {
1952 cmd.arg("--nodejs").arg(nodejs);
1953 } else if mode == "rustdoc-js" {
1954 panic!("need nodejs to run rustdoc-js suite");
1955 }
1956 if let Some(ref npm) = builder.config.npm {
1957 cmd.arg("--npm").arg(npm);
1958 }
1959 if builder.config.rust_optimize_tests {
1960 cmd.arg("--optimize-tests");
1961 }
1962 if builder.config.rust_randomize_layout {
1963 cmd.arg("--rust-randomized-layout");
1964 }
1965 if builder.config.cmd.only_modified() {
1966 cmd.arg("--only-modified");
1967 }
1968 if let Some(compiletest_diff_tool) = &builder.config.compiletest_diff_tool {
1969 cmd.arg("--compiletest-diff-tool").arg(compiletest_diff_tool);
1970 }
1971
1972 let mut flags = if is_rustdoc { Vec::new() } else { vec!["-Crpath".to_string()] };
1973 flags.push(format!(
1974 "-Cdebuginfo={}",
1975 if mode == "codegen" {
1976 if builder.config.rust_debuginfo_level_tests
1979 != crate::core::config::DebuginfoLevel::None
1980 {
1981 println!(
1982 "NOTE: ignoring `rust.debuginfo-level-tests={}` for codegen tests",
1983 builder.config.rust_debuginfo_level_tests
1984 );
1985 }
1986 crate::core::config::DebuginfoLevel::None
1987 } else {
1988 builder.config.rust_debuginfo_level_tests
1989 }
1990 ));
1991 flags.extend(builder.config.cmd.compiletest_rustc_args().iter().map(|s| s.to_string()));
1992
1993 if suite != "mir-opt" {
1994 if let Some(linker) = builder.linker(target) {
1995 cmd.arg("--target-linker").arg(linker);
1996 }
1997 if let Some(linker) = builder.linker(test_compiler.host) {
1998 cmd.arg("--host-linker").arg(linker);
1999 }
2000 }
2001
2002 if suite == "ui-fulldeps" && target.ends_with("darwin") {
2004 flags.push("-Alinker_messages".into());
2005 }
2006
2007 let mut hostflags = flags.clone();
2008 hostflags.extend(linker_flags(builder, test_compiler.host, LldThreads::No));
2009
2010 let mut targetflags = flags;
2011
2012 if suite == "ui" || suite == "incremental" {
2014 builder.ensure(TestHelpers { target: test_compiler.host });
2015 builder.ensure(TestHelpers { target });
2016 hostflags.push(format!(
2017 "-Lnative={}",
2018 builder.test_helpers_out(test_compiler.host).display()
2019 ));
2020 targetflags.push(format!("-Lnative={}", builder.test_helpers_out(target).display()));
2021 }
2022
2023 for flag in hostflags {
2024 cmd.arg("--host-rustcflags").arg(flag);
2025 }
2026 for flag in targetflags {
2027 cmd.arg("--target-rustcflags").arg(flag);
2028 }
2029
2030 cmd.arg("--python").arg(builder.python());
2031
2032 if let Some(ref gdb) = builder.config.gdb {
2033 cmd.arg("--gdb").arg(gdb);
2034 }
2035
2036 let lldb_exe = builder.config.lldb.clone().unwrap_or_else(|| PathBuf::from("lldb"));
2037 let lldb_version = command(&lldb_exe)
2038 .allow_failure()
2039 .arg("--version")
2040 .run_capture(builder)
2041 .stdout_if_ok()
2042 .and_then(|v| if v.trim().is_empty() { None } else { Some(v) });
2043 if let Some(ref vers) = lldb_version {
2044 cmd.arg("--lldb-version").arg(vers);
2045 let lldb_python_dir = command(&lldb_exe)
2046 .allow_failure()
2047 .arg("-P")
2048 .run_capture_stdout(builder)
2049 .stdout_if_ok()
2050 .map(|p| p.lines().next().expect("lldb Python dir not found").to_string());
2051 if let Some(ref dir) = lldb_python_dir {
2052 cmd.arg("--lldb-python-dir").arg(dir);
2053 }
2054 }
2055
2056 if helpers::forcing_clang_based_tests() {
2057 let clang_exe = builder.llvm_out(target).join("bin").join("clang");
2058 cmd.arg("--run-clang-based-tests-with").arg(clang_exe);
2059 }
2060
2061 for exclude in &builder.config.skip {
2062 cmd.arg("--skip");
2063 cmd.arg(exclude);
2064 }
2065
2066 let paths = match &builder.config.cmd {
2068 Subcommand::Test { .. } => &builder.config.paths[..],
2069 _ => &[],
2070 };
2071
2072 let mut test_args: Vec<&str> = paths
2074 .iter()
2075 .filter_map(|p| helpers::is_valid_test_suite_arg(p, suite_path, builder))
2076 .collect();
2077
2078 test_args.append(&mut builder.config.test_args());
2079
2080 if cfg!(windows) {
2083 let test_args_win: Vec<String> =
2084 test_args.iter().map(|s| s.replace('/', "\\")).collect();
2085 cmd.args(&test_args_win);
2086 } else {
2087 cmd.args(&test_args);
2088 }
2089
2090 if builder.is_verbose() {
2091 cmd.arg("--verbose");
2092 }
2093
2094 if builder.config.rustc_debug_assertions {
2095 cmd.arg("--with-rustc-debug-assertions");
2096 }
2097
2098 if builder.config.std_debug_assertions {
2099 cmd.arg("--with-std-debug-assertions");
2100 }
2101
2102 let mut llvm_components_passed = false;
2103 let mut copts_passed = false;
2104 if builder.config.llvm_enabled(test_compiler.host) {
2105 let llvm::LlvmResult { host_llvm_config, .. } =
2106 builder.ensure(llvm::Llvm { target: builder.config.host_target });
2107 if !builder.config.dry_run() {
2108 let llvm_version = get_llvm_version(builder, &host_llvm_config);
2109 let llvm_components = command(&host_llvm_config)
2110 .cached()
2111 .arg("--components")
2112 .run_capture_stdout(builder)
2113 .stdout();
2114 cmd.arg("--llvm-version")
2116 .arg(llvm_version.trim())
2117 .arg("--llvm-components")
2118 .arg(llvm_components.trim());
2119 llvm_components_passed = true;
2120 }
2121 if !builder.config.is_rust_llvm(target) {
2122 cmd.arg("--system-llvm");
2123 }
2124
2125 if !builder.config.dry_run() && suite.ends_with("fulldeps") {
2130 let llvm_libdir = command(&host_llvm_config)
2131 .cached()
2132 .arg("--libdir")
2133 .run_capture_stdout(builder)
2134 .stdout();
2135 let link_llvm = if target.is_msvc() {
2136 format!("-Clink-arg=-LIBPATH:{llvm_libdir}")
2137 } else {
2138 format!("-Clink-arg=-L{llvm_libdir}")
2139 };
2140 cmd.arg("--host-rustcflags").arg(link_llvm);
2141 }
2142
2143 if !builder.config.dry_run() && matches!(mode, "run-make" | "coverage-run") {
2144 let llvm_bin_path = host_llvm_config
2149 .parent()
2150 .expect("Expected llvm-config to be contained in directory");
2151 assert!(llvm_bin_path.is_dir());
2152 cmd.arg("--llvm-bin-dir").arg(llvm_bin_path);
2153 }
2154
2155 if !builder.config.dry_run() && mode == "run-make" {
2156 if builder.config.lld_enabled {
2158 let lld_install_root =
2159 builder.ensure(llvm::Lld { target: builder.config.host_target });
2160
2161 let lld_bin_path = lld_install_root.join("bin");
2162
2163 let old_path = env::var_os("PATH").unwrap_or_default();
2164 let new_path = env::join_paths(
2165 std::iter::once(lld_bin_path).chain(env::split_paths(&old_path)),
2166 )
2167 .expect("Could not add LLD bin path to PATH");
2168 cmd.env("PATH", new_path);
2169 }
2170 }
2171 }
2172
2173 if !builder.config.dry_run() && mode == "run-make" {
2176 let mut cflags = builder.cc_handled_clags(target, CLang::C);
2177 cflags.extend(builder.cc_unhandled_cflags(target, GitRepo::Rustc, CLang::C));
2178 let mut cxxflags = builder.cc_handled_clags(target, CLang::Cxx);
2179 cxxflags.extend(builder.cc_unhandled_cflags(target, GitRepo::Rustc, CLang::Cxx));
2180 cmd.arg("--cc")
2181 .arg(builder.cc(target))
2182 .arg("--cxx")
2183 .arg(builder.cxx(target).unwrap())
2184 .arg("--cflags")
2185 .arg(cflags.join(" "))
2186 .arg("--cxxflags")
2187 .arg(cxxflags.join(" "));
2188 copts_passed = true;
2189 if let Some(ar) = builder.ar(target) {
2190 cmd.arg("--ar").arg(ar);
2191 }
2192 }
2193
2194 if !llvm_components_passed {
2195 cmd.arg("--llvm-components").arg("");
2196 }
2197 if !copts_passed {
2198 cmd.arg("--cc")
2199 .arg("")
2200 .arg("--cxx")
2201 .arg("")
2202 .arg("--cflags")
2203 .arg("")
2204 .arg("--cxxflags")
2205 .arg("");
2206 }
2207
2208 if builder.remote_tested(target) {
2209 cmd.arg("--remote-test-client").arg(builder.tool_exe(Tool::RemoteTestClient));
2210 } else if let Some(tool) = builder.runner(target) {
2211 cmd.arg("--runner").arg(tool);
2212 }
2213
2214 if suite != "mir-opt" {
2215 if !builder.config.dry_run() && target.is_msvc() {
2221 for (k, v) in builder.cc[&target].env() {
2222 if k != "PATH" {
2223 cmd.env(k, v);
2224 }
2225 }
2226 }
2227 }
2228
2229 if !builder.config.dry_run()
2231 && target.contains("msvc")
2232 && builder.config.sanitizers_enabled(target)
2233 {
2234 cmd.env("ASAN_WIN_CONTINUE_ON_INTERCEPTION_FAILURE", "1");
2237 let asan_runtime_path = builder.cc[&target].path().parent().unwrap().to_path_buf();
2239 let old_path = cmd
2240 .get_envs()
2241 .find_map(|(k, v)| (k == "PATH").then_some(v))
2242 .flatten()
2243 .map_or_else(|| env::var_os("PATH").unwrap_or_default(), |v| v.to_owned());
2244 let new_path = env::join_paths(
2245 env::split_paths(&old_path).chain(std::iter::once(asan_runtime_path)),
2246 )
2247 .expect("Could not add ASAN runtime path to PATH");
2248 cmd.env("PATH", new_path);
2249 }
2250
2251 cmd.env_remove("CARGO");
2254
2255 cmd.env("RUSTC_BOOTSTRAP", "1");
2256 cmd.env("RUSTC_FORCE_RUSTC_VERSION", "compiletest");
2259 cmd.env("DOC_RUST_LANG_ORG_CHANNEL", builder.doc_rust_lang_org_channel());
2260 builder.add_rust_test_threads(&mut cmd);
2261
2262 if builder.config.sanitizers_enabled(target) {
2263 cmd.env("RUSTC_SANITIZER_SUPPORT", "1");
2264 }
2265
2266 if builder.config.profiler_enabled(target) {
2267 cmd.arg("--profiler-runtime");
2268 }
2269
2270 cmd.env("RUST_TEST_TMPDIR", builder.tempdir());
2271
2272 cmd.arg("--adb-path").arg("adb");
2273 cmd.arg("--adb-test-dir").arg(ADB_TEST_DIR);
2274 if target.contains("android") && !builder.config.dry_run() {
2275 cmd.arg("--android-cross-path")
2277 .arg(builder.cc(target).parent().unwrap().parent().unwrap());
2278 } else {
2279 cmd.arg("--android-cross-path").arg("");
2280 }
2281
2282 if builder.config.cmd.rustfix_coverage() {
2283 cmd.arg("--rustfix-coverage");
2284 }
2285
2286 cmd.arg("--channel").arg(&builder.config.channel);
2287
2288 if !builder.config.omit_git_hash {
2289 cmd.arg("--git-hash");
2290 }
2291
2292 let git_config = builder.config.git_config();
2293 cmd.arg("--nightly-branch").arg(git_config.nightly_branch);
2294 cmd.arg("--git-merge-commit-email").arg(git_config.git_merge_commit_email);
2295 cmd.force_coloring_in_ci();
2296
2297 #[cfg(feature = "build-metrics")]
2298 builder.metrics.begin_test_suite(
2299 build_helper::metrics::TestSuiteMetadata::Compiletest {
2300 suite: suite.into(),
2301 mode: mode.into(),
2302 compare_mode: None,
2303 target: self.target.triple.to_string(),
2304 host: self.test_compiler.host.triple.to_string(),
2305 stage: self.test_compiler.stage,
2306 },
2307 builder,
2308 );
2309
2310 let _group = builder.msg_test(
2311 format!("with compiletest suite={suite} mode={mode}"),
2312 target,
2313 test_compiler.stage,
2314 );
2315 try_run_tests(builder, &mut cmd, false);
2316
2317 if let Some(compare_mode) = compare_mode {
2318 cmd.arg("--compare-mode").arg(compare_mode);
2319
2320 #[cfg(feature = "build-metrics")]
2321 builder.metrics.begin_test_suite(
2322 build_helper::metrics::TestSuiteMetadata::Compiletest {
2323 suite: suite.into(),
2324 mode: mode.into(),
2325 compare_mode: Some(compare_mode.into()),
2326 target: self.target.triple.to_string(),
2327 host: self.test_compiler.host.triple.to_string(),
2328 stage: self.test_compiler.stage,
2329 },
2330 builder,
2331 );
2332
2333 builder.info(&format!(
2334 "Check compiletest suite={} mode={} compare_mode={} ({} -> {})",
2335 suite, mode, compare_mode, &test_compiler.host, target
2336 ));
2337 let _time = helpers::timeit(builder);
2338 try_run_tests(builder, &mut cmd, false);
2339 }
2340 }
2341
2342 fn metadata(&self) -> Option<StepMetadata> {
2343 Some(
2344 StepMetadata::test(&format!("compiletest-{}", self.suite), self.target)
2345 .stage(self.test_compiler.stage),
2346 )
2347 }
2348}
2349
2350#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2352struct BookTest {
2353 test_compiler: Compiler,
2354 path: PathBuf,
2355 name: &'static str,
2356 is_ext_doc: bool,
2357 dependencies: Vec<&'static str>,
2358}
2359
2360impl Step for BookTest {
2361 type Output = ();
2362 const IS_HOST: bool = true;
2363
2364 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2365 run.never()
2366 }
2367
2368 fn run(self, builder: &Builder<'_>) {
2369 if self.is_ext_doc {
2379 self.run_ext_doc(builder);
2380 } else {
2381 self.run_local_doc(builder);
2382 }
2383 }
2384}
2385
2386impl BookTest {
2387 fn run_ext_doc(self, builder: &Builder<'_>) {
2390 let test_compiler = self.test_compiler;
2391
2392 builder.std(test_compiler, test_compiler.host);
2393
2394 let mut rustdoc_path = builder.rustdoc_for_compiler(test_compiler);
2397 rustdoc_path.pop();
2398 let old_path = env::var_os("PATH").unwrap_or_default();
2399 let new_path = env::join_paths(iter::once(rustdoc_path).chain(env::split_paths(&old_path)))
2400 .expect("could not add rustdoc to PATH");
2401
2402 let mut rustbook_cmd = builder.tool_cmd(Tool::Rustbook);
2403 let path = builder.src.join(&self.path);
2404 rustbook_cmd.env("RUSTC_BOOTSTRAP", "1");
2406 rustbook_cmd.env("PATH", new_path).arg("test").arg(path);
2407
2408 let libs = if !self.dependencies.is_empty() {
2413 let mut lib_paths = vec![];
2414 for dep in self.dependencies {
2415 let mode = Mode::ToolRustcPrivate;
2416 let target = builder.config.host_target;
2417 let cargo = tool::prepare_tool_cargo(
2418 builder,
2419 test_compiler,
2420 mode,
2421 target,
2422 Kind::Build,
2423 dep,
2424 SourceType::Submodule,
2425 &[],
2426 );
2427
2428 let stamp = BuildStamp::new(&builder.cargo_out(test_compiler, mode, target))
2429 .with_prefix(PathBuf::from(dep).file_name().and_then(|v| v.to_str()).unwrap());
2430
2431 let output_paths = run_cargo(builder, cargo, vec![], &stamp, vec![], false, false);
2432 let directories = output_paths
2433 .into_iter()
2434 .filter_map(|p| p.parent().map(ToOwned::to_owned))
2435 .fold(HashSet::new(), |mut set, dir| {
2436 set.insert(dir);
2437 set
2438 });
2439
2440 lib_paths.extend(directories);
2441 }
2442 lib_paths
2443 } else {
2444 vec![]
2445 };
2446
2447 if !libs.is_empty() {
2448 let paths = libs
2449 .into_iter()
2450 .map(|path| path.into_os_string())
2451 .collect::<Vec<OsString>>()
2452 .join(OsStr::new(","));
2453 rustbook_cmd.args([OsString::from("--library-path"), paths]);
2454 }
2455
2456 builder.add_rust_test_threads(&mut rustbook_cmd);
2457 let _guard = builder.msg_test(
2458 format_args!("mdbook {}", self.path.display()),
2459 test_compiler.host,
2460 test_compiler.stage,
2461 );
2462 let _time = helpers::timeit(builder);
2463 let toolstate = if rustbook_cmd.delay_failure().run(builder) {
2464 ToolState::TestPass
2465 } else {
2466 ToolState::TestFail
2467 };
2468 builder.save_toolstate(self.name, toolstate);
2469 }
2470
2471 fn run_local_doc(self, builder: &Builder<'_>) {
2473 let test_compiler = self.test_compiler;
2474 let host = self.test_compiler.host;
2475
2476 builder.std(test_compiler, host);
2477
2478 let _guard = builder.msg_test(
2479 format!("book {}", self.name),
2480 test_compiler.host,
2481 test_compiler.stage,
2482 );
2483
2484 let mut stack = vec![builder.src.join(self.path)];
2487 let _time = helpers::timeit(builder);
2488 let mut files = Vec::new();
2489 while let Some(p) = stack.pop() {
2490 if p.is_dir() {
2491 stack.extend(t!(p.read_dir()).map(|p| t!(p).path()));
2492 continue;
2493 }
2494
2495 if p.extension().and_then(|s| s.to_str()) != Some("md") {
2496 continue;
2497 }
2498
2499 files.push(p);
2500 }
2501
2502 files.sort();
2503
2504 for file in files {
2505 markdown_test(builder, test_compiler, &file);
2506 }
2507 }
2508}
2509
2510macro_rules! test_book {
2511 ($(
2512 $name:ident, $path:expr, $book_name:expr,
2513 default=$default:expr
2514 $(,submodules = $submodules:expr)?
2515 $(,dependencies=$dependencies:expr)?
2516 ;
2517 )+) => {
2518 $(
2519 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
2520 pub struct $name {
2521 test_compiler: Compiler,
2522 }
2523
2524 impl Step for $name {
2525 type Output = ();
2526 const DEFAULT: bool = $default;
2527 const IS_HOST: bool = true;
2528
2529 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2530 run.path($path)
2531 }
2532
2533 fn make_run(run: RunConfig<'_>) {
2534 run.builder.ensure($name {
2535 test_compiler: run.builder.compiler(run.builder.top_stage, run.target),
2536 });
2537 }
2538
2539 fn run(self, builder: &Builder<'_>) {
2540 $(
2541 for submodule in $submodules {
2542 builder.require_submodule(submodule, None);
2543 }
2544 )*
2545
2546 let dependencies = vec![];
2547 $(
2548 let mut dependencies = dependencies;
2549 for dep in $dependencies {
2550 dependencies.push(dep);
2551 }
2552 )?
2553
2554 builder.ensure(BookTest {
2555 test_compiler: self.test_compiler,
2556 path: PathBuf::from($path),
2557 name: $book_name,
2558 is_ext_doc: !$default,
2559 dependencies,
2560 });
2561 }
2562 }
2563 )+
2564 }
2565}
2566
2567test_book!(
2568 Nomicon, "src/doc/nomicon", "nomicon", default=false, submodules=["src/doc/nomicon"];
2569 Reference, "src/doc/reference", "reference", default=false, submodules=["src/doc/reference"];
2570 RustdocBook, "src/doc/rustdoc", "rustdoc", default=true;
2571 RustcBook, "src/doc/rustc", "rustc", default=true;
2572 RustByExample, "src/doc/rust-by-example", "rust-by-example", default=false, submodules=["src/doc/rust-by-example"];
2573 EmbeddedBook, "src/doc/embedded-book", "embedded-book", default=false, submodules=["src/doc/embedded-book"];
2574 TheBook, "src/doc/book", "book", default=false, submodules=["src/doc/book"], dependencies=["src/doc/book/packages/trpl"];
2575 UnstableBook, "src/doc/unstable-book", "unstable-book", default=true;
2576 EditionGuide, "src/doc/edition-guide", "edition-guide", default=false, submodules=["src/doc/edition-guide"];
2577);
2578
2579#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2580pub struct ErrorIndex {
2581 compilers: RustcPrivateCompilers,
2582}
2583
2584impl Step for ErrorIndex {
2585 type Output = ();
2586 const DEFAULT: bool = true;
2587 const IS_HOST: bool = true;
2588
2589 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2590 run.path("src/tools/error_index_generator").alias("error-index")
2593 }
2594
2595 fn make_run(run: RunConfig<'_>) {
2596 let compilers = RustcPrivateCompilers::new(
2600 run.builder,
2601 run.builder.top_stage,
2602 run.builder.config.host_target,
2603 );
2604 run.builder.ensure(ErrorIndex { compilers });
2605 }
2606
2607 fn run(self, builder: &Builder<'_>) {
2614 let target_compiler = self.compilers.target_compiler();
2616
2617 let dir = testdir(builder, target_compiler.host);
2618 t!(fs::create_dir_all(&dir));
2619 let output = dir.join("error-index.md");
2620
2621 let mut tool = tool::ErrorIndex::command(builder, self.compilers);
2622 tool.arg("markdown").arg(&output);
2623
2624 let guard = builder.msg_test("error-index", target_compiler.host, target_compiler.stage);
2625 let _time = helpers::timeit(builder);
2626 tool.run_capture(builder);
2627 drop(guard);
2628 builder.std(target_compiler, target_compiler.host);
2631 markdown_test(builder, target_compiler, &output);
2632 }
2633}
2634
2635fn markdown_test(builder: &Builder<'_>, compiler: Compiler, markdown: &Path) -> bool {
2636 if let Ok(contents) = fs::read_to_string(markdown)
2637 && !contents.contains("```")
2638 {
2639 return true;
2640 }
2641
2642 builder.verbose(|| println!("doc tests for: {}", markdown.display()));
2643 let mut cmd = builder.rustdoc_cmd(compiler);
2644 builder.add_rust_test_threads(&mut cmd);
2645 cmd.arg("-Z");
2647 cmd.arg("unstable-options");
2648 cmd.arg("--test");
2649 cmd.arg(markdown);
2650 cmd.env("RUSTC_BOOTSTRAP", "1");
2651
2652 let test_args = builder.config.test_args().join(" ");
2653 cmd.arg("--test-args").arg(test_args);
2654
2655 cmd = cmd.delay_failure();
2656 if !builder.config.verbose_tests {
2657 cmd.run_capture(builder).is_success()
2658 } else {
2659 cmd.run(builder)
2660 }
2661}
2662
2663#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2668pub struct CrateLibrustc {
2669 build_compiler: Compiler,
2671 target: TargetSelection,
2672 crates: Vec<String>,
2673}
2674
2675impl Step for CrateLibrustc {
2676 type Output = ();
2677 const DEFAULT: bool = true;
2678 const IS_HOST: bool = true;
2679
2680 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2681 run.crate_or_deps("rustc-main").path("compiler")
2682 }
2683
2684 fn make_run(run: RunConfig<'_>) {
2685 let builder = run.builder;
2686 let host = run.build_triple();
2687 let build_compiler = builder.compiler(builder.top_stage - 1, host);
2688 let crates = run.make_run_crates(Alias::Compiler);
2689
2690 builder.ensure(CrateLibrustc { build_compiler, target: run.target, crates });
2691 }
2692
2693 fn run(self, builder: &Builder<'_>) {
2694 builder.std(self.build_compiler, self.target);
2695
2696 builder.ensure(Crate {
2698 build_compiler: self.build_compiler,
2699 target: self.target,
2700 mode: Mode::Rustc,
2701 crates: self.crates,
2702 });
2703 }
2704
2705 fn metadata(&self) -> Option<StepMetadata> {
2706 Some(StepMetadata::test("CrateLibrustc", self.target).built_by(self.build_compiler))
2707 }
2708}
2709
2710fn run_cargo_test<'a>(
2714 cargo: builder::Cargo,
2715 libtest_args: &[&str],
2716 crates: &[String],
2717 description: impl Into<Option<&'a str>>,
2718 target: TargetSelection,
2719 builder: &Builder<'_>,
2720) -> bool {
2721 let compiler = cargo.compiler();
2722 let mut cargo = prepare_cargo_test(cargo, libtest_args, crates, target, builder);
2723 let _time = helpers::timeit(builder);
2724 let _group =
2725 description.into().and_then(|what| builder.msg_test(what, target, compiler.stage + 1));
2726
2727 #[cfg(feature = "build-metrics")]
2728 builder.metrics.begin_test_suite(
2729 build_helper::metrics::TestSuiteMetadata::CargoPackage {
2730 crates: crates.iter().map(|c| c.to_string()).collect(),
2731 target: target.triple.to_string(),
2732 host: compiler.host.triple.to_string(),
2733 stage: compiler.stage,
2734 },
2735 builder,
2736 );
2737 add_flags_and_try_run_tests(builder, &mut cargo)
2738}
2739
2740fn prepare_cargo_test(
2742 cargo: builder::Cargo,
2743 libtest_args: &[&str],
2744 crates: &[String],
2745 target: TargetSelection,
2746 builder: &Builder<'_>,
2747) -> BootstrapCommand {
2748 let compiler = cargo.compiler();
2749 let mut cargo: BootstrapCommand = cargo.into();
2750
2751 if builder.config.cmd.bless() && !cargo.get_envs().any(|v| v.0 == "RUSTC_BLESS") {
2755 cargo.env("RUSTC_BLESS", "Gesundheit");
2756 }
2757
2758 if builder.kind == Kind::Test && !builder.fail_fast {
2762 cargo.arg("--no-fail-fast");
2763 }
2764
2765 if builder.config.json_output {
2766 cargo.arg("--message-format=json");
2767 }
2768
2769 match builder.doc_tests {
2770 DocTests::Only => {
2771 cargo.arg("--doc");
2772 }
2773 DocTests::No => {
2774 cargo.args(["--bins", "--examples", "--tests", "--benches"]);
2775 }
2776 DocTests::Yes => {}
2777 }
2778
2779 for krate in crates {
2780 cargo.arg("-p").arg(krate);
2781 }
2782
2783 cargo.arg("--").args(builder.config.test_args()).args(libtest_args);
2784 if !builder.config.verbose_tests {
2785 cargo.arg("--quiet");
2786 }
2787
2788 if builder.kind != Kind::Miri {
2797 let mut dylib_paths = builder.rustc_lib_paths(compiler);
2798 dylib_paths.push(builder.sysroot_target_libdir(compiler, target));
2799 helpers::add_dylib_path(dylib_paths, &mut cargo);
2800 }
2801
2802 if builder.remote_tested(target) {
2803 cargo.env(
2804 format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)),
2805 format!("{} run 0", builder.tool_exe(Tool::RemoteTestClient).display()),
2806 );
2807 } else if let Some(tool) = builder.runner(target) {
2808 cargo.env(format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)), tool);
2809 }
2810
2811 cargo
2812}
2813
2814#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2822pub struct Crate {
2823 build_compiler: Compiler,
2825 target: TargetSelection,
2826 mode: Mode,
2827 crates: Vec<String>,
2828}
2829
2830impl Step for Crate {
2831 type Output = ();
2832 const DEFAULT: bool = true;
2833
2834 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2835 run.crate_or_deps("sysroot").crate_or_deps("coretests").crate_or_deps("alloctests")
2836 }
2837
2838 fn make_run(run: RunConfig<'_>) {
2839 let builder = run.builder;
2840 let host = run.build_triple();
2841 let build_compiler = builder.compiler(builder.top_stage, host);
2842 let crates = run
2843 .paths
2844 .iter()
2845 .map(|p| builder.crate_paths[&p.assert_single_path().path].clone())
2846 .collect();
2847
2848 builder.ensure(Crate { build_compiler, target: run.target, mode: Mode::Std, crates });
2849 }
2850
2851 fn run(self, builder: &Builder<'_>) {
2860 let build_compiler = self.build_compiler;
2861 let target = self.target;
2862 let mode = self.mode;
2863
2864 builder.ensure(Std::new(build_compiler, build_compiler.host).force_recompile(true));
2867
2868 let mut cargo = if builder.kind == Kind::Miri {
2869 if builder.top_stage == 0 {
2870 eprintln!("ERROR: `x.py miri` requires stage 1 or higher");
2871 std::process::exit(1);
2872 }
2873
2874 let mut cargo = builder::Cargo::new(
2877 builder,
2878 build_compiler,
2879 mode,
2880 SourceType::InTree,
2881 target,
2882 Kind::MiriTest,
2883 );
2884 cargo.env("MIRI_REPLACE_LIBRS_IF_NOT_TEST", "1");
2896 cargo.rustflag("-Zforce-unstable-if-unmarked");
2900 cargo
2901 } else {
2902 if !builder.config.is_host_target(target) {
2904 builder.ensure(compile::Std::new(build_compiler, target).force_recompile(true));
2905 builder.ensure(RemoteCopyLibs { build_compiler, target });
2906 }
2907
2908 builder::Cargo::new(
2910 builder,
2911 build_compiler,
2912 mode,
2913 SourceType::InTree,
2914 target,
2915 builder.kind,
2916 )
2917 };
2918
2919 match mode {
2920 Mode::Std => {
2921 if builder.kind == Kind::Miri {
2922 cargo
2928 .arg("--manifest-path")
2929 .arg(builder.src.join("library/sysroot/Cargo.toml"));
2930 } else {
2931 compile::std_cargo(builder, target, &mut cargo);
2932 }
2933 }
2934 Mode::Rustc => {
2935 compile::rustc_cargo(builder, &mut cargo, target, &build_compiler, &self.crates);
2936 }
2937 _ => panic!("can only test libraries"),
2938 };
2939
2940 let mut crates = self.crates.clone();
2941 if crates.iter().any(|crate_| crate_ == "core") {
2946 crates.push("coretests".to_owned());
2947 }
2948 if crates.iter().any(|crate_| crate_ == "alloc") {
2949 crates.push("alloctests".to_owned());
2950 }
2951
2952 run_cargo_test(cargo, &[], &crates, &*crate_description(&self.crates), target, builder);
2953 }
2954}
2955
2956#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2959pub struct CrateRustdoc {
2960 host: TargetSelection,
2961}
2962
2963impl Step for CrateRustdoc {
2964 type Output = ();
2965 const DEFAULT: bool = true;
2966 const IS_HOST: bool = true;
2967
2968 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2969 run.paths(&["src/librustdoc", "src/tools/rustdoc"])
2970 }
2971
2972 fn make_run(run: RunConfig<'_>) {
2973 let builder = run.builder;
2974
2975 builder.ensure(CrateRustdoc { host: run.target });
2976 }
2977
2978 fn run(self, builder: &Builder<'_>) {
2979 let target = self.host;
2980
2981 let compiler = if builder.download_rustc() {
2982 builder.compiler(builder.top_stage, target)
2983 } else {
2984 builder.compiler_for(builder.top_stage, target, target)
2989 };
2990 builder.std(compiler, target);
2995 builder.ensure(compile::Rustc::new(compiler, target));
2996
2997 let mut cargo = tool::prepare_tool_cargo(
2998 builder,
2999 compiler,
3000 Mode::ToolRustcPrivate,
3001 target,
3002 builder.kind,
3003 "src/tools/rustdoc",
3004 SourceType::InTree,
3005 &[],
3006 );
3007 if self.host.contains("musl") {
3008 cargo.arg("'-Ctarget-feature=-crt-static'");
3009 }
3010
3011 let libdir = if builder.download_rustc() {
3038 builder.rustc_libdir(compiler)
3039 } else {
3040 builder.sysroot_target_libdir(compiler, target).to_path_buf()
3041 };
3042 let mut dylib_path = dylib_path();
3043 dylib_path.insert(0, PathBuf::from(&*libdir));
3044 cargo.env(dylib_path_var(), env::join_paths(&dylib_path).unwrap());
3045
3046 run_cargo_test(cargo, &[], &["rustdoc:0.0.0".to_string()], "rustdoc", target, builder);
3047 }
3048}
3049
3050#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3051pub struct CrateRustdocJsonTypes {
3052 build_compiler: Compiler,
3053 target: TargetSelection,
3054}
3055
3056impl Step for CrateRustdocJsonTypes {
3057 type Output = ();
3058 const DEFAULT: bool = true;
3059 const IS_HOST: bool = true;
3060
3061 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3062 run.path("src/rustdoc-json-types")
3063 }
3064
3065 fn make_run(run: RunConfig<'_>) {
3066 let builder = run.builder;
3067
3068 builder.ensure(CrateRustdocJsonTypes {
3069 build_compiler: get_tool_target_compiler(
3070 builder,
3071 ToolTargetBuildMode::Build(run.target),
3072 ),
3073 target: run.target,
3074 });
3075 }
3076
3077 fn run(self, builder: &Builder<'_>) {
3078 let target = self.target;
3079
3080 let cargo = tool::prepare_tool_cargo(
3081 builder,
3082 self.build_compiler,
3083 Mode::ToolTarget,
3084 target,
3085 builder.kind,
3086 "src/rustdoc-json-types",
3087 SourceType::InTree,
3088 &[],
3089 );
3090
3091 let libtest_args = if target.contains("musl") {
3093 ["'-Ctarget-feature=-crt-static'"].as_slice()
3094 } else {
3095 &[]
3096 };
3097
3098 run_cargo_test(
3099 cargo,
3100 libtest_args,
3101 &["rustdoc-json-types".to_string()],
3102 "rustdoc-json-types",
3103 target,
3104 builder,
3105 );
3106 }
3107}
3108
3109#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3119pub struct RemoteCopyLibs {
3120 build_compiler: Compiler,
3121 target: TargetSelection,
3122}
3123
3124impl Step for RemoteCopyLibs {
3125 type Output = ();
3126
3127 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3128 run.never()
3129 }
3130
3131 fn run(self, builder: &Builder<'_>) {
3132 let build_compiler = self.build_compiler;
3133 let target = self.target;
3134 if !builder.remote_tested(target) {
3135 return;
3136 }
3137
3138 builder.std(build_compiler, target);
3139
3140 builder.info(&format!("REMOTE copy libs to emulator ({target})"));
3141
3142 let remote_test_server = builder.ensure(tool::RemoteTestServer { build_compiler, target });
3143
3144 let tool = builder.tool_exe(Tool::RemoteTestClient);
3146 let mut cmd = command(&tool);
3147 cmd.arg("spawn-emulator")
3148 .arg(target.triple)
3149 .arg(&remote_test_server.tool_path)
3150 .arg(builder.tempdir());
3151 if let Some(rootfs) = builder.qemu_rootfs(target) {
3152 cmd.arg(rootfs);
3153 }
3154 cmd.run(builder);
3155
3156 for f in t!(builder.sysroot_target_libdir(build_compiler, target).read_dir()) {
3158 let f = t!(f);
3159 if helpers::is_dylib(&f.path()) {
3160 command(&tool).arg("push").arg(f.path()).run(builder);
3161 }
3162 }
3163 }
3164}
3165
3166#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3167pub struct Distcheck;
3168
3169impl Step for Distcheck {
3170 type Output = ();
3171
3172 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3173 run.alias("distcheck")
3174 }
3175
3176 fn make_run(run: RunConfig<'_>) {
3177 run.builder.ensure(Distcheck);
3178 }
3179
3180 fn run(self, builder: &Builder<'_>) {
3190 let root_dir = std::env::temp_dir().join("distcheck");
3193
3194 distcheck_plain_source_tarball(builder, &root_dir.join("distcheck-rustc-src"));
3195 distcheck_rust_src(builder, &root_dir.join("distcheck-rust-src"));
3196 distcheck_rustc_dev(builder, &root_dir.join("distcheck-rustc-dev"));
3197 }
3198}
3199
3200fn distcheck_plain_source_tarball(builder: &Builder<'_>, plain_src_dir: &Path) {
3202 builder.info("Distcheck plain source tarball");
3203 let plain_src_tarball = builder.ensure(dist::PlainSourceTarball);
3204 builder.clear_dir(plain_src_dir);
3205
3206 let configure_args: Vec<String> = std::env::var("DISTCHECK_CONFIGURE_ARGS")
3207 .map(|args| args.split(" ").map(|s| s.to_string()).collect::<Vec<String>>())
3208 .unwrap_or_default();
3209
3210 command("tar")
3211 .arg("-xf")
3212 .arg(plain_src_tarball.tarball())
3213 .arg("--strip-components=1")
3214 .current_dir(plain_src_dir)
3215 .run(builder);
3216 command("./configure")
3217 .arg("--set")
3218 .arg("rust.omit-git-hash=false")
3219 .args(&configure_args)
3220 .arg("--enable-vendor")
3221 .current_dir(plain_src_dir)
3222 .run(builder);
3223 command(helpers::make(&builder.config.host_target.triple))
3224 .arg("check")
3225 .env("GITHUB_ACTIONS", "0")
3228 .current_dir(plain_src_dir)
3229 .run(builder);
3230}
3231
3232fn distcheck_rust_src(builder: &Builder<'_>, src_dir: &Path) {
3234 builder.info("Distcheck rust-src");
3235 let src_tarball = builder.ensure(dist::Src);
3236 builder.clear_dir(src_dir);
3237
3238 command("tar")
3239 .arg("-xf")
3240 .arg(src_tarball.tarball())
3241 .arg("--strip-components=1")
3242 .current_dir(src_dir)
3243 .run(builder);
3244
3245 let toml = src_dir.join("rust-src/lib/rustlib/src/rust/library/std/Cargo.toml");
3246 command(&builder.initial_cargo)
3247 .env("RUSTC_BOOTSTRAP", "1")
3250 .arg("generate-lockfile")
3251 .arg("--manifest-path")
3252 .arg(&toml)
3253 .current_dir(src_dir)
3254 .run(builder);
3255}
3256
3257fn distcheck_rustc_dev(builder: &Builder<'_>, dir: &Path) {
3259 builder.info("Distcheck rustc-dev");
3260 let tarball = builder.ensure(dist::RustcDev::new(builder, builder.host_target)).unwrap();
3261 builder.clear_dir(dir);
3262
3263 command("tar")
3264 .arg("-xf")
3265 .arg(tarball.tarball())
3266 .arg("--strip-components=1")
3267 .current_dir(dir)
3268 .run(builder);
3269
3270 command(&builder.initial_cargo)
3271 .arg("metadata")
3272 .arg("--manifest-path")
3273 .arg("rustc-dev/lib/rustlib/rustc-src/rust/compiler/rustc/Cargo.toml")
3274 .env("RUSTC_BOOTSTRAP", "1")
3275 .env("RUSTC", &builder.initial_rustc)
3277 .current_dir(dir)
3278 .run(builder);
3279}
3280
3281#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3282pub struct Bootstrap;
3283
3284impl Step for Bootstrap {
3285 type Output = ();
3286 const DEFAULT: bool = true;
3287 const IS_HOST: bool = true;
3288
3289 fn run(self, builder: &Builder<'_>) {
3291 let host = builder.config.host_target;
3292 let build_compiler = builder.compiler(0, host);
3293
3294 builder.build.require_submodule("src/tools/cargo", None);
3296
3297 let mut check_bootstrap = command(builder.python());
3298 check_bootstrap
3299 .args(["-m", "unittest", "bootstrap_test.py"])
3300 .env("BUILD_DIR", &builder.out)
3301 .env("BUILD_PLATFORM", builder.build.host_target.triple)
3302 .env("BOOTSTRAP_TEST_RUSTC_BIN", &builder.initial_rustc)
3303 .env("BOOTSTRAP_TEST_CARGO_BIN", &builder.initial_cargo)
3304 .current_dir(builder.src.join("src/bootstrap/"));
3305 check_bootstrap.delay_failure().run(builder);
3308
3309 let mut cargo = tool::prepare_tool_cargo(
3310 builder,
3311 build_compiler,
3312 Mode::ToolBootstrap,
3313 host,
3314 Kind::Test,
3315 "src/bootstrap",
3316 SourceType::InTree,
3317 &[],
3318 );
3319
3320 cargo.release_build(false);
3321
3322 cargo
3323 .rustflag("-Cdebuginfo=2")
3324 .env("CARGO_TARGET_DIR", builder.out.join("bootstrap"))
3325 .env("INSTA_WORKSPACE_ROOT", &builder.src)
3327 .env("RUSTC_BOOTSTRAP", "1");
3328
3329 run_cargo_test(cargo, &[], &[], None, host, builder);
3330 }
3331
3332 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3333 let runs_on_ci = run.builder.config.is_running_on_ci;
3337 run.path("src/bootstrap").default_condition(runs_on_ci)
3338 }
3339
3340 fn make_run(run: RunConfig<'_>) {
3341 run.builder.ensure(Bootstrap);
3342 }
3343}
3344
3345fn get_compiler_to_test(builder: &Builder<'_>, target: TargetSelection) -> Compiler {
3346 builder.compiler(builder.top_stage, target)
3347}
3348
3349#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3352pub struct TierCheck {
3353 test_compiler: Compiler,
3354}
3355
3356impl Step for TierCheck {
3357 type Output = ();
3358 const DEFAULT: bool = true;
3359 const IS_HOST: bool = true;
3360
3361 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3362 run.path("src/tools/tier-check")
3363 }
3364
3365 fn make_run(run: RunConfig<'_>) {
3366 run.builder
3367 .ensure(TierCheck { test_compiler: get_compiler_to_test(run.builder, run.target) });
3368 }
3369
3370 fn run(self, builder: &Builder<'_>) {
3371 let tool_build_compiler = builder.compiler(0, builder.host_target);
3372
3373 let mut cargo = tool::prepare_tool_cargo(
3374 builder,
3375 tool_build_compiler,
3376 Mode::ToolBootstrap,
3377 tool_build_compiler.host,
3378 Kind::Run,
3379 "src/tools/tier-check",
3380 SourceType::InTree,
3381 &[],
3382 );
3383 cargo.arg(builder.src.join("src/doc/rustc/src/platform-support.md"));
3384 cargo.arg(builder.rustc(self.test_compiler));
3385 if builder.is_verbose() {
3386 cargo.arg("--verbose");
3387 }
3388
3389 let _guard = builder.msg_test(
3390 "platform support check",
3391 self.test_compiler.host,
3392 self.test_compiler.stage,
3393 );
3394 BootstrapCommand::from(cargo).delay_failure().run(builder);
3395 }
3396
3397 fn metadata(&self) -> Option<StepMetadata> {
3398 Some(StepMetadata::test("tier-check", self.test_compiler.host))
3399 }
3400}
3401
3402#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3403pub struct LintDocs {
3404 build_compiler: Compiler,
3405 target: TargetSelection,
3406}
3407
3408impl Step for LintDocs {
3409 type Output = ();
3410 const DEFAULT: bool = true;
3411 const IS_HOST: bool = true;
3412
3413 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3414 let stage = run.builder.top_stage;
3415 run.path("src/tools/lint-docs").default_condition(stage > 1)
3418 }
3419
3420 fn make_run(run: RunConfig<'_>) {
3421 if run.builder.top_stage < 2 {
3422 eprintln!("WARNING: lint-docs tests might not work below stage 2");
3423 }
3424
3425 run.builder.ensure(LintDocs {
3426 build_compiler: prepare_doc_compiler(
3427 run.builder,
3428 run.builder.config.host_target,
3429 run.builder.top_stage,
3430 ),
3431 target: run.target,
3432 });
3433 }
3434
3435 fn run(self, builder: &Builder<'_>) {
3438 builder.ensure(crate::core::build_steps::doc::RustcBook::validate(
3439 self.build_compiler,
3440 self.target,
3441 ));
3442 }
3443
3444 fn metadata(&self) -> Option<StepMetadata> {
3445 Some(StepMetadata::test("lint-docs", self.target).built_by(self.build_compiler))
3446 }
3447}
3448
3449#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3450pub struct RustInstaller;
3451
3452impl Step for RustInstaller {
3453 type Output = ();
3454 const IS_HOST: bool = true;
3455 const DEFAULT: bool = true;
3456
3457 fn run(self, builder: &Builder<'_>) {
3459 let bootstrap_host = builder.config.host_target;
3460 let build_compiler = builder.compiler(0, bootstrap_host);
3461 let cargo = tool::prepare_tool_cargo(
3462 builder,
3463 build_compiler,
3464 Mode::ToolBootstrap,
3465 bootstrap_host,
3466 Kind::Test,
3467 "src/tools/rust-installer",
3468 SourceType::InTree,
3469 &[],
3470 );
3471
3472 let _guard = builder.msg_test("rust-installer", bootstrap_host, 1);
3473 run_cargo_test(cargo, &[], &[], None, bootstrap_host, builder);
3474
3475 if bootstrap_host != "x86_64-unknown-linux-gnu" {
3479 return;
3480 }
3481
3482 let mut cmd = command(builder.src.join("src/tools/rust-installer/test.sh"));
3483 let tmpdir = testdir(builder, build_compiler.host).join("rust-installer");
3484 let _ = std::fs::remove_dir_all(&tmpdir);
3485 let _ = std::fs::create_dir_all(&tmpdir);
3486 cmd.current_dir(&tmpdir);
3487 cmd.env("CARGO_TARGET_DIR", tmpdir.join("cargo-target"));
3488 cmd.env("CARGO", &builder.initial_cargo);
3489 cmd.env("RUSTC", &builder.initial_rustc);
3490 cmd.env("TMP_DIR", &tmpdir);
3491 cmd.delay_failure().run(builder);
3492 }
3493
3494 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3495 run.path("src/tools/rust-installer")
3496 }
3497
3498 fn make_run(run: RunConfig<'_>) {
3499 run.builder.ensure(Self);
3500 }
3501}
3502
3503#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3504pub struct TestHelpers {
3505 pub target: TargetSelection,
3506}
3507
3508impl Step for TestHelpers {
3509 type Output = ();
3510
3511 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3512 run.path("tests/auxiliary/rust_test_helpers.c")
3513 }
3514
3515 fn make_run(run: RunConfig<'_>) {
3516 run.builder.ensure(TestHelpers { target: run.target })
3517 }
3518
3519 fn run(self, builder: &Builder<'_>) {
3522 if builder.config.dry_run() {
3523 return;
3524 }
3525 let target = if self.target == "x86_64-fortanix-unknown-sgx" {
3529 TargetSelection::from_user("x86_64-unknown-linux-gnu")
3530 } else {
3531 self.target
3532 };
3533 let dst = builder.test_helpers_out(target);
3534 let src = builder.src.join("tests/auxiliary/rust_test_helpers.c");
3535 if up_to_date(&src, &dst.join("librust_test_helpers.a")) {
3536 return;
3537 }
3538
3539 let _guard = builder.msg_unstaged(Kind::Build, "test helpers", target);
3540 t!(fs::create_dir_all(&dst));
3541 let mut cfg = cc::Build::new();
3542
3543 if !target.is_msvc() {
3547 if let Some(ar) = builder.ar(target) {
3548 cfg.archiver(ar);
3549 }
3550 cfg.compiler(builder.cc(target));
3551 }
3552 cfg.cargo_metadata(false)
3553 .out_dir(&dst)
3554 .target(&target.triple)
3555 .host(&builder.config.host_target.triple)
3556 .opt_level(0)
3557 .warnings(false)
3558 .debug(false)
3559 .file(builder.src.join("tests/auxiliary/rust_test_helpers.c"))
3560 .compile("rust_test_helpers");
3561 }
3562}
3563
3564#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3565pub struct CodegenCranelift {
3566 compilers: RustcPrivateCompilers,
3567 target: TargetSelection,
3568}
3569
3570impl Step for CodegenCranelift {
3571 type Output = ();
3572 const DEFAULT: bool = true;
3573 const IS_HOST: bool = true;
3574
3575 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3576 run.paths(&["compiler/rustc_codegen_cranelift"])
3577 }
3578
3579 fn make_run(run: RunConfig<'_>) {
3580 let builder = run.builder;
3581 let host = run.build_triple();
3582 let compilers = RustcPrivateCompilers::new(run.builder, run.builder.top_stage, host);
3583
3584 if builder.doc_tests == DocTests::Only {
3585 return;
3586 }
3587
3588 if builder.download_rustc() {
3589 builder.info("CI rustc uses the default codegen backend. skipping");
3590 return;
3591 }
3592
3593 if !target_supports_cranelift_backend(run.target) {
3594 builder.info("target not supported by rustc_codegen_cranelift. skipping");
3595 return;
3596 }
3597
3598 if builder.remote_tested(run.target) {
3599 builder.info("remote testing is not supported by rustc_codegen_cranelift. skipping");
3600 return;
3601 }
3602
3603 if !builder
3604 .config
3605 .enabled_codegen_backends(run.target)
3606 .contains(&CodegenBackendKind::Cranelift)
3607 {
3608 builder.info("cranelift not in rust.codegen-backends. skipping");
3609 return;
3610 }
3611
3612 builder.ensure(CodegenCranelift { compilers, target: run.target });
3613 }
3614
3615 fn run(self, builder: &Builder<'_>) {
3616 let compilers = self.compilers;
3617 let build_compiler = compilers.build_compiler();
3618
3619 let target_compiler = compilers.target_compiler();
3622 let target = self.target;
3623
3624 builder.std(target_compiler, target);
3625
3626 let mut cargo = builder::Cargo::new(
3627 builder,
3628 target_compiler,
3629 Mode::Codegen, SourceType::InTree,
3631 target,
3632 Kind::Run,
3633 );
3634
3635 cargo.current_dir(&builder.src.join("compiler/rustc_codegen_cranelift"));
3636 cargo
3637 .arg("--manifest-path")
3638 .arg(builder.src.join("compiler/rustc_codegen_cranelift/build_system/Cargo.toml"));
3639 compile::rustc_cargo_env(builder, &mut cargo, target);
3640
3641 cargo.env("CARGO_BUILD_INCREMENTAL", "false");
3643
3644 let _guard = builder.msg_test(
3645 "rustc_codegen_cranelift",
3646 target_compiler.host,
3647 target_compiler.stage,
3648 );
3649
3650 let download_dir = builder.out.join("cg_clif_download");
3652
3653 cargo
3654 .arg("--")
3655 .arg("test")
3656 .arg("--download-dir")
3657 .arg(&download_dir)
3658 .arg("--out-dir")
3659 .arg(builder.stage_out(build_compiler, Mode::Codegen).join("cg_clif"))
3660 .arg("--no-unstable-features")
3661 .arg("--use-backend")
3662 .arg("cranelift")
3663 .arg("--sysroot")
3665 .arg("llvm")
3666 .arg("--skip-test")
3669 .arg("testsuite.extended_sysroot");
3670
3671 cargo.into_cmd().run(builder);
3672 }
3673
3674 fn metadata(&self) -> Option<StepMetadata> {
3675 Some(
3676 StepMetadata::test("rustc_codegen_cranelift", self.target)
3677 .built_by(self.compilers.build_compiler()),
3678 )
3679 }
3680}
3681
3682#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3683pub struct CodegenGCC {
3684 compilers: RustcPrivateCompilers,
3685 target: TargetSelection,
3686}
3687
3688impl Step for CodegenGCC {
3689 type Output = ();
3690 const DEFAULT: bool = true;
3691 const IS_HOST: bool = true;
3692
3693 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3694 run.paths(&["compiler/rustc_codegen_gcc"])
3695 }
3696
3697 fn make_run(run: RunConfig<'_>) {
3698 let builder = run.builder;
3699 let host = run.build_triple();
3700 let compilers = RustcPrivateCompilers::new(run.builder, run.builder.top_stage, host);
3701
3702 if builder.doc_tests == DocTests::Only {
3703 return;
3704 }
3705
3706 if builder.download_rustc() {
3707 builder.info("CI rustc uses the default codegen backend. skipping");
3708 return;
3709 }
3710
3711 let triple = run.target.triple;
3712 let target_supported =
3713 if triple.contains("linux") { triple.contains("x86_64") } else { false };
3714 if !target_supported {
3715 builder.info("target not supported by rustc_codegen_gcc. skipping");
3716 return;
3717 }
3718
3719 if builder.remote_tested(run.target) {
3720 builder.info("remote testing is not supported by rustc_codegen_gcc. skipping");
3721 return;
3722 }
3723
3724 if !builder.config.enabled_codegen_backends(run.target).contains(&CodegenBackendKind::Gcc) {
3725 builder.info("gcc not in rust.codegen-backends. skipping");
3726 return;
3727 }
3728
3729 builder.ensure(CodegenGCC { compilers, target: run.target });
3730 }
3731
3732 fn run(self, builder: &Builder<'_>) {
3733 let compilers = self.compilers;
3734 let target = self.target;
3735
3736 let gcc = builder.ensure(Gcc { target });
3737
3738 builder.ensure(
3739 compile::Std::new(compilers.build_compiler(), target)
3740 .extra_rust_args(&["-Csymbol-mangling-version=v0", "-Cpanic=abort"]),
3741 );
3742
3743 let _guard = builder.msg_test(
3744 "rustc_codegen_gcc",
3745 compilers.target(),
3746 compilers.target_compiler().stage,
3747 );
3748
3749 let mut cargo = builder::Cargo::new(
3750 builder,
3751 compilers.build_compiler(),
3752 Mode::Codegen, SourceType::InTree,
3754 target,
3755 Kind::Run,
3756 );
3757
3758 cargo.current_dir(&builder.src.join("compiler/rustc_codegen_gcc"));
3759 cargo
3760 .arg("--manifest-path")
3761 .arg(builder.src.join("compiler/rustc_codegen_gcc/build_system/Cargo.toml"));
3762 compile::rustc_cargo_env(builder, &mut cargo, target);
3763 add_cg_gcc_cargo_flags(&mut cargo, &gcc);
3764
3765 cargo.env("CARGO_BUILD_INCREMENTAL", "false");
3767 cargo.rustflag("-Cpanic=abort");
3768
3769 cargo
3770 .env("CG_RUSTFLAGS", "-Alinker-messages")
3772 .arg("--")
3773 .arg("test")
3774 .arg("--use-backend")
3775 .arg("gcc")
3776 .arg("--gcc-path")
3777 .arg(gcc.libgccjit.parent().unwrap())
3778 .arg("--out-dir")
3779 .arg(builder.stage_out(compilers.build_compiler(), Mode::Codegen).join("cg_gcc"))
3780 .arg("--release")
3781 .arg("--mini-tests")
3782 .arg("--std-tests");
3783 cargo.args(builder.config.test_args());
3784
3785 cargo.into_cmd().run(builder);
3786 }
3787
3788 fn metadata(&self) -> Option<StepMetadata> {
3789 Some(
3790 StepMetadata::test("rustc_codegen_gcc", self.target)
3791 .built_by(self.compilers.build_compiler()),
3792 )
3793 }
3794}
3795
3796#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3801pub struct TestFloatParse {
3802 build_compiler: Compiler,
3811 target: TargetSelection,
3813}
3814
3815impl Step for TestFloatParse {
3816 type Output = ();
3817 const IS_HOST: bool = true;
3818 const DEFAULT: bool = true;
3819
3820 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3821 run.path("src/tools/test-float-parse")
3822 }
3823
3824 fn make_run(run: RunConfig<'_>) {
3825 run.builder.ensure(Self {
3826 build_compiler: get_compiler_to_test(run.builder, run.target),
3827 target: run.target,
3828 });
3829 }
3830
3831 fn run(self, builder: &Builder<'_>) {
3832 let build_compiler = self.build_compiler;
3833 let target = self.target;
3834
3835 builder.std(build_compiler, target);
3837 builder.std(build_compiler, builder.host_target);
3838
3839 let mut cargo_test = tool::prepare_tool_cargo(
3841 builder,
3842 build_compiler,
3843 Mode::ToolStd,
3844 target,
3845 Kind::Test,
3846 "src/tools/test-float-parse",
3847 SourceType::InTree,
3848 &[],
3849 );
3850 cargo_test.allow_features(TEST_FLOAT_PARSE_ALLOW_FEATURES);
3851
3852 run_cargo_test(cargo_test, &[], &[], "test-float-parse", target, builder);
3853
3854 let mut cargo_run = tool::prepare_tool_cargo(
3856 builder,
3857 build_compiler,
3858 Mode::ToolStd,
3859 target,
3860 Kind::Run,
3861 "src/tools/test-float-parse",
3862 SourceType::InTree,
3863 &[],
3864 );
3865 cargo_run.allow_features(TEST_FLOAT_PARSE_ALLOW_FEATURES);
3866
3867 if !matches!(env::var("FLOAT_PARSE_TESTS_NO_SKIP_HUGE").as_deref(), Ok("1") | Ok("true")) {
3868 cargo_run.args(["--", "--skip-huge"]);
3869 }
3870
3871 cargo_run.into_cmd().run(builder);
3872 }
3873}
3874
3875#[derive(Debug, Clone, Hash, PartialEq, Eq)]
3879pub struct CollectLicenseMetadata;
3880
3881impl Step for CollectLicenseMetadata {
3882 type Output = PathBuf;
3883 const IS_HOST: bool = true;
3884
3885 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3886 run.path("src/tools/collect-license-metadata")
3887 }
3888
3889 fn make_run(run: RunConfig<'_>) {
3890 run.builder.ensure(CollectLicenseMetadata);
3891 }
3892
3893 fn run(self, builder: &Builder<'_>) -> Self::Output {
3894 let Some(reuse) = &builder.config.reuse else {
3895 panic!("REUSE is required to collect the license metadata");
3896 };
3897
3898 let dest = builder.src.join("license-metadata.json");
3899
3900 let mut cmd = builder.tool_cmd(Tool::CollectLicenseMetadata);
3901 cmd.env("REUSE_EXE", reuse);
3902 cmd.env("DEST", &dest);
3903 cmd.env("ONLY_CHECK", "1");
3904 cmd.run(builder);
3905
3906 dest
3907 }
3908}