1use std::collections::HashSet;
7use std::ffi::{OsStr, OsString};
8use std::path::{Path, PathBuf};
9use std::{env, fs, iter};
10
11use clap_complete::shells;
12
13use crate::core::build_steps::compile::run_cargo;
14use crate::core::build_steps::doc::DocumentationFormat;
15use crate::core::build_steps::llvm::get_llvm_version;
16use crate::core::build_steps::synthetic_targets::MirOptPanicAbortSyntheticTarget;
17use crate::core::build_steps::tool::{self, SourceType, Tool};
18use crate::core::build_steps::toolstate::ToolState;
19use crate::core::build_steps::{compile, dist, llvm};
20use crate::core::builder::{
21 self, Alias, Builder, Compiler, Kind, RunConfig, ShouldRun, Step, crate_description,
22};
23use crate::core::config::TargetSelection;
24use crate::core::config::flags::{Subcommand, get_completion};
25use crate::utils::build_stamp::{self, BuildStamp};
26use crate::utils::exec::{BootstrapCommand, command};
27use crate::utils::helpers::{
28 self, LldThreads, add_rustdoc_cargo_linker_args, dylib_path, dylib_path_var, linker_args,
29 linker_flags, t, target_supports_cranelift_backend, up_to_date,
30};
31use crate::utils::render_tests::{add_flags_and_try_run_tests, try_run_tests};
32use crate::{CLang, DocTests, GitRepo, Mode, PathSet, envify};
33
34const ADB_TEST_DIR: &str = "/data/local/tmp/work";
35
36#[derive(Debug, Clone, PartialEq, Eq, Hash)]
38pub struct CrateBootstrap {
39 path: PathBuf,
40 host: TargetSelection,
41}
42
43impl Step for CrateBootstrap {
44 type Output = ();
45 const ONLY_HOSTS: bool = true;
46 const DEFAULT: bool = true;
47
48 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
49 run.path("src/tools/jsondoclint")
54 .path("src/tools/suggest-tests")
55 .path("src/tools/replace-version-placeholder")
56 .alias("tidyselftest")
59 }
60
61 fn make_run(run: RunConfig<'_>) {
62 for path in run.paths {
65 let path = path.assert_single_path().path.clone();
66 run.builder.ensure(CrateBootstrap { host: run.target, path });
67 }
68 }
69
70 fn run(self, builder: &Builder<'_>) {
71 let bootstrap_host = builder.config.build;
72 let compiler = builder.compiler(0, bootstrap_host);
73 let mut path = self.path.to_str().unwrap();
74
75 if path == "tidyselftest" {
77 path = "src/tools/tidy";
78 }
79
80 let cargo = tool::prepare_tool_cargo(
81 builder,
82 compiler,
83 Mode::ToolBootstrap,
84 bootstrap_host,
85 Kind::Test,
86 path,
87 SourceType::InTree,
88 &[],
89 );
90
91 let crate_name = path.rsplit_once('/').unwrap().1;
92 run_cargo_test(cargo, &[], &[], crate_name, crate_name, bootstrap_host, builder);
93 }
94}
95
96#[derive(Debug, Clone, PartialEq, Eq, Hash)]
97pub struct Linkcheck {
98 host: TargetSelection,
99}
100
101impl Step for Linkcheck {
102 type Output = ();
103 const ONLY_HOSTS: bool = true;
104 const DEFAULT: bool = true;
105
106 fn run(self, builder: &Builder<'_>) {
111 let host = self.host;
112 let hosts = &builder.hosts;
113 let targets = &builder.targets;
114
115 if (hosts != targets) && !hosts.is_empty() && !targets.is_empty() {
120 panic!(
121 "Linkcheck currently does not support builds with different hosts and targets.
122You can skip linkcheck with --skip src/tools/linkchecker"
123 );
124 }
125
126 builder.info(&format!("Linkcheck ({host})"));
127
128 let bootstrap_host = builder.config.build;
130 let compiler = builder.compiler(0, bootstrap_host);
131
132 let cargo = tool::prepare_tool_cargo(
133 builder,
134 compiler,
135 Mode::ToolBootstrap,
136 bootstrap_host,
137 Kind::Test,
138 "src/tools/linkchecker",
139 SourceType::InTree,
140 &[],
141 );
142 run_cargo_test(
143 cargo,
144 &[],
145 &[],
146 "linkchecker",
147 "linkchecker self tests",
148 bootstrap_host,
149 builder,
150 );
151
152 if builder.doc_tests == DocTests::No {
153 return;
154 }
155
156 builder.default_doc(&[]);
158
159 let linkchecker = builder.tool_cmd(Tool::Linkchecker);
161
162 let _guard =
164 builder.msg(Kind::Test, compiler.stage, "Linkcheck", bootstrap_host, bootstrap_host);
165 let _time = helpers::timeit(builder);
166 linkchecker.delay_failure().arg(builder.out.join(host).join("doc")).run(builder);
167 }
168
169 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
170 let builder = run.builder;
171 let run = run.path("src/tools/linkchecker");
172 run.default_condition(builder.config.docs)
173 }
174
175 fn make_run(run: RunConfig<'_>) {
176 run.builder.ensure(Linkcheck { host: run.target });
177 }
178}
179
180fn check_if_tidy_is_installed(builder: &Builder<'_>) -> bool {
181 command("tidy").allow_failure().arg("--version").run_capture_stdout(builder).is_success()
182}
183
184#[derive(Debug, Clone, PartialEq, Eq, Hash)]
185pub struct HtmlCheck {
186 target: TargetSelection,
187}
188
189impl Step for HtmlCheck {
190 type Output = ();
191 const DEFAULT: bool = true;
192 const ONLY_HOSTS: bool = true;
193
194 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
195 let builder = run.builder;
196 let run = run.path("src/tools/html-checker");
197 run.lazy_default_condition(Box::new(|| check_if_tidy_is_installed(builder)))
198 }
199
200 fn make_run(run: RunConfig<'_>) {
201 run.builder.ensure(HtmlCheck { target: run.target });
202 }
203
204 fn run(self, builder: &Builder<'_>) {
205 if !check_if_tidy_is_installed(builder) {
206 eprintln!("not running HTML-check tool because `tidy` is missing");
207 eprintln!(
208 "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."
209 );
210 panic!("Cannot run html-check tests");
211 }
212 builder.default_doc(&[]);
214 builder.ensure(crate::core::build_steps::doc::Rustc::new(
215 builder.top_stage,
216 self.target,
217 builder,
218 ));
219
220 builder
221 .tool_cmd(Tool::HtmlChecker)
222 .delay_failure()
223 .arg(builder.doc_out(self.target))
224 .run(builder);
225 }
226}
227
228#[derive(Debug, Clone, PartialEq, Eq, Hash)]
232pub struct Cargotest {
233 stage: u32,
234 host: TargetSelection,
235}
236
237impl Step for Cargotest {
238 type Output = ();
239 const ONLY_HOSTS: bool = true;
240
241 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
242 run.path("src/tools/cargotest")
243 }
244
245 fn make_run(run: RunConfig<'_>) {
246 run.builder.ensure(Cargotest { stage: run.builder.top_stage, host: run.target });
247 }
248
249 fn run(self, builder: &Builder<'_>) {
254 let compiler = builder.compiler(self.stage, self.host);
255 builder.ensure(compile::Rustc::new(compiler, compiler.host));
256 let cargo = builder.ensure(tool::Cargo { compiler, target: compiler.host });
257
258 let out_dir = builder.out.join("ct");
262 t!(fs::create_dir_all(&out_dir));
263
264 let _time = helpers::timeit(builder);
265 let mut cmd = builder.tool_cmd(Tool::CargoTest);
266 cmd.arg(&cargo)
267 .arg(&out_dir)
268 .args(builder.config.test_args())
269 .env("RUSTC", builder.rustc(compiler))
270 .env("RUSTDOC", builder.rustdoc(compiler));
271 add_rustdoc_cargo_linker_args(&mut cmd, builder, compiler.host, LldThreads::No);
272 cmd.delay_failure().run(builder);
273 }
274}
275
276#[derive(Debug, Clone, PartialEq, Eq, Hash)]
278pub struct Cargo {
279 stage: u32,
280 host: TargetSelection,
281}
282
283impl Cargo {
284 const CRATE_PATH: &str = "src/tools/cargo";
285}
286
287impl Step for Cargo {
288 type Output = ();
289 const ONLY_HOSTS: bool = true;
290
291 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
292 run.path(Self::CRATE_PATH)
293 }
294
295 fn make_run(run: RunConfig<'_>) {
296 run.builder.ensure(Cargo { stage: run.builder.top_stage, host: run.target });
297 }
298
299 fn run(self, builder: &Builder<'_>) {
301 let compiler = builder.compiler(self.stage, self.host);
302
303 builder.ensure(tool::Cargo { compiler, target: self.host });
304 let cargo = tool::prepare_tool_cargo(
305 builder,
306 compiler,
307 Mode::ToolRustc,
308 self.host,
309 Kind::Test,
310 Self::CRATE_PATH,
311 SourceType::Submodule,
312 &[],
313 );
314
315 let mut cargo = prepare_cargo_test(cargo, &[], &[], "cargo", self.host, builder);
317
318 cargo.env("CFG_DISABLE_CROSS_TESTS", "1");
321 cargo.env("CARGO_TEST_DISABLE_NIGHTLY", "1");
324 cargo.env("PATH", path_for_cargo(builder, compiler));
325 cargo.env("CARGO_RUSTC_CURRENT_DIR", builder.src.display().to_string());
329
330 #[cfg(feature = "build-metrics")]
331 builder.metrics.begin_test_suite(
332 build_helper::metrics::TestSuiteMetadata::CargoPackage {
333 crates: vec!["cargo".into()],
334 target: self.host.triple.to_string(),
335 host: self.host.triple.to_string(),
336 stage: self.stage,
337 },
338 builder,
339 );
340
341 let _time = helpers::timeit(builder);
342 add_flags_and_try_run_tests(builder, &mut cargo);
343 }
344}
345
346#[derive(Debug, Clone, PartialEq, Eq, Hash)]
347pub struct RustAnalyzer {
348 stage: u32,
349 host: TargetSelection,
350}
351
352impl Step for RustAnalyzer {
353 type Output = ();
354 const ONLY_HOSTS: bool = true;
355 const DEFAULT: bool = true;
356
357 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
358 run.path("src/tools/rust-analyzer")
359 }
360
361 fn make_run(run: RunConfig<'_>) {
362 run.builder.ensure(Self { stage: run.builder.top_stage, host: run.target });
363 }
364
365 fn run(self, builder: &Builder<'_>) {
367 let stage = self.stage;
368 let host = self.host;
369 let compiler = builder.compiler(stage, host);
370
371 builder.ensure(compile::Rustc::new(compiler, host));
374
375 let workspace_path = "src/tools/rust-analyzer";
376 let crate_path = "src/tools/rust-analyzer/crates/proc-macro-srv";
379 let mut cargo = tool::prepare_tool_cargo(
380 builder,
381 compiler,
382 Mode::ToolRustc,
383 host,
384 Kind::Test,
385 crate_path,
386 SourceType::InTree,
387 &["in-rust-tree".to_owned()],
388 );
389 cargo.allow_features(tool::RustAnalyzer::ALLOW_FEATURES);
390
391 let dir = builder.src.join(workspace_path);
392 cargo.env("CARGO_WORKSPACE_DIR", &dir);
395
396 cargo.env("SKIP_SLOW_TESTS", "1");
399
400 cargo.add_rustc_lib_path(builder);
401 run_cargo_test(cargo, &[], &[], "rust-analyzer", "rust-analyzer", host, builder);
402 }
403}
404
405#[derive(Debug, Clone, PartialEq, Eq, Hash)]
407pub struct Rustfmt {
408 stage: u32,
409 host: TargetSelection,
410}
411
412impl Step for Rustfmt {
413 type Output = ();
414 const ONLY_HOSTS: bool = true;
415
416 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
417 run.path("src/tools/rustfmt")
418 }
419
420 fn make_run(run: RunConfig<'_>) {
421 run.builder.ensure(Rustfmt { stage: run.builder.top_stage, host: run.target });
422 }
423
424 fn run(self, builder: &Builder<'_>) {
426 let stage = self.stage;
427 let host = self.host;
428 let compiler = builder.compiler(stage, host);
429
430 builder.ensure(tool::Rustfmt { compiler, target: self.host });
431
432 let mut cargo = tool::prepare_tool_cargo(
433 builder,
434 compiler,
435 Mode::ToolRustc,
436 host,
437 Kind::Test,
438 "src/tools/rustfmt",
439 SourceType::InTree,
440 &[],
441 );
442
443 let dir = testdir(builder, compiler.host);
444 t!(fs::create_dir_all(&dir));
445 cargo.env("RUSTFMT_TEST_DIR", dir);
446
447 cargo.add_rustc_lib_path(builder);
448
449 run_cargo_test(cargo, &[], &[], "rustfmt", "rustfmt", host, builder);
450 }
451}
452
453#[derive(Debug, Clone, PartialEq, Eq, Hash)]
454pub struct Miri {
455 target: TargetSelection,
456}
457
458impl Miri {
459 pub fn build_miri_sysroot(
461 builder: &Builder<'_>,
462 compiler: Compiler,
463 target: TargetSelection,
464 ) -> PathBuf {
465 let miri_sysroot = builder.out.join(compiler.host).join("miri-sysroot");
466 let mut cargo = builder::Cargo::new(
467 builder,
468 compiler,
469 Mode::Std,
470 SourceType::Submodule,
471 target,
472 Kind::MiriSetup,
473 );
474
475 cargo.env("MIRI_LIB_SRC", builder.src.join("library"));
477 cargo.env("MIRI_SYSROOT", &miri_sysroot);
479
480 let mut cargo = BootstrapCommand::from(cargo);
481 let _guard =
482 builder.msg(Kind::Build, compiler.stage, "miri sysroot", compiler.host, target);
483 cargo.run(builder);
484
485 cargo.arg("--print-sysroot");
491
492 builder.verbose(|| println!("running: {cargo:?}"));
493 let stdout = cargo.run_capture_stdout(builder).stdout();
494 let sysroot = stdout.trim_end();
496 builder.verbose(|| println!("`cargo miri setup --print-sysroot` said: {sysroot:?}"));
497 PathBuf::from(sysroot)
498 }
499}
500
501impl Step for Miri {
502 type Output = ();
503 const ONLY_HOSTS: bool = false;
504
505 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
506 run.path("src/tools/miri")
507 }
508
509 fn make_run(run: RunConfig<'_>) {
510 run.builder.ensure(Miri { target: run.target });
511 }
512
513 fn run(self, builder: &Builder<'_>) {
515 let host = builder.build.build;
516 let target = self.target;
517 let stage = builder.top_stage;
518 if stage == 0 {
519 eprintln!("miri cannot be tested at stage 0");
520 std::process::exit(1);
521 }
522
523 let target_compiler = builder.compiler(stage, host);
525 let host_compiler = builder.compiler(stage - 1, host);
530
531 let miri = builder.ensure(tool::Miri { compiler: host_compiler, target: host });
533 builder.ensure(tool::CargoMiri { compiler: host_compiler, target: host });
535
536 let miri_sysroot = Miri::build_miri_sysroot(builder, target_compiler, target);
539 builder.ensure(compile::Std::new(target_compiler, host));
540 let host_sysroot = builder.sysroot(target_compiler);
541
542 if !builder.config.dry_run() {
545 let ui_test_dep_dir = builder.stage_out(host_compiler, Mode::ToolStd).join("miri_ui");
546 build_stamp::clear_if_dirty(builder, &ui_test_dep_dir, &miri_sysroot);
550 }
551
552 let mut cargo = tool::prepare_tool_cargo(
555 builder,
556 host_compiler,
557 Mode::ToolRustc,
558 host,
559 Kind::Test,
560 "src/tools/miri",
561 SourceType::InTree,
562 &[],
563 );
564
565 cargo.add_rustc_lib_path(builder);
566
567 let mut cargo = prepare_cargo_test(cargo, &[], &[], "miri", host, builder);
570
571 cargo.env("MIRI_SYSROOT", &miri_sysroot);
573 cargo.env("MIRI_HOST_SYSROOT", &host_sysroot);
574 cargo.env("MIRI", &miri);
575
576 cargo.env("MIRI_TEST_TARGET", target.rustc_target_arg());
578
579 {
580 let _guard = builder.msg_sysroot_tool(Kind::Test, stage, "miri", host, target);
581 let _time = helpers::timeit(builder);
582 cargo.run(builder);
583 }
584
585 if builder.config.test_args().is_empty() {
587 cargo.env("MIRIFLAGS", "-O -Zmir-opt-level=4 -Cdebug-assertions=yes");
588 cargo.env("MIRI_SKIP_UI_CHECKS", "1");
590 cargo.env_remove("RUSTC_BLESS");
592 cargo.args(["tests/pass", "tests/panic"]);
594
595 {
596 let _guard = builder.msg_sysroot_tool(
597 Kind::Test,
598 stage,
599 "miri (mir-opt-level 4)",
600 host,
601 target,
602 );
603 let _time = helpers::timeit(builder);
604 cargo.run(builder);
605 }
606 }
607 }
608}
609
610#[derive(Debug, Clone, PartialEq, Eq, Hash)]
613pub struct CargoMiri {
614 target: TargetSelection,
615}
616
617impl Step for CargoMiri {
618 type Output = ();
619 const ONLY_HOSTS: bool = false;
620
621 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
622 run.path("src/tools/miri/cargo-miri")
623 }
624
625 fn make_run(run: RunConfig<'_>) {
626 run.builder.ensure(CargoMiri { target: run.target });
627 }
628
629 fn run(self, builder: &Builder<'_>) {
631 let host = builder.build.build;
632 let target = self.target;
633 let stage = builder.top_stage;
634 if stage == 0 {
635 eprintln!("cargo-miri cannot be tested at stage 0");
636 std::process::exit(1);
637 }
638
639 let compiler = builder.compiler(stage, host);
641
642 let mut cargo = tool::prepare_tool_cargo(
647 builder,
648 compiler,
649 Mode::ToolStd, target,
651 Kind::MiriTest,
652 "src/tools/miri/test-cargo-miri",
653 SourceType::Submodule,
654 &[],
655 );
656
657 match builder.doc_tests {
660 DocTests::Yes => {}
661 DocTests::No => {
662 cargo.args(["--lib", "--bins", "--examples", "--tests", "--benches"]);
663 }
664 DocTests::Only => {
665 cargo.arg("--doc");
666 }
667 }
668
669 cargo.arg("--").args(builder.config.test_args());
671 let mut cargo = BootstrapCommand::from(cargo);
672 {
673 let _guard = builder.msg_sysroot_tool(Kind::Test, stage, "cargo-miri", host, target);
674 let _time = helpers::timeit(builder);
675 cargo.run(builder);
676 }
677 }
678}
679
680#[derive(Debug, Clone, PartialEq, Eq, Hash)]
681pub struct CompiletestTest {
682 host: TargetSelection,
683}
684
685impl Step for CompiletestTest {
686 type Output = ();
687
688 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
689 run.path("src/tools/compiletest")
690 }
691
692 fn make_run(run: RunConfig<'_>) {
693 run.builder.ensure(CompiletestTest { host: run.target });
694 }
695
696 fn run(self, builder: &Builder<'_>) {
698 let host = self.host;
699 let compiler = builder.compiler(builder.top_stage, host);
700
701 builder.ensure(compile::Std::new(compiler, host));
704 let mut cargo = tool::prepare_tool_cargo(
705 builder,
706 compiler,
707 Mode::ToolStd,
710 host,
711 Kind::Test,
712 "src/tools/compiletest",
713 SourceType::InTree,
714 &[],
715 );
716 cargo.allow_features("test");
717 run_cargo_test(cargo, &[], &[], "compiletest", "compiletest self test", host, builder);
718 }
719}
720
721#[derive(Debug, Clone, PartialEq, Eq, Hash)]
722pub struct Clippy {
723 stage: u32,
724 host: TargetSelection,
725}
726
727impl Step for Clippy {
728 type Output = ();
729 const ONLY_HOSTS: bool = true;
730 const DEFAULT: bool = false;
731
732 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
733 run.path("src/tools/clippy")
734 }
735
736 fn make_run(run: RunConfig<'_>) {
737 run.builder.ensure(Clippy { stage: run.builder.top_stage, host: run.target });
738 }
739
740 fn run(self, builder: &Builder<'_>) {
742 let stage = self.stage;
743 let host = self.host;
744 let compiler = builder.compiler(stage, host);
745
746 builder.ensure(tool::Clippy { compiler, target: self.host });
747 let mut cargo = tool::prepare_tool_cargo(
748 builder,
749 compiler,
750 Mode::ToolRustc,
751 host,
752 Kind::Test,
753 "src/tools/clippy",
754 SourceType::InTree,
755 &[],
756 );
757
758 cargo.env("RUSTC_TEST_SUITE", builder.rustc(compiler));
759 cargo.env("RUSTC_LIB_PATH", builder.rustc_libdir(compiler));
760 let host_libs = builder.stage_out(compiler, Mode::ToolRustc).join(builder.cargo_dir());
761 cargo.env("HOST_LIBS", host_libs);
762
763 cargo.add_rustc_lib_path(builder);
764 let cargo = prepare_cargo_test(cargo, &[], &[], "clippy", host, builder);
765
766 let _guard = builder.msg_sysroot_tool(Kind::Test, compiler.stage, "clippy", host, host);
767
768 if cargo.allow_failure().run(builder) {
770 return;
772 }
773
774 if !builder.config.cmd.bless() {
775 crate::exit!(1);
776 }
777 }
778}
779
780fn path_for_cargo(builder: &Builder<'_>, compiler: Compiler) -> OsString {
781 let path = builder.sysroot(compiler).join("bin");
785 let old_path = env::var_os("PATH").unwrap_or_default();
786 env::join_paths(iter::once(path).chain(env::split_paths(&old_path))).expect("")
787}
788
789#[derive(Debug, Clone, Hash, PartialEq, Eq)]
790pub struct RustdocTheme {
791 pub compiler: Compiler,
792}
793
794impl Step for RustdocTheme {
795 type Output = ();
796 const DEFAULT: bool = true;
797 const ONLY_HOSTS: bool = true;
798
799 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
800 run.path("src/tools/rustdoc-themes")
801 }
802
803 fn make_run(run: RunConfig<'_>) {
804 let compiler = run.builder.compiler(run.builder.top_stage, run.target);
805
806 run.builder.ensure(RustdocTheme { compiler });
807 }
808
809 fn run(self, builder: &Builder<'_>) {
810 let rustdoc = builder.bootstrap_out.join("rustdoc");
811 let mut cmd = builder.tool_cmd(Tool::RustdocTheme);
812 cmd.arg(rustdoc.to_str().unwrap())
813 .arg(builder.src.join("src/librustdoc/html/static/css/rustdoc.css").to_str().unwrap())
814 .env("RUSTC_STAGE", self.compiler.stage.to_string())
815 .env("RUSTC_SYSROOT", builder.sysroot(self.compiler))
816 .env("RUSTDOC_LIBDIR", builder.sysroot_target_libdir(self.compiler, self.compiler.host))
817 .env("CFG_RELEASE_CHANNEL", &builder.config.channel)
818 .env("RUSTDOC_REAL", builder.rustdoc(self.compiler))
819 .env("RUSTC_BOOTSTRAP", "1");
820 cmd.args(linker_args(builder, self.compiler.host, LldThreads::No));
821
822 cmd.delay_failure().run(builder);
823 }
824}
825
826#[derive(Debug, Clone, Hash, PartialEq, Eq)]
827pub struct RustdocJSStd {
828 pub target: TargetSelection,
829}
830
831impl Step for RustdocJSStd {
832 type Output = ();
833 const DEFAULT: bool = true;
834 const ONLY_HOSTS: bool = true;
835
836 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
837 let default = run.builder.config.nodejs.is_some();
838 run.suite_path("tests/rustdoc-js-std").default_condition(default)
839 }
840
841 fn make_run(run: RunConfig<'_>) {
842 run.builder.ensure(RustdocJSStd { target: run.target });
843 }
844
845 fn run(self, builder: &Builder<'_>) {
846 let nodejs =
847 builder.config.nodejs.as_ref().expect("need nodejs to run rustdoc-js-std tests");
848 let mut command = command(nodejs);
849 command
850 .arg(builder.src.join("src/tools/rustdoc-js/tester.js"))
851 .arg("--crate-name")
852 .arg("std")
853 .arg("--resource-suffix")
854 .arg(&builder.version)
855 .arg("--doc-folder")
856 .arg(builder.doc_out(self.target))
857 .arg("--test-folder")
858 .arg(builder.src.join("tests/rustdoc-js-std"));
859 for path in &builder.paths {
860 if let Some(p) = helpers::is_valid_test_suite_arg(path, "tests/rustdoc-js-std", builder)
861 {
862 if !p.ends_with(".js") {
863 eprintln!("A non-js file was given: `{}`", path.display());
864 panic!("Cannot run rustdoc-js-std tests");
865 }
866 command.arg("--test-file").arg(path);
867 }
868 }
869 builder.ensure(crate::core::build_steps::doc::Std::new(
870 builder.top_stage,
871 self.target,
872 DocumentationFormat::Html,
873 ));
874 let _guard = builder.msg(
875 Kind::Test,
876 builder.top_stage,
877 "rustdoc-js-std",
878 builder.config.build,
879 self.target,
880 );
881 command.run(builder);
882 }
883}
884
885#[derive(Debug, Clone, Hash, PartialEq, Eq)]
886pub struct RustdocJSNotStd {
887 pub target: TargetSelection,
888 pub compiler: Compiler,
889}
890
891impl Step for RustdocJSNotStd {
892 type Output = ();
893 const DEFAULT: bool = true;
894 const ONLY_HOSTS: bool = true;
895
896 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
897 let default = run.builder.config.nodejs.is_some();
898 run.suite_path("tests/rustdoc-js").default_condition(default)
899 }
900
901 fn make_run(run: RunConfig<'_>) {
902 let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
903 run.builder.ensure(RustdocJSNotStd { target: run.target, compiler });
904 }
905
906 fn run(self, builder: &Builder<'_>) {
907 builder.ensure(Compiletest {
908 compiler: self.compiler,
909 target: self.target,
910 mode: "rustdoc-js",
911 suite: "rustdoc-js",
912 path: "tests/rustdoc-js",
913 compare_mode: None,
914 });
915 }
916}
917
918fn get_browser_ui_test_version_inner(
919 builder: &Builder<'_>,
920 npm: &Path,
921 global: bool,
922) -> Option<String> {
923 let mut command = command(npm);
924 command.arg("list").arg("--parseable").arg("--long").arg("--depth=0");
925 if global {
926 command.arg("--global");
927 }
928 let lines = command.allow_failure().run_capture(builder).stdout();
929 lines
930 .lines()
931 .find_map(|l| l.split(':').nth(1)?.strip_prefix("browser-ui-test@"))
932 .map(|v| v.to_owned())
933}
934
935fn get_browser_ui_test_version(builder: &Builder<'_>, npm: &Path) -> Option<String> {
936 get_browser_ui_test_version_inner(builder, npm, false)
937 .or_else(|| get_browser_ui_test_version_inner(builder, npm, true))
938}
939
940#[derive(Debug, Clone, Hash, PartialEq, Eq)]
941pub struct RustdocGUI {
942 pub target: TargetSelection,
943 pub compiler: Compiler,
944}
945
946impl Step for RustdocGUI {
947 type Output = ();
948 const DEFAULT: bool = true;
949 const ONLY_HOSTS: bool = true;
950
951 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
952 let builder = run.builder;
953 let run = run.suite_path("tests/rustdoc-gui");
954 run.lazy_default_condition(Box::new(move || {
955 builder.config.nodejs.is_some()
956 && builder.doc_tests != DocTests::Only
957 && builder
958 .config
959 .npm
960 .as_ref()
961 .map(|p| get_browser_ui_test_version(builder, p).is_some())
962 .unwrap_or(false)
963 }))
964 }
965
966 fn make_run(run: RunConfig<'_>) {
967 let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
968 run.builder.ensure(RustdocGUI { target: run.target, compiler });
969 }
970
971 fn run(self, builder: &Builder<'_>) {
972 builder.ensure(compile::Std::new(self.compiler, self.target));
973
974 let mut cmd = builder.tool_cmd(Tool::RustdocGUITest);
975
976 let out_dir = builder.test_out(self.target).join("rustdoc-gui");
977 build_stamp::clear_if_dirty(builder, &out_dir, &builder.rustdoc(self.compiler));
978
979 if let Some(src) = builder.config.src.to_str() {
980 cmd.arg("--rust-src").arg(src);
981 }
982
983 if let Some(out_dir) = out_dir.to_str() {
984 cmd.arg("--out-dir").arg(out_dir);
985 }
986
987 if let Some(initial_cargo) = builder.config.initial_cargo.to_str() {
988 cmd.arg("--initial-cargo").arg(initial_cargo);
989 }
990
991 cmd.arg("--jobs").arg(builder.jobs().to_string());
992
993 cmd.env("RUSTDOC", builder.rustdoc(self.compiler))
994 .env("RUSTC", builder.rustc(self.compiler));
995
996 add_rustdoc_cargo_linker_args(&mut cmd, builder, self.compiler.host, LldThreads::No);
997
998 for path in &builder.paths {
999 if let Some(p) = helpers::is_valid_test_suite_arg(path, "tests/rustdoc-gui", builder) {
1000 if !p.ends_with(".goml") {
1001 eprintln!("A non-goml file was given: `{}`", path.display());
1002 panic!("Cannot run rustdoc-gui tests");
1003 }
1004 if let Some(name) = path.file_name().and_then(|f| f.to_str()) {
1005 cmd.arg("--goml-file").arg(name);
1006 }
1007 }
1008 }
1009
1010 for test_arg in builder.config.test_args() {
1011 cmd.arg("--test-arg").arg(test_arg);
1012 }
1013
1014 if let Some(ref nodejs) = builder.config.nodejs {
1015 cmd.arg("--nodejs").arg(nodejs);
1016 }
1017
1018 if let Some(ref npm) = builder.config.npm {
1019 cmd.arg("--npm").arg(npm);
1020 }
1021
1022 let _time = helpers::timeit(builder);
1023 let _guard = builder.msg_sysroot_tool(
1024 Kind::Test,
1025 self.compiler.stage,
1026 "rustdoc-gui",
1027 self.compiler.host,
1028 self.target,
1029 );
1030 try_run_tests(builder, &mut cmd, true);
1031 }
1032}
1033
1034#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1039pub struct Tidy;
1040
1041impl Step for Tidy {
1042 type Output = ();
1043 const DEFAULT: bool = true;
1044 const ONLY_HOSTS: bool = true;
1045
1046 fn run(self, builder: &Builder<'_>) {
1055 let mut cmd = builder.tool_cmd(Tool::Tidy);
1056 cmd.arg(&builder.src);
1057 cmd.arg(&builder.initial_cargo);
1058 cmd.arg(&builder.out);
1059 let jobs = builder.config.jobs.unwrap_or_else(|| {
1061 8 * std::thread::available_parallelism().map_or(1, std::num::NonZeroUsize::get) as u32
1062 });
1063 cmd.arg(jobs.to_string());
1064 if builder.is_verbose() {
1065 cmd.arg("--verbose");
1066 }
1067 if builder.config.cmd.bless() {
1068 cmd.arg("--bless");
1069 }
1070 if let Some(s) = builder.config.cmd.extra_checks() {
1071 cmd.arg(format!("--extra-checks={s}"));
1072 }
1073 let mut args = std::env::args_os();
1074 if args.any(|arg| arg == OsStr::new("--")) {
1075 cmd.arg("--");
1076 cmd.args(args);
1077 }
1078
1079 if builder.config.channel == "dev" || builder.config.channel == "nightly" {
1080 if !builder.config.json_output {
1081 builder.info("fmt check");
1082 if builder.initial_rustfmt().is_none() {
1083 let inferred_rustfmt_dir = builder.initial_sysroot.join("bin");
1084 eprintln!(
1085 "\
1086ERROR: no `rustfmt` binary found in {PATH}
1087INFO: `rust.channel` is currently set to \"{CHAN}\"
1088HELP: if you are testing a beta branch, set `rust.channel` to \"beta\" in the `config.toml` file
1089HELP: to skip test's attempt to check tidiness, pass `--skip src/tools/tidy` to `x.py test`",
1090 PATH = inferred_rustfmt_dir.display(),
1091 CHAN = builder.config.channel,
1092 );
1093 crate::exit!(1);
1094 }
1095 let all = false;
1096 crate::core::build_steps::format::format(
1097 builder,
1098 !builder.config.cmd.bless(),
1099 all,
1100 &[],
1101 );
1102 } else {
1103 eprintln!(
1104 "WARNING: `--json-output` is not supported on rustfmt, formatting will be skipped"
1105 );
1106 }
1107 }
1108
1109 builder.info("tidy check");
1110 cmd.delay_failure().run(builder);
1111
1112 builder.info("x.py completions check");
1113 let [bash, zsh, fish, powershell] = ["x.py.sh", "x.py.zsh", "x.py.fish", "x.py.ps1"]
1114 .map(|filename| builder.src.join("src/etc/completions").join(filename));
1115 if builder.config.cmd.bless() {
1116 builder.ensure(crate::core::build_steps::run::GenerateCompletions);
1117 } else if get_completion(shells::Bash, &bash).is_some()
1118 || get_completion(shells::Fish, &fish).is_some()
1119 || get_completion(shells::PowerShell, &powershell).is_some()
1120 || crate::flags::get_completion(shells::Zsh, &zsh).is_some()
1121 {
1122 eprintln!(
1123 "x.py completions were changed; run `x.py run generate-completions` to update them"
1124 );
1125 crate::exit!(1);
1126 }
1127 }
1128
1129 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1130 let default = run.builder.doc_tests != DocTests::Only;
1131 run.path("src/tools/tidy").default_condition(default)
1132 }
1133
1134 fn make_run(run: RunConfig<'_>) {
1135 run.builder.ensure(Tidy);
1136 }
1137}
1138
1139fn testdir(builder: &Builder<'_>, host: TargetSelection) -> PathBuf {
1140 builder.out.join(host).join("test")
1141}
1142
1143macro_rules! test {
1145 (
1146 $( #[$attr:meta] )* $name:ident {
1148 path: $path:expr,
1149 mode: $mode:expr,
1150 suite: $suite:expr,
1151 default: $default:expr
1152 $( , only_hosts: $only_hosts:expr )? $( , compare_mode: $compare_mode:expr )? $( , )? }
1156 ) => {
1157 $( #[$attr] )*
1158 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
1159 pub struct $name {
1160 pub compiler: Compiler,
1161 pub target: TargetSelection,
1162 }
1163
1164 impl Step for $name {
1165 type Output = ();
1166 const DEFAULT: bool = $default;
1167 const ONLY_HOSTS: bool = (const {
1168 #[allow(unused_assignments, unused_mut)]
1169 let mut value = false;
1170 $( value = $only_hosts; )?
1171 value
1172 });
1173
1174 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1175 run.suite_path($path)
1176 }
1177
1178 fn make_run(run: RunConfig<'_>) {
1179 let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1180
1181 run.builder.ensure($name { compiler, target: run.target });
1182 }
1183
1184 fn run(self, builder: &Builder<'_>) {
1185 builder.ensure(Compiletest {
1186 compiler: self.compiler,
1187 target: self.target,
1188 mode: $mode,
1189 suite: $suite,
1190 path: $path,
1191 compare_mode: (const {
1192 #[allow(unused_assignments, unused_mut)]
1193 let mut value = None;
1194 $( value = $compare_mode; )?
1195 value
1196 }),
1197 })
1198 }
1199 }
1200 };
1201}
1202
1203#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Ord, PartialOrd)]
1204pub struct RunMakeSupport {
1205 pub compiler: Compiler,
1206 pub target: TargetSelection,
1207}
1208
1209impl Step for RunMakeSupport {
1210 type Output = PathBuf;
1211 const DEFAULT: bool = true;
1212
1213 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1214 run.never()
1215 }
1216
1217 fn make_run(run: RunConfig<'_>) {
1218 let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1219 run.builder.ensure(RunMakeSupport { compiler, target: run.build_triple() });
1220 }
1221
1222 fn run(self, builder: &Builder<'_>) -> PathBuf {
1224 builder.ensure(compile::Std::new(self.compiler, self.target));
1225
1226 let cargo = tool::prepare_tool_cargo(
1227 builder,
1228 self.compiler,
1229 Mode::ToolStd,
1230 self.target,
1231 Kind::Build,
1232 "src/tools/run-make-support",
1233 SourceType::InTree,
1234 &[],
1235 );
1236
1237 cargo.into_cmd().run(builder);
1238
1239 let lib_name = "librun_make_support.rlib";
1240 let lib = builder.tools_dir(self.compiler).join(lib_name);
1241
1242 let cargo_out = builder.cargo_out(self.compiler, Mode::ToolStd, self.target).join(lib_name);
1243 builder.copy_link(&cargo_out, &lib);
1244 lib
1245 }
1246}
1247
1248#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1251pub struct CrateRunMakeSupport {
1252 host: TargetSelection,
1253}
1254
1255impl Step for CrateRunMakeSupport {
1256 type Output = ();
1257 const ONLY_HOSTS: bool = true;
1258
1259 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1260 run.path("src/tools/run-make-support")
1261 }
1262
1263 fn make_run(run: RunConfig<'_>) {
1264 run.builder.ensure(CrateRunMakeSupport { host: run.target });
1265 }
1266
1267 fn run(self, builder: &Builder<'_>) {
1269 let host = self.host;
1270 let compiler = builder.compiler(0, host);
1271
1272 let mut cargo = tool::prepare_tool_cargo(
1273 builder,
1274 compiler,
1275 Mode::ToolBootstrap,
1276 host,
1277 Kind::Test,
1278 "src/tools/run-make-support",
1279 SourceType::InTree,
1280 &[],
1281 );
1282 cargo.allow_features("test");
1283 run_cargo_test(
1284 cargo,
1285 &[],
1286 &[],
1287 "run-make-support",
1288 "run-make-support self test",
1289 host,
1290 builder,
1291 );
1292 }
1293}
1294
1295#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1296pub struct CrateBuildHelper {
1297 host: TargetSelection,
1298}
1299
1300impl Step for CrateBuildHelper {
1301 type Output = ();
1302 const ONLY_HOSTS: bool = true;
1303
1304 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1305 run.path("src/build_helper")
1306 }
1307
1308 fn make_run(run: RunConfig<'_>) {
1309 run.builder.ensure(CrateBuildHelper { host: run.target });
1310 }
1311
1312 fn run(self, builder: &Builder<'_>) {
1314 let host = self.host;
1315 let compiler = builder.compiler(0, host);
1316
1317 let mut cargo = tool::prepare_tool_cargo(
1318 builder,
1319 compiler,
1320 Mode::ToolBootstrap,
1321 host,
1322 Kind::Test,
1323 "src/build_helper",
1324 SourceType::InTree,
1325 &[],
1326 );
1327 cargo.allow_features("test");
1328 run_cargo_test(cargo, &[], &[], "build_helper", "build_helper self test", host, builder);
1329 }
1330}
1331
1332test!(Ui { path: "tests/ui", mode: "ui", suite: "ui", default: true });
1333
1334test!(Crashes { path: "tests/crashes", mode: "crashes", suite: "crashes", default: true });
1335
1336test!(Codegen { path: "tests/codegen", mode: "codegen", suite: "codegen", default: true });
1337
1338test!(CodegenUnits {
1339 path: "tests/codegen-units",
1340 mode: "codegen-units",
1341 suite: "codegen-units",
1342 default: true,
1343});
1344
1345test!(Incremental {
1346 path: "tests/incremental",
1347 mode: "incremental",
1348 suite: "incremental",
1349 default: true,
1350});
1351
1352test!(Debuginfo {
1353 path: "tests/debuginfo",
1354 mode: "debuginfo",
1355 suite: "debuginfo",
1356 default: true,
1357 compare_mode: Some("split-dwarf"),
1358});
1359
1360test!(UiFullDeps {
1361 path: "tests/ui-fulldeps",
1362 mode: "ui",
1363 suite: "ui-fulldeps",
1364 default: true,
1365 only_hosts: true,
1366});
1367
1368test!(Rustdoc {
1369 path: "tests/rustdoc",
1370 mode: "rustdoc",
1371 suite: "rustdoc",
1372 default: true,
1373 only_hosts: true,
1374});
1375test!(RustdocUi {
1376 path: "tests/rustdoc-ui",
1377 mode: "ui",
1378 suite: "rustdoc-ui",
1379 default: true,
1380 only_hosts: true,
1381});
1382
1383test!(RustdocJson {
1384 path: "tests/rustdoc-json",
1385 mode: "rustdoc-json",
1386 suite: "rustdoc-json",
1387 default: true,
1388 only_hosts: true,
1389});
1390
1391test!(Pretty {
1392 path: "tests/pretty",
1393 mode: "pretty",
1394 suite: "pretty",
1395 default: true,
1396 only_hosts: true,
1397});
1398
1399#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1402pub struct RunMake {
1403 pub compiler: Compiler,
1404 pub target: TargetSelection,
1405}
1406
1407impl Step for RunMake {
1408 type Output = ();
1409 const DEFAULT: bool = true;
1410 const ONLY_HOSTS: bool = false;
1411
1412 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1413 run.suite_path("tests/run-make")
1414 }
1415
1416 fn make_run(run: RunConfig<'_>) {
1417 let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1418 run.builder.ensure(RunMakeSupport { compiler, target: run.build_triple() });
1419 run.builder.ensure(RunMake { compiler, target: run.target });
1420 }
1421
1422 fn run(self, builder: &Builder<'_>) {
1423 builder.ensure(Compiletest {
1424 compiler: self.compiler,
1425 target: self.target,
1426 mode: "run-make",
1427 suite: "run-make",
1428 path: "tests/run-make",
1429 compare_mode: None,
1430 });
1431 }
1432}
1433
1434test!(Assembly { path: "tests/assembly", mode: "assembly", suite: "assembly", default: true });
1435
1436#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
1439pub struct Coverage {
1440 pub compiler: Compiler,
1441 pub target: TargetSelection,
1442 pub mode: &'static str,
1443}
1444
1445impl Coverage {
1446 const PATH: &'static str = "tests/coverage";
1447 const SUITE: &'static str = "coverage";
1448 const ALL_MODES: &[&str] = &["coverage-map", "coverage-run"];
1449}
1450
1451impl Step for Coverage {
1452 type Output = ();
1453 const DEFAULT: bool = true;
1454 const ONLY_HOSTS: bool = false;
1456
1457 fn should_run(mut run: ShouldRun<'_>) -> ShouldRun<'_> {
1458 run = run.suite_path(Self::PATH);
1464 for mode in Self::ALL_MODES {
1465 run = run.alias(mode);
1466 }
1467 run
1468 }
1469
1470 fn make_run(run: RunConfig<'_>) {
1471 let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1472 let target = run.target;
1473
1474 let mut modes = vec![];
1478
1479 for path in &run.paths {
1482 match path {
1483 PathSet::Set(_) => {
1484 for mode in Self::ALL_MODES {
1485 if path.assert_single_path().path == Path::new(mode) {
1486 modes.push(mode);
1487 break;
1488 }
1489 }
1490 }
1491 PathSet::Suite(_) => {
1492 modes.extend(Self::ALL_MODES);
1493 break;
1494 }
1495 }
1496 }
1497
1498 modes.retain(|mode| !run.builder.config.skip.iter().any(|skip| skip == Path::new(mode)));
1501
1502 for mode in modes {
1510 run.builder.ensure(Coverage { compiler, target, mode });
1511 }
1512 }
1513
1514 fn run(self, builder: &Builder<'_>) {
1515 let Self { compiler, target, mode } = self;
1516 builder.ensure(Compiletest {
1519 compiler,
1520 target,
1521 mode,
1522 suite: Self::SUITE,
1523 path: Self::PATH,
1524 compare_mode: None,
1525 });
1526 }
1527}
1528
1529test!(CoverageRunRustdoc {
1530 path: "tests/coverage-run-rustdoc",
1531 mode: "coverage-run",
1532 suite: "coverage-run-rustdoc",
1533 default: true,
1534 only_hosts: true,
1535});
1536
1537#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1539pub struct MirOpt {
1540 pub compiler: Compiler,
1541 pub target: TargetSelection,
1542}
1543
1544impl Step for MirOpt {
1545 type Output = ();
1546 const DEFAULT: bool = true;
1547 const ONLY_HOSTS: bool = false;
1548
1549 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1550 run.suite_path("tests/mir-opt")
1551 }
1552
1553 fn make_run(run: RunConfig<'_>) {
1554 let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1555 run.builder.ensure(MirOpt { compiler, target: run.target });
1556 }
1557
1558 fn run(self, builder: &Builder<'_>) {
1559 let run = |target| {
1560 builder.ensure(Compiletest {
1561 compiler: self.compiler,
1562 target,
1563 mode: "mir-opt",
1564 suite: "mir-opt",
1565 path: "tests/mir-opt",
1566 compare_mode: None,
1567 })
1568 };
1569
1570 run(self.target);
1571
1572 if builder.config.cmd.bless() {
1575 for target in ["aarch64-unknown-linux-gnu", "i686-pc-windows-msvc"] {
1581 run(TargetSelection::from_user(target));
1582 }
1583
1584 for target in ["x86_64-apple-darwin", "i686-unknown-linux-musl"] {
1585 let target = TargetSelection::from_user(target);
1586 let panic_abort_target = builder.ensure(MirOptPanicAbortSyntheticTarget {
1587 compiler: self.compiler,
1588 base: target,
1589 });
1590 run(panic_abort_target);
1591 }
1592 }
1593 }
1594}
1595
1596#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1597struct Compiletest {
1598 compiler: Compiler,
1599 target: TargetSelection,
1600 mode: &'static str,
1601 suite: &'static str,
1602 path: &'static str,
1603 compare_mode: Option<&'static str>,
1604}
1605
1606impl Step for Compiletest {
1607 type Output = ();
1608
1609 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1610 run.never()
1611 }
1612
1613 fn run(self, builder: &Builder<'_>) {
1619 if builder.doc_tests == DocTests::Only {
1620 return;
1621 }
1622
1623 if builder.top_stage == 0 && env::var("COMPILETEST_FORCE_STAGE0").is_err() {
1624 eprintln!("\
1625ERROR: `--stage 0` runs compiletest on the beta compiler, not your local changes, and will almost always cause tests to fail
1626HELP: to test the compiler, use `--stage 1` instead
1627HELP: to test the standard library, use `--stage 0 library/std` instead
1628NOTE: if you're sure you want to do this, please open an issue as to why. In the meantime, you can override this with `COMPILETEST_FORCE_STAGE0=1`."
1629 );
1630 crate::exit!(1);
1631 }
1632
1633 let mut compiler = self.compiler;
1634 let target = self.target;
1635 let mode = self.mode;
1636 let suite = self.suite;
1637
1638 let suite_path = self.path;
1640
1641 if !builder.config.codegen_tests && suite == "codegen" {
1643 return;
1644 }
1645
1646 let (stage, stage_id) = if suite == "ui-fulldeps" && compiler.stage == 1 {
1653 let build = builder.build.build;
1657 compiler = builder.compiler(compiler.stage - 1, build);
1658 let test_stage = compiler.stage + 1;
1659 (test_stage, format!("stage{}-{}", test_stage, build))
1660 } else {
1661 let stage = compiler.stage;
1662 (stage, format!("stage{}-{}", stage, target))
1663 };
1664
1665 if suite.ends_with("fulldeps") {
1666 builder.ensure(compile::Rustc::new(compiler, target));
1667 }
1668
1669 if suite == "debuginfo" {
1670 builder.ensure(dist::DebuggerScripts {
1671 sysroot: builder.sysroot(compiler).to_path_buf(),
1672 host: target,
1673 });
1674 }
1675
1676 builder.ensure(TestHelpers { target: compiler.host });
1678
1679 if suite == "mir-opt" {
1681 builder.ensure(compile::Std::new(compiler, compiler.host).is_for_mir_opt_tests(true));
1682 } else {
1683 builder.ensure(compile::Std::new(compiler, compiler.host));
1684 }
1685
1686 if suite != "mir-opt" {
1688 builder.ensure(TestHelpers { target });
1689 }
1690
1691 let mut cmd = builder.tool_cmd(Tool::Compiletest);
1692
1693 if suite == "mir-opt" {
1694 builder.ensure(compile::Std::new(compiler, target).is_for_mir_opt_tests(true));
1695 } else {
1696 builder.ensure(compile::Std::new(compiler, target));
1697 }
1698
1699 builder.ensure(RemoteCopyLibs { compiler, target });
1700
1701 cmd.arg("--stage").arg(stage.to_string());
1705 cmd.arg("--stage-id").arg(stage_id);
1706
1707 cmd.arg("--compile-lib-path").arg(builder.rustc_libdir(compiler));
1708 cmd.arg("--run-lib-path").arg(builder.sysroot_target_libdir(compiler, target));
1709 cmd.arg("--rustc-path").arg(builder.rustc(compiler));
1710
1711 cmd.arg("--minicore-path")
1714 .arg(builder.src.join("tests").join("auxiliary").join("minicore.rs"));
1715
1716 let is_rustdoc = suite == "rustdoc-ui" || suite == "rustdoc-js";
1717
1718 if mode == "run-make" {
1719 let cargo_path = if builder.top_stage == 0 {
1720 builder.initial_cargo.clone()
1722 } else {
1723 let compiler = builder.download_rustc().then_some(compiler).unwrap_or_else(||
1726 builder.compiler(builder.top_stage - 1, compiler.host));
1733
1734 builder.ensure(tool::Cargo { compiler, target: compiler.host })
1735 };
1736
1737 cmd.arg("--cargo-path").arg(cargo_path);
1738 }
1739
1740 if mode == "rustdoc"
1742 || mode == "run-make"
1743 || (mode == "ui" && is_rustdoc)
1744 || mode == "rustdoc-js"
1745 || mode == "rustdoc-json"
1746 || suite == "coverage-run-rustdoc"
1747 {
1748 cmd.arg("--rustdoc-path").arg(builder.rustdoc(compiler));
1749 }
1750
1751 if mode == "rustdoc-json" {
1752 let json_compiler = compiler.with_stage(0);
1754 cmd.arg("--jsondocck-path")
1755 .arg(builder.ensure(tool::JsonDocCk { compiler: json_compiler, target }));
1756 cmd.arg("--jsondoclint-path")
1757 .arg(builder.ensure(tool::JsonDocLint { compiler: json_compiler, target }));
1758 }
1759
1760 if matches!(mode, "coverage-map" | "coverage-run") {
1761 let coverage_dump = builder.tool_exe(Tool::CoverageDump);
1762 cmd.arg("--coverage-dump-path").arg(coverage_dump);
1763 }
1764
1765 cmd.arg("--src-base").arg(builder.src.join("tests").join(suite));
1766 cmd.arg("--build-base").arg(testdir(builder, compiler.host).join(suite));
1767
1768 let sysroot = if builder.top_stage == 0 {
1771 builder.initial_sysroot.clone()
1772 } else {
1773 builder.sysroot(compiler).to_path_buf()
1774 };
1775
1776 cmd.arg("--sysroot-base").arg(sysroot);
1777
1778 cmd.arg("--suite").arg(suite);
1779 cmd.arg("--mode").arg(mode);
1780 cmd.arg("--target").arg(target.rustc_target_arg());
1781 cmd.arg("--host").arg(&*compiler.host.triple);
1782 cmd.arg("--llvm-filecheck").arg(builder.llvm_filecheck(builder.config.build));
1783
1784 if builder.build.config.llvm_enzyme {
1785 cmd.arg("--has-enzyme");
1786 }
1787
1788 if builder.config.cmd.bless() {
1789 cmd.arg("--bless");
1790 }
1791
1792 if builder.config.cmd.force_rerun() {
1793 cmd.arg("--force-rerun");
1794 }
1795
1796 if builder.config.cmd.no_capture() {
1797 cmd.arg("--no-capture");
1798 }
1799
1800 let compare_mode =
1801 builder.config.cmd.compare_mode().or_else(|| {
1802 if builder.config.test_compare_mode { self.compare_mode } else { None }
1803 });
1804
1805 if let Some(ref pass) = builder.config.cmd.pass() {
1806 cmd.arg("--pass");
1807 cmd.arg(pass);
1808 }
1809
1810 if let Some(ref run) = builder.config.cmd.run() {
1811 cmd.arg("--run");
1812 cmd.arg(run);
1813 }
1814
1815 if let Some(ref nodejs) = builder.config.nodejs {
1816 cmd.arg("--nodejs").arg(nodejs);
1817 } else if mode == "rustdoc-js" {
1818 panic!("need nodejs to run rustdoc-js suite");
1819 }
1820 if let Some(ref npm) = builder.config.npm {
1821 cmd.arg("--npm").arg(npm);
1822 }
1823 if builder.config.rust_optimize_tests {
1824 cmd.arg("--optimize-tests");
1825 }
1826 if builder.config.rust_randomize_layout {
1827 cmd.arg("--rust-randomized-layout");
1828 }
1829 if builder.config.cmd.only_modified() {
1830 cmd.arg("--only-modified");
1831 }
1832 if let Some(compiletest_diff_tool) = &builder.config.compiletest_diff_tool {
1833 cmd.arg("--compiletest-diff-tool").arg(compiletest_diff_tool);
1834 }
1835
1836 let mut flags = if is_rustdoc { Vec::new() } else { vec!["-Crpath".to_string()] };
1837 flags.push(format!("-Cdebuginfo={}", builder.config.rust_debuginfo_level_tests));
1838 flags.extend(builder.config.cmd.compiletest_rustc_args().iter().map(|s| s.to_string()));
1839
1840 if suite != "mir-opt" {
1841 if let Some(linker) = builder.linker(target) {
1842 cmd.arg("--target-linker").arg(linker);
1843 }
1844 if let Some(linker) = builder.linker(compiler.host) {
1845 cmd.arg("--host-linker").arg(linker);
1846 }
1847 }
1848
1849 if suite == "ui-fulldeps" && compiler.stage > 1 && target.ends_with("darwin") {
1854 flags.push("-Alinker_messages".into());
1855 }
1856
1857 let mut hostflags = flags.clone();
1858 hostflags.push(format!("-Lnative={}", builder.test_helpers_out(compiler.host).display()));
1859 hostflags.extend(linker_flags(builder, compiler.host, LldThreads::No));
1860
1861 let mut targetflags = flags;
1862 targetflags.push(format!("-Lnative={}", builder.test_helpers_out(target).display()));
1863
1864 for flag in hostflags {
1865 cmd.arg("--host-rustcflags").arg(flag);
1866 }
1867 for flag in targetflags {
1868 cmd.arg("--target-rustcflags").arg(flag);
1869 }
1870
1871 cmd.arg("--python").arg(builder.python());
1872
1873 if let Some(ref gdb) = builder.config.gdb {
1874 cmd.arg("--gdb").arg(gdb);
1875 }
1876
1877 let lldb_exe = builder.config.lldb.clone().unwrap_or_else(|| PathBuf::from("lldb"));
1878 let lldb_version = command(&lldb_exe)
1879 .allow_failure()
1880 .arg("--version")
1881 .run_capture(builder)
1882 .stdout_if_ok()
1883 .and_then(|v| if v.trim().is_empty() { None } else { Some(v) });
1884 if let Some(ref vers) = lldb_version {
1885 cmd.arg("--lldb-version").arg(vers);
1886 let lldb_python_dir = command(&lldb_exe)
1887 .allow_failure()
1888 .arg("-P")
1889 .run_capture_stdout(builder)
1890 .stdout_if_ok()
1891 .map(|p| p.lines().next().expect("lldb Python dir not found").to_string());
1892 if let Some(ref dir) = lldb_python_dir {
1893 cmd.arg("--lldb-python-dir").arg(dir);
1894 }
1895 }
1896
1897 if helpers::forcing_clang_based_tests() {
1898 let clang_exe = builder.llvm_out(target).join("bin").join("clang");
1899 cmd.arg("--run-clang-based-tests-with").arg(clang_exe);
1900 }
1901
1902 for exclude in &builder.config.skip {
1903 cmd.arg("--skip");
1904 cmd.arg(exclude);
1905 }
1906
1907 let paths = match &builder.config.cmd {
1909 Subcommand::Test { .. } => &builder.config.paths[..],
1910 _ => &[],
1911 };
1912
1913 let mut test_args: Vec<&str> = paths
1915 .iter()
1916 .filter_map(|p| helpers::is_valid_test_suite_arg(p, suite_path, builder))
1917 .collect();
1918
1919 test_args.append(&mut builder.config.test_args());
1920
1921 if cfg!(windows) {
1924 let test_args_win: Vec<String> =
1925 test_args.iter().map(|s| s.replace('/', "\\")).collect();
1926 cmd.args(&test_args_win);
1927 } else {
1928 cmd.args(&test_args);
1929 }
1930
1931 if builder.is_verbose() {
1932 cmd.arg("--verbose");
1933 }
1934
1935 cmd.arg("--json");
1936
1937 if builder.config.rustc_debug_assertions {
1938 cmd.arg("--with-rustc-debug-assertions");
1939 }
1940
1941 if builder.config.std_debug_assertions {
1942 cmd.arg("--with-std-debug-assertions");
1943 }
1944
1945 let mut llvm_components_passed = false;
1946 let mut copts_passed = false;
1947 if builder.config.llvm_enabled(compiler.host) {
1948 let llvm::LlvmResult { llvm_config, .. } =
1949 builder.ensure(llvm::Llvm { target: builder.config.build });
1950 if !builder.config.dry_run() {
1951 let llvm_version = get_llvm_version(builder, &llvm_config);
1952 let llvm_components =
1953 command(&llvm_config).arg("--components").run_capture_stdout(builder).stdout();
1954 cmd.arg("--llvm-version")
1956 .arg(llvm_version.trim())
1957 .arg("--llvm-components")
1958 .arg(llvm_components.trim());
1959 llvm_components_passed = true;
1960 }
1961 if !builder.is_rust_llvm(target) {
1962 cmd.arg("--system-llvm");
1965 }
1966
1967 if !builder.config.dry_run() && suite.ends_with("fulldeps") {
1972 let llvm_libdir =
1973 command(&llvm_config).arg("--libdir").run_capture_stdout(builder).stdout();
1974 let link_llvm = if target.is_msvc() {
1975 format!("-Clink-arg=-LIBPATH:{llvm_libdir}")
1976 } else {
1977 format!("-Clink-arg=-L{llvm_libdir}")
1978 };
1979 cmd.arg("--host-rustcflags").arg(link_llvm);
1980 }
1981
1982 if !builder.config.dry_run() && matches!(mode, "run-make" | "coverage-run") {
1983 let llvm_bin_path = llvm_config
1988 .parent()
1989 .expect("Expected llvm-config to be contained in directory");
1990 assert!(llvm_bin_path.is_dir());
1991 cmd.arg("--llvm-bin-dir").arg(llvm_bin_path);
1992 }
1993
1994 if !builder.config.dry_run() && mode == "run-make" {
1995 if builder.config.lld_enabled {
1997 let lld_install_root =
1998 builder.ensure(llvm::Lld { target: builder.config.build });
1999
2000 let lld_bin_path = lld_install_root.join("bin");
2001
2002 let old_path = env::var_os("PATH").unwrap_or_default();
2003 let new_path = env::join_paths(
2004 std::iter::once(lld_bin_path).chain(env::split_paths(&old_path)),
2005 )
2006 .expect("Could not add LLD bin path to PATH");
2007 cmd.env("PATH", new_path);
2008 }
2009 }
2010 }
2011
2012 if !builder.config.dry_run() && mode == "run-make" {
2015 let mut cflags = builder.cc_handled_clags(target, CLang::C);
2016 cflags.extend(builder.cc_unhandled_cflags(target, GitRepo::Rustc, CLang::C));
2017 let mut cxxflags = builder.cc_handled_clags(target, CLang::Cxx);
2018 cxxflags.extend(builder.cc_unhandled_cflags(target, GitRepo::Rustc, CLang::Cxx));
2019 cmd.arg("--cc")
2020 .arg(builder.cc(target))
2021 .arg("--cxx")
2022 .arg(builder.cxx(target).unwrap())
2023 .arg("--cflags")
2024 .arg(cflags.join(" "))
2025 .arg("--cxxflags")
2026 .arg(cxxflags.join(" "));
2027 copts_passed = true;
2028 if let Some(ar) = builder.ar(target) {
2029 cmd.arg("--ar").arg(ar);
2030 }
2031 }
2032
2033 if !llvm_components_passed {
2034 cmd.arg("--llvm-components").arg("");
2035 }
2036 if !copts_passed {
2037 cmd.arg("--cc")
2038 .arg("")
2039 .arg("--cxx")
2040 .arg("")
2041 .arg("--cflags")
2042 .arg("")
2043 .arg("--cxxflags")
2044 .arg("");
2045 }
2046
2047 if builder.remote_tested(target) {
2048 cmd.arg("--remote-test-client").arg(builder.tool_exe(Tool::RemoteTestClient));
2049 } else if let Some(tool) = builder.runner(target) {
2050 cmd.arg("--runner").arg(tool);
2051 }
2052
2053 if suite != "mir-opt" {
2054 if !builder.config.dry_run() && target.is_msvc() {
2060 for (k, v) in builder.cc.borrow()[&target].env() {
2061 if k != "PATH" {
2062 cmd.env(k, v);
2063 }
2064 }
2065 }
2066 }
2067
2068 if !builder.config.dry_run()
2070 && target.contains("msvc")
2071 && builder.config.sanitizers_enabled(target)
2072 {
2073 cmd.env("ASAN_WIN_CONTINUE_ON_INTERCEPTION_FAILURE", "1");
2076 let asan_runtime_path =
2078 builder.cc.borrow()[&target].path().parent().unwrap().to_path_buf();
2079 let old_path = cmd
2080 .get_envs()
2081 .find_map(|(k, v)| (k == "PATH").then_some(v))
2082 .flatten()
2083 .map_or_else(|| env::var_os("PATH").unwrap_or_default(), |v| v.to_owned());
2084 let new_path = env::join_paths(
2085 env::split_paths(&old_path).chain(std::iter::once(asan_runtime_path)),
2086 )
2087 .expect("Could not add ASAN runtime path to PATH");
2088 cmd.env("PATH", new_path);
2089 }
2090
2091 cmd.env_remove("CARGO");
2094
2095 cmd.env("RUSTC_BOOTSTRAP", "1");
2096 cmd.env("RUSTC_FORCE_RUSTC_VERSION", "compiletest");
2099 cmd.env("DOC_RUST_LANG_ORG_CHANNEL", builder.doc_rust_lang_org_channel());
2100 builder.add_rust_test_threads(&mut cmd);
2101
2102 if builder.config.sanitizers_enabled(target) {
2103 cmd.env("RUSTC_SANITIZER_SUPPORT", "1");
2104 }
2105
2106 if builder.config.profiler_enabled(target) {
2107 cmd.arg("--profiler-runtime");
2108 }
2109
2110 cmd.env("RUST_TEST_TMPDIR", builder.tempdir());
2111
2112 cmd.arg("--adb-path").arg("adb");
2113 cmd.arg("--adb-test-dir").arg(ADB_TEST_DIR);
2114 if target.contains("android") && !builder.config.dry_run() {
2115 cmd.arg("--android-cross-path")
2117 .arg(builder.cc(target).parent().unwrap().parent().unwrap());
2118 } else {
2119 cmd.arg("--android-cross-path").arg("");
2120 }
2121
2122 if builder.config.cmd.rustfix_coverage() {
2123 cmd.arg("--rustfix-coverage");
2124 }
2125
2126 cmd.arg("--channel").arg(&builder.config.channel);
2127
2128 if !builder.config.omit_git_hash {
2129 cmd.arg("--git-hash");
2130 }
2131
2132 let git_config = builder.config.git_config();
2133 cmd.arg("--git-repository").arg(git_config.git_repository);
2134 cmd.arg("--nightly-branch").arg(git_config.nightly_branch);
2135 cmd.arg("--git-merge-commit-email").arg(git_config.git_merge_commit_email);
2136 cmd.force_coloring_in_ci();
2137
2138 #[cfg(feature = "build-metrics")]
2139 builder.metrics.begin_test_suite(
2140 build_helper::metrics::TestSuiteMetadata::Compiletest {
2141 suite: suite.into(),
2142 mode: mode.into(),
2143 compare_mode: None,
2144 target: self.target.triple.to_string(),
2145 host: self.compiler.host.triple.to_string(),
2146 stage: self.compiler.stage,
2147 },
2148 builder,
2149 );
2150
2151 let _group = builder.msg(
2152 Kind::Test,
2153 compiler.stage,
2154 format!("compiletest suite={suite} mode={mode}"),
2155 compiler.host,
2156 target,
2157 );
2158 try_run_tests(builder, &mut cmd, false);
2159
2160 if let Some(compare_mode) = compare_mode {
2161 cmd.arg("--compare-mode").arg(compare_mode);
2162
2163 #[cfg(feature = "build-metrics")]
2164 builder.metrics.begin_test_suite(
2165 build_helper::metrics::TestSuiteMetadata::Compiletest {
2166 suite: suite.into(),
2167 mode: mode.into(),
2168 compare_mode: Some(compare_mode.into()),
2169 target: self.target.triple.to_string(),
2170 host: self.compiler.host.triple.to_string(),
2171 stage: self.compiler.stage,
2172 },
2173 builder,
2174 );
2175
2176 builder.info(&format!(
2177 "Check compiletest suite={} mode={} compare_mode={} ({} -> {})",
2178 suite, mode, compare_mode, &compiler.host, target
2179 ));
2180 let _time = helpers::timeit(builder);
2181 try_run_tests(builder, &mut cmd, false);
2182 }
2183 }
2184}
2185
2186#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2187struct BookTest {
2188 compiler: Compiler,
2189 path: PathBuf,
2190 name: &'static str,
2191 is_ext_doc: bool,
2192 dependencies: Vec<&'static str>,
2193}
2194
2195impl Step for BookTest {
2196 type Output = ();
2197 const ONLY_HOSTS: bool = true;
2198
2199 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2200 run.never()
2201 }
2202
2203 fn run(self, builder: &Builder<'_>) {
2207 if self.is_ext_doc {
2217 self.run_ext_doc(builder);
2218 } else {
2219 self.run_local_doc(builder);
2220 }
2221 }
2222}
2223
2224impl BookTest {
2225 fn run_ext_doc(self, builder: &Builder<'_>) {
2228 let compiler = self.compiler;
2229
2230 builder.ensure(compile::Std::new(compiler, compiler.host));
2231
2232 let mut rustdoc_path = builder.rustdoc(compiler);
2235 rustdoc_path.pop();
2236 let old_path = env::var_os("PATH").unwrap_or_default();
2237 let new_path = env::join_paths(iter::once(rustdoc_path).chain(env::split_paths(&old_path)))
2238 .expect("could not add rustdoc to PATH");
2239
2240 let mut rustbook_cmd = builder.tool_cmd(Tool::Rustbook);
2241 let path = builder.src.join(&self.path);
2242 rustbook_cmd.env("RUSTC_BOOTSTRAP", "1");
2244 rustbook_cmd.env("PATH", new_path).arg("test").arg(path);
2245
2246 let libs = if !self.dependencies.is_empty() {
2251 let mut lib_paths = vec![];
2252 for dep in self.dependencies {
2253 let mode = Mode::ToolRustc;
2254 let target = builder.config.build;
2255 let cargo = tool::prepare_tool_cargo(
2256 builder,
2257 compiler,
2258 mode,
2259 target,
2260 Kind::Build,
2261 dep,
2262 SourceType::Submodule,
2263 &[],
2264 );
2265
2266 let stamp = BuildStamp::new(&builder.cargo_out(compiler, mode, target))
2267 .with_prefix(PathBuf::from(dep).file_name().and_then(|v| v.to_str()).unwrap());
2268
2269 let output_paths = run_cargo(builder, cargo, vec![], &stamp, vec![], false, false);
2270 let directories = output_paths
2271 .into_iter()
2272 .filter_map(|p| p.parent().map(ToOwned::to_owned))
2273 .fold(HashSet::new(), |mut set, dir| {
2274 set.insert(dir);
2275 set
2276 });
2277
2278 lib_paths.extend(directories);
2279 }
2280 lib_paths
2281 } else {
2282 vec![]
2283 };
2284
2285 if !libs.is_empty() {
2286 let paths = libs
2287 .into_iter()
2288 .map(|path| path.into_os_string())
2289 .collect::<Vec<OsString>>()
2290 .join(OsStr::new(","));
2291 rustbook_cmd.args([OsString::from("--library-path"), paths]);
2292 }
2293
2294 builder.add_rust_test_threads(&mut rustbook_cmd);
2295 let _guard = builder.msg(
2296 Kind::Test,
2297 compiler.stage,
2298 format_args!("mdbook {}", self.path.display()),
2299 compiler.host,
2300 compiler.host,
2301 );
2302 let _time = helpers::timeit(builder);
2303 let toolstate = if rustbook_cmd.delay_failure().run(builder) {
2304 ToolState::TestPass
2305 } else {
2306 ToolState::TestFail
2307 };
2308 builder.save_toolstate(self.name, toolstate);
2309 }
2310
2311 fn run_local_doc(self, builder: &Builder<'_>) {
2313 let compiler = self.compiler;
2314 let host = self.compiler.host;
2315
2316 builder.ensure(compile::Std::new(compiler, host));
2317
2318 let _guard =
2319 builder.msg(Kind::Test, compiler.stage, format!("book {}", self.name), host, host);
2320
2321 let mut stack = vec![builder.src.join(self.path)];
2324 let _time = helpers::timeit(builder);
2325 let mut files = Vec::new();
2326 while let Some(p) = stack.pop() {
2327 if p.is_dir() {
2328 stack.extend(t!(p.read_dir()).map(|p| t!(p).path()));
2329 continue;
2330 }
2331
2332 if p.extension().and_then(|s| s.to_str()) != Some("md") {
2333 continue;
2334 }
2335
2336 files.push(p);
2337 }
2338
2339 files.sort();
2340
2341 for file in files {
2342 markdown_test(builder, compiler, &file);
2343 }
2344 }
2345}
2346
2347macro_rules! test_book {
2348 ($(
2349 $name:ident, $path:expr, $book_name:expr,
2350 default=$default:expr
2351 $(,submodules = $submodules:expr)?
2352 $(,dependencies=$dependencies:expr)?
2353 ;
2354 )+) => {
2355 $(
2356 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
2357 pub struct $name {
2358 compiler: Compiler,
2359 }
2360
2361 impl Step for $name {
2362 type Output = ();
2363 const DEFAULT: bool = $default;
2364 const ONLY_HOSTS: bool = true;
2365
2366 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2367 run.path($path)
2368 }
2369
2370 fn make_run(run: RunConfig<'_>) {
2371 run.builder.ensure($name {
2372 compiler: run.builder.compiler(run.builder.top_stage, run.target),
2373 });
2374 }
2375
2376 fn run(self, builder: &Builder<'_>) {
2377 $(
2378 for submodule in $submodules {
2379 builder.require_submodule(submodule, None);
2380 }
2381 )*
2382
2383 let dependencies = vec![];
2384 $(
2385 let mut dependencies = dependencies;
2386 for dep in $dependencies {
2387 dependencies.push(dep);
2388 }
2389 )?
2390
2391 builder.ensure(BookTest {
2392 compiler: self.compiler,
2393 path: PathBuf::from($path),
2394 name: $book_name,
2395 is_ext_doc: !$default,
2396 dependencies,
2397 });
2398 }
2399 }
2400 )+
2401 }
2402}
2403
2404test_book!(
2405 Nomicon, "src/doc/nomicon", "nomicon", default=false, submodules=["src/doc/nomicon"];
2406 Reference, "src/doc/reference", "reference", default=false, submodules=["src/doc/reference"];
2407 RustdocBook, "src/doc/rustdoc", "rustdoc", default=true;
2408 RustcBook, "src/doc/rustc", "rustc", default=true;
2409 RustByExample, "src/doc/rust-by-example", "rust-by-example", default=false, submodules=["src/doc/rust-by-example"];
2410 EmbeddedBook, "src/doc/embedded-book", "embedded-book", default=false, submodules=["src/doc/embedded-book"];
2411 TheBook, "src/doc/book", "book", default=false, submodules=["src/doc/book"], dependencies=["src/doc/book/packages/trpl"];
2412 UnstableBook, "src/doc/unstable-book", "unstable-book", default=true;
2413 EditionGuide, "src/doc/edition-guide", "edition-guide", default=false, submodules=["src/doc/edition-guide"];
2414);
2415
2416#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2417pub struct ErrorIndex {
2418 compiler: Compiler,
2419}
2420
2421impl Step for ErrorIndex {
2422 type Output = ();
2423 const DEFAULT: bool = true;
2424 const ONLY_HOSTS: bool = true;
2425
2426 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2427 run.path("src/tools/error_index_generator").alias("error-index")
2430 }
2431
2432 fn make_run(run: RunConfig<'_>) {
2433 let compiler = run.builder.compiler(run.builder.top_stage, run.builder.config.build);
2437 run.builder.ensure(ErrorIndex { compiler });
2438 }
2439
2440 fn run(self, builder: &Builder<'_>) {
2447 let compiler = self.compiler;
2448
2449 let dir = testdir(builder, compiler.host);
2450 t!(fs::create_dir_all(&dir));
2451 let output = dir.join("error-index.md");
2452
2453 let mut tool = tool::ErrorIndex::command(builder);
2454 tool.arg("markdown").arg(&output);
2455
2456 let guard =
2457 builder.msg(Kind::Test, compiler.stage, "error-index", compiler.host, compiler.host);
2458 let _time = helpers::timeit(builder);
2459 tool.run_capture(builder);
2460 drop(guard);
2461 builder.ensure(compile::Std::new(compiler, compiler.host));
2464 markdown_test(builder, compiler, &output);
2465 }
2466}
2467
2468fn markdown_test(builder: &Builder<'_>, compiler: Compiler, markdown: &Path) -> bool {
2469 if let Ok(contents) = fs::read_to_string(markdown) {
2470 if !contents.contains("```") {
2471 return true;
2472 }
2473 }
2474
2475 builder.verbose(|| println!("doc tests for: {}", markdown.display()));
2476 let mut cmd = builder.rustdoc_cmd(compiler);
2477 builder.add_rust_test_threads(&mut cmd);
2478 cmd.arg("-Z");
2480 cmd.arg("unstable-options");
2481 cmd.arg("--test");
2482 cmd.arg(markdown);
2483 cmd.env("RUSTC_BOOTSTRAP", "1");
2484
2485 let test_args = builder.config.test_args().join(" ");
2486 cmd.arg("--test-args").arg(test_args);
2487
2488 cmd = cmd.delay_failure();
2489 if !builder.config.verbose_tests {
2490 cmd.run_capture(builder).is_success()
2491 } else {
2492 cmd.run(builder)
2493 }
2494}
2495
2496#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2501pub struct CrateLibrustc {
2502 compiler: Compiler,
2503 target: TargetSelection,
2504 crates: Vec<String>,
2505}
2506
2507impl Step for CrateLibrustc {
2508 type Output = ();
2509 const DEFAULT: bool = true;
2510 const ONLY_HOSTS: bool = true;
2511
2512 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2513 run.crate_or_deps("rustc-main").path("compiler")
2514 }
2515
2516 fn make_run(run: RunConfig<'_>) {
2517 let builder = run.builder;
2518 let host = run.build_triple();
2519 let compiler = builder.compiler_for(builder.top_stage, host, host);
2520 let crates = run.make_run_crates(Alias::Compiler);
2521
2522 builder.ensure(CrateLibrustc { compiler, target: run.target, crates });
2523 }
2524
2525 fn run(self, builder: &Builder<'_>) {
2526 builder.ensure(compile::Std::new(self.compiler, self.target));
2527
2528 builder.ensure(Crate {
2530 compiler: self.compiler,
2531 target: self.target,
2532 mode: Mode::Rustc,
2533 crates: self.crates,
2534 });
2535 }
2536}
2537
2538fn run_cargo_test<'a>(
2542 cargo: builder::Cargo,
2543 libtest_args: &[&str],
2544 crates: &[String],
2545 primary_crate: &str,
2546 description: impl Into<Option<&'a str>>,
2547 target: TargetSelection,
2548 builder: &Builder<'_>,
2549) -> bool {
2550 let compiler = cargo.compiler();
2551 let mut cargo = prepare_cargo_test(cargo, libtest_args, crates, primary_crate, target, builder);
2552 let _time = helpers::timeit(builder);
2553 let _group = description.into().and_then(|what| {
2554 builder.msg_sysroot_tool(Kind::Test, compiler.stage, what, compiler.host, target)
2555 });
2556
2557 #[cfg(feature = "build-metrics")]
2558 builder.metrics.begin_test_suite(
2559 build_helper::metrics::TestSuiteMetadata::CargoPackage {
2560 crates: crates.iter().map(|c| c.to_string()).collect(),
2561 target: target.triple.to_string(),
2562 host: compiler.host.triple.to_string(),
2563 stage: compiler.stage,
2564 },
2565 builder,
2566 );
2567 add_flags_and_try_run_tests(builder, &mut cargo)
2568}
2569
2570fn prepare_cargo_test(
2572 cargo: builder::Cargo,
2573 libtest_args: &[&str],
2574 crates: &[String],
2575 primary_crate: &str,
2576 target: TargetSelection,
2577 builder: &Builder<'_>,
2578) -> BootstrapCommand {
2579 let compiler = cargo.compiler();
2580 let mut cargo: BootstrapCommand = cargo.into();
2581
2582 if builder.config.cmd.bless() && !cargo.get_envs().any(|v| v.0 == "RUSTC_BLESS") {
2586 cargo.env("RUSTC_BLESS", "Gesundheit");
2587 }
2588
2589 if builder.kind == Kind::Test && !builder.fail_fast {
2593 cargo.arg("--no-fail-fast");
2594 }
2595
2596 if builder.config.json_output {
2597 cargo.arg("--message-format=json");
2598 }
2599
2600 match builder.doc_tests {
2601 DocTests::Only => {
2602 cargo.arg("--doc");
2603 }
2604 DocTests::No => {
2605 let krate = &builder
2606 .crates
2607 .get(primary_crate)
2608 .unwrap_or_else(|| panic!("missing crate {primary_crate}"));
2609 if krate.has_lib {
2610 cargo.arg("--lib");
2611 }
2612 cargo.args(["--bins", "--examples", "--tests", "--benches"]);
2613 }
2614 DocTests::Yes => {}
2615 }
2616
2617 for krate in crates {
2618 cargo.arg("-p").arg(krate);
2619 }
2620
2621 cargo.arg("--").args(builder.config.test_args()).args(libtest_args);
2622 if !builder.config.verbose_tests {
2623 cargo.arg("--quiet");
2624 }
2625
2626 if builder.kind != Kind::Miri {
2635 let mut dylib_path = dylib_path();
2636 dylib_path.insert(0, PathBuf::from(&*builder.sysroot_target_libdir(compiler, target)));
2637 cargo.env(dylib_path_var(), env::join_paths(&dylib_path).unwrap());
2638 }
2639
2640 if builder.remote_tested(target) {
2641 cargo.env(
2642 format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)),
2643 format!("{} run 0", builder.tool_exe(Tool::RemoteTestClient).display()),
2644 );
2645 } else if let Some(tool) = builder.runner(target) {
2646 cargo.env(format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)), tool);
2647 }
2648
2649 cargo
2650}
2651
2652#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
2660pub struct Crate {
2661 pub compiler: Compiler,
2662 pub target: TargetSelection,
2663 pub mode: Mode,
2664 pub crates: Vec<String>,
2665}
2666
2667impl Step for Crate {
2668 type Output = ();
2669 const DEFAULT: bool = true;
2670
2671 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2672 run.crate_or_deps("sysroot").crate_or_deps("coretests")
2673 }
2674
2675 fn make_run(run: RunConfig<'_>) {
2676 let builder = run.builder;
2677 let host = run.build_triple();
2678 let compiler = builder.compiler_for(builder.top_stage, host, host);
2679 let crates = run
2680 .paths
2681 .iter()
2682 .map(|p| builder.crate_paths[&p.assert_single_path().path].clone())
2683 .collect();
2684
2685 builder.ensure(Crate { compiler, target: run.target, mode: Mode::Std, crates });
2686 }
2687
2688 fn run(self, builder: &Builder<'_>) {
2697 let compiler = self.compiler;
2698 let target = self.target;
2699 let mode = self.mode;
2700
2701 builder.ensure(compile::Std::new(compiler, compiler.host).force_recompile(true));
2704
2705 let compiler = builder.compiler_for(compiler.stage, compiler.host, target);
2710
2711 let mut cargo = if builder.kind == Kind::Miri {
2712 if builder.top_stage == 0 {
2713 eprintln!("ERROR: `x.py miri` requires stage 1 or higher");
2714 std::process::exit(1);
2715 }
2716
2717 let mut cargo = builder::Cargo::new(
2720 builder,
2721 compiler,
2722 mode,
2723 SourceType::InTree,
2724 target,
2725 Kind::MiriTest,
2726 );
2727 cargo.env("MIRI_REPLACE_LIBRS_IF_NOT_TEST", "1");
2739 cargo.rustflag("-Zforce-unstable-if-unmarked");
2743 cargo
2744 } else {
2745 if !builder.is_builder_target(&target) {
2747 builder.ensure(compile::Std::new(compiler, target).force_recompile(true));
2748 builder.ensure(RemoteCopyLibs { compiler, target });
2749 }
2750
2751 builder::Cargo::new(builder, compiler, mode, SourceType::InTree, target, builder.kind)
2753 };
2754
2755 match mode {
2756 Mode::Std => {
2757 if builder.kind == Kind::Miri {
2758 cargo
2764 .arg("--manifest-path")
2765 .arg(builder.src.join("library/sysroot/Cargo.toml"));
2766 } else {
2767 compile::std_cargo(builder, target, compiler.stage, &mut cargo);
2768 if builder.download_rustc() && compiler.stage > 0 {
2772 let sysroot = builder
2773 .out
2774 .join(compiler.host)
2775 .join(format!("stage{}-test-sysroot", compiler.stage));
2776 cargo.env("RUSTC_SYSROOT", sysroot);
2777 }
2778 }
2779 }
2780 Mode::Rustc => {
2781 compile::rustc_cargo(builder, &mut cargo, target, &compiler, &self.crates);
2782 }
2783 _ => panic!("can only test libraries"),
2784 };
2785
2786 run_cargo_test(
2787 cargo,
2788 &[],
2789 &self.crates,
2790 &self.crates[0],
2791 &*crate_description(&self.crates),
2792 target,
2793 builder,
2794 );
2795 }
2796}
2797
2798#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2800pub struct CrateRustdoc {
2801 host: TargetSelection,
2802}
2803
2804impl Step for CrateRustdoc {
2805 type Output = ();
2806 const DEFAULT: bool = true;
2807 const ONLY_HOSTS: bool = true;
2808
2809 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2810 run.paths(&["src/librustdoc", "src/tools/rustdoc"])
2811 }
2812
2813 fn make_run(run: RunConfig<'_>) {
2814 let builder = run.builder;
2815
2816 builder.ensure(CrateRustdoc { host: run.target });
2817 }
2818
2819 fn run(self, builder: &Builder<'_>) {
2820 let target = self.host;
2821
2822 let compiler = if builder.download_rustc() {
2823 builder.compiler(builder.top_stage, target)
2824 } else {
2825 builder.compiler_for(builder.top_stage, target, target)
2830 };
2831 builder.ensure(compile::Std::new(compiler, target));
2836 builder.ensure(compile::Rustc::new(compiler, target));
2837
2838 let mut cargo = tool::prepare_tool_cargo(
2839 builder,
2840 compiler,
2841 Mode::ToolRustc,
2842 target,
2843 builder.kind,
2844 "src/tools/rustdoc",
2845 SourceType::InTree,
2846 &[],
2847 );
2848 if self.host.contains("musl") {
2849 cargo.arg("'-Ctarget-feature=-crt-static'");
2850 }
2851
2852 let libdir = if builder.download_rustc() {
2879 builder.rustc_libdir(compiler)
2880 } else {
2881 builder.sysroot_target_libdir(compiler, target).to_path_buf()
2882 };
2883 let mut dylib_path = dylib_path();
2884 dylib_path.insert(0, PathBuf::from(&*libdir));
2885 cargo.env(dylib_path_var(), env::join_paths(&dylib_path).unwrap());
2886
2887 run_cargo_test(
2888 cargo,
2889 &[],
2890 &["rustdoc:0.0.0".to_string()],
2891 "rustdoc",
2892 "rustdoc",
2893 target,
2894 builder,
2895 );
2896 }
2897}
2898
2899#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2900pub struct CrateRustdocJsonTypes {
2901 host: TargetSelection,
2902}
2903
2904impl Step for CrateRustdocJsonTypes {
2905 type Output = ();
2906 const DEFAULT: bool = true;
2907 const ONLY_HOSTS: bool = true;
2908
2909 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2910 run.path("src/rustdoc-json-types")
2911 }
2912
2913 fn make_run(run: RunConfig<'_>) {
2914 let builder = run.builder;
2915
2916 builder.ensure(CrateRustdocJsonTypes { host: run.target });
2917 }
2918
2919 fn run(self, builder: &Builder<'_>) {
2920 let target = self.host;
2921
2922 let compiler = builder.compiler_for(builder.top_stage, target, target);
2927 builder.ensure(compile::Rustc::new(compiler, target));
2928
2929 let cargo = tool::prepare_tool_cargo(
2930 builder,
2931 compiler,
2932 Mode::ToolRustc,
2933 target,
2934 builder.kind,
2935 "src/rustdoc-json-types",
2936 SourceType::InTree,
2937 &[],
2938 );
2939
2940 let libtest_args = if self.host.contains("musl") {
2942 ["'-Ctarget-feature=-crt-static'"].as_slice()
2943 } else {
2944 &[]
2945 };
2946
2947 run_cargo_test(
2948 cargo,
2949 libtest_args,
2950 &["rustdoc-json-types".to_string()],
2951 "rustdoc-json-types",
2952 "rustdoc-json-types",
2953 target,
2954 builder,
2955 );
2956 }
2957}
2958
2959#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2969pub struct RemoteCopyLibs {
2970 compiler: Compiler,
2971 target: TargetSelection,
2972}
2973
2974impl Step for RemoteCopyLibs {
2975 type Output = ();
2976
2977 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2978 run.never()
2979 }
2980
2981 fn run(self, builder: &Builder<'_>) {
2982 let compiler = self.compiler;
2983 let target = self.target;
2984 if !builder.remote_tested(target) {
2985 return;
2986 }
2987
2988 builder.ensure(compile::Std::new(compiler, target));
2989
2990 builder.info(&format!("REMOTE copy libs to emulator ({target})"));
2991
2992 let server = builder.ensure(tool::RemoteTestServer { compiler, target });
2993
2994 let tool = builder.tool_exe(Tool::RemoteTestClient);
2996 let mut cmd = command(&tool);
2997 cmd.arg("spawn-emulator").arg(target.triple).arg(&server).arg(builder.tempdir());
2998 if let Some(rootfs) = builder.qemu_rootfs(target) {
2999 cmd.arg(rootfs);
3000 }
3001 cmd.run(builder);
3002
3003 for f in t!(builder.sysroot_target_libdir(compiler, target).read_dir()) {
3005 let f = t!(f);
3006 if helpers::is_dylib(&f.path()) {
3007 command(&tool).arg("push").arg(f.path()).run(builder);
3008 }
3009 }
3010 }
3011}
3012
3013#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3014pub struct Distcheck;
3015
3016impl Step for Distcheck {
3017 type Output = ();
3018
3019 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3020 run.alias("distcheck")
3021 }
3022
3023 fn make_run(run: RunConfig<'_>) {
3024 run.builder.ensure(Distcheck);
3025 }
3026
3027 fn run(self, builder: &Builder<'_>) {
3029 builder.info("Distcheck");
3030 let dir = builder.tempdir().join("distcheck");
3031 let _ = fs::remove_dir_all(&dir);
3032 t!(fs::create_dir_all(&dir));
3033
3034 builder.ensure(dist::PlainSourceTarball);
3036 builder.ensure(dist::Src);
3037
3038 command("tar")
3039 .arg("-xf")
3040 .arg(builder.ensure(dist::PlainSourceTarball).tarball())
3041 .arg("--strip-components=1")
3042 .current_dir(&dir)
3043 .run(builder);
3044 command("./configure")
3045 .args(&builder.config.configure_args)
3046 .arg("--enable-vendor")
3047 .current_dir(&dir)
3048 .run(builder);
3049 command(helpers::make(&builder.config.build.triple))
3050 .arg("check")
3051 .current_dir(&dir)
3052 .run(builder);
3053
3054 builder.info("Distcheck rust-src");
3056 let dir = builder.tempdir().join("distcheck-src");
3057 let _ = fs::remove_dir_all(&dir);
3058 t!(fs::create_dir_all(&dir));
3059
3060 command("tar")
3061 .arg("-xf")
3062 .arg(builder.ensure(dist::Src).tarball())
3063 .arg("--strip-components=1")
3064 .current_dir(&dir)
3065 .run(builder);
3066
3067 let toml = dir.join("rust-src/lib/rustlib/src/rust/library/std/Cargo.toml");
3068 command(&builder.initial_cargo)
3069 .env("RUSTC_BOOTSTRAP", "1")
3072 .arg("generate-lockfile")
3073 .arg("--manifest-path")
3074 .arg(&toml)
3075 .current_dir(&dir)
3076 .run(builder);
3077 }
3078}
3079
3080#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3081pub struct Bootstrap;
3082
3083impl Step for Bootstrap {
3084 type Output = ();
3085 const DEFAULT: bool = true;
3086 const ONLY_HOSTS: bool = true;
3087
3088 fn run(self, builder: &Builder<'_>) {
3090 let host = builder.config.build;
3091 let compiler = builder.compiler(0, host);
3092 let _guard = builder.msg(Kind::Test, 0, "bootstrap", host, host);
3093
3094 builder.build.require_submodule("src/tools/cargo", None);
3096
3097 let mut check_bootstrap = command(builder.python());
3098 check_bootstrap
3099 .args(["-m", "unittest", "bootstrap_test.py"])
3100 .env("BUILD_DIR", &builder.out)
3101 .env("BUILD_PLATFORM", builder.build.build.triple)
3102 .env("BOOTSTRAP_TEST_RUSTC_BIN", &builder.initial_rustc)
3103 .env("BOOTSTRAP_TEST_CARGO_BIN", &builder.initial_cargo)
3104 .current_dir(builder.src.join("src/bootstrap/"));
3105 check_bootstrap.delay_failure().run(builder);
3108
3109 let mut cargo = tool::prepare_tool_cargo(
3110 builder,
3111 compiler,
3112 Mode::ToolBootstrap,
3113 host,
3114 Kind::Test,
3115 "src/bootstrap",
3116 SourceType::InTree,
3117 &[],
3118 );
3119
3120 cargo.release_build(false);
3121
3122 cargo
3123 .rustflag("-Cdebuginfo=2")
3124 .env("CARGO_TARGET_DIR", builder.out.join("bootstrap"))
3125 .env("RUSTC_BOOTSTRAP", "1");
3126
3127 run_cargo_test(cargo, &["--test-threads=1"], &[], "bootstrap", None, host, builder);
3130 }
3131
3132 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3133 run.path("src/bootstrap")
3134 }
3135
3136 fn make_run(run: RunConfig<'_>) {
3137 run.builder.ensure(Bootstrap);
3138 }
3139}
3140
3141#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3142pub struct TierCheck {
3143 pub compiler: Compiler,
3144}
3145
3146impl Step for TierCheck {
3147 type Output = ();
3148 const DEFAULT: bool = true;
3149 const ONLY_HOSTS: bool = true;
3150
3151 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3152 run.path("src/tools/tier-check")
3153 }
3154
3155 fn make_run(run: RunConfig<'_>) {
3156 let compiler =
3157 run.builder.compiler_for(run.builder.top_stage, run.builder.build.build, run.target);
3158 run.builder.ensure(TierCheck { compiler });
3159 }
3160
3161 fn run(self, builder: &Builder<'_>) {
3163 builder.ensure(compile::Std::new(self.compiler, self.compiler.host));
3164 let mut cargo = tool::prepare_tool_cargo(
3165 builder,
3166 self.compiler,
3167 Mode::ToolStd,
3168 self.compiler.host,
3169 Kind::Run,
3170 "src/tools/tier-check",
3171 SourceType::InTree,
3172 &[],
3173 );
3174 cargo.arg(builder.src.join("src/doc/rustc/src/platform-support.md"));
3175 cargo.arg(builder.rustc(self.compiler));
3176 if builder.is_verbose() {
3177 cargo.arg("--verbose");
3178 }
3179
3180 let _guard = builder.msg(
3181 Kind::Test,
3182 self.compiler.stage,
3183 "platform support check",
3184 self.compiler.host,
3185 self.compiler.host,
3186 );
3187 BootstrapCommand::from(cargo).delay_failure().run(builder);
3188 }
3189}
3190
3191#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3192pub struct LintDocs {
3193 pub compiler: Compiler,
3194 pub target: TargetSelection,
3195}
3196
3197impl Step for LintDocs {
3198 type Output = ();
3199 const DEFAULT: bool = true;
3200 const ONLY_HOSTS: bool = true;
3201
3202 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3203 run.path("src/tools/lint-docs")
3204 }
3205
3206 fn make_run(run: RunConfig<'_>) {
3207 run.builder.ensure(LintDocs {
3208 compiler: run.builder.compiler(run.builder.top_stage, run.builder.config.build),
3209 target: run.target,
3210 });
3211 }
3212
3213 fn run(self, builder: &Builder<'_>) {
3216 builder.ensure(crate::core::build_steps::doc::RustcBook {
3217 compiler: self.compiler,
3218 target: self.target,
3219 validate: true,
3220 });
3221 }
3222}
3223
3224#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3225pub struct RustInstaller;
3226
3227impl Step for RustInstaller {
3228 type Output = ();
3229 const ONLY_HOSTS: bool = true;
3230 const DEFAULT: bool = true;
3231
3232 fn run(self, builder: &Builder<'_>) {
3234 let bootstrap_host = builder.config.build;
3235 let compiler = builder.compiler(0, bootstrap_host);
3236 let cargo = tool::prepare_tool_cargo(
3237 builder,
3238 compiler,
3239 Mode::ToolBootstrap,
3240 bootstrap_host,
3241 Kind::Test,
3242 "src/tools/rust-installer",
3243 SourceType::InTree,
3244 &[],
3245 );
3246
3247 let _guard = builder.msg(
3248 Kind::Test,
3249 compiler.stage,
3250 "rust-installer",
3251 bootstrap_host,
3252 bootstrap_host,
3253 );
3254 run_cargo_test(cargo, &[], &[], "installer", None, bootstrap_host, builder);
3255
3256 if bootstrap_host != "x86_64-unknown-linux-gnu" {
3260 return;
3261 }
3262
3263 let mut cmd = command(builder.src.join("src/tools/rust-installer/test.sh"));
3264 let tmpdir = testdir(builder, compiler.host).join("rust-installer");
3265 let _ = std::fs::remove_dir_all(&tmpdir);
3266 let _ = std::fs::create_dir_all(&tmpdir);
3267 cmd.current_dir(&tmpdir);
3268 cmd.env("CARGO_TARGET_DIR", tmpdir.join("cargo-target"));
3269 cmd.env("CARGO", &builder.initial_cargo);
3270 cmd.env("RUSTC", &builder.initial_rustc);
3271 cmd.env("TMP_DIR", &tmpdir);
3272 cmd.delay_failure().run(builder);
3273 }
3274
3275 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3276 run.path("src/tools/rust-installer")
3277 }
3278
3279 fn make_run(run: RunConfig<'_>) {
3280 run.builder.ensure(Self);
3281 }
3282}
3283
3284#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3285pub struct TestHelpers {
3286 pub target: TargetSelection,
3287}
3288
3289impl Step for TestHelpers {
3290 type Output = ();
3291
3292 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3293 run.path("tests/auxiliary/rust_test_helpers.c")
3294 }
3295
3296 fn make_run(run: RunConfig<'_>) {
3297 run.builder.ensure(TestHelpers { target: run.target })
3298 }
3299
3300 fn run(self, builder: &Builder<'_>) {
3303 if builder.config.dry_run() {
3304 return;
3305 }
3306 let target = if self.target == "x86_64-fortanix-unknown-sgx" {
3310 TargetSelection::from_user("x86_64-unknown-linux-gnu")
3311 } else {
3312 self.target
3313 };
3314 let dst = builder.test_helpers_out(target);
3315 let src = builder.src.join("tests/auxiliary/rust_test_helpers.c");
3316 if up_to_date(&src, &dst.join("librust_test_helpers.a")) {
3317 return;
3318 }
3319
3320 let _guard = builder.msg_unstaged(Kind::Build, "test helpers", target);
3321 t!(fs::create_dir_all(&dst));
3322 let mut cfg = cc::Build::new();
3323
3324 if !target.is_msvc() {
3328 if let Some(ar) = builder.ar(target) {
3329 cfg.archiver(ar);
3330 }
3331 cfg.compiler(builder.cc(target));
3332 }
3333 cfg.cargo_metadata(false)
3334 .out_dir(&dst)
3335 .target(&target.triple)
3336 .host(&builder.config.build.triple)
3337 .opt_level(0)
3338 .warnings(false)
3339 .debug(false)
3340 .file(builder.src.join("tests/auxiliary/rust_test_helpers.c"))
3341 .compile("rust_test_helpers");
3342 }
3343}
3344
3345#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3346pub struct CodegenCranelift {
3347 compiler: Compiler,
3348 target: TargetSelection,
3349}
3350
3351impl Step for CodegenCranelift {
3352 type Output = ();
3353 const DEFAULT: bool = true;
3354 const ONLY_HOSTS: bool = true;
3355
3356 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3357 run.paths(&["compiler/rustc_codegen_cranelift"])
3358 }
3359
3360 fn make_run(run: RunConfig<'_>) {
3361 let builder = run.builder;
3362 let host = run.build_triple();
3363 let compiler = run.builder.compiler_for(run.builder.top_stage, host, host);
3364
3365 if builder.doc_tests == DocTests::Only {
3366 return;
3367 }
3368
3369 if builder.download_rustc() {
3370 builder.info("CI rustc uses the default codegen backend. skipping");
3371 return;
3372 }
3373
3374 if !target_supports_cranelift_backend(run.target) {
3375 builder.info("target not supported by rustc_codegen_cranelift. skipping");
3376 return;
3377 }
3378
3379 if builder.remote_tested(run.target) {
3380 builder.info("remote testing is not supported by rustc_codegen_cranelift. skipping");
3381 return;
3382 }
3383
3384 if !builder.config.codegen_backends(run.target).contains(&"cranelift".to_owned()) {
3385 builder.info("cranelift not in rust.codegen-backends. skipping");
3386 return;
3387 }
3388
3389 builder.ensure(CodegenCranelift { compiler, target: run.target });
3390 }
3391
3392 fn run(self, builder: &Builder<'_>) {
3393 let compiler = self.compiler;
3394 let target = self.target;
3395
3396 builder.ensure(compile::Std::new(compiler, target));
3397
3398 let compiler = builder.compiler_for(compiler.stage, compiler.host, target);
3403
3404 let build_cargo = || {
3405 let mut cargo = builder::Cargo::new(
3406 builder,
3407 compiler,
3408 Mode::Codegen, SourceType::InTree,
3410 target,
3411 Kind::Run,
3412 );
3413
3414 cargo.current_dir(&builder.src.join("compiler/rustc_codegen_cranelift"));
3415 cargo
3416 .arg("--manifest-path")
3417 .arg(builder.src.join("compiler/rustc_codegen_cranelift/build_system/Cargo.toml"));
3418 compile::rustc_cargo_env(builder, &mut cargo, target, compiler.stage);
3419
3420 cargo.env("CARGO_BUILD_INCREMENTAL", "false");
3422
3423 cargo
3424 };
3425
3426 builder.info(&format!(
3427 "{} cranelift stage{} ({} -> {})",
3428 Kind::Test.description(),
3429 compiler.stage,
3430 &compiler.host,
3431 target
3432 ));
3433 let _time = helpers::timeit(builder);
3434
3435 let download_dir = builder.out.join("cg_clif_download");
3437
3438 let mut cargo = build_cargo();
3447 cargo
3448 .arg("--")
3449 .arg("test")
3450 .arg("--download-dir")
3451 .arg(&download_dir)
3452 .arg("--out-dir")
3453 .arg(builder.stage_out(compiler, Mode::ToolRustc).join("cg_clif"))
3454 .arg("--no-unstable-features")
3455 .arg("--use-backend")
3456 .arg("cranelift")
3457 .arg("--sysroot")
3459 .arg("llvm")
3460 .arg("--skip-test")
3463 .arg("testsuite.extended_sysroot");
3464
3465 cargo.into_cmd().run(builder);
3466 }
3467}
3468
3469#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3470pub struct CodegenGCC {
3471 compiler: Compiler,
3472 target: TargetSelection,
3473}
3474
3475impl Step for CodegenGCC {
3476 type Output = ();
3477 const DEFAULT: bool = true;
3478 const ONLY_HOSTS: bool = true;
3479
3480 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3481 run.paths(&["compiler/rustc_codegen_gcc"])
3482 }
3483
3484 fn make_run(run: RunConfig<'_>) {
3485 let builder = run.builder;
3486 let host = run.build_triple();
3487 let compiler = run.builder.compiler_for(run.builder.top_stage, host, host);
3488
3489 if builder.doc_tests == DocTests::Only {
3490 return;
3491 }
3492
3493 if builder.download_rustc() {
3494 builder.info("CI rustc uses the default codegen backend. skipping");
3495 return;
3496 }
3497
3498 let triple = run.target.triple;
3499 let target_supported =
3500 if triple.contains("linux") { triple.contains("x86_64") } else { false };
3501 if !target_supported {
3502 builder.info("target not supported by rustc_codegen_gcc. skipping");
3503 return;
3504 }
3505
3506 if builder.remote_tested(run.target) {
3507 builder.info("remote testing is not supported by rustc_codegen_gcc. skipping");
3508 return;
3509 }
3510
3511 if !builder.config.codegen_backends(run.target).contains(&"gcc".to_owned()) {
3512 builder.info("gcc not in rust.codegen-backends. skipping");
3513 return;
3514 }
3515
3516 builder.ensure(CodegenGCC { compiler, target: run.target });
3517 }
3518
3519 fn run(self, builder: &Builder<'_>) {
3520 let compiler = self.compiler;
3521 let target = self.target;
3522
3523 builder.ensure(
3524 compile::Std::new(compiler, target)
3525 .extra_rust_args(&["-Csymbol-mangling-version=v0", "-Cpanic=abort"]),
3526 );
3527
3528 let compiler = builder.compiler_for(compiler.stage, compiler.host, target);
3533
3534 let build_cargo = || {
3535 let mut cargo = builder::Cargo::new(
3536 builder,
3537 compiler,
3538 Mode::Codegen, SourceType::InTree,
3540 target,
3541 Kind::Run,
3542 );
3543
3544 cargo.current_dir(&builder.src.join("compiler/rustc_codegen_gcc"));
3545 cargo
3546 .arg("--manifest-path")
3547 .arg(builder.src.join("compiler/rustc_codegen_gcc/build_system/Cargo.toml"));
3548 compile::rustc_cargo_env(builder, &mut cargo, target, compiler.stage);
3549
3550 cargo.env("CARGO_BUILD_INCREMENTAL", "false");
3552 cargo.rustflag("-Cpanic=abort");
3553
3554 cargo
3555 };
3556
3557 builder.info(&format!(
3558 "{} GCC stage{} ({} -> {})",
3559 Kind::Test.description(),
3560 compiler.stage,
3561 &compiler.host,
3562 target
3563 ));
3564 let _time = helpers::timeit(builder);
3565
3566 let mut cargo = build_cargo();
3575
3576 cargo
3577 .env("CG_RUSTFLAGS", "-Alinker-messages")
3579 .arg("--")
3580 .arg("test")
3581 .arg("--use-system-gcc")
3582 .arg("--use-backend")
3583 .arg("gcc")
3584 .arg("--out-dir")
3585 .arg(builder.stage_out(compiler, Mode::ToolRustc).join("cg_gcc"))
3586 .arg("--release")
3587 .arg("--mini-tests")
3588 .arg("--std-tests");
3589 cargo.args(builder.config.test_args());
3590
3591 cargo.into_cmd().run(builder);
3592 }
3593}
3594
3595#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3600pub struct TestFloatParse {
3601 path: PathBuf,
3602 host: TargetSelection,
3603}
3604
3605impl Step for TestFloatParse {
3606 type Output = ();
3607 const ONLY_HOSTS: bool = true;
3608 const DEFAULT: bool = true;
3609
3610 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3611 run.path("src/etc/test-float-parse")
3612 }
3613
3614 fn make_run(run: RunConfig<'_>) {
3615 for path in run.paths {
3616 let path = path.assert_single_path().path.clone();
3617 run.builder.ensure(Self { path, host: run.target });
3618 }
3619 }
3620
3621 fn run(self, builder: &Builder<'_>) {
3622 let bootstrap_host = builder.config.build;
3623 let compiler = builder.compiler(builder.top_stage, bootstrap_host);
3624 let path = self.path.to_str().unwrap();
3625 let crate_name = self.path.components().last().unwrap().as_os_str().to_str().unwrap();
3626
3627 builder.ensure(tool::TestFloatParse { host: self.host });
3628
3629 let cargo_test = tool::prepare_tool_cargo(
3631 builder,
3632 compiler,
3633 Mode::ToolStd,
3634 bootstrap_host,
3635 Kind::Test,
3636 path,
3637 SourceType::InTree,
3638 &[],
3639 );
3640
3641 run_cargo_test(cargo_test, &[], &[], crate_name, crate_name, bootstrap_host, builder);
3642
3643 let mut cargo_run = tool::prepare_tool_cargo(
3645 builder,
3646 compiler,
3647 Mode::ToolStd,
3648 bootstrap_host,
3649 Kind::Run,
3650 path,
3651 SourceType::InTree,
3652 &[],
3653 );
3654
3655 if !matches!(env::var("FLOAT_PARSE_TESTS_NO_SKIP_HUGE").as_deref(), Ok("1") | Ok("true")) {
3656 cargo_run.args(["--", "--skip-huge"]);
3657 }
3658
3659 cargo_run.into_cmd().run(builder);
3660 }
3661}
3662
3663#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
3667pub struct CollectLicenseMetadata;
3668
3669impl Step for CollectLicenseMetadata {
3670 type Output = PathBuf;
3671 const ONLY_HOSTS: bool = true;
3672
3673 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3674 run.path("src/tools/collect-license-metadata")
3675 }
3676
3677 fn make_run(run: RunConfig<'_>) {
3678 run.builder.ensure(CollectLicenseMetadata);
3679 }
3680
3681 fn run(self, builder: &Builder<'_>) -> Self::Output {
3682 let Some(reuse) = &builder.config.reuse else {
3683 panic!("REUSE is required to collect the license metadata");
3684 };
3685
3686 let dest = builder.src.join("license-metadata.json");
3687
3688 let mut cmd = builder.tool_cmd(Tool::CollectLicenseMetadata);
3689 cmd.env("REUSE_EXE", reuse);
3690 cmd.env("DEST", &dest);
3691 cmd.env("ONLY_CHECK", "1");
3692 cmd.run(builder);
3693
3694 dest
3695 }
3696}