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::gcc::{Gcc, add_cg_gcc_cargo_flags};
16use crate::core::build_steps::llvm::get_llvm_version;
17use crate::core::build_steps::synthetic_targets::MirOptPanicAbortSyntheticTarget;
18use crate::core::build_steps::tool::{self, COMPILETEST_ALLOW_FEATURES, SourceType, Tool};
19use crate::core::build_steps::toolstate::ToolState;
20use crate::core::build_steps::{compile, dist, llvm};
21use crate::core::builder::{
22 self, Alias, Builder, Compiler, Kind, RunConfig, ShouldRun, Step, crate_description,
23};
24use crate::core::config::TargetSelection;
25use crate::core::config::flags::{Subcommand, get_completion};
26use crate::utils::build_stamp::{self, BuildStamp};
27use crate::utils::exec::{BootstrapCommand, command};
28use crate::utils::helpers::{
29 self, LldThreads, add_rustdoc_cargo_linker_args, dylib_path, dylib_path_var, linker_args,
30 linker_flags, t, target_supports_cranelift_backend, up_to_date,
31};
32use crate::utils::render_tests::{add_flags_and_try_run_tests, try_run_tests};
33use crate::{CLang, DocTests, GitRepo, Mode, PathSet, envify};
34
35const ADB_TEST_DIR: &str = "/data/local/tmp/work";
36
37#[derive(Debug, Clone, PartialEq, Eq, Hash)]
39pub struct CrateBootstrap {
40 path: PathBuf,
41 host: TargetSelection,
42}
43
44impl Step for CrateBootstrap {
45 type Output = ();
46 const ONLY_HOSTS: bool = true;
47 const DEFAULT: bool = true;
48
49 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
50 run.path("src/tools/jsondoclint")
55 .path("src/tools/suggest-tests")
56 .path("src/tools/replace-version-placeholder")
57 .path("src/tools/coverage-dump")
58 .alias("tidyselftest")
61 }
62
63 fn make_run(run: RunConfig<'_>) {
64 for path in run.paths {
67 let path = path.assert_single_path().path.clone();
68 run.builder.ensure(CrateBootstrap { host: run.target, path });
69 }
70 }
71
72 fn run(self, builder: &Builder<'_>) {
73 let bootstrap_host = builder.config.build;
74 let compiler = builder.compiler(0, bootstrap_host);
75 let mut path = self.path.to_str().unwrap();
76
77 if path == "tidyselftest" {
79 path = "src/tools/tidy";
80 }
81
82 let cargo = tool::prepare_tool_cargo(
83 builder,
84 compiler,
85 Mode::ToolBootstrap,
86 bootstrap_host,
87 Kind::Test,
88 path,
89 SourceType::InTree,
90 &[],
91 );
92
93 let crate_name = path.rsplit_once('/').unwrap().1;
94 run_cargo_test(cargo, &[], &[], crate_name, bootstrap_host, builder);
95 }
96}
97
98#[derive(Debug, Clone, PartialEq, Eq, Hash)]
99pub struct Linkcheck {
100 host: TargetSelection,
101}
102
103impl Step for Linkcheck {
104 type Output = ();
105 const ONLY_HOSTS: bool = true;
106 const DEFAULT: bool = true;
107
108 fn run(self, builder: &Builder<'_>) {
113 let host = self.host;
114 let hosts = &builder.hosts;
115 let targets = &builder.targets;
116
117 if (hosts != targets) && !hosts.is_empty() && !targets.is_empty() {
122 panic!(
123 "Linkcheck currently does not support builds with different hosts and targets.
124You can skip linkcheck with --skip src/tools/linkchecker"
125 );
126 }
127
128 builder.info(&format!("Linkcheck ({host})"));
129
130 let bootstrap_host = builder.config.build;
132 let compiler = builder.compiler(0, bootstrap_host);
133
134 let cargo = tool::prepare_tool_cargo(
135 builder,
136 compiler,
137 Mode::ToolBootstrap,
138 bootstrap_host,
139 Kind::Test,
140 "src/tools/linkchecker",
141 SourceType::InTree,
142 &[],
143 );
144 run_cargo_test(cargo, &[], &[], "linkchecker self tests", bootstrap_host, builder);
145
146 if builder.doc_tests == DocTests::No {
147 return;
148 }
149
150 builder.default_doc(&[]);
152
153 let linkchecker = builder.tool_cmd(Tool::Linkchecker);
155
156 let _guard =
158 builder.msg(Kind::Test, compiler.stage, "Linkcheck", bootstrap_host, bootstrap_host);
159 let _time = helpers::timeit(builder);
160 linkchecker.delay_failure().arg(builder.out.join(host).join("doc")).run(builder);
161 }
162
163 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
164 let builder = run.builder;
165 let run = run.path("src/tools/linkchecker");
166 run.default_condition(builder.config.docs)
167 }
168
169 fn make_run(run: RunConfig<'_>) {
170 run.builder.ensure(Linkcheck { host: run.target });
171 }
172}
173
174fn check_if_tidy_is_installed(builder: &Builder<'_>) -> bool {
175 command("tidy").allow_failure().arg("--version").run_capture_stdout(builder).is_success()
176}
177
178#[derive(Debug, Clone, PartialEq, Eq, Hash)]
179pub struct HtmlCheck {
180 target: TargetSelection,
181}
182
183impl Step for HtmlCheck {
184 type Output = ();
185 const DEFAULT: bool = true;
186 const ONLY_HOSTS: bool = true;
187
188 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
189 let builder = run.builder;
190 let run = run.path("src/tools/html-checker");
191 run.lazy_default_condition(Box::new(|| check_if_tidy_is_installed(builder)))
192 }
193
194 fn make_run(run: RunConfig<'_>) {
195 run.builder.ensure(HtmlCheck { target: run.target });
196 }
197
198 fn run(self, builder: &Builder<'_>) {
199 if !check_if_tidy_is_installed(builder) {
200 eprintln!("not running HTML-check tool because `tidy` is missing");
201 eprintln!(
202 "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."
203 );
204 panic!("Cannot run html-check tests");
205 }
206 builder.default_doc(&[]);
208 builder.ensure(crate::core::build_steps::doc::Rustc::new(
209 builder.top_stage,
210 self.target,
211 builder,
212 ));
213
214 builder
215 .tool_cmd(Tool::HtmlChecker)
216 .delay_failure()
217 .arg(builder.doc_out(self.target))
218 .run(builder);
219 }
220}
221
222#[derive(Debug, Clone, PartialEq, Eq, Hash)]
226pub struct Cargotest {
227 stage: u32,
228 host: TargetSelection,
229}
230
231impl Step for Cargotest {
232 type Output = ();
233 const ONLY_HOSTS: bool = true;
234
235 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
236 run.path("src/tools/cargotest")
237 }
238
239 fn make_run(run: RunConfig<'_>) {
240 run.builder.ensure(Cargotest { stage: run.builder.top_stage, host: run.target });
241 }
242
243 fn run(self, builder: &Builder<'_>) {
248 let compiler = builder.compiler(self.stage, self.host);
249 builder.ensure(compile::Rustc::new(compiler, compiler.host));
250 let cargo = builder.ensure(tool::Cargo { compiler, target: compiler.host });
251
252 let out_dir = builder.out.join("ct");
256 t!(fs::create_dir_all(&out_dir));
257
258 let _time = helpers::timeit(builder);
259 let mut cmd = builder.tool_cmd(Tool::CargoTest);
260 cmd.arg(&cargo.tool_path)
261 .arg(&out_dir)
262 .args(builder.config.test_args())
263 .env("RUSTC", builder.rustc(compiler))
264 .env("RUSTDOC", builder.rustdoc(compiler));
265 add_rustdoc_cargo_linker_args(&mut cmd, builder, compiler.host, LldThreads::No);
266 cmd.delay_failure().run(builder);
267 }
268}
269
270#[derive(Debug, Clone, PartialEq, Eq, Hash)]
272pub struct Cargo {
273 stage: u32,
274 host: TargetSelection,
275}
276
277impl Cargo {
278 const CRATE_PATH: &str = "src/tools/cargo";
279}
280
281impl Step for Cargo {
282 type Output = ();
283 const ONLY_HOSTS: bool = true;
284
285 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
286 run.path(Self::CRATE_PATH)
287 }
288
289 fn make_run(run: RunConfig<'_>) {
290 let stage = if run.builder.config.is_explicit_stage() || run.builder.top_stage >= 2 {
293 run.builder.top_stage
294 } else {
295 2
296 };
297
298 run.builder.ensure(Cargo { stage, host: run.target });
299 }
300
301 fn run(self, builder: &Builder<'_>) {
303 let stage = self.stage;
304
305 if stage < 2 {
306 eprintln!("WARNING: cargo tests on stage {stage} may not behave well.");
307 eprintln!("HELP: consider using stage 2");
308 }
309
310 let compiler = builder.compiler(stage, self.host);
311
312 let cargo = builder.ensure(tool::Cargo { compiler, target: self.host });
313 let compiler = cargo.build_compiler;
314
315 let cargo = tool::prepare_tool_cargo(
316 builder,
317 compiler,
318 Mode::ToolRustc,
319 self.host,
320 Kind::Test,
321 Self::CRATE_PATH,
322 SourceType::Submodule,
323 &[],
324 );
325
326 let mut cargo = prepare_cargo_test(cargo, &[], &[], self.host, builder);
328
329 cargo.env("CFG_DISABLE_CROSS_TESTS", "1");
332 cargo.env("CARGO_TEST_DISABLE_NIGHTLY", "1");
335 cargo.env("PATH", path_for_cargo(builder, compiler));
336 cargo.env("CARGO_RUSTC_CURRENT_DIR", builder.src.display().to_string());
340
341 #[cfg(feature = "build-metrics")]
342 builder.metrics.begin_test_suite(
343 build_helper::metrics::TestSuiteMetadata::CargoPackage {
344 crates: vec!["cargo".into()],
345 target: self.host.triple.to_string(),
346 host: self.host.triple.to_string(),
347 stage,
348 },
349 builder,
350 );
351
352 let _time = helpers::timeit(builder);
353 add_flags_and_try_run_tests(builder, &mut cargo);
354 }
355}
356
357#[derive(Debug, Clone, PartialEq, Eq, Hash)]
358pub struct RustAnalyzer {
359 stage: u32,
360 host: TargetSelection,
361}
362
363impl Step for RustAnalyzer {
364 type Output = ();
365 const ONLY_HOSTS: bool = true;
366 const DEFAULT: bool = true;
367
368 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
369 run.path("src/tools/rust-analyzer")
370 }
371
372 fn make_run(run: RunConfig<'_>) {
373 run.builder.ensure(Self { stage: run.builder.top_stage, host: run.target });
374 }
375
376 fn run(self, builder: &Builder<'_>) {
378 let stage = self.stage;
379 let host = self.host;
380 let compiler = builder.compiler(stage, host);
381 let compiler = tool::get_tool_rustc_compiler(builder, compiler);
382
383 builder.ensure(compile::Rustc::new(compiler, host));
386
387 let workspace_path = "src/tools/rust-analyzer";
388 let crate_path = "src/tools/rust-analyzer/crates/proc-macro-srv";
391 let mut cargo = tool::prepare_tool_cargo(
392 builder,
393 compiler,
394 Mode::ToolRustc,
395 host,
396 Kind::Test,
397 crate_path,
398 SourceType::InTree,
399 &["in-rust-tree".to_owned()],
400 );
401 cargo.allow_features(tool::RustAnalyzer::ALLOW_FEATURES);
402
403 let dir = builder.src.join(workspace_path);
404 cargo.env("CARGO_WORKSPACE_DIR", &dir);
407
408 cargo.env("SKIP_SLOW_TESTS", "1");
411
412 cargo.add_rustc_lib_path(builder);
413 run_cargo_test(cargo, &[], &[], "rust-analyzer", host, builder);
414 }
415}
416
417#[derive(Debug, Clone, PartialEq, Eq, Hash)]
419pub struct Rustfmt {
420 stage: u32,
421 host: TargetSelection,
422}
423
424impl Step for Rustfmt {
425 type Output = ();
426 const ONLY_HOSTS: bool = true;
427
428 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
429 run.path("src/tools/rustfmt")
430 }
431
432 fn make_run(run: RunConfig<'_>) {
433 run.builder.ensure(Rustfmt { stage: run.builder.top_stage, host: run.target });
434 }
435
436 fn run(self, builder: &Builder<'_>) {
438 let stage = self.stage;
439 let host = self.host;
440 let compiler = builder.compiler(stage, host);
441
442 let tool_result = builder.ensure(tool::Rustfmt { compiler, target: self.host });
443 let compiler = tool_result.build_compiler;
444
445 let mut cargo = tool::prepare_tool_cargo(
446 builder,
447 compiler,
448 Mode::ToolRustc,
449 host,
450 Kind::Test,
451 "src/tools/rustfmt",
452 SourceType::InTree,
453 &[],
454 );
455
456 let dir = testdir(builder, compiler.host);
457 t!(fs::create_dir_all(&dir));
458 cargo.env("RUSTFMT_TEST_DIR", dir);
459
460 cargo.add_rustc_lib_path(builder);
461
462 run_cargo_test(cargo, &[], &[], "rustfmt", host, builder);
463 }
464}
465
466#[derive(Debug, Clone, PartialEq, Eq, Hash)]
467pub struct Miri {
468 target: TargetSelection,
469}
470
471impl Miri {
472 pub fn build_miri_sysroot(
474 builder: &Builder<'_>,
475 compiler: Compiler,
476 target: TargetSelection,
477 ) -> PathBuf {
478 let miri_sysroot = builder.out.join(compiler.host).join("miri-sysroot");
479 let mut cargo = builder::Cargo::new(
480 builder,
481 compiler,
482 Mode::Std,
483 SourceType::Submodule,
484 target,
485 Kind::MiriSetup,
486 );
487
488 cargo.env("MIRI_LIB_SRC", builder.src.join("library"));
490 cargo.env("MIRI_SYSROOT", &miri_sysroot);
492
493 let mut cargo = BootstrapCommand::from(cargo);
494 let _guard =
495 builder.msg(Kind::Build, compiler.stage, "miri sysroot", compiler.host, target);
496 cargo.run(builder);
497
498 cargo.arg("--print-sysroot");
504
505 builder.verbose(|| println!("running: {cargo:?}"));
506 let stdout = cargo.run_capture_stdout(builder).stdout();
507 let sysroot = stdout.trim_end();
509 builder.verbose(|| println!("`cargo miri setup --print-sysroot` said: {sysroot:?}"));
510 PathBuf::from(sysroot)
511 }
512}
513
514impl Step for Miri {
515 type Output = ();
516 const ONLY_HOSTS: bool = false;
517
518 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
519 run.path("src/tools/miri")
520 }
521
522 fn make_run(run: RunConfig<'_>) {
523 run.builder.ensure(Miri { target: run.target });
524 }
525
526 fn run(self, builder: &Builder<'_>) {
528 let host = builder.build.build;
529 let target = self.target;
530 let stage = builder.top_stage;
531 if stage == 0 {
532 eprintln!("miri cannot be tested at stage 0");
533 std::process::exit(1);
534 }
535
536 let target_compiler = builder.compiler(stage, host);
538
539 let miri = builder.ensure(tool::Miri { compiler: target_compiler, target: host });
541 builder.ensure(tool::CargoMiri { compiler: target_compiler, target: host });
543
544 let miri_sysroot = Miri::build_miri_sysroot(builder, target_compiler, target);
547 builder.ensure(compile::Std::new(target_compiler, host));
548 let host_sysroot = builder.sysroot(target_compiler);
549
550 if !builder.config.dry_run() {
553 let ui_test_dep_dir =
554 builder.stage_out(miri.build_compiler, Mode::ToolStd).join("miri_ui");
555 build_stamp::clear_if_dirty(builder, &ui_test_dep_dir, &miri_sysroot);
559 }
560
561 let mut cargo = tool::prepare_tool_cargo(
564 builder,
565 miri.build_compiler,
566 Mode::ToolRustc,
567 host,
568 Kind::Test,
569 "src/tools/miri",
570 SourceType::InTree,
571 &[],
572 );
573
574 cargo.add_rustc_lib_path(builder);
575
576 let mut cargo = prepare_cargo_test(cargo, &[], &[], host, builder);
579
580 cargo.env("MIRI_SYSROOT", &miri_sysroot);
582 cargo.env("MIRI_HOST_SYSROOT", &host_sysroot);
583 cargo.env("MIRI", &miri.tool_path);
584
585 cargo.env("MIRI_TEST_TARGET", target.rustc_target_arg());
587
588 {
589 let _guard = builder.msg_sysroot_tool(Kind::Test, stage, "miri", host, target);
590 let _time = helpers::timeit(builder);
591 cargo.run(builder);
592 }
593
594 if builder.config.test_args().is_empty() {
596 cargo.env("MIRIFLAGS", "-O -Zmir-opt-level=4 -Cdebug-assertions=yes");
597 cargo.env("MIRI_SKIP_UI_CHECKS", "1");
599 cargo.env_remove("RUSTC_BLESS");
601 cargo.args(["tests/pass", "tests/panic"]);
603
604 {
605 let _guard = builder.msg_sysroot_tool(
606 Kind::Test,
607 stage,
608 "miri (mir-opt-level 4)",
609 host,
610 target,
611 );
612 let _time = helpers::timeit(builder);
613 cargo.run(builder);
614 }
615 }
616 }
617}
618
619#[derive(Debug, Clone, PartialEq, Eq, Hash)]
622pub struct CargoMiri {
623 target: TargetSelection,
624}
625
626impl Step for CargoMiri {
627 type Output = ();
628 const ONLY_HOSTS: bool = false;
629
630 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
631 run.path("src/tools/miri/cargo-miri")
632 }
633
634 fn make_run(run: RunConfig<'_>) {
635 run.builder.ensure(CargoMiri { target: run.target });
636 }
637
638 fn run(self, builder: &Builder<'_>) {
640 let host = builder.build.build;
641 let target = self.target;
642 let stage = builder.top_stage;
643 if stage == 0 {
644 eprintln!("cargo-miri cannot be tested at stage 0");
645 std::process::exit(1);
646 }
647
648 let compiler = builder.compiler(stage, host);
650
651 let mut cargo = tool::prepare_tool_cargo(
656 builder,
657 compiler,
658 Mode::ToolStd, target,
660 Kind::MiriTest,
661 "src/tools/miri/test-cargo-miri",
662 SourceType::Submodule,
663 &[],
664 );
665
666 match builder.doc_tests {
669 DocTests::Yes => {}
670 DocTests::No => {
671 cargo.args(["--lib", "--bins", "--examples", "--tests", "--benches"]);
672 }
673 DocTests::Only => {
674 cargo.arg("--doc");
675 }
676 }
677
678 cargo.arg("--").args(builder.config.test_args());
680 let mut cargo = BootstrapCommand::from(cargo);
681 {
682 let _guard = builder.msg_sysroot_tool(Kind::Test, stage, "cargo-miri", host, target);
683 let _time = helpers::timeit(builder);
684 cargo.run(builder);
685 }
686 }
687}
688
689#[derive(Debug, Clone, PartialEq, Eq, Hash)]
690pub struct CompiletestTest {
691 host: TargetSelection,
692}
693
694impl Step for CompiletestTest {
695 type Output = ();
696
697 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
698 run.path("src/tools/compiletest")
699 }
700
701 fn make_run(run: RunConfig<'_>) {
702 run.builder.ensure(CompiletestTest { host: run.target });
703 }
704
705 fn run(self, builder: &Builder<'_>) {
707 let host = self.host;
708 let compiler = builder.compiler(builder.top_stage, host);
709
710 builder.ensure(compile::Std::new(compiler, host));
713 let mut cargo = tool::prepare_tool_cargo(
714 builder,
715 compiler,
716 Mode::ToolStd,
719 host,
720 Kind::Test,
721 "src/tools/compiletest",
722 SourceType::InTree,
723 &[],
724 );
725 cargo.allow_features(COMPILETEST_ALLOW_FEATURES);
726 run_cargo_test(cargo, &[], &[], "compiletest self test", host, builder);
727 }
728}
729
730#[derive(Debug, Clone, PartialEq, Eq, Hash)]
731pub struct Clippy {
732 stage: u32,
733 host: TargetSelection,
734}
735
736impl Step for Clippy {
737 type Output = ();
738 const ONLY_HOSTS: bool = true;
739 const DEFAULT: bool = false;
740
741 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
742 run.suite_path("src/tools/clippy/tests").path("src/tools/clippy")
743 }
744
745 fn make_run(run: RunConfig<'_>) {
746 let stage = if run.builder.config.is_explicit_stage() || run.builder.top_stage >= 2 {
749 run.builder.top_stage
750 } else {
751 2
752 };
753
754 run.builder.ensure(Clippy { stage, host: run.target });
755 }
756
757 fn run(self, builder: &Builder<'_>) {
759 let stage = self.stage;
760 let host = self.host;
761 let compiler = builder.compiler(stage, host);
762
763 if stage < 2 {
764 eprintln!("WARNING: clippy tests on stage {stage} may not behave well.");
765 eprintln!("HELP: consider using stage 2");
766 }
767
768 let tool_result = builder.ensure(tool::Clippy { compiler, target: self.host });
769 let compiler = tool_result.build_compiler;
770 let mut cargo = tool::prepare_tool_cargo(
771 builder,
772 compiler,
773 Mode::ToolRustc,
774 host,
775 Kind::Test,
776 "src/tools/clippy",
777 SourceType::InTree,
778 &[],
779 );
780
781 cargo.env("RUSTC_TEST_SUITE", builder.rustc(compiler));
782 cargo.env("RUSTC_LIB_PATH", builder.rustc_libdir(compiler));
783 let host_libs = builder.stage_out(compiler, Mode::ToolRustc).join(builder.cargo_dir());
784 cargo.env("HOST_LIBS", host_libs);
785
786 'partially_test: {
788 let paths = &builder.config.paths[..];
789 let mut test_names = Vec::new();
790 for path in paths {
791 if let Some(path) =
792 helpers::is_valid_test_suite_arg(path, "src/tools/clippy/tests", builder)
793 {
794 test_names.push(path);
795 } else if path.ends_with("src/tools/clippy") {
796 break 'partially_test;
798 }
799 }
800 cargo.env("TESTNAME", test_names.join(","));
801 }
802
803 cargo.add_rustc_lib_path(builder);
804 let cargo = prepare_cargo_test(cargo, &[], &[], host, builder);
805
806 let _guard = builder.msg_sysroot_tool(Kind::Test, compiler.stage, "clippy", host, host);
807
808 if cargo.allow_failure().run(builder) {
810 return;
812 }
813
814 if !builder.config.cmd.bless() {
815 crate::exit!(1);
816 }
817 }
818}
819
820fn path_for_cargo(builder: &Builder<'_>, compiler: Compiler) -> OsString {
821 let path = builder.sysroot(compiler).join("bin");
825 let old_path = env::var_os("PATH").unwrap_or_default();
826 env::join_paths(iter::once(path).chain(env::split_paths(&old_path))).expect("")
827}
828
829#[derive(Debug, Clone, Hash, PartialEq, Eq)]
830pub struct RustdocTheme {
831 pub compiler: Compiler,
832}
833
834impl Step for RustdocTheme {
835 type Output = ();
836 const DEFAULT: bool = true;
837 const ONLY_HOSTS: bool = true;
838
839 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
840 run.path("src/tools/rustdoc-themes")
841 }
842
843 fn make_run(run: RunConfig<'_>) {
844 let compiler = run.builder.compiler(run.builder.top_stage, run.target);
845
846 run.builder.ensure(RustdocTheme { compiler });
847 }
848
849 fn run(self, builder: &Builder<'_>) {
850 let rustdoc = builder.bootstrap_out.join("rustdoc");
851 let mut cmd = builder.tool_cmd(Tool::RustdocTheme);
852 cmd.arg(rustdoc.to_str().unwrap())
853 .arg(builder.src.join("src/librustdoc/html/static/css/rustdoc.css").to_str().unwrap())
854 .env("RUSTC_STAGE", self.compiler.stage.to_string())
855 .env("RUSTC_SYSROOT", builder.sysroot(self.compiler))
856 .env("RUSTDOC_LIBDIR", builder.sysroot_target_libdir(self.compiler, self.compiler.host))
857 .env("CFG_RELEASE_CHANNEL", &builder.config.channel)
858 .env("RUSTDOC_REAL", builder.rustdoc(self.compiler))
859 .env("RUSTC_BOOTSTRAP", "1");
860 cmd.args(linker_args(builder, self.compiler.host, LldThreads::No));
861
862 cmd.delay_failure().run(builder);
863 }
864}
865
866#[derive(Debug, Clone, Hash, PartialEq, Eq)]
867pub struct RustdocJSStd {
868 pub target: TargetSelection,
869}
870
871impl Step for RustdocJSStd {
872 type Output = ();
873 const DEFAULT: bool = true;
874 const ONLY_HOSTS: bool = true;
875
876 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
877 let default = run.builder.config.nodejs.is_some();
878 run.suite_path("tests/rustdoc-js-std").default_condition(default)
879 }
880
881 fn make_run(run: RunConfig<'_>) {
882 run.builder.ensure(RustdocJSStd { target: run.target });
883 }
884
885 fn run(self, builder: &Builder<'_>) {
886 let nodejs =
887 builder.config.nodejs.as_ref().expect("need nodejs to run rustdoc-js-std tests");
888 let mut command = command(nodejs);
889 command
890 .arg(builder.src.join("src/tools/rustdoc-js/tester.js"))
891 .arg("--crate-name")
892 .arg("std")
893 .arg("--resource-suffix")
894 .arg(&builder.version)
895 .arg("--doc-folder")
896 .arg(builder.doc_out(self.target))
897 .arg("--test-folder")
898 .arg(builder.src.join("tests/rustdoc-js-std"));
899 for path in &builder.paths {
900 if let Some(p) = helpers::is_valid_test_suite_arg(path, "tests/rustdoc-js-std", builder)
901 {
902 if !p.ends_with(".js") {
903 eprintln!("A non-js file was given: `{}`", path.display());
904 panic!("Cannot run rustdoc-js-std tests");
905 }
906 command.arg("--test-file").arg(path);
907 }
908 }
909 builder.ensure(crate::core::build_steps::doc::Std::new(
910 builder.top_stage,
911 self.target,
912 DocumentationFormat::Html,
913 ));
914 let _guard = builder.msg(
915 Kind::Test,
916 builder.top_stage,
917 "rustdoc-js-std",
918 builder.config.build,
919 self.target,
920 );
921 command.run(builder);
922 }
923}
924
925#[derive(Debug, Clone, Hash, PartialEq, Eq)]
926pub struct RustdocJSNotStd {
927 pub target: TargetSelection,
928 pub compiler: Compiler,
929}
930
931impl Step for RustdocJSNotStd {
932 type Output = ();
933 const DEFAULT: bool = true;
934 const ONLY_HOSTS: bool = true;
935
936 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
937 let default = run.builder.config.nodejs.is_some();
938 run.suite_path("tests/rustdoc-js").default_condition(default)
939 }
940
941 fn make_run(run: RunConfig<'_>) {
942 let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
943 run.builder.ensure(RustdocJSNotStd { target: run.target, compiler });
944 }
945
946 fn run(self, builder: &Builder<'_>) {
947 builder.ensure(Compiletest {
948 compiler: self.compiler,
949 target: self.target,
950 mode: "rustdoc-js",
951 suite: "rustdoc-js",
952 path: "tests/rustdoc-js",
953 compare_mode: None,
954 });
955 }
956}
957
958fn get_browser_ui_test_version_inner(
959 builder: &Builder<'_>,
960 npm: &Path,
961 global: bool,
962) -> Option<String> {
963 let mut command = command(npm);
964 command.arg("list").arg("--parseable").arg("--long").arg("--depth=0");
965 if global {
966 command.arg("--global");
967 }
968 let lines = command.allow_failure().run_capture(builder).stdout();
969 lines
970 .lines()
971 .find_map(|l| l.split(':').nth(1)?.strip_prefix("browser-ui-test@"))
972 .map(|v| v.to_owned())
973}
974
975fn get_browser_ui_test_version(builder: &Builder<'_>, npm: &Path) -> Option<String> {
976 get_browser_ui_test_version_inner(builder, npm, false)
977 .or_else(|| get_browser_ui_test_version_inner(builder, npm, true))
978}
979
980#[derive(Debug, Clone, Hash, PartialEq, Eq)]
981pub struct RustdocGUI {
982 pub target: TargetSelection,
983 pub compiler: Compiler,
984}
985
986impl Step for RustdocGUI {
987 type Output = ();
988 const DEFAULT: bool = true;
989 const ONLY_HOSTS: bool = true;
990
991 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
992 let builder = run.builder;
993 let run = run.suite_path("tests/rustdoc-gui");
994 run.lazy_default_condition(Box::new(move || {
995 builder.config.nodejs.is_some()
996 && builder.doc_tests != DocTests::Only
997 && builder
998 .config
999 .npm
1000 .as_ref()
1001 .map(|p| get_browser_ui_test_version(builder, p).is_some())
1002 .unwrap_or(false)
1003 }))
1004 }
1005
1006 fn make_run(run: RunConfig<'_>) {
1007 let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1008 run.builder.ensure(RustdocGUI { target: run.target, compiler });
1009 }
1010
1011 fn run(self, builder: &Builder<'_>) {
1012 builder.ensure(compile::Std::new(self.compiler, self.target));
1013
1014 let mut cmd = builder.tool_cmd(Tool::RustdocGUITest);
1015
1016 let out_dir = builder.test_out(self.target).join("rustdoc-gui");
1017 build_stamp::clear_if_dirty(builder, &out_dir, &builder.rustdoc(self.compiler));
1018
1019 if let Some(src) = builder.config.src.to_str() {
1020 cmd.arg("--rust-src").arg(src);
1021 }
1022
1023 if let Some(out_dir) = out_dir.to_str() {
1024 cmd.arg("--out-dir").arg(out_dir);
1025 }
1026
1027 if let Some(initial_cargo) = builder.config.initial_cargo.to_str() {
1028 cmd.arg("--initial-cargo").arg(initial_cargo);
1029 }
1030
1031 cmd.arg("--jobs").arg(builder.jobs().to_string());
1032
1033 cmd.env("RUSTDOC", builder.rustdoc(self.compiler))
1034 .env("RUSTC", builder.rustc(self.compiler));
1035
1036 add_rustdoc_cargo_linker_args(&mut cmd, builder, self.compiler.host, LldThreads::No);
1037
1038 for path in &builder.paths {
1039 if let Some(p) = helpers::is_valid_test_suite_arg(path, "tests/rustdoc-gui", builder) {
1040 if !p.ends_with(".goml") {
1041 eprintln!("A non-goml file was given: `{}`", path.display());
1042 panic!("Cannot run rustdoc-gui tests");
1043 }
1044 if let Some(name) = path.file_name().and_then(|f| f.to_str()) {
1045 cmd.arg("--goml-file").arg(name);
1046 }
1047 }
1048 }
1049
1050 for test_arg in builder.config.test_args() {
1051 cmd.arg("--test-arg").arg(test_arg);
1052 }
1053
1054 if let Some(ref nodejs) = builder.config.nodejs {
1055 cmd.arg("--nodejs").arg(nodejs);
1056 }
1057
1058 if let Some(ref npm) = builder.config.npm {
1059 cmd.arg("--npm").arg(npm);
1060 }
1061
1062 let _time = helpers::timeit(builder);
1063 let _guard = builder.msg_sysroot_tool(
1064 Kind::Test,
1065 self.compiler.stage,
1066 "rustdoc-gui",
1067 self.compiler.host,
1068 self.target,
1069 );
1070 try_run_tests(builder, &mut cmd, true);
1071 }
1072}
1073
1074#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1079pub struct Tidy;
1080
1081impl Step for Tidy {
1082 type Output = ();
1083 const DEFAULT: bool = true;
1084 const ONLY_HOSTS: bool = true;
1085
1086 fn run(self, builder: &Builder<'_>) {
1095 let mut cmd = builder.tool_cmd(Tool::Tidy);
1096 cmd.arg(&builder.src);
1097 cmd.arg(&builder.initial_cargo);
1098 cmd.arg(&builder.out);
1099 let jobs = builder.config.jobs.unwrap_or_else(|| {
1101 8 * std::thread::available_parallelism().map_or(1, std::num::NonZeroUsize::get) as u32
1102 });
1103 cmd.arg(jobs.to_string());
1104 if builder.is_verbose() {
1105 cmd.arg("--verbose");
1106 }
1107 if builder.config.cmd.bless() {
1108 cmd.arg("--bless");
1109 }
1110 if let Some(s) = builder.config.cmd.extra_checks() {
1111 cmd.arg(format!("--extra-checks={s}"));
1112 }
1113 let mut args = std::env::args_os();
1114 if args.any(|arg| arg == OsStr::new("--")) {
1115 cmd.arg("--");
1116 cmd.args(args);
1117 }
1118
1119 if builder.config.channel == "dev" || builder.config.channel == "nightly" {
1120 if !builder.config.json_output {
1121 builder.info("fmt check");
1122 if builder.config.initial_rustfmt.is_none() {
1123 let inferred_rustfmt_dir = builder.initial_sysroot.join("bin");
1124 eprintln!(
1125 "\
1126ERROR: no `rustfmt` binary found in {PATH}
1127INFO: `rust.channel` is currently set to \"{CHAN}\"
1128HELP: if you are testing a beta branch, set `rust.channel` to \"beta\" in the `bootstrap.toml` file
1129HELP: to skip test's attempt to check tidiness, pass `--skip src/tools/tidy` to `x.py test`",
1130 PATH = inferred_rustfmt_dir.display(),
1131 CHAN = builder.config.channel,
1132 );
1133 crate::exit!(1);
1134 }
1135 let all = false;
1136 crate::core::build_steps::format::format(
1137 builder,
1138 !builder.config.cmd.bless(),
1139 all,
1140 &[],
1141 );
1142 } else {
1143 eprintln!(
1144 "WARNING: `--json-output` is not supported on rustfmt, formatting will be skipped"
1145 );
1146 }
1147 }
1148
1149 builder.info("tidy check");
1150 cmd.delay_failure().run(builder);
1151
1152 builder.info("x.py completions check");
1153 let [bash, zsh, fish, powershell] = ["x.py.sh", "x.py.zsh", "x.py.fish", "x.py.ps1"]
1154 .map(|filename| builder.src.join("src/etc/completions").join(filename));
1155 if builder.config.cmd.bless() {
1156 builder.ensure(crate::core::build_steps::run::GenerateCompletions);
1157 } else if get_completion(shells::Bash, &bash).is_some()
1158 || get_completion(shells::Fish, &fish).is_some()
1159 || get_completion(shells::PowerShell, &powershell).is_some()
1160 || crate::flags::get_completion(shells::Zsh, &zsh).is_some()
1161 {
1162 eprintln!(
1163 "x.py completions were changed; run `x.py run generate-completions` to update them"
1164 );
1165 crate::exit!(1);
1166 }
1167 }
1168
1169 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1170 let default = run.builder.doc_tests != DocTests::Only;
1171 run.path("src/tools/tidy").default_condition(default)
1172 }
1173
1174 fn make_run(run: RunConfig<'_>) {
1175 run.builder.ensure(Tidy);
1176 }
1177}
1178
1179fn testdir(builder: &Builder<'_>, host: TargetSelection) -> PathBuf {
1180 builder.out.join(host).join("test")
1181}
1182
1183macro_rules! test {
1185 (
1186 $( #[$attr:meta] )* $name:ident {
1188 path: $path:expr,
1189 mode: $mode:expr,
1190 suite: $suite:expr,
1191 default: $default:expr
1192 $( , only_hosts: $only_hosts:expr )? $( , compare_mode: $compare_mode:expr )? $( , )? }
1196 ) => {
1197 $( #[$attr] )*
1198 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
1199 pub struct $name {
1200 pub compiler: Compiler,
1201 pub target: TargetSelection,
1202 }
1203
1204 impl Step for $name {
1205 type Output = ();
1206 const DEFAULT: bool = $default;
1207 const ONLY_HOSTS: bool = (const {
1208 #[allow(unused_assignments, unused_mut)]
1209 let mut value = false;
1210 $( value = $only_hosts; )?
1211 value
1212 });
1213
1214 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1215 run.suite_path($path)
1216 }
1217
1218 fn make_run(run: RunConfig<'_>) {
1219 let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1220
1221 run.builder.ensure($name { compiler, target: run.target });
1222 }
1223
1224 fn run(self, builder: &Builder<'_>) {
1225 builder.ensure(Compiletest {
1226 compiler: self.compiler,
1227 target: self.target,
1228 mode: $mode,
1229 suite: $suite,
1230 path: $path,
1231 compare_mode: (const {
1232 #[allow(unused_assignments, unused_mut)]
1233 let mut value = None;
1234 $( value = $compare_mode; )?
1235 value
1236 }),
1237 })
1238 }
1239 }
1240 };
1241}
1242
1243#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1246pub struct CrateRunMakeSupport {
1247 host: TargetSelection,
1248}
1249
1250impl Step for CrateRunMakeSupport {
1251 type Output = ();
1252 const ONLY_HOSTS: bool = true;
1253
1254 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1255 run.path("src/tools/run-make-support")
1256 }
1257
1258 fn make_run(run: RunConfig<'_>) {
1259 run.builder.ensure(CrateRunMakeSupport { host: run.target });
1260 }
1261
1262 fn run(self, builder: &Builder<'_>) {
1264 let host = self.host;
1265 let compiler = builder.compiler(0, host);
1266
1267 let mut cargo = tool::prepare_tool_cargo(
1268 builder,
1269 compiler,
1270 Mode::ToolBootstrap,
1271 host,
1272 Kind::Test,
1273 "src/tools/run-make-support",
1274 SourceType::InTree,
1275 &[],
1276 );
1277 cargo.allow_features("test");
1278 run_cargo_test(cargo, &[], &[], "run-make-support self test", host, builder);
1279 }
1280}
1281
1282#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1283pub struct CrateBuildHelper {
1284 host: TargetSelection,
1285}
1286
1287impl Step for CrateBuildHelper {
1288 type Output = ();
1289 const ONLY_HOSTS: bool = true;
1290
1291 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1292 run.path("src/build_helper")
1293 }
1294
1295 fn make_run(run: RunConfig<'_>) {
1296 run.builder.ensure(CrateBuildHelper { host: run.target });
1297 }
1298
1299 fn run(self, builder: &Builder<'_>) {
1301 let host = self.host;
1302 let compiler = builder.compiler(0, host);
1303
1304 let mut cargo = tool::prepare_tool_cargo(
1305 builder,
1306 compiler,
1307 Mode::ToolBootstrap,
1308 host,
1309 Kind::Test,
1310 "src/build_helper",
1311 SourceType::InTree,
1312 &[],
1313 );
1314 cargo.allow_features("test");
1315 run_cargo_test(cargo, &[], &[], "build_helper self test", host, builder);
1316 }
1317}
1318
1319test!(Ui { path: "tests/ui", mode: "ui", suite: "ui", default: true });
1320
1321test!(Crashes { path: "tests/crashes", mode: "crashes", suite: "crashes", default: true });
1322
1323test!(Codegen { path: "tests/codegen", mode: "codegen", suite: "codegen", default: true });
1324
1325test!(CodegenUnits {
1326 path: "tests/codegen-units",
1327 mode: "codegen-units",
1328 suite: "codegen-units",
1329 default: true,
1330});
1331
1332test!(Incremental {
1333 path: "tests/incremental",
1334 mode: "incremental",
1335 suite: "incremental",
1336 default: true,
1337});
1338
1339test!(Debuginfo {
1340 path: "tests/debuginfo",
1341 mode: "debuginfo",
1342 suite: "debuginfo",
1343 default: true,
1344 compare_mode: Some("split-dwarf"),
1345});
1346
1347test!(UiFullDeps {
1348 path: "tests/ui-fulldeps",
1349 mode: "ui",
1350 suite: "ui-fulldeps",
1351 default: true,
1352 only_hosts: true,
1353});
1354
1355test!(Rustdoc {
1356 path: "tests/rustdoc",
1357 mode: "rustdoc",
1358 suite: "rustdoc",
1359 default: true,
1360 only_hosts: true,
1361});
1362test!(RustdocUi {
1363 path: "tests/rustdoc-ui",
1364 mode: "ui",
1365 suite: "rustdoc-ui",
1366 default: true,
1367 only_hosts: true,
1368});
1369
1370test!(RustdocJson {
1371 path: "tests/rustdoc-json",
1372 mode: "rustdoc-json",
1373 suite: "rustdoc-json",
1374 default: true,
1375 only_hosts: true,
1376});
1377
1378test!(Pretty {
1379 path: "tests/pretty",
1380 mode: "pretty",
1381 suite: "pretty",
1382 default: true,
1383 only_hosts: true,
1384});
1385
1386test!(RunMake { path: "tests/run-make", mode: "run-make", suite: "run-make", default: true });
1387
1388test!(Assembly { path: "tests/assembly", mode: "assembly", suite: "assembly", default: true });
1389
1390#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
1393pub struct Coverage {
1394 pub compiler: Compiler,
1395 pub target: TargetSelection,
1396 pub mode: &'static str,
1397}
1398
1399impl Coverage {
1400 const PATH: &'static str = "tests/coverage";
1401 const SUITE: &'static str = "coverage";
1402 const ALL_MODES: &[&str] = &["coverage-map", "coverage-run"];
1403}
1404
1405impl Step for Coverage {
1406 type Output = ();
1407 const DEFAULT: bool = true;
1408 const ONLY_HOSTS: bool = false;
1410
1411 fn should_run(mut run: ShouldRun<'_>) -> ShouldRun<'_> {
1412 run = run.suite_path(Self::PATH);
1418 for mode in Self::ALL_MODES {
1419 run = run.alias(mode);
1420 }
1421 run
1422 }
1423
1424 fn make_run(run: RunConfig<'_>) {
1425 let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1426 let target = run.target;
1427
1428 let mut modes = vec![];
1432
1433 for path in &run.paths {
1436 match path {
1437 PathSet::Set(_) => {
1438 for mode in Self::ALL_MODES {
1439 if path.assert_single_path().path == Path::new(mode) {
1440 modes.push(mode);
1441 break;
1442 }
1443 }
1444 }
1445 PathSet::Suite(_) => {
1446 modes.extend(Self::ALL_MODES);
1447 break;
1448 }
1449 }
1450 }
1451
1452 modes.retain(|mode| !run.builder.config.skip.iter().any(|skip| skip == Path::new(mode)));
1455
1456 for mode in modes {
1464 run.builder.ensure(Coverage { compiler, target, mode });
1465 }
1466 }
1467
1468 fn run(self, builder: &Builder<'_>) {
1469 let Self { compiler, target, mode } = self;
1470 builder.ensure(Compiletest {
1473 compiler,
1474 target,
1475 mode,
1476 suite: Self::SUITE,
1477 path: Self::PATH,
1478 compare_mode: None,
1479 });
1480 }
1481}
1482
1483test!(CoverageRunRustdoc {
1484 path: "tests/coverage-run-rustdoc",
1485 mode: "coverage-run",
1486 suite: "coverage-run-rustdoc",
1487 default: true,
1488 only_hosts: true,
1489});
1490
1491#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1493pub struct MirOpt {
1494 pub compiler: Compiler,
1495 pub target: TargetSelection,
1496}
1497
1498impl Step for MirOpt {
1499 type Output = ();
1500 const DEFAULT: bool = true;
1501 const ONLY_HOSTS: bool = false;
1502
1503 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1504 run.suite_path("tests/mir-opt")
1505 }
1506
1507 fn make_run(run: RunConfig<'_>) {
1508 let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1509 run.builder.ensure(MirOpt { compiler, target: run.target });
1510 }
1511
1512 fn run(self, builder: &Builder<'_>) {
1513 let run = |target| {
1514 builder.ensure(Compiletest {
1515 compiler: self.compiler,
1516 target,
1517 mode: "mir-opt",
1518 suite: "mir-opt",
1519 path: "tests/mir-opt",
1520 compare_mode: None,
1521 })
1522 };
1523
1524 run(self.target);
1525
1526 if builder.config.cmd.bless() {
1529 for target in ["aarch64-unknown-linux-gnu", "i686-pc-windows-msvc"] {
1535 run(TargetSelection::from_user(target));
1536 }
1537
1538 for target in ["x86_64-apple-darwin", "i686-unknown-linux-musl"] {
1539 let target = TargetSelection::from_user(target);
1540 let panic_abort_target = builder.ensure(MirOptPanicAbortSyntheticTarget {
1541 compiler: self.compiler,
1542 base: target,
1543 });
1544 run(panic_abort_target);
1545 }
1546 }
1547 }
1548}
1549
1550#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1551struct Compiletest {
1552 compiler: Compiler,
1553 target: TargetSelection,
1554 mode: &'static str,
1555 suite: &'static str,
1556 path: &'static str,
1557 compare_mode: Option<&'static str>,
1558}
1559
1560impl Step for Compiletest {
1561 type Output = ();
1562
1563 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1564 run.never()
1565 }
1566
1567 fn run(self, builder: &Builder<'_>) {
1573 if builder.doc_tests == DocTests::Only {
1574 return;
1575 }
1576
1577 if builder.top_stage == 0 && env::var("COMPILETEST_FORCE_STAGE0").is_err() {
1578 eprintln!("\
1579ERROR: `--stage 0` runs compiletest on the beta compiler, not your local changes, and will almost always cause tests to fail
1580HELP: to test the compiler, use `--stage 1` instead
1581HELP: to test the standard library, use `--stage 0 library/std` instead
1582NOTE: 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`."
1583 );
1584 crate::exit!(1);
1585 }
1586
1587 let mut compiler = self.compiler;
1588 let target = self.target;
1589 let mode = self.mode;
1590 let suite = self.suite;
1591
1592 let suite_path = self.path;
1594
1595 if !builder.config.codegen_tests && suite == "codegen" {
1597 return;
1598 }
1599
1600 let (stage, stage_id) = if suite == "ui-fulldeps" && compiler.stage == 1 {
1607 let build = builder.build.build;
1611 compiler = builder.compiler(compiler.stage - 1, build);
1612 let test_stage = compiler.stage + 1;
1613 (test_stage, format!("stage{test_stage}-{build}"))
1614 } else {
1615 let stage = compiler.stage;
1616 (stage, format!("stage{stage}-{target}"))
1617 };
1618
1619 if suite.ends_with("fulldeps") {
1620 builder.ensure(compile::Rustc::new(compiler, target));
1621 }
1622
1623 if suite == "debuginfo" {
1624 builder.ensure(dist::DebuggerScripts {
1625 sysroot: builder.sysroot(compiler).to_path_buf(),
1626 host: target,
1627 });
1628 }
1629 if suite == "run-make" {
1630 builder.tool_exe(Tool::RunMakeSupport);
1631 }
1632
1633 if suite == "mir-opt" {
1635 builder.ensure(compile::Std::new(compiler, compiler.host).is_for_mir_opt_tests(true));
1636 } else {
1637 builder.ensure(compile::Std::new(compiler, compiler.host));
1638 }
1639
1640 let mut cmd = builder.tool_cmd(Tool::Compiletest);
1641
1642 if suite == "mir-opt" {
1643 builder.ensure(compile::Std::new(compiler, target).is_for_mir_opt_tests(true));
1644 } else {
1645 builder.ensure(compile::Std::new(compiler, target));
1646 }
1647
1648 builder.ensure(RemoteCopyLibs { compiler, target });
1649
1650 cmd.arg("--stage").arg(stage.to_string());
1654 cmd.arg("--stage-id").arg(stage_id);
1655
1656 cmd.arg("--compile-lib-path").arg(builder.rustc_libdir(compiler));
1657 cmd.arg("--run-lib-path").arg(builder.sysroot_target_libdir(compiler, target));
1658 cmd.arg("--rustc-path").arg(builder.rustc(compiler));
1659
1660 cmd.arg("--minicore-path")
1663 .arg(builder.src.join("tests").join("auxiliary").join("minicore.rs"));
1664
1665 let is_rustdoc = suite == "rustdoc-ui" || suite == "rustdoc-js";
1666
1667 if mode == "run-make" {
1668 let cargo_path = if builder.top_stage == 0 {
1669 builder.initial_cargo.clone()
1671 } else {
1672 builder.ensure(tool::Cargo { compiler, target: compiler.host }).tool_path
1673 };
1674
1675 cmd.arg("--cargo-path").arg(cargo_path);
1676
1677 let stage0_rustc_path = builder.compiler(0, compiler.host);
1680 cmd.arg("--stage0-rustc-path").arg(builder.rustc(stage0_rustc_path));
1681 }
1682
1683 if mode == "rustdoc"
1685 || mode == "run-make"
1686 || (mode == "ui" && is_rustdoc)
1687 || mode == "rustdoc-js"
1688 || mode == "rustdoc-json"
1689 || suite == "coverage-run-rustdoc"
1690 {
1691 cmd.arg("--rustdoc-path").arg(builder.rustdoc(compiler));
1692 }
1693
1694 if mode == "rustdoc-json" {
1695 let json_compiler = compiler.with_stage(0);
1697 cmd.arg("--jsondocck-path")
1698 .arg(builder.ensure(tool::JsonDocCk { compiler: json_compiler, target }).tool_path);
1699 cmd.arg("--jsondoclint-path").arg(
1700 builder.ensure(tool::JsonDocLint { compiler: json_compiler, target }).tool_path,
1701 );
1702 }
1703
1704 if matches!(mode, "coverage-map" | "coverage-run") {
1705 let coverage_dump = builder.tool_exe(Tool::CoverageDump);
1706 cmd.arg("--coverage-dump-path").arg(coverage_dump);
1707 }
1708
1709 cmd.arg("--src-root").arg(&builder.src);
1710 cmd.arg("--src-test-suite-root").arg(builder.src.join("tests").join(suite));
1711
1712 cmd.arg("--build-root").arg(&builder.out);
1716 cmd.arg("--build-test-suite-root").arg(testdir(builder, compiler.host).join(suite));
1717
1718 let sysroot = if builder.top_stage == 0 {
1721 builder.initial_sysroot.clone()
1722 } else {
1723 builder.sysroot(compiler)
1724 };
1725
1726 cmd.arg("--sysroot-base").arg(sysroot);
1727
1728 cmd.arg("--suite").arg(suite);
1729 cmd.arg("--mode").arg(mode);
1730 cmd.arg("--target").arg(target.rustc_target_arg());
1731 cmd.arg("--host").arg(&*compiler.host.triple);
1732 cmd.arg("--llvm-filecheck").arg(builder.llvm_filecheck(builder.config.build));
1733
1734 if builder.build.config.llvm_enzyme {
1735 cmd.arg("--has-enzyme");
1736 }
1737
1738 if builder.config.cmd.bless() {
1739 cmd.arg("--bless");
1740 }
1741
1742 if builder.config.cmd.force_rerun() {
1743 cmd.arg("--force-rerun");
1744 }
1745
1746 if builder.config.cmd.no_capture() {
1747 cmd.arg("--no-capture");
1748 }
1749
1750 let compare_mode =
1751 builder.config.cmd.compare_mode().or_else(|| {
1752 if builder.config.test_compare_mode { self.compare_mode } else { None }
1753 });
1754
1755 if let Some(ref pass) = builder.config.cmd.pass() {
1756 cmd.arg("--pass");
1757 cmd.arg(pass);
1758 }
1759
1760 if let Some(ref run) = builder.config.cmd.run() {
1761 cmd.arg("--run");
1762 cmd.arg(run);
1763 }
1764
1765 if let Some(ref nodejs) = builder.config.nodejs {
1766 cmd.arg("--nodejs").arg(nodejs);
1767 } else if mode == "rustdoc-js" {
1768 panic!("need nodejs to run rustdoc-js suite");
1769 }
1770 if let Some(ref npm) = builder.config.npm {
1771 cmd.arg("--npm").arg(npm);
1772 }
1773 if builder.config.rust_optimize_tests {
1774 cmd.arg("--optimize-tests");
1775 }
1776 if builder.config.rust_randomize_layout {
1777 cmd.arg("--rust-randomized-layout");
1778 }
1779 if builder.config.cmd.only_modified() {
1780 cmd.arg("--only-modified");
1781 }
1782 if let Some(compiletest_diff_tool) = &builder.config.compiletest_diff_tool {
1783 cmd.arg("--compiletest-diff-tool").arg(compiletest_diff_tool);
1784 }
1785
1786 let mut flags = if is_rustdoc { Vec::new() } else { vec!["-Crpath".to_string()] };
1787 flags.push(format!("-Cdebuginfo={}", builder.config.rust_debuginfo_level_tests));
1788 flags.extend(builder.config.cmd.compiletest_rustc_args().iter().map(|s| s.to_string()));
1789
1790 if suite != "mir-opt" {
1791 if let Some(linker) = builder.linker(target) {
1792 cmd.arg("--target-linker").arg(linker);
1793 }
1794 if let Some(linker) = builder.linker(compiler.host) {
1795 cmd.arg("--host-linker").arg(linker);
1796 }
1797 }
1798
1799 if suite == "ui-fulldeps" && target.ends_with("darwin") {
1801 flags.push("-Alinker_messages".into());
1802 }
1803
1804 let mut hostflags = flags.clone();
1805 hostflags.extend(linker_flags(builder, compiler.host, LldThreads::No));
1806
1807 let mut targetflags = flags;
1808
1809 if suite == "ui" || suite == "incremental" {
1811 builder.ensure(TestHelpers { target: compiler.host });
1812 builder.ensure(TestHelpers { target });
1813 hostflags
1814 .push(format!("-Lnative={}", builder.test_helpers_out(compiler.host).display()));
1815 targetflags.push(format!("-Lnative={}", builder.test_helpers_out(target).display()));
1816 }
1817
1818 for flag in hostflags {
1819 cmd.arg("--host-rustcflags").arg(flag);
1820 }
1821 for flag in targetflags {
1822 cmd.arg("--target-rustcflags").arg(flag);
1823 }
1824
1825 cmd.arg("--python").arg(builder.python());
1826
1827 if let Some(ref gdb) = builder.config.gdb {
1828 cmd.arg("--gdb").arg(gdb);
1829 }
1830
1831 let lldb_exe = builder.config.lldb.clone().unwrap_or_else(|| PathBuf::from("lldb"));
1832 let lldb_version = command(&lldb_exe)
1833 .allow_failure()
1834 .arg("--version")
1835 .run_capture(builder)
1836 .stdout_if_ok()
1837 .and_then(|v| if v.trim().is_empty() { None } else { Some(v) });
1838 if let Some(ref vers) = lldb_version {
1839 cmd.arg("--lldb-version").arg(vers);
1840 let lldb_python_dir = command(&lldb_exe)
1841 .allow_failure()
1842 .arg("-P")
1843 .run_capture_stdout(builder)
1844 .stdout_if_ok()
1845 .map(|p| p.lines().next().expect("lldb Python dir not found").to_string());
1846 if let Some(ref dir) = lldb_python_dir {
1847 cmd.arg("--lldb-python-dir").arg(dir);
1848 }
1849 }
1850
1851 if helpers::forcing_clang_based_tests() {
1852 let clang_exe = builder.llvm_out(target).join("bin").join("clang");
1853 cmd.arg("--run-clang-based-tests-with").arg(clang_exe);
1854 }
1855
1856 for exclude in &builder.config.skip {
1857 cmd.arg("--skip");
1858 cmd.arg(exclude);
1859 }
1860
1861 let paths = match &builder.config.cmd {
1863 Subcommand::Test { .. } => &builder.config.paths[..],
1864 _ => &[],
1865 };
1866
1867 let mut test_args: Vec<&str> = paths
1869 .iter()
1870 .filter_map(|p| helpers::is_valid_test_suite_arg(p, suite_path, builder))
1871 .collect();
1872
1873 test_args.append(&mut builder.config.test_args());
1874
1875 if cfg!(windows) {
1878 let test_args_win: Vec<String> =
1879 test_args.iter().map(|s| s.replace('/', "\\")).collect();
1880 cmd.args(&test_args_win);
1881 } else {
1882 cmd.args(&test_args);
1883 }
1884
1885 if builder.is_verbose() {
1886 cmd.arg("--verbose");
1887 }
1888
1889 cmd.arg("--json");
1890
1891 if builder.config.rustc_debug_assertions {
1892 cmd.arg("--with-rustc-debug-assertions");
1893 }
1894
1895 if builder.config.std_debug_assertions {
1896 cmd.arg("--with-std-debug-assertions");
1897 }
1898
1899 let mut llvm_components_passed = false;
1900 let mut copts_passed = false;
1901 if builder.config.llvm_enabled(compiler.host) {
1902 let llvm::LlvmResult { llvm_config, .. } =
1903 builder.ensure(llvm::Llvm { target: builder.config.build });
1904 if !builder.config.dry_run() {
1905 let llvm_version = get_llvm_version(builder, &llvm_config);
1906 let llvm_components =
1907 command(&llvm_config).arg("--components").run_capture_stdout(builder).stdout();
1908 cmd.arg("--llvm-version")
1910 .arg(llvm_version.trim())
1911 .arg("--llvm-components")
1912 .arg(llvm_components.trim());
1913 llvm_components_passed = true;
1914 }
1915 if !builder.config.is_rust_llvm(target) {
1916 cmd.arg("--system-llvm");
1917 }
1918
1919 if !builder.config.dry_run() && suite.ends_with("fulldeps") {
1924 let llvm_libdir =
1925 command(&llvm_config).arg("--libdir").run_capture_stdout(builder).stdout();
1926 let link_llvm = if target.is_msvc() {
1927 format!("-Clink-arg=-LIBPATH:{llvm_libdir}")
1928 } else {
1929 format!("-Clink-arg=-L{llvm_libdir}")
1930 };
1931 cmd.arg("--host-rustcflags").arg(link_llvm);
1932 }
1933
1934 if !builder.config.dry_run() && matches!(mode, "run-make" | "coverage-run") {
1935 let llvm_bin_path = llvm_config
1940 .parent()
1941 .expect("Expected llvm-config to be contained in directory");
1942 assert!(llvm_bin_path.is_dir());
1943 cmd.arg("--llvm-bin-dir").arg(llvm_bin_path);
1944 }
1945
1946 if !builder.config.dry_run() && mode == "run-make" {
1947 if builder.config.lld_enabled {
1949 let lld_install_root =
1950 builder.ensure(llvm::Lld { target: builder.config.build });
1951
1952 let lld_bin_path = lld_install_root.join("bin");
1953
1954 let old_path = env::var_os("PATH").unwrap_or_default();
1955 let new_path = env::join_paths(
1956 std::iter::once(lld_bin_path).chain(env::split_paths(&old_path)),
1957 )
1958 .expect("Could not add LLD bin path to PATH");
1959 cmd.env("PATH", new_path);
1960 }
1961 }
1962 }
1963
1964 if !builder.config.dry_run() && mode == "run-make" {
1967 let mut cflags = builder.cc_handled_clags(target, CLang::C);
1968 cflags.extend(builder.cc_unhandled_cflags(target, GitRepo::Rustc, CLang::C));
1969 let mut cxxflags = builder.cc_handled_clags(target, CLang::Cxx);
1970 cxxflags.extend(builder.cc_unhandled_cflags(target, GitRepo::Rustc, CLang::Cxx));
1971 cmd.arg("--cc")
1972 .arg(builder.cc(target))
1973 .arg("--cxx")
1974 .arg(builder.cxx(target).unwrap())
1975 .arg("--cflags")
1976 .arg(cflags.join(" "))
1977 .arg("--cxxflags")
1978 .arg(cxxflags.join(" "));
1979 copts_passed = true;
1980 if let Some(ar) = builder.ar(target) {
1981 cmd.arg("--ar").arg(ar);
1982 }
1983 }
1984
1985 if !llvm_components_passed {
1986 cmd.arg("--llvm-components").arg("");
1987 }
1988 if !copts_passed {
1989 cmd.arg("--cc")
1990 .arg("")
1991 .arg("--cxx")
1992 .arg("")
1993 .arg("--cflags")
1994 .arg("")
1995 .arg("--cxxflags")
1996 .arg("");
1997 }
1998
1999 if builder.remote_tested(target) {
2000 cmd.arg("--remote-test-client").arg(builder.tool_exe(Tool::RemoteTestClient));
2001 } else if let Some(tool) = builder.runner(target) {
2002 cmd.arg("--runner").arg(tool);
2003 }
2004
2005 if suite != "mir-opt" {
2006 if !builder.config.dry_run() && target.is_msvc() {
2012 for (k, v) in builder.cc.borrow()[&target].env() {
2013 if k != "PATH" {
2014 cmd.env(k, v);
2015 }
2016 }
2017 }
2018 }
2019
2020 if !builder.config.dry_run()
2022 && target.contains("msvc")
2023 && builder.config.sanitizers_enabled(target)
2024 {
2025 cmd.env("ASAN_WIN_CONTINUE_ON_INTERCEPTION_FAILURE", "1");
2028 let asan_runtime_path =
2030 builder.cc.borrow()[&target].path().parent().unwrap().to_path_buf();
2031 let old_path = cmd
2032 .get_envs()
2033 .find_map(|(k, v)| (k == "PATH").then_some(v))
2034 .flatten()
2035 .map_or_else(|| env::var_os("PATH").unwrap_or_default(), |v| v.to_owned());
2036 let new_path = env::join_paths(
2037 env::split_paths(&old_path).chain(std::iter::once(asan_runtime_path)),
2038 )
2039 .expect("Could not add ASAN runtime path to PATH");
2040 cmd.env("PATH", new_path);
2041 }
2042
2043 cmd.env_remove("CARGO");
2046
2047 cmd.env("RUSTC_BOOTSTRAP", "1");
2048 cmd.env("RUSTC_FORCE_RUSTC_VERSION", "compiletest");
2051 cmd.env("DOC_RUST_LANG_ORG_CHANNEL", builder.doc_rust_lang_org_channel());
2052 builder.add_rust_test_threads(&mut cmd);
2053
2054 if builder.config.sanitizers_enabled(target) {
2055 cmd.env("RUSTC_SANITIZER_SUPPORT", "1");
2056 }
2057
2058 if builder.config.profiler_enabled(target) {
2059 cmd.arg("--profiler-runtime");
2060 }
2061
2062 cmd.env("RUST_TEST_TMPDIR", builder.tempdir());
2063
2064 cmd.arg("--adb-path").arg("adb");
2065 cmd.arg("--adb-test-dir").arg(ADB_TEST_DIR);
2066 if target.contains("android") && !builder.config.dry_run() {
2067 cmd.arg("--android-cross-path")
2069 .arg(builder.cc(target).parent().unwrap().parent().unwrap());
2070 } else {
2071 cmd.arg("--android-cross-path").arg("");
2072 }
2073
2074 if builder.config.cmd.rustfix_coverage() {
2075 cmd.arg("--rustfix-coverage");
2076 }
2077
2078 cmd.arg("--channel").arg(&builder.config.channel);
2079
2080 if !builder.config.omit_git_hash {
2081 cmd.arg("--git-hash");
2082 }
2083
2084 let git_config = builder.config.git_config();
2085 cmd.arg("--nightly-branch").arg(git_config.nightly_branch);
2086 cmd.arg("--git-merge-commit-email").arg(git_config.git_merge_commit_email);
2087 cmd.force_coloring_in_ci();
2088
2089 #[cfg(feature = "build-metrics")]
2090 builder.metrics.begin_test_suite(
2091 build_helper::metrics::TestSuiteMetadata::Compiletest {
2092 suite: suite.into(),
2093 mode: mode.into(),
2094 compare_mode: None,
2095 target: self.target.triple.to_string(),
2096 host: self.compiler.host.triple.to_string(),
2097 stage: self.compiler.stage,
2098 },
2099 builder,
2100 );
2101
2102 let _group = builder.msg(
2103 Kind::Test,
2104 compiler.stage,
2105 format!("compiletest suite={suite} mode={mode}"),
2106 compiler.host,
2107 target,
2108 );
2109 try_run_tests(builder, &mut cmd, false);
2110
2111 if let Some(compare_mode) = compare_mode {
2112 cmd.arg("--compare-mode").arg(compare_mode);
2113
2114 #[cfg(feature = "build-metrics")]
2115 builder.metrics.begin_test_suite(
2116 build_helper::metrics::TestSuiteMetadata::Compiletest {
2117 suite: suite.into(),
2118 mode: mode.into(),
2119 compare_mode: Some(compare_mode.into()),
2120 target: self.target.triple.to_string(),
2121 host: self.compiler.host.triple.to_string(),
2122 stage: self.compiler.stage,
2123 },
2124 builder,
2125 );
2126
2127 builder.info(&format!(
2128 "Check compiletest suite={} mode={} compare_mode={} ({} -> {})",
2129 suite, mode, compare_mode, &compiler.host, target
2130 ));
2131 let _time = helpers::timeit(builder);
2132 try_run_tests(builder, &mut cmd, false);
2133 }
2134 }
2135}
2136
2137#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2138struct BookTest {
2139 compiler: Compiler,
2140 path: PathBuf,
2141 name: &'static str,
2142 is_ext_doc: bool,
2143 dependencies: Vec<&'static str>,
2144}
2145
2146impl Step for BookTest {
2147 type Output = ();
2148 const ONLY_HOSTS: bool = true;
2149
2150 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2151 run.never()
2152 }
2153
2154 fn run(self, builder: &Builder<'_>) {
2158 if self.is_ext_doc {
2168 self.run_ext_doc(builder);
2169 } else {
2170 self.run_local_doc(builder);
2171 }
2172 }
2173}
2174
2175impl BookTest {
2176 fn run_ext_doc(self, builder: &Builder<'_>) {
2179 let compiler = self.compiler;
2180
2181 builder.ensure(compile::Std::new(compiler, compiler.host));
2182
2183 let mut rustdoc_path = builder.rustdoc(compiler);
2186 rustdoc_path.pop();
2187 let old_path = env::var_os("PATH").unwrap_or_default();
2188 let new_path = env::join_paths(iter::once(rustdoc_path).chain(env::split_paths(&old_path)))
2189 .expect("could not add rustdoc to PATH");
2190
2191 let mut rustbook_cmd = builder.tool_cmd(Tool::Rustbook);
2192 let path = builder.src.join(&self.path);
2193 rustbook_cmd.env("RUSTC_BOOTSTRAP", "1");
2195 rustbook_cmd.env("PATH", new_path).arg("test").arg(path);
2196
2197 let libs = if !self.dependencies.is_empty() {
2202 let mut lib_paths = vec![];
2203 for dep in self.dependencies {
2204 let mode = Mode::ToolRustc;
2205 let target = builder.config.build;
2206 let cargo = tool::prepare_tool_cargo(
2207 builder,
2208 compiler,
2209 mode,
2210 target,
2211 Kind::Build,
2212 dep,
2213 SourceType::Submodule,
2214 &[],
2215 );
2216
2217 let stamp = BuildStamp::new(&builder.cargo_out(compiler, mode, target))
2218 .with_prefix(PathBuf::from(dep).file_name().and_then(|v| v.to_str()).unwrap());
2219
2220 let output_paths = run_cargo(builder, cargo, vec![], &stamp, vec![], false, false);
2221 let directories = output_paths
2222 .into_iter()
2223 .filter_map(|p| p.parent().map(ToOwned::to_owned))
2224 .fold(HashSet::new(), |mut set, dir| {
2225 set.insert(dir);
2226 set
2227 });
2228
2229 lib_paths.extend(directories);
2230 }
2231 lib_paths
2232 } else {
2233 vec![]
2234 };
2235
2236 if !libs.is_empty() {
2237 let paths = libs
2238 .into_iter()
2239 .map(|path| path.into_os_string())
2240 .collect::<Vec<OsString>>()
2241 .join(OsStr::new(","));
2242 rustbook_cmd.args([OsString::from("--library-path"), paths]);
2243 }
2244
2245 builder.add_rust_test_threads(&mut rustbook_cmd);
2246 let _guard = builder.msg(
2247 Kind::Test,
2248 compiler.stage,
2249 format_args!("mdbook {}", self.path.display()),
2250 compiler.host,
2251 compiler.host,
2252 );
2253 let _time = helpers::timeit(builder);
2254 let toolstate = if rustbook_cmd.delay_failure().run(builder) {
2255 ToolState::TestPass
2256 } else {
2257 ToolState::TestFail
2258 };
2259 builder.save_toolstate(self.name, toolstate);
2260 }
2261
2262 fn run_local_doc(self, builder: &Builder<'_>) {
2264 let compiler = self.compiler;
2265 let host = self.compiler.host;
2266
2267 builder.ensure(compile::Std::new(compiler, host));
2268
2269 let _guard =
2270 builder.msg(Kind::Test, compiler.stage, format!("book {}", self.name), host, host);
2271
2272 let mut stack = vec![builder.src.join(self.path)];
2275 let _time = helpers::timeit(builder);
2276 let mut files = Vec::new();
2277 while let Some(p) = stack.pop() {
2278 if p.is_dir() {
2279 stack.extend(t!(p.read_dir()).map(|p| t!(p).path()));
2280 continue;
2281 }
2282
2283 if p.extension().and_then(|s| s.to_str()) != Some("md") {
2284 continue;
2285 }
2286
2287 files.push(p);
2288 }
2289
2290 files.sort();
2291
2292 for file in files {
2293 markdown_test(builder, compiler, &file);
2294 }
2295 }
2296}
2297
2298macro_rules! test_book {
2299 ($(
2300 $name:ident, $path:expr, $book_name:expr,
2301 default=$default:expr
2302 $(,submodules = $submodules:expr)?
2303 $(,dependencies=$dependencies:expr)?
2304 ;
2305 )+) => {
2306 $(
2307 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
2308 pub struct $name {
2309 compiler: Compiler,
2310 }
2311
2312 impl Step for $name {
2313 type Output = ();
2314 const DEFAULT: bool = $default;
2315 const ONLY_HOSTS: bool = true;
2316
2317 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2318 run.path($path)
2319 }
2320
2321 fn make_run(run: RunConfig<'_>) {
2322 run.builder.ensure($name {
2323 compiler: run.builder.compiler(run.builder.top_stage, run.target),
2324 });
2325 }
2326
2327 fn run(self, builder: &Builder<'_>) {
2328 $(
2329 for submodule in $submodules {
2330 builder.require_submodule(submodule, None);
2331 }
2332 )*
2333
2334 let dependencies = vec![];
2335 $(
2336 let mut dependencies = dependencies;
2337 for dep in $dependencies {
2338 dependencies.push(dep);
2339 }
2340 )?
2341
2342 builder.ensure(BookTest {
2343 compiler: self.compiler,
2344 path: PathBuf::from($path),
2345 name: $book_name,
2346 is_ext_doc: !$default,
2347 dependencies,
2348 });
2349 }
2350 }
2351 )+
2352 }
2353}
2354
2355test_book!(
2356 Nomicon, "src/doc/nomicon", "nomicon", default=false, submodules=["src/doc/nomicon"];
2357 Reference, "src/doc/reference", "reference", default=false, submodules=["src/doc/reference"];
2358 RustdocBook, "src/doc/rustdoc", "rustdoc", default=true;
2359 RustcBook, "src/doc/rustc", "rustc", default=true;
2360 RustByExample, "src/doc/rust-by-example", "rust-by-example", default=false, submodules=["src/doc/rust-by-example"];
2361 EmbeddedBook, "src/doc/embedded-book", "embedded-book", default=false, submodules=["src/doc/embedded-book"];
2362 TheBook, "src/doc/book", "book", default=false, submodules=["src/doc/book"], dependencies=["src/doc/book/packages/trpl"];
2363 UnstableBook, "src/doc/unstable-book", "unstable-book", default=true;
2364 EditionGuide, "src/doc/edition-guide", "edition-guide", default=false, submodules=["src/doc/edition-guide"];
2365);
2366
2367#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2368pub struct ErrorIndex {
2369 compiler: Compiler,
2370}
2371
2372impl Step for ErrorIndex {
2373 type Output = ();
2374 const DEFAULT: bool = true;
2375 const ONLY_HOSTS: bool = true;
2376
2377 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2378 run.path("src/tools/error_index_generator").alias("error-index")
2381 }
2382
2383 fn make_run(run: RunConfig<'_>) {
2384 let compiler = run.builder.compiler(run.builder.top_stage, run.builder.config.build);
2388 run.builder.ensure(ErrorIndex { compiler });
2389 }
2390
2391 fn run(self, builder: &Builder<'_>) {
2398 let compiler = self.compiler;
2399
2400 let dir = testdir(builder, compiler.host);
2401 t!(fs::create_dir_all(&dir));
2402 let output = dir.join("error-index.md");
2403
2404 let mut tool = tool::ErrorIndex::command(builder);
2405 tool.arg("markdown").arg(&output);
2406
2407 let guard =
2408 builder.msg(Kind::Test, compiler.stage, "error-index", compiler.host, compiler.host);
2409 let _time = helpers::timeit(builder);
2410 tool.run_capture(builder);
2411 drop(guard);
2412 builder.ensure(compile::Std::new(compiler, compiler.host));
2415 markdown_test(builder, compiler, &output);
2416 }
2417}
2418
2419fn markdown_test(builder: &Builder<'_>, compiler: Compiler, markdown: &Path) -> bool {
2420 if let Ok(contents) = fs::read_to_string(markdown) {
2421 if !contents.contains("```") {
2422 return true;
2423 }
2424 }
2425
2426 builder.verbose(|| println!("doc tests for: {}", markdown.display()));
2427 let mut cmd = builder.rustdoc_cmd(compiler);
2428 builder.add_rust_test_threads(&mut cmd);
2429 cmd.arg("-Z");
2431 cmd.arg("unstable-options");
2432 cmd.arg("--test");
2433 cmd.arg(markdown);
2434 cmd.env("RUSTC_BOOTSTRAP", "1");
2435
2436 let test_args = builder.config.test_args().join(" ");
2437 cmd.arg("--test-args").arg(test_args);
2438
2439 cmd = cmd.delay_failure();
2440 if !builder.config.verbose_tests {
2441 cmd.run_capture(builder).is_success()
2442 } else {
2443 cmd.run(builder)
2444 }
2445}
2446
2447#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2452pub struct CrateLibrustc {
2453 compiler: Compiler,
2454 target: TargetSelection,
2455 crates: Vec<String>,
2456}
2457
2458impl Step for CrateLibrustc {
2459 type Output = ();
2460 const DEFAULT: bool = true;
2461 const ONLY_HOSTS: bool = true;
2462
2463 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2464 run.crate_or_deps("rustc-main").path("compiler")
2465 }
2466
2467 fn make_run(run: RunConfig<'_>) {
2468 let builder = run.builder;
2469 let host = run.build_triple();
2470 let compiler = builder.compiler_for(builder.top_stage, host, host);
2471 let crates = run.make_run_crates(Alias::Compiler);
2472
2473 builder.ensure(CrateLibrustc { compiler, target: run.target, crates });
2474 }
2475
2476 fn run(self, builder: &Builder<'_>) {
2477 builder.ensure(compile::Std::new(self.compiler, self.target));
2478
2479 builder.ensure(Crate {
2481 compiler: self.compiler,
2482 target: self.target,
2483 mode: Mode::Rustc,
2484 crates: self.crates,
2485 });
2486 }
2487}
2488
2489fn run_cargo_test<'a>(
2493 cargo: builder::Cargo,
2494 libtest_args: &[&str],
2495 crates: &[String],
2496 description: impl Into<Option<&'a str>>,
2497 target: TargetSelection,
2498 builder: &Builder<'_>,
2499) -> bool {
2500 let compiler = cargo.compiler();
2501 let mut cargo = prepare_cargo_test(cargo, libtest_args, crates, target, builder);
2502 let _time = helpers::timeit(builder);
2503 let _group = description.into().and_then(|what| {
2504 builder.msg_sysroot_tool(Kind::Test, compiler.stage, what, compiler.host, target)
2505 });
2506
2507 #[cfg(feature = "build-metrics")]
2508 builder.metrics.begin_test_suite(
2509 build_helper::metrics::TestSuiteMetadata::CargoPackage {
2510 crates: crates.iter().map(|c| c.to_string()).collect(),
2511 target: target.triple.to_string(),
2512 host: compiler.host.triple.to_string(),
2513 stage: compiler.stage,
2514 },
2515 builder,
2516 );
2517 add_flags_and_try_run_tests(builder, &mut cargo)
2518}
2519
2520fn prepare_cargo_test(
2522 cargo: builder::Cargo,
2523 libtest_args: &[&str],
2524 crates: &[String],
2525 target: TargetSelection,
2526 builder: &Builder<'_>,
2527) -> BootstrapCommand {
2528 let compiler = cargo.compiler();
2529 let mut cargo: BootstrapCommand = cargo.into();
2530
2531 if builder.config.cmd.bless() && !cargo.get_envs().any(|v| v.0 == "RUSTC_BLESS") {
2535 cargo.env("RUSTC_BLESS", "Gesundheit");
2536 }
2537
2538 if builder.kind == Kind::Test && !builder.fail_fast {
2542 cargo.arg("--no-fail-fast");
2543 }
2544
2545 if builder.config.json_output {
2546 cargo.arg("--message-format=json");
2547 }
2548
2549 match builder.doc_tests {
2550 DocTests::Only => {
2551 cargo.arg("--doc");
2552 }
2553 DocTests::No => {
2554 cargo.args(["--bins", "--examples", "--tests", "--benches"]);
2555 }
2556 DocTests::Yes => {}
2557 }
2558
2559 for krate in crates {
2560 cargo.arg("-p").arg(krate);
2561 }
2562
2563 cargo.arg("--").args(builder.config.test_args()).args(libtest_args);
2564 if !builder.config.verbose_tests {
2565 cargo.arg("--quiet");
2566 }
2567
2568 if builder.kind != Kind::Miri {
2577 let mut dylib_paths = builder.rustc_lib_paths(compiler);
2578 dylib_paths.push(PathBuf::from(&builder.sysroot_target_libdir(compiler, target)));
2579 helpers::add_dylib_path(dylib_paths, &mut cargo);
2580 }
2581
2582 if builder.remote_tested(target) {
2583 cargo.env(
2584 format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)),
2585 format!("{} run 0", builder.tool_exe(Tool::RemoteTestClient).display()),
2586 );
2587 } else if let Some(tool) = builder.runner(target) {
2588 cargo.env(format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)), tool);
2589 }
2590
2591 cargo
2592}
2593
2594#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
2602pub struct Crate {
2603 pub compiler: Compiler,
2604 pub target: TargetSelection,
2605 pub mode: Mode,
2606 pub crates: Vec<String>,
2607}
2608
2609impl Step for Crate {
2610 type Output = ();
2611 const DEFAULT: bool = true;
2612
2613 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2614 run.crate_or_deps("sysroot").crate_or_deps("coretests").crate_or_deps("alloctests")
2615 }
2616
2617 fn make_run(run: RunConfig<'_>) {
2618 let builder = run.builder;
2619 let host = run.build_triple();
2620 let compiler = builder.compiler_for(builder.top_stage, host, host);
2621 let crates = run
2622 .paths
2623 .iter()
2624 .map(|p| builder.crate_paths[&p.assert_single_path().path].clone())
2625 .collect();
2626
2627 builder.ensure(Crate { compiler, target: run.target, mode: Mode::Std, crates });
2628 }
2629
2630 fn run(self, builder: &Builder<'_>) {
2639 let compiler = self.compiler;
2640 let target = self.target;
2641 let mode = self.mode;
2642
2643 builder.ensure(compile::Std::new(compiler, compiler.host).force_recompile(true));
2646
2647 let compiler = builder.compiler_for(compiler.stage, compiler.host, target);
2652
2653 let mut cargo = if builder.kind == Kind::Miri {
2654 if builder.top_stage == 0 {
2655 eprintln!("ERROR: `x.py miri` requires stage 1 or higher");
2656 std::process::exit(1);
2657 }
2658
2659 let mut cargo = builder::Cargo::new(
2662 builder,
2663 compiler,
2664 mode,
2665 SourceType::InTree,
2666 target,
2667 Kind::MiriTest,
2668 );
2669 cargo.env("MIRI_REPLACE_LIBRS_IF_NOT_TEST", "1");
2681 cargo.rustflag("-Zforce-unstable-if-unmarked");
2685 cargo
2686 } else {
2687 if !builder.config.is_host_target(target) {
2689 builder.ensure(compile::Std::new(compiler, target).force_recompile(true));
2690 builder.ensure(RemoteCopyLibs { compiler, target });
2691 }
2692
2693 builder::Cargo::new(builder, compiler, mode, SourceType::InTree, target, builder.kind)
2695 };
2696
2697 match mode {
2698 Mode::Std => {
2699 if builder.kind == Kind::Miri {
2700 cargo
2706 .arg("--manifest-path")
2707 .arg(builder.src.join("library/sysroot/Cargo.toml"));
2708 } else {
2709 compile::std_cargo(builder, target, compiler.stage, &mut cargo);
2710 if builder.download_rustc() && compiler.stage > 0 {
2714 let sysroot = builder
2715 .out
2716 .join(compiler.host)
2717 .join(format!("stage{}-test-sysroot", compiler.stage));
2718 cargo.env("RUSTC_SYSROOT", sysroot);
2719 }
2720 }
2721 }
2722 Mode::Rustc => {
2723 compile::rustc_cargo(builder, &mut cargo, target, &compiler, &self.crates);
2724 }
2725 _ => panic!("can only test libraries"),
2726 };
2727
2728 let mut crates = self.crates.clone();
2729 if crates.iter().any(|crate_| crate_ == "core") {
2734 crates.push("coretests".to_owned());
2735 }
2736 if crates.iter().any(|crate_| crate_ == "alloc") {
2737 crates.push("alloctests".to_owned());
2738 }
2739
2740 run_cargo_test(cargo, &[], &crates, &*crate_description(&self.crates), target, builder);
2741 }
2742}
2743
2744#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2746pub struct CrateRustdoc {
2747 host: TargetSelection,
2748}
2749
2750impl Step for CrateRustdoc {
2751 type Output = ();
2752 const DEFAULT: bool = true;
2753 const ONLY_HOSTS: bool = true;
2754
2755 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2756 run.paths(&["src/librustdoc", "src/tools/rustdoc"])
2757 }
2758
2759 fn make_run(run: RunConfig<'_>) {
2760 let builder = run.builder;
2761
2762 builder.ensure(CrateRustdoc { host: run.target });
2763 }
2764
2765 fn run(self, builder: &Builder<'_>) {
2766 let target = self.host;
2767
2768 let compiler = if builder.download_rustc() {
2769 builder.compiler(builder.top_stage, target)
2770 } else {
2771 builder.compiler_for(builder.top_stage, target, target)
2776 };
2777 builder.ensure(compile::Std::new(compiler, target));
2782 builder.ensure(compile::Rustc::new(compiler, target));
2783
2784 let mut cargo = tool::prepare_tool_cargo(
2785 builder,
2786 compiler,
2787 Mode::ToolRustc,
2788 target,
2789 builder.kind,
2790 "src/tools/rustdoc",
2791 SourceType::InTree,
2792 &[],
2793 );
2794 if self.host.contains("musl") {
2795 cargo.arg("'-Ctarget-feature=-crt-static'");
2796 }
2797
2798 let libdir = if builder.download_rustc() {
2825 builder.rustc_libdir(compiler)
2826 } else {
2827 builder.sysroot_target_libdir(compiler, target).to_path_buf()
2828 };
2829 let mut dylib_path = dylib_path();
2830 dylib_path.insert(0, PathBuf::from(&*libdir));
2831 cargo.env(dylib_path_var(), env::join_paths(&dylib_path).unwrap());
2832
2833 run_cargo_test(cargo, &[], &["rustdoc:0.0.0".to_string()], "rustdoc", target, builder);
2834 }
2835}
2836
2837#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2838pub struct CrateRustdocJsonTypes {
2839 host: TargetSelection,
2840}
2841
2842impl Step for CrateRustdocJsonTypes {
2843 type Output = ();
2844 const DEFAULT: bool = true;
2845 const ONLY_HOSTS: bool = true;
2846
2847 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2848 run.path("src/rustdoc-json-types")
2849 }
2850
2851 fn make_run(run: RunConfig<'_>) {
2852 let builder = run.builder;
2853
2854 builder.ensure(CrateRustdocJsonTypes { host: run.target });
2855 }
2856
2857 fn run(self, builder: &Builder<'_>) {
2858 let target = self.host;
2859
2860 let compiler = builder.compiler_for(builder.top_stage, target, target);
2865 builder.ensure(compile::Rustc::new(compiler, target));
2866
2867 let cargo = tool::prepare_tool_cargo(
2868 builder,
2869 compiler,
2870 Mode::ToolRustc,
2871 target,
2872 builder.kind,
2873 "src/rustdoc-json-types",
2874 SourceType::InTree,
2875 &[],
2876 );
2877
2878 let libtest_args = if self.host.contains("musl") {
2880 ["'-Ctarget-feature=-crt-static'"].as_slice()
2881 } else {
2882 &[]
2883 };
2884
2885 run_cargo_test(
2886 cargo,
2887 libtest_args,
2888 &["rustdoc-json-types".to_string()],
2889 "rustdoc-json-types",
2890 target,
2891 builder,
2892 );
2893 }
2894}
2895
2896#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2906pub struct RemoteCopyLibs {
2907 compiler: Compiler,
2908 target: TargetSelection,
2909}
2910
2911impl Step for RemoteCopyLibs {
2912 type Output = ();
2913
2914 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2915 run.never()
2916 }
2917
2918 fn run(self, builder: &Builder<'_>) {
2919 let compiler = self.compiler;
2920 let target = self.target;
2921 if !builder.remote_tested(target) {
2922 return;
2923 }
2924
2925 builder.ensure(compile::Std::new(compiler, target));
2926
2927 builder.info(&format!("REMOTE copy libs to emulator ({target})"));
2928
2929 let remote_test_server = builder.ensure(tool::RemoteTestServer { compiler, target });
2930
2931 let tool = builder.tool_exe(Tool::RemoteTestClient);
2933 let mut cmd = command(&tool);
2934 cmd.arg("spawn-emulator")
2935 .arg(target.triple)
2936 .arg(&remote_test_server.tool_path)
2937 .arg(builder.tempdir());
2938 if let Some(rootfs) = builder.qemu_rootfs(target) {
2939 cmd.arg(rootfs);
2940 }
2941 cmd.run(builder);
2942
2943 for f in t!(builder.sysroot_target_libdir(compiler, target).read_dir()) {
2945 let f = t!(f);
2946 if helpers::is_dylib(&f.path()) {
2947 command(&tool).arg("push").arg(f.path()).run(builder);
2948 }
2949 }
2950 }
2951}
2952
2953#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2954pub struct Distcheck;
2955
2956impl Step for Distcheck {
2957 type Output = ();
2958
2959 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2960 run.alias("distcheck")
2961 }
2962
2963 fn make_run(run: RunConfig<'_>) {
2964 run.builder.ensure(Distcheck);
2965 }
2966
2967 fn run(self, builder: &Builder<'_>) {
2976 builder.info("Distcheck");
2977 let dir = builder.tempdir().join("distcheck");
2978 let _ = fs::remove_dir_all(&dir);
2979 t!(fs::create_dir_all(&dir));
2980
2981 builder.ensure(dist::PlainSourceTarball);
2983 builder.ensure(dist::Src);
2984
2985 command("tar")
2986 .arg("-xf")
2987 .arg(builder.ensure(dist::PlainSourceTarball).tarball())
2988 .arg("--strip-components=1")
2989 .current_dir(&dir)
2990 .run(builder);
2991 command("./configure")
2992 .args(&builder.config.configure_args)
2993 .arg("--enable-vendor")
2994 .current_dir(&dir)
2995 .run(builder);
2996 command(helpers::make(&builder.config.build.triple))
2997 .arg("check")
2998 .current_dir(&dir)
2999 .run(builder);
3000
3001 builder.info("Distcheck rust-src");
3003 let dir = builder.tempdir().join("distcheck-src");
3004 let _ = fs::remove_dir_all(&dir);
3005 t!(fs::create_dir_all(&dir));
3006
3007 command("tar")
3008 .arg("-xf")
3009 .arg(builder.ensure(dist::Src).tarball())
3010 .arg("--strip-components=1")
3011 .current_dir(&dir)
3012 .run(builder);
3013
3014 let toml = dir.join("rust-src/lib/rustlib/src/rust/library/std/Cargo.toml");
3015 command(&builder.initial_cargo)
3016 .env("RUSTC_BOOTSTRAP", "1")
3019 .arg("generate-lockfile")
3020 .arg("--manifest-path")
3021 .arg(&toml)
3022 .current_dir(&dir)
3023 .run(builder);
3024 }
3025}
3026
3027#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3028pub struct Bootstrap;
3029
3030impl Step for Bootstrap {
3031 type Output = ();
3032 const DEFAULT: bool = true;
3033 const ONLY_HOSTS: bool = true;
3034
3035 fn run(self, builder: &Builder<'_>) {
3037 let host = builder.config.build;
3038 let compiler = builder.compiler(0, host);
3039 let _guard = builder.msg(Kind::Test, 0, "bootstrap", host, host);
3040
3041 builder.build.require_submodule("src/tools/cargo", None);
3043
3044 let mut check_bootstrap = command(builder.python());
3045 check_bootstrap
3046 .args(["-m", "unittest", "bootstrap_test.py"])
3047 .env("BUILD_DIR", &builder.out)
3048 .env("BUILD_PLATFORM", builder.build.build.triple)
3049 .env("BOOTSTRAP_TEST_RUSTC_BIN", &builder.initial_rustc)
3050 .env("BOOTSTRAP_TEST_CARGO_BIN", &builder.initial_cargo)
3051 .current_dir(builder.src.join("src/bootstrap/"));
3052 check_bootstrap.delay_failure().run(builder);
3055
3056 let mut cargo = tool::prepare_tool_cargo(
3057 builder,
3058 compiler,
3059 Mode::ToolBootstrap,
3060 host,
3061 Kind::Test,
3062 "src/bootstrap",
3063 SourceType::InTree,
3064 &[],
3065 );
3066
3067 cargo.release_build(false);
3068
3069 cargo
3070 .rustflag("-Cdebuginfo=2")
3071 .env("CARGO_TARGET_DIR", builder.out.join("bootstrap"))
3072 .env("RUSTC_BOOTSTRAP", "1");
3073
3074 run_cargo_test(cargo, &["--test-threads=1"], &[], None, host, builder);
3077 }
3078
3079 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3080 run.path("src/bootstrap")
3081 }
3082
3083 fn make_run(run: RunConfig<'_>) {
3084 run.builder.ensure(Bootstrap);
3085 }
3086}
3087
3088#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3089pub struct TierCheck {
3090 pub compiler: Compiler,
3091}
3092
3093impl Step for TierCheck {
3094 type Output = ();
3095 const DEFAULT: bool = true;
3096 const ONLY_HOSTS: bool = true;
3097
3098 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3099 run.path("src/tools/tier-check")
3100 }
3101
3102 fn make_run(run: RunConfig<'_>) {
3103 let compiler =
3104 run.builder.compiler_for(run.builder.top_stage, run.builder.build.build, run.target);
3105 run.builder.ensure(TierCheck { compiler });
3106 }
3107
3108 fn run(self, builder: &Builder<'_>) {
3110 builder.ensure(compile::Std::new(self.compiler, self.compiler.host));
3111 let mut cargo = tool::prepare_tool_cargo(
3112 builder,
3113 self.compiler,
3114 Mode::ToolStd,
3115 self.compiler.host,
3116 Kind::Run,
3117 "src/tools/tier-check",
3118 SourceType::InTree,
3119 &[],
3120 );
3121 cargo.arg(builder.src.join("src/doc/rustc/src/platform-support.md"));
3122 cargo.arg(builder.rustc(self.compiler));
3123 if builder.is_verbose() {
3124 cargo.arg("--verbose");
3125 }
3126
3127 let _guard = builder.msg(
3128 Kind::Test,
3129 self.compiler.stage,
3130 "platform support check",
3131 self.compiler.host,
3132 self.compiler.host,
3133 );
3134 BootstrapCommand::from(cargo).delay_failure().run(builder);
3135 }
3136}
3137
3138#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3139pub struct LintDocs {
3140 pub compiler: Compiler,
3141 pub target: TargetSelection,
3142}
3143
3144impl Step for LintDocs {
3145 type Output = ();
3146 const DEFAULT: bool = true;
3147 const ONLY_HOSTS: bool = true;
3148
3149 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3150 run.path("src/tools/lint-docs")
3151 }
3152
3153 fn make_run(run: RunConfig<'_>) {
3154 run.builder.ensure(LintDocs {
3155 compiler: run.builder.compiler(run.builder.top_stage, run.builder.config.build),
3156 target: run.target,
3157 });
3158 }
3159
3160 fn run(self, builder: &Builder<'_>) {
3163 builder.ensure(crate::core::build_steps::doc::RustcBook {
3164 compiler: self.compiler,
3165 target: self.target,
3166 validate: true,
3167 });
3168 }
3169}
3170
3171#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3172pub struct RustInstaller;
3173
3174impl Step for RustInstaller {
3175 type Output = ();
3176 const ONLY_HOSTS: bool = true;
3177 const DEFAULT: bool = true;
3178
3179 fn run(self, builder: &Builder<'_>) {
3181 let bootstrap_host = builder.config.build;
3182 let compiler = builder.compiler(0, bootstrap_host);
3183 let cargo = tool::prepare_tool_cargo(
3184 builder,
3185 compiler,
3186 Mode::ToolBootstrap,
3187 bootstrap_host,
3188 Kind::Test,
3189 "src/tools/rust-installer",
3190 SourceType::InTree,
3191 &[],
3192 );
3193
3194 let _guard = builder.msg(
3195 Kind::Test,
3196 compiler.stage,
3197 "rust-installer",
3198 bootstrap_host,
3199 bootstrap_host,
3200 );
3201 run_cargo_test(cargo, &[], &[], None, bootstrap_host, builder);
3202
3203 if bootstrap_host != "x86_64-unknown-linux-gnu" {
3207 return;
3208 }
3209
3210 let mut cmd = command(builder.src.join("src/tools/rust-installer/test.sh"));
3211 let tmpdir = testdir(builder, compiler.host).join("rust-installer");
3212 let _ = std::fs::remove_dir_all(&tmpdir);
3213 let _ = std::fs::create_dir_all(&tmpdir);
3214 cmd.current_dir(&tmpdir);
3215 cmd.env("CARGO_TARGET_DIR", tmpdir.join("cargo-target"));
3216 cmd.env("CARGO", &builder.initial_cargo);
3217 cmd.env("RUSTC", &builder.initial_rustc);
3218 cmd.env("TMP_DIR", &tmpdir);
3219 cmd.delay_failure().run(builder);
3220 }
3221
3222 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3223 run.path("src/tools/rust-installer")
3224 }
3225
3226 fn make_run(run: RunConfig<'_>) {
3227 run.builder.ensure(Self);
3228 }
3229}
3230
3231#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3232pub struct TestHelpers {
3233 pub target: TargetSelection,
3234}
3235
3236impl Step for TestHelpers {
3237 type Output = ();
3238
3239 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3240 run.path("tests/auxiliary/rust_test_helpers.c")
3241 }
3242
3243 fn make_run(run: RunConfig<'_>) {
3244 run.builder.ensure(TestHelpers { target: run.target })
3245 }
3246
3247 fn run(self, builder: &Builder<'_>) {
3250 if builder.config.dry_run() {
3251 return;
3252 }
3253 let target = if self.target == "x86_64-fortanix-unknown-sgx" {
3257 TargetSelection::from_user("x86_64-unknown-linux-gnu")
3258 } else {
3259 self.target
3260 };
3261 let dst = builder.test_helpers_out(target);
3262 let src = builder.src.join("tests/auxiliary/rust_test_helpers.c");
3263 if up_to_date(&src, &dst.join("librust_test_helpers.a")) {
3264 return;
3265 }
3266
3267 let _guard = builder.msg_unstaged(Kind::Build, "test helpers", target);
3268 t!(fs::create_dir_all(&dst));
3269 let mut cfg = cc::Build::new();
3270
3271 if !target.is_msvc() {
3275 if let Some(ar) = builder.ar(target) {
3276 cfg.archiver(ar);
3277 }
3278 cfg.compiler(builder.cc(target));
3279 }
3280 cfg.cargo_metadata(false)
3281 .out_dir(&dst)
3282 .target(&target.triple)
3283 .host(&builder.config.build.triple)
3284 .opt_level(0)
3285 .warnings(false)
3286 .debug(false)
3287 .file(builder.src.join("tests/auxiliary/rust_test_helpers.c"))
3288 .compile("rust_test_helpers");
3289 }
3290}
3291
3292#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3293pub struct CodegenCranelift {
3294 compiler: Compiler,
3295 target: TargetSelection,
3296}
3297
3298impl Step for CodegenCranelift {
3299 type Output = ();
3300 const DEFAULT: bool = true;
3301 const ONLY_HOSTS: bool = true;
3302
3303 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3304 run.paths(&["compiler/rustc_codegen_cranelift"])
3305 }
3306
3307 fn make_run(run: RunConfig<'_>) {
3308 let builder = run.builder;
3309 let host = run.build_triple();
3310 let compiler = run.builder.compiler_for(run.builder.top_stage, host, host);
3311
3312 if builder.doc_tests == DocTests::Only {
3313 return;
3314 }
3315
3316 if builder.download_rustc() {
3317 builder.info("CI rustc uses the default codegen backend. skipping");
3318 return;
3319 }
3320
3321 if !target_supports_cranelift_backend(run.target) {
3322 builder.info("target not supported by rustc_codegen_cranelift. skipping");
3323 return;
3324 }
3325
3326 if builder.remote_tested(run.target) {
3327 builder.info("remote testing is not supported by rustc_codegen_cranelift. skipping");
3328 return;
3329 }
3330
3331 if !builder.config.codegen_backends(run.target).contains(&"cranelift".to_owned()) {
3332 builder.info("cranelift not in rust.codegen-backends. skipping");
3333 return;
3334 }
3335
3336 builder.ensure(CodegenCranelift { compiler, target: run.target });
3337 }
3338
3339 fn run(self, builder: &Builder<'_>) {
3340 let compiler = self.compiler;
3341 let target = self.target;
3342
3343 builder.ensure(compile::Std::new(compiler, target));
3344
3345 let compiler = builder.compiler_for(compiler.stage, compiler.host, target);
3350
3351 let build_cargo = || {
3352 let mut cargo = builder::Cargo::new(
3353 builder,
3354 compiler,
3355 Mode::Codegen, SourceType::InTree,
3357 target,
3358 Kind::Run,
3359 );
3360
3361 cargo.current_dir(&builder.src.join("compiler/rustc_codegen_cranelift"));
3362 cargo
3363 .arg("--manifest-path")
3364 .arg(builder.src.join("compiler/rustc_codegen_cranelift/build_system/Cargo.toml"));
3365 compile::rustc_cargo_env(builder, &mut cargo, target, compiler.stage);
3366
3367 cargo.env("CARGO_BUILD_INCREMENTAL", "false");
3369
3370 cargo
3371 };
3372
3373 builder.info(&format!(
3374 "{} cranelift stage{} ({} -> {})",
3375 Kind::Test.description(),
3376 compiler.stage,
3377 &compiler.host,
3378 target
3379 ));
3380 let _time = helpers::timeit(builder);
3381
3382 let download_dir = builder.out.join("cg_clif_download");
3384
3385 let mut cargo = build_cargo();
3394 cargo
3395 .arg("--")
3396 .arg("test")
3397 .arg("--download-dir")
3398 .arg(&download_dir)
3399 .arg("--out-dir")
3400 .arg(builder.stage_out(compiler, Mode::ToolRustc).join("cg_clif"))
3401 .arg("--no-unstable-features")
3402 .arg("--use-backend")
3403 .arg("cranelift")
3404 .arg("--sysroot")
3406 .arg("llvm")
3407 .arg("--skip-test")
3410 .arg("testsuite.extended_sysroot");
3411
3412 cargo.into_cmd().run(builder);
3413 }
3414}
3415
3416#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3417pub struct CodegenGCC {
3418 compiler: Compiler,
3419 target: TargetSelection,
3420}
3421
3422impl Step for CodegenGCC {
3423 type Output = ();
3424 const DEFAULT: bool = true;
3425 const ONLY_HOSTS: bool = true;
3426
3427 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3428 run.paths(&["compiler/rustc_codegen_gcc"])
3429 }
3430
3431 fn make_run(run: RunConfig<'_>) {
3432 let builder = run.builder;
3433 let host = run.build_triple();
3434 let compiler = run.builder.compiler_for(run.builder.top_stage, host, host);
3435
3436 if builder.doc_tests == DocTests::Only {
3437 return;
3438 }
3439
3440 if builder.download_rustc() {
3441 builder.info("CI rustc uses the default codegen backend. skipping");
3442 return;
3443 }
3444
3445 let triple = run.target.triple;
3446 let target_supported =
3447 if triple.contains("linux") { triple.contains("x86_64") } else { false };
3448 if !target_supported {
3449 builder.info("target not supported by rustc_codegen_gcc. skipping");
3450 return;
3451 }
3452
3453 if builder.remote_tested(run.target) {
3454 builder.info("remote testing is not supported by rustc_codegen_gcc. skipping");
3455 return;
3456 }
3457
3458 if !builder.config.codegen_backends(run.target).contains(&"gcc".to_owned()) {
3459 builder.info("gcc not in rust.codegen-backends. skipping");
3460 return;
3461 }
3462
3463 builder.ensure(CodegenGCC { compiler, target: run.target });
3464 }
3465
3466 fn run(self, builder: &Builder<'_>) {
3467 let compiler = self.compiler;
3468 let target = self.target;
3469
3470 let gcc = builder.ensure(Gcc { target });
3471
3472 builder.ensure(
3473 compile::Std::new(compiler, target)
3474 .extra_rust_args(&["-Csymbol-mangling-version=v0", "-Cpanic=abort"]),
3475 );
3476
3477 let compiler = builder.compiler_for(compiler.stage, compiler.host, target);
3482
3483 let build_cargo = || {
3484 let mut cargo = builder::Cargo::new(
3485 builder,
3486 compiler,
3487 Mode::Codegen, SourceType::InTree,
3489 target,
3490 Kind::Run,
3491 );
3492
3493 cargo.current_dir(&builder.src.join("compiler/rustc_codegen_gcc"));
3494 cargo
3495 .arg("--manifest-path")
3496 .arg(builder.src.join("compiler/rustc_codegen_gcc/build_system/Cargo.toml"));
3497 compile::rustc_cargo_env(builder, &mut cargo, target, compiler.stage);
3498 add_cg_gcc_cargo_flags(&mut cargo, &gcc);
3499
3500 cargo.env("CARGO_BUILD_INCREMENTAL", "false");
3502 cargo.rustflag("-Cpanic=abort");
3503
3504 cargo
3505 };
3506
3507 builder.info(&format!(
3508 "{} GCC stage{} ({} -> {})",
3509 Kind::Test.description(),
3510 compiler.stage,
3511 &compiler.host,
3512 target
3513 ));
3514 let _time = helpers::timeit(builder);
3515
3516 let mut cargo = build_cargo();
3525
3526 cargo
3527 .env("CG_RUSTFLAGS", "-Alinker-messages")
3529 .arg("--")
3530 .arg("test")
3531 .arg("--use-backend")
3532 .arg("gcc")
3533 .arg("--gcc-path")
3534 .arg(gcc.libgccjit.parent().unwrap())
3535 .arg("--out-dir")
3536 .arg(builder.stage_out(compiler, Mode::ToolRustc).join("cg_gcc"))
3537 .arg("--release")
3538 .arg("--mini-tests")
3539 .arg("--std-tests");
3540 cargo.args(builder.config.test_args());
3541
3542 cargo.into_cmd().run(builder);
3543 }
3544}
3545
3546#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3551pub struct TestFloatParse {
3552 path: PathBuf,
3553 host: TargetSelection,
3554}
3555
3556impl Step for TestFloatParse {
3557 type Output = ();
3558 const ONLY_HOSTS: bool = true;
3559 const DEFAULT: bool = true;
3560
3561 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3562 run.path("src/etc/test-float-parse")
3563 }
3564
3565 fn make_run(run: RunConfig<'_>) {
3566 for path in run.paths {
3567 let path = path.assert_single_path().path.clone();
3568 run.builder.ensure(Self { path, host: run.target });
3569 }
3570 }
3571
3572 fn run(self, builder: &Builder<'_>) {
3573 let bootstrap_host = builder.config.build;
3574 let compiler = builder.compiler(builder.top_stage, bootstrap_host);
3575 let path = self.path.to_str().unwrap();
3576 let crate_name = self.path.iter().next_back().unwrap().to_str().unwrap();
3577
3578 builder.ensure(tool::TestFloatParse { host: self.host });
3579
3580 let mut cargo_test = tool::prepare_tool_cargo(
3582 builder,
3583 compiler,
3584 Mode::ToolStd,
3585 bootstrap_host,
3586 Kind::Test,
3587 path,
3588 SourceType::InTree,
3589 &[],
3590 );
3591 cargo_test.allow_features(tool::TestFloatParse::ALLOW_FEATURES);
3592
3593 run_cargo_test(cargo_test, &[], &[], crate_name, bootstrap_host, builder);
3594
3595 let mut cargo_run = tool::prepare_tool_cargo(
3597 builder,
3598 compiler,
3599 Mode::ToolStd,
3600 bootstrap_host,
3601 Kind::Run,
3602 path,
3603 SourceType::InTree,
3604 &[],
3605 );
3606 cargo_run.allow_features(tool::TestFloatParse::ALLOW_FEATURES);
3607
3608 if !matches!(env::var("FLOAT_PARSE_TESTS_NO_SKIP_HUGE").as_deref(), Ok("1") | Ok("true")) {
3609 cargo_run.args(["--", "--skip-huge"]);
3610 }
3611
3612 cargo_run.into_cmd().run(builder);
3613 }
3614}
3615
3616#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
3620pub struct CollectLicenseMetadata;
3621
3622impl Step for CollectLicenseMetadata {
3623 type Output = PathBuf;
3624 const ONLY_HOSTS: bool = true;
3625
3626 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3627 run.path("src/tools/collect-license-metadata")
3628 }
3629
3630 fn make_run(run: RunConfig<'_>) {
3631 run.builder.ensure(CollectLicenseMetadata);
3632 }
3633
3634 fn run(self, builder: &Builder<'_>) -> Self::Output {
3635 let Some(reuse) = &builder.config.reuse else {
3636 panic!("REUSE is required to collect the license metadata");
3637 };
3638
3639 let dest = builder.src.join("license-metadata.json");
3640
3641 let mut cmd = builder.tool_cmd(Tool::CollectLicenseMetadata);
3642 cmd.env("REUSE_EXE", reuse);
3643 cmd.env("DEST", &dest);
3644 cmd.env("ONLY_CHECK", "1");
3645 cmd.run(builder);
3646
3647 dest
3648 }
3649}