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.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 cargo.add_rustc_lib_path(builder);
787 let cargo = prepare_cargo_test(cargo, &[], &[], host, builder);
788
789 let _guard = builder.msg_sysroot_tool(Kind::Test, compiler.stage, "clippy", host, host);
790
791 if cargo.allow_failure().run(builder) {
793 return;
795 }
796
797 if !builder.config.cmd.bless() {
798 crate::exit!(1);
799 }
800 }
801}
802
803fn path_for_cargo(builder: &Builder<'_>, compiler: Compiler) -> OsString {
804 let path = builder.sysroot(compiler).join("bin");
808 let old_path = env::var_os("PATH").unwrap_or_default();
809 env::join_paths(iter::once(path).chain(env::split_paths(&old_path))).expect("")
810}
811
812#[derive(Debug, Clone, Hash, PartialEq, Eq)]
813pub struct RustdocTheme {
814 pub compiler: Compiler,
815}
816
817impl Step for RustdocTheme {
818 type Output = ();
819 const DEFAULT: bool = true;
820 const ONLY_HOSTS: bool = true;
821
822 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
823 run.path("src/tools/rustdoc-themes")
824 }
825
826 fn make_run(run: RunConfig<'_>) {
827 let compiler = run.builder.compiler(run.builder.top_stage, run.target);
828
829 run.builder.ensure(RustdocTheme { compiler });
830 }
831
832 fn run(self, builder: &Builder<'_>) {
833 let rustdoc = builder.bootstrap_out.join("rustdoc");
834 let mut cmd = builder.tool_cmd(Tool::RustdocTheme);
835 cmd.arg(rustdoc.to_str().unwrap())
836 .arg(builder.src.join("src/librustdoc/html/static/css/rustdoc.css").to_str().unwrap())
837 .env("RUSTC_STAGE", self.compiler.stage.to_string())
838 .env("RUSTC_SYSROOT", builder.sysroot(self.compiler))
839 .env("RUSTDOC_LIBDIR", builder.sysroot_target_libdir(self.compiler, self.compiler.host))
840 .env("CFG_RELEASE_CHANNEL", &builder.config.channel)
841 .env("RUSTDOC_REAL", builder.rustdoc(self.compiler))
842 .env("RUSTC_BOOTSTRAP", "1");
843 cmd.args(linker_args(builder, self.compiler.host, LldThreads::No));
844
845 cmd.delay_failure().run(builder);
846 }
847}
848
849#[derive(Debug, Clone, Hash, PartialEq, Eq)]
850pub struct RustdocJSStd {
851 pub target: TargetSelection,
852}
853
854impl Step for RustdocJSStd {
855 type Output = ();
856 const DEFAULT: bool = true;
857 const ONLY_HOSTS: bool = true;
858
859 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
860 let default = run.builder.config.nodejs.is_some();
861 run.suite_path("tests/rustdoc-js-std").default_condition(default)
862 }
863
864 fn make_run(run: RunConfig<'_>) {
865 run.builder.ensure(RustdocJSStd { target: run.target });
866 }
867
868 fn run(self, builder: &Builder<'_>) {
869 let nodejs =
870 builder.config.nodejs.as_ref().expect("need nodejs to run rustdoc-js-std tests");
871 let mut command = command(nodejs);
872 command
873 .arg(builder.src.join("src/tools/rustdoc-js/tester.js"))
874 .arg("--crate-name")
875 .arg("std")
876 .arg("--resource-suffix")
877 .arg(&builder.version)
878 .arg("--doc-folder")
879 .arg(builder.doc_out(self.target))
880 .arg("--test-folder")
881 .arg(builder.src.join("tests/rustdoc-js-std"));
882 for path in &builder.paths {
883 if let Some(p) = helpers::is_valid_test_suite_arg(path, "tests/rustdoc-js-std", builder)
884 {
885 if !p.ends_with(".js") {
886 eprintln!("A non-js file was given: `{}`", path.display());
887 panic!("Cannot run rustdoc-js-std tests");
888 }
889 command.arg("--test-file").arg(path);
890 }
891 }
892 builder.ensure(crate::core::build_steps::doc::Std::new(
893 builder.top_stage,
894 self.target,
895 DocumentationFormat::Html,
896 ));
897 let _guard = builder.msg(
898 Kind::Test,
899 builder.top_stage,
900 "rustdoc-js-std",
901 builder.config.build,
902 self.target,
903 );
904 command.run(builder);
905 }
906}
907
908#[derive(Debug, Clone, Hash, PartialEq, Eq)]
909pub struct RustdocJSNotStd {
910 pub target: TargetSelection,
911 pub compiler: Compiler,
912}
913
914impl Step for RustdocJSNotStd {
915 type Output = ();
916 const DEFAULT: bool = true;
917 const ONLY_HOSTS: bool = true;
918
919 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
920 let default = run.builder.config.nodejs.is_some();
921 run.suite_path("tests/rustdoc-js").default_condition(default)
922 }
923
924 fn make_run(run: RunConfig<'_>) {
925 let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
926 run.builder.ensure(RustdocJSNotStd { target: run.target, compiler });
927 }
928
929 fn run(self, builder: &Builder<'_>) {
930 builder.ensure(Compiletest {
931 compiler: self.compiler,
932 target: self.target,
933 mode: "rustdoc-js",
934 suite: "rustdoc-js",
935 path: "tests/rustdoc-js",
936 compare_mode: None,
937 });
938 }
939}
940
941fn get_browser_ui_test_version_inner(
942 builder: &Builder<'_>,
943 npm: &Path,
944 global: bool,
945) -> Option<String> {
946 let mut command = command(npm);
947 command.arg("list").arg("--parseable").arg("--long").arg("--depth=0");
948 if global {
949 command.arg("--global");
950 }
951 let lines = command.allow_failure().run_capture(builder).stdout();
952 lines
953 .lines()
954 .find_map(|l| l.split(':').nth(1)?.strip_prefix("browser-ui-test@"))
955 .map(|v| v.to_owned())
956}
957
958fn get_browser_ui_test_version(builder: &Builder<'_>, npm: &Path) -> Option<String> {
959 get_browser_ui_test_version_inner(builder, npm, false)
960 .or_else(|| get_browser_ui_test_version_inner(builder, npm, true))
961}
962
963#[derive(Debug, Clone, Hash, PartialEq, Eq)]
964pub struct RustdocGUI {
965 pub target: TargetSelection,
966 pub compiler: Compiler,
967}
968
969impl Step for RustdocGUI {
970 type Output = ();
971 const DEFAULT: bool = true;
972 const ONLY_HOSTS: bool = true;
973
974 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
975 let builder = run.builder;
976 let run = run.suite_path("tests/rustdoc-gui");
977 run.lazy_default_condition(Box::new(move || {
978 builder.config.nodejs.is_some()
979 && builder.doc_tests != DocTests::Only
980 && builder
981 .config
982 .npm
983 .as_ref()
984 .map(|p| get_browser_ui_test_version(builder, p).is_some())
985 .unwrap_or(false)
986 }))
987 }
988
989 fn make_run(run: RunConfig<'_>) {
990 let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
991 run.builder.ensure(RustdocGUI { target: run.target, compiler });
992 }
993
994 fn run(self, builder: &Builder<'_>) {
995 builder.ensure(compile::Std::new(self.compiler, self.target));
996
997 let mut cmd = builder.tool_cmd(Tool::RustdocGUITest);
998
999 let out_dir = builder.test_out(self.target).join("rustdoc-gui");
1000 build_stamp::clear_if_dirty(builder, &out_dir, &builder.rustdoc(self.compiler));
1001
1002 if let Some(src) = builder.config.src.to_str() {
1003 cmd.arg("--rust-src").arg(src);
1004 }
1005
1006 if let Some(out_dir) = out_dir.to_str() {
1007 cmd.arg("--out-dir").arg(out_dir);
1008 }
1009
1010 if let Some(initial_cargo) = builder.config.initial_cargo.to_str() {
1011 cmd.arg("--initial-cargo").arg(initial_cargo);
1012 }
1013
1014 cmd.arg("--jobs").arg(builder.jobs().to_string());
1015
1016 cmd.env("RUSTDOC", builder.rustdoc(self.compiler))
1017 .env("RUSTC", builder.rustc(self.compiler));
1018
1019 add_rustdoc_cargo_linker_args(&mut cmd, builder, self.compiler.host, LldThreads::No);
1020
1021 for path in &builder.paths {
1022 if let Some(p) = helpers::is_valid_test_suite_arg(path, "tests/rustdoc-gui", builder) {
1023 if !p.ends_with(".goml") {
1024 eprintln!("A non-goml file was given: `{}`", path.display());
1025 panic!("Cannot run rustdoc-gui tests");
1026 }
1027 if let Some(name) = path.file_name().and_then(|f| f.to_str()) {
1028 cmd.arg("--goml-file").arg(name);
1029 }
1030 }
1031 }
1032
1033 for test_arg in builder.config.test_args() {
1034 cmd.arg("--test-arg").arg(test_arg);
1035 }
1036
1037 if let Some(ref nodejs) = builder.config.nodejs {
1038 cmd.arg("--nodejs").arg(nodejs);
1039 }
1040
1041 if let Some(ref npm) = builder.config.npm {
1042 cmd.arg("--npm").arg(npm);
1043 }
1044
1045 let _time = helpers::timeit(builder);
1046 let _guard = builder.msg_sysroot_tool(
1047 Kind::Test,
1048 self.compiler.stage,
1049 "rustdoc-gui",
1050 self.compiler.host,
1051 self.target,
1052 );
1053 try_run_tests(builder, &mut cmd, true);
1054 }
1055}
1056
1057#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1062pub struct Tidy;
1063
1064impl Step for Tidy {
1065 type Output = ();
1066 const DEFAULT: bool = true;
1067 const ONLY_HOSTS: bool = true;
1068
1069 fn run(self, builder: &Builder<'_>) {
1078 let mut cmd = builder.tool_cmd(Tool::Tidy);
1079 cmd.arg(&builder.src);
1080 cmd.arg(&builder.initial_cargo);
1081 cmd.arg(&builder.out);
1082 let jobs = builder.config.jobs.unwrap_or_else(|| {
1084 8 * std::thread::available_parallelism().map_or(1, std::num::NonZeroUsize::get) as u32
1085 });
1086 cmd.arg(jobs.to_string());
1087 if builder.is_verbose() {
1088 cmd.arg("--verbose");
1089 }
1090 if builder.config.cmd.bless() {
1091 cmd.arg("--bless");
1092 }
1093 if let Some(s) = builder.config.cmd.extra_checks() {
1094 cmd.arg(format!("--extra-checks={s}"));
1095 }
1096 let mut args = std::env::args_os();
1097 if args.any(|arg| arg == OsStr::new("--")) {
1098 cmd.arg("--");
1099 cmd.args(args);
1100 }
1101
1102 if builder.config.channel == "dev" || builder.config.channel == "nightly" {
1103 if !builder.config.json_output {
1104 builder.info("fmt check");
1105 if builder.initial_rustfmt().is_none() {
1106 let inferred_rustfmt_dir = builder.initial_sysroot.join("bin");
1107 eprintln!(
1108 "\
1109ERROR: no `rustfmt` binary found in {PATH}
1110INFO: `rust.channel` is currently set to \"{CHAN}\"
1111HELP: if you are testing a beta branch, set `rust.channel` to \"beta\" in the `bootstrap.toml` file
1112HELP: to skip test's attempt to check tidiness, pass `--skip src/tools/tidy` to `x.py test`",
1113 PATH = inferred_rustfmt_dir.display(),
1114 CHAN = builder.config.channel,
1115 );
1116 crate::exit!(1);
1117 }
1118 let all = false;
1119 crate::core::build_steps::format::format(
1120 builder,
1121 !builder.config.cmd.bless(),
1122 all,
1123 &[],
1124 );
1125 } else {
1126 eprintln!(
1127 "WARNING: `--json-output` is not supported on rustfmt, formatting will be skipped"
1128 );
1129 }
1130 }
1131
1132 builder.info("tidy check");
1133 cmd.delay_failure().run(builder);
1134
1135 builder.info("x.py completions check");
1136 let [bash, zsh, fish, powershell] = ["x.py.sh", "x.py.zsh", "x.py.fish", "x.py.ps1"]
1137 .map(|filename| builder.src.join("src/etc/completions").join(filename));
1138 if builder.config.cmd.bless() {
1139 builder.ensure(crate::core::build_steps::run::GenerateCompletions);
1140 } else if get_completion(shells::Bash, &bash).is_some()
1141 || get_completion(shells::Fish, &fish).is_some()
1142 || get_completion(shells::PowerShell, &powershell).is_some()
1143 || crate::flags::get_completion(shells::Zsh, &zsh).is_some()
1144 {
1145 eprintln!(
1146 "x.py completions were changed; run `x.py run generate-completions` to update them"
1147 );
1148 crate::exit!(1);
1149 }
1150 }
1151
1152 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1153 let default = run.builder.doc_tests != DocTests::Only;
1154 run.path("src/tools/tidy").default_condition(default)
1155 }
1156
1157 fn make_run(run: RunConfig<'_>) {
1158 run.builder.ensure(Tidy);
1159 }
1160}
1161
1162fn testdir(builder: &Builder<'_>, host: TargetSelection) -> PathBuf {
1163 builder.out.join(host).join("test")
1164}
1165
1166macro_rules! test {
1168 (
1169 $( #[$attr:meta] )* $name:ident {
1171 path: $path:expr,
1172 mode: $mode:expr,
1173 suite: $suite:expr,
1174 default: $default:expr
1175 $( , only_hosts: $only_hosts:expr )? $( , compare_mode: $compare_mode:expr )? $( , )? }
1179 ) => {
1180 $( #[$attr] )*
1181 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
1182 pub struct $name {
1183 pub compiler: Compiler,
1184 pub target: TargetSelection,
1185 }
1186
1187 impl Step for $name {
1188 type Output = ();
1189 const DEFAULT: bool = $default;
1190 const ONLY_HOSTS: bool = (const {
1191 #[allow(unused_assignments, unused_mut)]
1192 let mut value = false;
1193 $( value = $only_hosts; )?
1194 value
1195 });
1196
1197 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1198 run.suite_path($path)
1199 }
1200
1201 fn make_run(run: RunConfig<'_>) {
1202 let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1203
1204 run.builder.ensure($name { compiler, target: run.target });
1205 }
1206
1207 fn run(self, builder: &Builder<'_>) {
1208 builder.ensure(Compiletest {
1209 compiler: self.compiler,
1210 target: self.target,
1211 mode: $mode,
1212 suite: $suite,
1213 path: $path,
1214 compare_mode: (const {
1215 #[allow(unused_assignments, unused_mut)]
1216 let mut value = None;
1217 $( value = $compare_mode; )?
1218 value
1219 }),
1220 })
1221 }
1222 }
1223 };
1224}
1225
1226#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1229pub struct CrateRunMakeSupport {
1230 host: TargetSelection,
1231}
1232
1233impl Step for CrateRunMakeSupport {
1234 type Output = ();
1235 const ONLY_HOSTS: bool = true;
1236
1237 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1238 run.path("src/tools/run-make-support")
1239 }
1240
1241 fn make_run(run: RunConfig<'_>) {
1242 run.builder.ensure(CrateRunMakeSupport { host: run.target });
1243 }
1244
1245 fn run(self, builder: &Builder<'_>) {
1247 let host = self.host;
1248 let compiler = builder.compiler(0, host);
1249
1250 let mut cargo = tool::prepare_tool_cargo(
1251 builder,
1252 compiler,
1253 Mode::ToolBootstrap,
1254 host,
1255 Kind::Test,
1256 "src/tools/run-make-support",
1257 SourceType::InTree,
1258 &[],
1259 );
1260 cargo.allow_features("test");
1261 run_cargo_test(cargo, &[], &[], "run-make-support self test", host, builder);
1262 }
1263}
1264
1265#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1266pub struct CrateBuildHelper {
1267 host: TargetSelection,
1268}
1269
1270impl Step for CrateBuildHelper {
1271 type Output = ();
1272 const ONLY_HOSTS: bool = true;
1273
1274 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1275 run.path("src/build_helper")
1276 }
1277
1278 fn make_run(run: RunConfig<'_>) {
1279 run.builder.ensure(CrateBuildHelper { host: run.target });
1280 }
1281
1282 fn run(self, builder: &Builder<'_>) {
1284 let host = self.host;
1285 let compiler = builder.compiler(0, host);
1286
1287 let mut cargo = tool::prepare_tool_cargo(
1288 builder,
1289 compiler,
1290 Mode::ToolBootstrap,
1291 host,
1292 Kind::Test,
1293 "src/build_helper",
1294 SourceType::InTree,
1295 &[],
1296 );
1297 cargo.allow_features("test");
1298 run_cargo_test(cargo, &[], &[], "build_helper self test", host, builder);
1299 }
1300}
1301
1302test!(Ui { path: "tests/ui", mode: "ui", suite: "ui", default: true });
1303
1304test!(Crashes { path: "tests/crashes", mode: "crashes", suite: "crashes", default: true });
1305
1306test!(Codegen { path: "tests/codegen", mode: "codegen", suite: "codegen", default: true });
1307
1308test!(CodegenUnits {
1309 path: "tests/codegen-units",
1310 mode: "codegen-units",
1311 suite: "codegen-units",
1312 default: true,
1313});
1314
1315test!(Incremental {
1316 path: "tests/incremental",
1317 mode: "incremental",
1318 suite: "incremental",
1319 default: true,
1320});
1321
1322test!(Debuginfo {
1323 path: "tests/debuginfo",
1324 mode: "debuginfo",
1325 suite: "debuginfo",
1326 default: true,
1327 compare_mode: Some("split-dwarf"),
1328});
1329
1330test!(UiFullDeps {
1331 path: "tests/ui-fulldeps",
1332 mode: "ui",
1333 suite: "ui-fulldeps",
1334 default: true,
1335 only_hosts: true,
1336});
1337
1338test!(Rustdoc {
1339 path: "tests/rustdoc",
1340 mode: "rustdoc",
1341 suite: "rustdoc",
1342 default: true,
1343 only_hosts: true,
1344});
1345test!(RustdocUi {
1346 path: "tests/rustdoc-ui",
1347 mode: "ui",
1348 suite: "rustdoc-ui",
1349 default: true,
1350 only_hosts: true,
1351});
1352
1353test!(RustdocJson {
1354 path: "tests/rustdoc-json",
1355 mode: "rustdoc-json",
1356 suite: "rustdoc-json",
1357 default: true,
1358 only_hosts: true,
1359});
1360
1361test!(Pretty {
1362 path: "tests/pretty",
1363 mode: "pretty",
1364 suite: "pretty",
1365 default: true,
1366 only_hosts: true,
1367});
1368
1369test!(RunMake { path: "tests/run-make", mode: "run-make", suite: "run-make", default: true });
1370
1371test!(Assembly { path: "tests/assembly", mode: "assembly", suite: "assembly", default: true });
1372
1373#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
1376pub struct Coverage {
1377 pub compiler: Compiler,
1378 pub target: TargetSelection,
1379 pub mode: &'static str,
1380}
1381
1382impl Coverage {
1383 const PATH: &'static str = "tests/coverage";
1384 const SUITE: &'static str = "coverage";
1385 const ALL_MODES: &[&str] = &["coverage-map", "coverage-run"];
1386}
1387
1388impl Step for Coverage {
1389 type Output = ();
1390 const DEFAULT: bool = true;
1391 const ONLY_HOSTS: bool = false;
1393
1394 fn should_run(mut run: ShouldRun<'_>) -> ShouldRun<'_> {
1395 run = run.suite_path(Self::PATH);
1401 for mode in Self::ALL_MODES {
1402 run = run.alias(mode);
1403 }
1404 run
1405 }
1406
1407 fn make_run(run: RunConfig<'_>) {
1408 let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1409 let target = run.target;
1410
1411 let mut modes = vec![];
1415
1416 for path in &run.paths {
1419 match path {
1420 PathSet::Set(_) => {
1421 for mode in Self::ALL_MODES {
1422 if path.assert_single_path().path == Path::new(mode) {
1423 modes.push(mode);
1424 break;
1425 }
1426 }
1427 }
1428 PathSet::Suite(_) => {
1429 modes.extend(Self::ALL_MODES);
1430 break;
1431 }
1432 }
1433 }
1434
1435 modes.retain(|mode| !run.builder.config.skip.iter().any(|skip| skip == Path::new(mode)));
1438
1439 for mode in modes {
1447 run.builder.ensure(Coverage { compiler, target, mode });
1448 }
1449 }
1450
1451 fn run(self, builder: &Builder<'_>) {
1452 let Self { compiler, target, mode } = self;
1453 builder.ensure(Compiletest {
1456 compiler,
1457 target,
1458 mode,
1459 suite: Self::SUITE,
1460 path: Self::PATH,
1461 compare_mode: None,
1462 });
1463 }
1464}
1465
1466test!(CoverageRunRustdoc {
1467 path: "tests/coverage-run-rustdoc",
1468 mode: "coverage-run",
1469 suite: "coverage-run-rustdoc",
1470 default: true,
1471 only_hosts: true,
1472});
1473
1474#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1476pub struct MirOpt {
1477 pub compiler: Compiler,
1478 pub target: TargetSelection,
1479}
1480
1481impl Step for MirOpt {
1482 type Output = ();
1483 const DEFAULT: bool = true;
1484 const ONLY_HOSTS: bool = false;
1485
1486 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1487 run.suite_path("tests/mir-opt")
1488 }
1489
1490 fn make_run(run: RunConfig<'_>) {
1491 let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1492 run.builder.ensure(MirOpt { compiler, target: run.target });
1493 }
1494
1495 fn run(self, builder: &Builder<'_>) {
1496 let run = |target| {
1497 builder.ensure(Compiletest {
1498 compiler: self.compiler,
1499 target,
1500 mode: "mir-opt",
1501 suite: "mir-opt",
1502 path: "tests/mir-opt",
1503 compare_mode: None,
1504 })
1505 };
1506
1507 run(self.target);
1508
1509 if builder.config.cmd.bless() {
1512 for target in ["aarch64-unknown-linux-gnu", "i686-pc-windows-msvc"] {
1518 run(TargetSelection::from_user(target));
1519 }
1520
1521 for target in ["x86_64-apple-darwin", "i686-unknown-linux-musl"] {
1522 let target = TargetSelection::from_user(target);
1523 let panic_abort_target = builder.ensure(MirOptPanicAbortSyntheticTarget {
1524 compiler: self.compiler,
1525 base: target,
1526 });
1527 run(panic_abort_target);
1528 }
1529 }
1530 }
1531}
1532
1533#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1534struct Compiletest {
1535 compiler: Compiler,
1536 target: TargetSelection,
1537 mode: &'static str,
1538 suite: &'static str,
1539 path: &'static str,
1540 compare_mode: Option<&'static str>,
1541}
1542
1543impl Step for Compiletest {
1544 type Output = ();
1545
1546 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1547 run.never()
1548 }
1549
1550 fn run(self, builder: &Builder<'_>) {
1556 if builder.doc_tests == DocTests::Only {
1557 return;
1558 }
1559
1560 if builder.top_stage == 0 && env::var("COMPILETEST_FORCE_STAGE0").is_err() {
1561 eprintln!("\
1562ERROR: `--stage 0` runs compiletest on the beta compiler, not your local changes, and will almost always cause tests to fail
1563HELP: to test the compiler, use `--stage 1` instead
1564HELP: to test the standard library, use `--stage 0 library/std` instead
1565NOTE: 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`."
1566 );
1567 crate::exit!(1);
1568 }
1569
1570 let mut compiler = self.compiler;
1571 let target = self.target;
1572 let mode = self.mode;
1573 let suite = self.suite;
1574
1575 let suite_path = self.path;
1577
1578 if !builder.config.codegen_tests && suite == "codegen" {
1580 return;
1581 }
1582
1583 let (stage, stage_id) = if suite == "ui-fulldeps" && compiler.stage == 1 {
1590 let build = builder.build.build;
1594 compiler = builder.compiler(compiler.stage - 1, build);
1595 let test_stage = compiler.stage + 1;
1596 (test_stage, format!("stage{}-{}", test_stage, build))
1597 } else {
1598 let stage = compiler.stage;
1599 (stage, format!("stage{}-{}", stage, target))
1600 };
1601
1602 if suite.ends_with("fulldeps") {
1603 builder.ensure(compile::Rustc::new(compiler, target));
1604 }
1605
1606 if suite == "debuginfo" {
1607 builder.ensure(dist::DebuggerScripts {
1608 sysroot: builder.sysroot(compiler).to_path_buf(),
1609 host: target,
1610 });
1611 }
1612 if suite == "run-make" {
1613 builder.tool_exe(Tool::RunMakeSupport);
1614 }
1615
1616 if suite == "mir-opt" {
1618 builder.ensure(compile::Std::new(compiler, compiler.host).is_for_mir_opt_tests(true));
1619 } else {
1620 builder.ensure(compile::Std::new(compiler, compiler.host));
1621 }
1622
1623 let mut cmd = builder.tool_cmd(Tool::Compiletest);
1624
1625 if suite == "mir-opt" {
1626 builder.ensure(compile::Std::new(compiler, target).is_for_mir_opt_tests(true));
1627 } else {
1628 builder.ensure(compile::Std::new(compiler, target));
1629 }
1630
1631 builder.ensure(RemoteCopyLibs { compiler, target });
1632
1633 cmd.arg("--stage").arg(stage.to_string());
1637 cmd.arg("--stage-id").arg(stage_id);
1638
1639 cmd.arg("--compile-lib-path").arg(builder.rustc_libdir(compiler));
1640 cmd.arg("--run-lib-path").arg(builder.sysroot_target_libdir(compiler, target));
1641 cmd.arg("--rustc-path").arg(builder.rustc(compiler));
1642
1643 cmd.arg("--minicore-path")
1646 .arg(builder.src.join("tests").join("auxiliary").join("minicore.rs"));
1647
1648 let is_rustdoc = suite == "rustdoc-ui" || suite == "rustdoc-js";
1649
1650 if mode == "run-make" {
1651 let cargo_path = if builder.top_stage == 0 {
1652 builder.initial_cargo.clone()
1654 } else {
1655 builder.ensure(tool::Cargo { compiler, target: compiler.host }).tool_path
1656 };
1657
1658 cmd.arg("--cargo-path").arg(cargo_path);
1659
1660 let stage0_rustc_path = builder.compiler(0, compiler.host);
1663 cmd.arg("--stage0-rustc-path").arg(builder.rustc(stage0_rustc_path));
1664 }
1665
1666 if mode == "rustdoc"
1668 || mode == "run-make"
1669 || (mode == "ui" && is_rustdoc)
1670 || mode == "rustdoc-js"
1671 || mode == "rustdoc-json"
1672 || suite == "coverage-run-rustdoc"
1673 {
1674 cmd.arg("--rustdoc-path").arg(builder.rustdoc(compiler));
1675 }
1676
1677 if mode == "rustdoc-json" {
1678 let json_compiler = compiler.with_stage(0);
1680 cmd.arg("--jsondocck-path")
1681 .arg(builder.ensure(tool::JsonDocCk { compiler: json_compiler, target }).tool_path);
1682 cmd.arg("--jsondoclint-path").arg(
1683 builder.ensure(tool::JsonDocLint { compiler: json_compiler, target }).tool_path,
1684 );
1685 }
1686
1687 if matches!(mode, "coverage-map" | "coverage-run") {
1688 let coverage_dump = builder.tool_exe(Tool::CoverageDump);
1689 cmd.arg("--coverage-dump-path").arg(coverage_dump);
1690 }
1691
1692 cmd.arg("--src-root").arg(&builder.src);
1693 cmd.arg("--src-test-suite-root").arg(builder.src.join("tests").join(suite));
1694
1695 cmd.arg("--build-root").arg(&builder.out);
1699 cmd.arg("--build-test-suite-root").arg(testdir(builder, compiler.host).join(suite));
1700
1701 let sysroot = if builder.top_stage == 0 {
1704 builder.initial_sysroot.clone()
1705 } else {
1706 builder.sysroot(compiler)
1707 };
1708
1709 cmd.arg("--sysroot-base").arg(sysroot);
1710
1711 cmd.arg("--suite").arg(suite);
1712 cmd.arg("--mode").arg(mode);
1713 cmd.arg("--target").arg(target.rustc_target_arg());
1714 cmd.arg("--host").arg(&*compiler.host.triple);
1715 cmd.arg("--llvm-filecheck").arg(builder.llvm_filecheck(builder.config.build));
1716
1717 if builder.build.config.llvm_enzyme {
1718 cmd.arg("--has-enzyme");
1719 }
1720
1721 if builder.config.cmd.bless() {
1722 cmd.arg("--bless");
1723 }
1724
1725 if builder.config.cmd.force_rerun() {
1726 cmd.arg("--force-rerun");
1727 }
1728
1729 if builder.config.cmd.no_capture() {
1730 cmd.arg("--no-capture");
1731 }
1732
1733 let compare_mode =
1734 builder.config.cmd.compare_mode().or_else(|| {
1735 if builder.config.test_compare_mode { self.compare_mode } else { None }
1736 });
1737
1738 if let Some(ref pass) = builder.config.cmd.pass() {
1739 cmd.arg("--pass");
1740 cmd.arg(pass);
1741 }
1742
1743 if let Some(ref run) = builder.config.cmd.run() {
1744 cmd.arg("--run");
1745 cmd.arg(run);
1746 }
1747
1748 if let Some(ref nodejs) = builder.config.nodejs {
1749 cmd.arg("--nodejs").arg(nodejs);
1750 } else if mode == "rustdoc-js" {
1751 panic!("need nodejs to run rustdoc-js suite");
1752 }
1753 if let Some(ref npm) = builder.config.npm {
1754 cmd.arg("--npm").arg(npm);
1755 }
1756 if builder.config.rust_optimize_tests {
1757 cmd.arg("--optimize-tests");
1758 }
1759 if builder.config.rust_randomize_layout {
1760 cmd.arg("--rust-randomized-layout");
1761 }
1762 if builder.config.cmd.only_modified() {
1763 cmd.arg("--only-modified");
1764 }
1765 if let Some(compiletest_diff_tool) = &builder.config.compiletest_diff_tool {
1766 cmd.arg("--compiletest-diff-tool").arg(compiletest_diff_tool);
1767 }
1768
1769 let mut flags = if is_rustdoc { Vec::new() } else { vec!["-Crpath".to_string()] };
1770 flags.push(format!("-Cdebuginfo={}", builder.config.rust_debuginfo_level_tests));
1771 flags.extend(builder.config.cmd.compiletest_rustc_args().iter().map(|s| s.to_string()));
1772
1773 if suite != "mir-opt" {
1774 if let Some(linker) = builder.linker(target) {
1775 cmd.arg("--target-linker").arg(linker);
1776 }
1777 if let Some(linker) = builder.linker(compiler.host) {
1778 cmd.arg("--host-linker").arg(linker);
1779 }
1780 }
1781
1782 if suite == "ui-fulldeps" && target.ends_with("darwin") {
1784 flags.push("-Alinker_messages".into());
1785 }
1786
1787 let mut hostflags = flags.clone();
1788 hostflags.extend(linker_flags(builder, compiler.host, LldThreads::No));
1789
1790 let mut targetflags = flags;
1791
1792 if suite == "ui" || suite == "incremental" {
1794 builder.ensure(TestHelpers { target: compiler.host });
1795 builder.ensure(TestHelpers { target });
1796 hostflags
1797 .push(format!("-Lnative={}", builder.test_helpers_out(compiler.host).display()));
1798 targetflags.push(format!("-Lnative={}", builder.test_helpers_out(target).display()));
1799 }
1800
1801 for flag in hostflags {
1802 cmd.arg("--host-rustcflags").arg(flag);
1803 }
1804 for flag in targetflags {
1805 cmd.arg("--target-rustcflags").arg(flag);
1806 }
1807
1808 cmd.arg("--python").arg(builder.python());
1809
1810 if let Some(ref gdb) = builder.config.gdb {
1811 cmd.arg("--gdb").arg(gdb);
1812 }
1813
1814 let lldb_exe = builder.config.lldb.clone().unwrap_or_else(|| PathBuf::from("lldb"));
1815 let lldb_version = command(&lldb_exe)
1816 .allow_failure()
1817 .arg("--version")
1818 .run_capture(builder)
1819 .stdout_if_ok()
1820 .and_then(|v| if v.trim().is_empty() { None } else { Some(v) });
1821 if let Some(ref vers) = lldb_version {
1822 cmd.arg("--lldb-version").arg(vers);
1823 let lldb_python_dir = command(&lldb_exe)
1824 .allow_failure()
1825 .arg("-P")
1826 .run_capture_stdout(builder)
1827 .stdout_if_ok()
1828 .map(|p| p.lines().next().expect("lldb Python dir not found").to_string());
1829 if let Some(ref dir) = lldb_python_dir {
1830 cmd.arg("--lldb-python-dir").arg(dir);
1831 }
1832 }
1833
1834 if helpers::forcing_clang_based_tests() {
1835 let clang_exe = builder.llvm_out(target).join("bin").join("clang");
1836 cmd.arg("--run-clang-based-tests-with").arg(clang_exe);
1837 }
1838
1839 for exclude in &builder.config.skip {
1840 cmd.arg("--skip");
1841 cmd.arg(exclude);
1842 }
1843
1844 let paths = match &builder.config.cmd {
1846 Subcommand::Test { .. } => &builder.config.paths[..],
1847 _ => &[],
1848 };
1849
1850 let mut test_args: Vec<&str> = paths
1852 .iter()
1853 .filter_map(|p| helpers::is_valid_test_suite_arg(p, suite_path, builder))
1854 .collect();
1855
1856 test_args.append(&mut builder.config.test_args());
1857
1858 if cfg!(windows) {
1861 let test_args_win: Vec<String> =
1862 test_args.iter().map(|s| s.replace('/', "\\")).collect();
1863 cmd.args(&test_args_win);
1864 } else {
1865 cmd.args(&test_args);
1866 }
1867
1868 if builder.is_verbose() {
1869 cmd.arg("--verbose");
1870 }
1871
1872 cmd.arg("--json");
1873
1874 if builder.config.rustc_debug_assertions {
1875 cmd.arg("--with-rustc-debug-assertions");
1876 }
1877
1878 if builder.config.std_debug_assertions {
1879 cmd.arg("--with-std-debug-assertions");
1880 }
1881
1882 let mut llvm_components_passed = false;
1883 let mut copts_passed = false;
1884 if builder.config.llvm_enabled(compiler.host) {
1885 let llvm::LlvmResult { llvm_config, .. } =
1886 builder.ensure(llvm::Llvm { target: builder.config.build });
1887 if !builder.config.dry_run() {
1888 let llvm_version = get_llvm_version(builder, &llvm_config);
1889 let llvm_components =
1890 command(&llvm_config).arg("--components").run_capture_stdout(builder).stdout();
1891 cmd.arg("--llvm-version")
1893 .arg(llvm_version.trim())
1894 .arg("--llvm-components")
1895 .arg(llvm_components.trim());
1896 llvm_components_passed = true;
1897 }
1898 if !builder.config.is_rust_llvm(target) {
1899 cmd.arg("--system-llvm");
1900 }
1901
1902 if !builder.config.dry_run() && suite.ends_with("fulldeps") {
1907 let llvm_libdir =
1908 command(&llvm_config).arg("--libdir").run_capture_stdout(builder).stdout();
1909 let link_llvm = if target.is_msvc() {
1910 format!("-Clink-arg=-LIBPATH:{llvm_libdir}")
1911 } else {
1912 format!("-Clink-arg=-L{llvm_libdir}")
1913 };
1914 cmd.arg("--host-rustcflags").arg(link_llvm);
1915 }
1916
1917 if !builder.config.dry_run() && matches!(mode, "run-make" | "coverage-run") {
1918 let llvm_bin_path = llvm_config
1923 .parent()
1924 .expect("Expected llvm-config to be contained in directory");
1925 assert!(llvm_bin_path.is_dir());
1926 cmd.arg("--llvm-bin-dir").arg(llvm_bin_path);
1927 }
1928
1929 if !builder.config.dry_run() && mode == "run-make" {
1930 if builder.config.lld_enabled {
1932 let lld_install_root =
1933 builder.ensure(llvm::Lld { target: builder.config.build });
1934
1935 let lld_bin_path = lld_install_root.join("bin");
1936
1937 let old_path = env::var_os("PATH").unwrap_or_default();
1938 let new_path = env::join_paths(
1939 std::iter::once(lld_bin_path).chain(env::split_paths(&old_path)),
1940 )
1941 .expect("Could not add LLD bin path to PATH");
1942 cmd.env("PATH", new_path);
1943 }
1944 }
1945 }
1946
1947 if !builder.config.dry_run() && mode == "run-make" {
1950 let mut cflags = builder.cc_handled_clags(target, CLang::C);
1951 cflags.extend(builder.cc_unhandled_cflags(target, GitRepo::Rustc, CLang::C));
1952 let mut cxxflags = builder.cc_handled_clags(target, CLang::Cxx);
1953 cxxflags.extend(builder.cc_unhandled_cflags(target, GitRepo::Rustc, CLang::Cxx));
1954 cmd.arg("--cc")
1955 .arg(builder.cc(target))
1956 .arg("--cxx")
1957 .arg(builder.cxx(target).unwrap())
1958 .arg("--cflags")
1959 .arg(cflags.join(" "))
1960 .arg("--cxxflags")
1961 .arg(cxxflags.join(" "));
1962 copts_passed = true;
1963 if let Some(ar) = builder.ar(target) {
1964 cmd.arg("--ar").arg(ar);
1965 }
1966 }
1967
1968 if !llvm_components_passed {
1969 cmd.arg("--llvm-components").arg("");
1970 }
1971 if !copts_passed {
1972 cmd.arg("--cc")
1973 .arg("")
1974 .arg("--cxx")
1975 .arg("")
1976 .arg("--cflags")
1977 .arg("")
1978 .arg("--cxxflags")
1979 .arg("");
1980 }
1981
1982 if builder.remote_tested(target) {
1983 cmd.arg("--remote-test-client").arg(builder.tool_exe(Tool::RemoteTestClient));
1984 } else if let Some(tool) = builder.runner(target) {
1985 cmd.arg("--runner").arg(tool);
1986 }
1987
1988 if suite != "mir-opt" {
1989 if !builder.config.dry_run() && target.is_msvc() {
1995 for (k, v) in builder.cc.borrow()[&target].env() {
1996 if k != "PATH" {
1997 cmd.env(k, v);
1998 }
1999 }
2000 }
2001 }
2002
2003 if !builder.config.dry_run()
2005 && target.contains("msvc")
2006 && builder.config.sanitizers_enabled(target)
2007 {
2008 cmd.env("ASAN_WIN_CONTINUE_ON_INTERCEPTION_FAILURE", "1");
2011 let asan_runtime_path =
2013 builder.cc.borrow()[&target].path().parent().unwrap().to_path_buf();
2014 let old_path = cmd
2015 .get_envs()
2016 .find_map(|(k, v)| (k == "PATH").then_some(v))
2017 .flatten()
2018 .map_or_else(|| env::var_os("PATH").unwrap_or_default(), |v| v.to_owned());
2019 let new_path = env::join_paths(
2020 env::split_paths(&old_path).chain(std::iter::once(asan_runtime_path)),
2021 )
2022 .expect("Could not add ASAN runtime path to PATH");
2023 cmd.env("PATH", new_path);
2024 }
2025
2026 cmd.env_remove("CARGO");
2029
2030 cmd.env("RUSTC_BOOTSTRAP", "1");
2031 cmd.env("RUSTC_FORCE_RUSTC_VERSION", "compiletest");
2034 cmd.env("DOC_RUST_LANG_ORG_CHANNEL", builder.doc_rust_lang_org_channel());
2035 builder.add_rust_test_threads(&mut cmd);
2036
2037 if builder.config.sanitizers_enabled(target) {
2038 cmd.env("RUSTC_SANITIZER_SUPPORT", "1");
2039 }
2040
2041 if builder.config.profiler_enabled(target) {
2042 cmd.arg("--profiler-runtime");
2043 }
2044
2045 cmd.env("RUST_TEST_TMPDIR", builder.tempdir());
2046
2047 cmd.arg("--adb-path").arg("adb");
2048 cmd.arg("--adb-test-dir").arg(ADB_TEST_DIR);
2049 if target.contains("android") && !builder.config.dry_run() {
2050 cmd.arg("--android-cross-path")
2052 .arg(builder.cc(target).parent().unwrap().parent().unwrap());
2053 } else {
2054 cmd.arg("--android-cross-path").arg("");
2055 }
2056
2057 if builder.config.cmd.rustfix_coverage() {
2058 cmd.arg("--rustfix-coverage");
2059 }
2060
2061 cmd.arg("--channel").arg(&builder.config.channel);
2062
2063 if !builder.config.omit_git_hash {
2064 cmd.arg("--git-hash");
2065 }
2066
2067 let git_config = builder.config.git_config();
2068 cmd.arg("--nightly-branch").arg(git_config.nightly_branch);
2069 cmd.arg("--git-merge-commit-email").arg(git_config.git_merge_commit_email);
2070 cmd.force_coloring_in_ci();
2071
2072 #[cfg(feature = "build-metrics")]
2073 builder.metrics.begin_test_suite(
2074 build_helper::metrics::TestSuiteMetadata::Compiletest {
2075 suite: suite.into(),
2076 mode: mode.into(),
2077 compare_mode: None,
2078 target: self.target.triple.to_string(),
2079 host: self.compiler.host.triple.to_string(),
2080 stage: self.compiler.stage,
2081 },
2082 builder,
2083 );
2084
2085 let _group = builder.msg(
2086 Kind::Test,
2087 compiler.stage,
2088 format!("compiletest suite={suite} mode={mode}"),
2089 compiler.host,
2090 target,
2091 );
2092 try_run_tests(builder, &mut cmd, false);
2093
2094 if let Some(compare_mode) = compare_mode {
2095 cmd.arg("--compare-mode").arg(compare_mode);
2096
2097 #[cfg(feature = "build-metrics")]
2098 builder.metrics.begin_test_suite(
2099 build_helper::metrics::TestSuiteMetadata::Compiletest {
2100 suite: suite.into(),
2101 mode: mode.into(),
2102 compare_mode: Some(compare_mode.into()),
2103 target: self.target.triple.to_string(),
2104 host: self.compiler.host.triple.to_string(),
2105 stage: self.compiler.stage,
2106 },
2107 builder,
2108 );
2109
2110 builder.info(&format!(
2111 "Check compiletest suite={} mode={} compare_mode={} ({} -> {})",
2112 suite, mode, compare_mode, &compiler.host, target
2113 ));
2114 let _time = helpers::timeit(builder);
2115 try_run_tests(builder, &mut cmd, false);
2116 }
2117 }
2118}
2119
2120#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2121struct BookTest {
2122 compiler: Compiler,
2123 path: PathBuf,
2124 name: &'static str,
2125 is_ext_doc: bool,
2126 dependencies: Vec<&'static str>,
2127}
2128
2129impl Step for BookTest {
2130 type Output = ();
2131 const ONLY_HOSTS: bool = true;
2132
2133 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2134 run.never()
2135 }
2136
2137 fn run(self, builder: &Builder<'_>) {
2141 if self.is_ext_doc {
2151 self.run_ext_doc(builder);
2152 } else {
2153 self.run_local_doc(builder);
2154 }
2155 }
2156}
2157
2158impl BookTest {
2159 fn run_ext_doc(self, builder: &Builder<'_>) {
2162 let compiler = self.compiler;
2163
2164 builder.ensure(compile::Std::new(compiler, compiler.host));
2165
2166 let mut rustdoc_path = builder.rustdoc(compiler);
2169 rustdoc_path.pop();
2170 let old_path = env::var_os("PATH").unwrap_or_default();
2171 let new_path = env::join_paths(iter::once(rustdoc_path).chain(env::split_paths(&old_path)))
2172 .expect("could not add rustdoc to PATH");
2173
2174 let mut rustbook_cmd = builder.tool_cmd(Tool::Rustbook);
2175 let path = builder.src.join(&self.path);
2176 rustbook_cmd.env("RUSTC_BOOTSTRAP", "1");
2178 rustbook_cmd.env("PATH", new_path).arg("test").arg(path);
2179
2180 let libs = if !self.dependencies.is_empty() {
2185 let mut lib_paths = vec![];
2186 for dep in self.dependencies {
2187 let mode = Mode::ToolRustc;
2188 let target = builder.config.build;
2189 let cargo = tool::prepare_tool_cargo(
2190 builder,
2191 compiler,
2192 mode,
2193 target,
2194 Kind::Build,
2195 dep,
2196 SourceType::Submodule,
2197 &[],
2198 );
2199
2200 let stamp = BuildStamp::new(&builder.cargo_out(compiler, mode, target))
2201 .with_prefix(PathBuf::from(dep).file_name().and_then(|v| v.to_str()).unwrap());
2202
2203 let output_paths = run_cargo(builder, cargo, vec![], &stamp, vec![], false, false);
2204 let directories = output_paths
2205 .into_iter()
2206 .filter_map(|p| p.parent().map(ToOwned::to_owned))
2207 .fold(HashSet::new(), |mut set, dir| {
2208 set.insert(dir);
2209 set
2210 });
2211
2212 lib_paths.extend(directories);
2213 }
2214 lib_paths
2215 } else {
2216 vec![]
2217 };
2218
2219 if !libs.is_empty() {
2220 let paths = libs
2221 .into_iter()
2222 .map(|path| path.into_os_string())
2223 .collect::<Vec<OsString>>()
2224 .join(OsStr::new(","));
2225 rustbook_cmd.args([OsString::from("--library-path"), paths]);
2226 }
2227
2228 builder.add_rust_test_threads(&mut rustbook_cmd);
2229 let _guard = builder.msg(
2230 Kind::Test,
2231 compiler.stage,
2232 format_args!("mdbook {}", self.path.display()),
2233 compiler.host,
2234 compiler.host,
2235 );
2236 let _time = helpers::timeit(builder);
2237 let toolstate = if rustbook_cmd.delay_failure().run(builder) {
2238 ToolState::TestPass
2239 } else {
2240 ToolState::TestFail
2241 };
2242 builder.save_toolstate(self.name, toolstate);
2243 }
2244
2245 fn run_local_doc(self, builder: &Builder<'_>) {
2247 let compiler = self.compiler;
2248 let host = self.compiler.host;
2249
2250 builder.ensure(compile::Std::new(compiler, host));
2251
2252 let _guard =
2253 builder.msg(Kind::Test, compiler.stage, format!("book {}", self.name), host, host);
2254
2255 let mut stack = vec![builder.src.join(self.path)];
2258 let _time = helpers::timeit(builder);
2259 let mut files = Vec::new();
2260 while let Some(p) = stack.pop() {
2261 if p.is_dir() {
2262 stack.extend(t!(p.read_dir()).map(|p| t!(p).path()));
2263 continue;
2264 }
2265
2266 if p.extension().and_then(|s| s.to_str()) != Some("md") {
2267 continue;
2268 }
2269
2270 files.push(p);
2271 }
2272
2273 files.sort();
2274
2275 for file in files {
2276 markdown_test(builder, compiler, &file);
2277 }
2278 }
2279}
2280
2281macro_rules! test_book {
2282 ($(
2283 $name:ident, $path:expr, $book_name:expr,
2284 default=$default:expr
2285 $(,submodules = $submodules:expr)?
2286 $(,dependencies=$dependencies:expr)?
2287 ;
2288 )+) => {
2289 $(
2290 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
2291 pub struct $name {
2292 compiler: Compiler,
2293 }
2294
2295 impl Step for $name {
2296 type Output = ();
2297 const DEFAULT: bool = $default;
2298 const ONLY_HOSTS: bool = true;
2299
2300 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2301 run.path($path)
2302 }
2303
2304 fn make_run(run: RunConfig<'_>) {
2305 run.builder.ensure($name {
2306 compiler: run.builder.compiler(run.builder.top_stage, run.target),
2307 });
2308 }
2309
2310 fn run(self, builder: &Builder<'_>) {
2311 $(
2312 for submodule in $submodules {
2313 builder.require_submodule(submodule, None);
2314 }
2315 )*
2316
2317 let dependencies = vec![];
2318 $(
2319 let mut dependencies = dependencies;
2320 for dep in $dependencies {
2321 dependencies.push(dep);
2322 }
2323 )?
2324
2325 builder.ensure(BookTest {
2326 compiler: self.compiler,
2327 path: PathBuf::from($path),
2328 name: $book_name,
2329 is_ext_doc: !$default,
2330 dependencies,
2331 });
2332 }
2333 }
2334 )+
2335 }
2336}
2337
2338test_book!(
2339 Nomicon, "src/doc/nomicon", "nomicon", default=false, submodules=["src/doc/nomicon"];
2340 Reference, "src/doc/reference", "reference", default=false, submodules=["src/doc/reference"];
2341 RustdocBook, "src/doc/rustdoc", "rustdoc", default=true;
2342 RustcBook, "src/doc/rustc", "rustc", default=true;
2343 RustByExample, "src/doc/rust-by-example", "rust-by-example", default=false, submodules=["src/doc/rust-by-example"];
2344 EmbeddedBook, "src/doc/embedded-book", "embedded-book", default=false, submodules=["src/doc/embedded-book"];
2345 TheBook, "src/doc/book", "book", default=false, submodules=["src/doc/book"], dependencies=["src/doc/book/packages/trpl"];
2346 UnstableBook, "src/doc/unstable-book", "unstable-book", default=true;
2347 EditionGuide, "src/doc/edition-guide", "edition-guide", default=false, submodules=["src/doc/edition-guide"];
2348);
2349
2350#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2351pub struct ErrorIndex {
2352 compiler: Compiler,
2353}
2354
2355impl Step for ErrorIndex {
2356 type Output = ();
2357 const DEFAULT: bool = true;
2358 const ONLY_HOSTS: bool = true;
2359
2360 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2361 run.path("src/tools/error_index_generator").alias("error-index")
2364 }
2365
2366 fn make_run(run: RunConfig<'_>) {
2367 let compiler = run.builder.compiler(run.builder.top_stage, run.builder.config.build);
2371 run.builder.ensure(ErrorIndex { compiler });
2372 }
2373
2374 fn run(self, builder: &Builder<'_>) {
2381 let compiler = self.compiler;
2382
2383 let dir = testdir(builder, compiler.host);
2384 t!(fs::create_dir_all(&dir));
2385 let output = dir.join("error-index.md");
2386
2387 let mut tool = tool::ErrorIndex::command(builder);
2388 tool.arg("markdown").arg(&output);
2389
2390 let guard =
2391 builder.msg(Kind::Test, compiler.stage, "error-index", compiler.host, compiler.host);
2392 let _time = helpers::timeit(builder);
2393 tool.run_capture(builder);
2394 drop(guard);
2395 builder.ensure(compile::Std::new(compiler, compiler.host));
2398 markdown_test(builder, compiler, &output);
2399 }
2400}
2401
2402fn markdown_test(builder: &Builder<'_>, compiler: Compiler, markdown: &Path) -> bool {
2403 if let Ok(contents) = fs::read_to_string(markdown) {
2404 if !contents.contains("```") {
2405 return true;
2406 }
2407 }
2408
2409 builder.verbose(|| println!("doc tests for: {}", markdown.display()));
2410 let mut cmd = builder.rustdoc_cmd(compiler);
2411 builder.add_rust_test_threads(&mut cmd);
2412 cmd.arg("-Z");
2414 cmd.arg("unstable-options");
2415 cmd.arg("--test");
2416 cmd.arg(markdown);
2417 cmd.env("RUSTC_BOOTSTRAP", "1");
2418
2419 let test_args = builder.config.test_args().join(" ");
2420 cmd.arg("--test-args").arg(test_args);
2421
2422 cmd = cmd.delay_failure();
2423 if !builder.config.verbose_tests {
2424 cmd.run_capture(builder).is_success()
2425 } else {
2426 cmd.run(builder)
2427 }
2428}
2429
2430#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2435pub struct CrateLibrustc {
2436 compiler: Compiler,
2437 target: TargetSelection,
2438 crates: Vec<String>,
2439}
2440
2441impl Step for CrateLibrustc {
2442 type Output = ();
2443 const DEFAULT: bool = true;
2444 const ONLY_HOSTS: bool = true;
2445
2446 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2447 run.crate_or_deps("rustc-main").path("compiler")
2448 }
2449
2450 fn make_run(run: RunConfig<'_>) {
2451 let builder = run.builder;
2452 let host = run.build_triple();
2453 let compiler = builder.compiler_for(builder.top_stage, host, host);
2454 let crates = run.make_run_crates(Alias::Compiler);
2455
2456 builder.ensure(CrateLibrustc { compiler, target: run.target, crates });
2457 }
2458
2459 fn run(self, builder: &Builder<'_>) {
2460 builder.ensure(compile::Std::new(self.compiler, self.target));
2461
2462 builder.ensure(Crate {
2464 compiler: self.compiler,
2465 target: self.target,
2466 mode: Mode::Rustc,
2467 crates: self.crates,
2468 });
2469 }
2470}
2471
2472fn run_cargo_test<'a>(
2476 cargo: builder::Cargo,
2477 libtest_args: &[&str],
2478 crates: &[String],
2479 description: impl Into<Option<&'a str>>,
2480 target: TargetSelection,
2481 builder: &Builder<'_>,
2482) -> bool {
2483 let compiler = cargo.compiler();
2484 let mut cargo = prepare_cargo_test(cargo, libtest_args, crates, target, builder);
2485 let _time = helpers::timeit(builder);
2486 let _group = description.into().and_then(|what| {
2487 builder.msg_sysroot_tool(Kind::Test, compiler.stage, what, compiler.host, target)
2488 });
2489
2490 #[cfg(feature = "build-metrics")]
2491 builder.metrics.begin_test_suite(
2492 build_helper::metrics::TestSuiteMetadata::CargoPackage {
2493 crates: crates.iter().map(|c| c.to_string()).collect(),
2494 target: target.triple.to_string(),
2495 host: compiler.host.triple.to_string(),
2496 stage: compiler.stage,
2497 },
2498 builder,
2499 );
2500 add_flags_and_try_run_tests(builder, &mut cargo)
2501}
2502
2503fn prepare_cargo_test(
2505 cargo: builder::Cargo,
2506 libtest_args: &[&str],
2507 crates: &[String],
2508 target: TargetSelection,
2509 builder: &Builder<'_>,
2510) -> BootstrapCommand {
2511 let compiler = cargo.compiler();
2512 let mut cargo: BootstrapCommand = cargo.into();
2513
2514 if builder.config.cmd.bless() && !cargo.get_envs().any(|v| v.0 == "RUSTC_BLESS") {
2518 cargo.env("RUSTC_BLESS", "Gesundheit");
2519 }
2520
2521 if builder.kind == Kind::Test && !builder.fail_fast {
2525 cargo.arg("--no-fail-fast");
2526 }
2527
2528 if builder.config.json_output {
2529 cargo.arg("--message-format=json");
2530 }
2531
2532 match builder.doc_tests {
2533 DocTests::Only => {
2534 cargo.arg("--doc");
2535 }
2536 DocTests::No => {
2537 cargo.args(["--bins", "--examples", "--tests", "--benches"]);
2538 }
2539 DocTests::Yes => {}
2540 }
2541
2542 for krate in crates {
2543 cargo.arg("-p").arg(krate);
2544 }
2545
2546 cargo.arg("--").args(builder.config.test_args()).args(libtest_args);
2547 if !builder.config.verbose_tests {
2548 cargo.arg("--quiet");
2549 }
2550
2551 if builder.kind != Kind::Miri {
2560 let mut dylib_paths = builder.rustc_lib_paths(compiler);
2561 dylib_paths.push(PathBuf::from(&builder.sysroot_target_libdir(compiler, target)));
2562 helpers::add_dylib_path(dylib_paths, &mut cargo);
2563 }
2564
2565 if builder.remote_tested(target) {
2566 cargo.env(
2567 format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)),
2568 format!("{} run 0", builder.tool_exe(Tool::RemoteTestClient).display()),
2569 );
2570 } else if let Some(tool) = builder.runner(target) {
2571 cargo.env(format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)), tool);
2572 }
2573
2574 cargo
2575}
2576
2577#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
2585pub struct Crate {
2586 pub compiler: Compiler,
2587 pub target: TargetSelection,
2588 pub mode: Mode,
2589 pub crates: Vec<String>,
2590}
2591
2592impl Step for Crate {
2593 type Output = ();
2594 const DEFAULT: bool = true;
2595
2596 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2597 run.crate_or_deps("sysroot").crate_or_deps("coretests").crate_or_deps("alloctests")
2598 }
2599
2600 fn make_run(run: RunConfig<'_>) {
2601 let builder = run.builder;
2602 let host = run.build_triple();
2603 let compiler = builder.compiler_for(builder.top_stage, host, host);
2604 let crates = run
2605 .paths
2606 .iter()
2607 .map(|p| builder.crate_paths[&p.assert_single_path().path].clone())
2608 .collect();
2609
2610 builder.ensure(Crate { compiler, target: run.target, mode: Mode::Std, crates });
2611 }
2612
2613 fn run(self, builder: &Builder<'_>) {
2622 let compiler = self.compiler;
2623 let target = self.target;
2624 let mode = self.mode;
2625
2626 builder.ensure(compile::Std::new(compiler, compiler.host).force_recompile(true));
2629
2630 let compiler = builder.compiler_for(compiler.stage, compiler.host, target);
2635
2636 let mut cargo = if builder.kind == Kind::Miri {
2637 if builder.top_stage == 0 {
2638 eprintln!("ERROR: `x.py miri` requires stage 1 or higher");
2639 std::process::exit(1);
2640 }
2641
2642 let mut cargo = builder::Cargo::new(
2645 builder,
2646 compiler,
2647 mode,
2648 SourceType::InTree,
2649 target,
2650 Kind::MiriTest,
2651 );
2652 cargo.env("MIRI_REPLACE_LIBRS_IF_NOT_TEST", "1");
2664 cargo.rustflag("-Zforce-unstable-if-unmarked");
2668 cargo
2669 } else {
2670 if !builder.config.is_host_target(target) {
2672 builder.ensure(compile::Std::new(compiler, target).force_recompile(true));
2673 builder.ensure(RemoteCopyLibs { compiler, target });
2674 }
2675
2676 builder::Cargo::new(builder, compiler, mode, SourceType::InTree, target, builder.kind)
2678 };
2679
2680 match mode {
2681 Mode::Std => {
2682 if builder.kind == Kind::Miri {
2683 cargo
2689 .arg("--manifest-path")
2690 .arg(builder.src.join("library/sysroot/Cargo.toml"));
2691 } else {
2692 compile::std_cargo(builder, target, compiler.stage, &mut cargo);
2693 if builder.download_rustc() && compiler.stage > 0 {
2697 let sysroot = builder
2698 .out
2699 .join(compiler.host)
2700 .join(format!("stage{}-test-sysroot", compiler.stage));
2701 cargo.env("RUSTC_SYSROOT", sysroot);
2702 }
2703 }
2704 }
2705 Mode::Rustc => {
2706 compile::rustc_cargo(builder, &mut cargo, target, &compiler, &self.crates);
2707 }
2708 _ => panic!("can only test libraries"),
2709 };
2710
2711 let mut crates = self.crates.clone();
2712 if crates.iter().any(|crate_| crate_ == "core") {
2717 crates.push("coretests".to_owned());
2718 }
2719 if crates.iter().any(|crate_| crate_ == "alloc") {
2720 crates.push("alloctests".to_owned());
2721 }
2722
2723 run_cargo_test(cargo, &[], &crates, &*crate_description(&self.crates), target, builder);
2724 }
2725}
2726
2727#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2729pub struct CrateRustdoc {
2730 host: TargetSelection,
2731}
2732
2733impl Step for CrateRustdoc {
2734 type Output = ();
2735 const DEFAULT: bool = true;
2736 const ONLY_HOSTS: bool = true;
2737
2738 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2739 run.paths(&["src/librustdoc", "src/tools/rustdoc"])
2740 }
2741
2742 fn make_run(run: RunConfig<'_>) {
2743 let builder = run.builder;
2744
2745 builder.ensure(CrateRustdoc { host: run.target });
2746 }
2747
2748 fn run(self, builder: &Builder<'_>) {
2749 let target = self.host;
2750
2751 let compiler = if builder.download_rustc() {
2752 builder.compiler(builder.top_stage, target)
2753 } else {
2754 builder.compiler_for(builder.top_stage, target, target)
2759 };
2760 builder.ensure(compile::Std::new(compiler, target));
2765 builder.ensure(compile::Rustc::new(compiler, target));
2766
2767 let mut cargo = tool::prepare_tool_cargo(
2768 builder,
2769 compiler,
2770 Mode::ToolRustc,
2771 target,
2772 builder.kind,
2773 "src/tools/rustdoc",
2774 SourceType::InTree,
2775 &[],
2776 );
2777 if self.host.contains("musl") {
2778 cargo.arg("'-Ctarget-feature=-crt-static'");
2779 }
2780
2781 let libdir = if builder.download_rustc() {
2808 builder.rustc_libdir(compiler)
2809 } else {
2810 builder.sysroot_target_libdir(compiler, target).to_path_buf()
2811 };
2812 let mut dylib_path = dylib_path();
2813 dylib_path.insert(0, PathBuf::from(&*libdir));
2814 cargo.env(dylib_path_var(), env::join_paths(&dylib_path).unwrap());
2815
2816 run_cargo_test(cargo, &[], &["rustdoc:0.0.0".to_string()], "rustdoc", target, builder);
2817 }
2818}
2819
2820#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2821pub struct CrateRustdocJsonTypes {
2822 host: TargetSelection,
2823}
2824
2825impl Step for CrateRustdocJsonTypes {
2826 type Output = ();
2827 const DEFAULT: bool = true;
2828 const ONLY_HOSTS: bool = true;
2829
2830 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2831 run.path("src/rustdoc-json-types")
2832 }
2833
2834 fn make_run(run: RunConfig<'_>) {
2835 let builder = run.builder;
2836
2837 builder.ensure(CrateRustdocJsonTypes { host: run.target });
2838 }
2839
2840 fn run(self, builder: &Builder<'_>) {
2841 let target = self.host;
2842
2843 let compiler = builder.compiler_for(builder.top_stage, target, target);
2848 builder.ensure(compile::Rustc::new(compiler, target));
2849
2850 let cargo = tool::prepare_tool_cargo(
2851 builder,
2852 compiler,
2853 Mode::ToolRustc,
2854 target,
2855 builder.kind,
2856 "src/rustdoc-json-types",
2857 SourceType::InTree,
2858 &[],
2859 );
2860
2861 let libtest_args = if self.host.contains("musl") {
2863 ["'-Ctarget-feature=-crt-static'"].as_slice()
2864 } else {
2865 &[]
2866 };
2867
2868 run_cargo_test(
2869 cargo,
2870 libtest_args,
2871 &["rustdoc-json-types".to_string()],
2872 "rustdoc-json-types",
2873 target,
2874 builder,
2875 );
2876 }
2877}
2878
2879#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2889pub struct RemoteCopyLibs {
2890 compiler: Compiler,
2891 target: TargetSelection,
2892}
2893
2894impl Step for RemoteCopyLibs {
2895 type Output = ();
2896
2897 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2898 run.never()
2899 }
2900
2901 fn run(self, builder: &Builder<'_>) {
2902 let compiler = self.compiler;
2903 let target = self.target;
2904 if !builder.remote_tested(target) {
2905 return;
2906 }
2907
2908 builder.ensure(compile::Std::new(compiler, target));
2909
2910 builder.info(&format!("REMOTE copy libs to emulator ({target})"));
2911
2912 let remote_test_server = builder.ensure(tool::RemoteTestServer { compiler, target });
2913
2914 let tool = builder.tool_exe(Tool::RemoteTestClient);
2916 let mut cmd = command(&tool);
2917 cmd.arg("spawn-emulator")
2918 .arg(target.triple)
2919 .arg(&remote_test_server.tool_path)
2920 .arg(builder.tempdir());
2921 if let Some(rootfs) = builder.qemu_rootfs(target) {
2922 cmd.arg(rootfs);
2923 }
2924 cmd.run(builder);
2925
2926 for f in t!(builder.sysroot_target_libdir(compiler, target).read_dir()) {
2928 let f = t!(f);
2929 if helpers::is_dylib(&f.path()) {
2930 command(&tool).arg("push").arg(f.path()).run(builder);
2931 }
2932 }
2933 }
2934}
2935
2936#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2937pub struct Distcheck;
2938
2939impl Step for Distcheck {
2940 type Output = ();
2941
2942 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2943 run.alias("distcheck")
2944 }
2945
2946 fn make_run(run: RunConfig<'_>) {
2947 run.builder.ensure(Distcheck);
2948 }
2949
2950 fn run(self, builder: &Builder<'_>) {
2952 builder.info("Distcheck");
2953 let dir = builder.tempdir().join("distcheck");
2954 let _ = fs::remove_dir_all(&dir);
2955 t!(fs::create_dir_all(&dir));
2956
2957 builder.ensure(dist::PlainSourceTarball);
2959 builder.ensure(dist::Src);
2960
2961 command("tar")
2962 .arg("-xf")
2963 .arg(builder.ensure(dist::PlainSourceTarball).tarball())
2964 .arg("--strip-components=1")
2965 .current_dir(&dir)
2966 .run(builder);
2967 command("./configure")
2968 .args(&builder.config.configure_args)
2969 .arg("--enable-vendor")
2970 .current_dir(&dir)
2971 .run(builder);
2972 command(helpers::make(&builder.config.build.triple))
2973 .arg("check")
2974 .current_dir(&dir)
2975 .run(builder);
2976
2977 builder.info("Distcheck rust-src");
2979 let dir = builder.tempdir().join("distcheck-src");
2980 let _ = fs::remove_dir_all(&dir);
2981 t!(fs::create_dir_all(&dir));
2982
2983 command("tar")
2984 .arg("-xf")
2985 .arg(builder.ensure(dist::Src).tarball())
2986 .arg("--strip-components=1")
2987 .current_dir(&dir)
2988 .run(builder);
2989
2990 let toml = dir.join("rust-src/lib/rustlib/src/rust/library/std/Cargo.toml");
2991 command(&builder.initial_cargo)
2992 .env("RUSTC_BOOTSTRAP", "1")
2995 .arg("generate-lockfile")
2996 .arg("--manifest-path")
2997 .arg(&toml)
2998 .current_dir(&dir)
2999 .run(builder);
3000 }
3001}
3002
3003#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3004pub struct Bootstrap;
3005
3006impl Step for Bootstrap {
3007 type Output = ();
3008 const DEFAULT: bool = true;
3009 const ONLY_HOSTS: bool = true;
3010
3011 fn run(self, builder: &Builder<'_>) {
3013 let host = builder.config.build;
3014 let compiler = builder.compiler(0, host);
3015 let _guard = builder.msg(Kind::Test, 0, "bootstrap", host, host);
3016
3017 builder.build.require_submodule("src/tools/cargo", None);
3019
3020 let mut check_bootstrap = command(builder.python());
3021 check_bootstrap
3022 .args(["-m", "unittest", "bootstrap_test.py"])
3023 .env("BUILD_DIR", &builder.out)
3024 .env("BUILD_PLATFORM", builder.build.build.triple)
3025 .env("BOOTSTRAP_TEST_RUSTC_BIN", &builder.initial_rustc)
3026 .env("BOOTSTRAP_TEST_CARGO_BIN", &builder.initial_cargo)
3027 .current_dir(builder.src.join("src/bootstrap/"));
3028 check_bootstrap.delay_failure().run(builder);
3031
3032 let mut cargo = tool::prepare_tool_cargo(
3033 builder,
3034 compiler,
3035 Mode::ToolBootstrap,
3036 host,
3037 Kind::Test,
3038 "src/bootstrap",
3039 SourceType::InTree,
3040 &[],
3041 );
3042
3043 cargo.release_build(false);
3044
3045 cargo
3046 .rustflag("-Cdebuginfo=2")
3047 .env("CARGO_TARGET_DIR", builder.out.join("bootstrap"))
3048 .env("RUSTC_BOOTSTRAP", "1");
3049
3050 run_cargo_test(cargo, &["--test-threads=1"], &[], None, host, builder);
3053 }
3054
3055 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3056 run.path("src/bootstrap")
3057 }
3058
3059 fn make_run(run: RunConfig<'_>) {
3060 run.builder.ensure(Bootstrap);
3061 }
3062}
3063
3064#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3065pub struct TierCheck {
3066 pub compiler: Compiler,
3067}
3068
3069impl Step for TierCheck {
3070 type Output = ();
3071 const DEFAULT: bool = true;
3072 const ONLY_HOSTS: bool = true;
3073
3074 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3075 run.path("src/tools/tier-check")
3076 }
3077
3078 fn make_run(run: RunConfig<'_>) {
3079 let compiler =
3080 run.builder.compiler_for(run.builder.top_stage, run.builder.build.build, run.target);
3081 run.builder.ensure(TierCheck { compiler });
3082 }
3083
3084 fn run(self, builder: &Builder<'_>) {
3086 builder.ensure(compile::Std::new(self.compiler, self.compiler.host));
3087 let mut cargo = tool::prepare_tool_cargo(
3088 builder,
3089 self.compiler,
3090 Mode::ToolStd,
3091 self.compiler.host,
3092 Kind::Run,
3093 "src/tools/tier-check",
3094 SourceType::InTree,
3095 &[],
3096 );
3097 cargo.arg(builder.src.join("src/doc/rustc/src/platform-support.md"));
3098 cargo.arg(builder.rustc(self.compiler));
3099 if builder.is_verbose() {
3100 cargo.arg("--verbose");
3101 }
3102
3103 let _guard = builder.msg(
3104 Kind::Test,
3105 self.compiler.stage,
3106 "platform support check",
3107 self.compiler.host,
3108 self.compiler.host,
3109 );
3110 BootstrapCommand::from(cargo).delay_failure().run(builder);
3111 }
3112}
3113
3114#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3115pub struct LintDocs {
3116 pub compiler: Compiler,
3117 pub target: TargetSelection,
3118}
3119
3120impl Step for LintDocs {
3121 type Output = ();
3122 const DEFAULT: bool = true;
3123 const ONLY_HOSTS: bool = true;
3124
3125 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3126 run.path("src/tools/lint-docs")
3127 }
3128
3129 fn make_run(run: RunConfig<'_>) {
3130 run.builder.ensure(LintDocs {
3131 compiler: run.builder.compiler(run.builder.top_stage, run.builder.config.build),
3132 target: run.target,
3133 });
3134 }
3135
3136 fn run(self, builder: &Builder<'_>) {
3139 builder.ensure(crate::core::build_steps::doc::RustcBook {
3140 compiler: self.compiler,
3141 target: self.target,
3142 validate: true,
3143 });
3144 }
3145}
3146
3147#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3148pub struct RustInstaller;
3149
3150impl Step for RustInstaller {
3151 type Output = ();
3152 const ONLY_HOSTS: bool = true;
3153 const DEFAULT: bool = true;
3154
3155 fn run(self, builder: &Builder<'_>) {
3157 let bootstrap_host = builder.config.build;
3158 let compiler = builder.compiler(0, bootstrap_host);
3159 let cargo = tool::prepare_tool_cargo(
3160 builder,
3161 compiler,
3162 Mode::ToolBootstrap,
3163 bootstrap_host,
3164 Kind::Test,
3165 "src/tools/rust-installer",
3166 SourceType::InTree,
3167 &[],
3168 );
3169
3170 let _guard = builder.msg(
3171 Kind::Test,
3172 compiler.stage,
3173 "rust-installer",
3174 bootstrap_host,
3175 bootstrap_host,
3176 );
3177 run_cargo_test(cargo, &[], &[], None, bootstrap_host, builder);
3178
3179 if bootstrap_host != "x86_64-unknown-linux-gnu" {
3183 return;
3184 }
3185
3186 let mut cmd = command(builder.src.join("src/tools/rust-installer/test.sh"));
3187 let tmpdir = testdir(builder, compiler.host).join("rust-installer");
3188 let _ = std::fs::remove_dir_all(&tmpdir);
3189 let _ = std::fs::create_dir_all(&tmpdir);
3190 cmd.current_dir(&tmpdir);
3191 cmd.env("CARGO_TARGET_DIR", tmpdir.join("cargo-target"));
3192 cmd.env("CARGO", &builder.initial_cargo);
3193 cmd.env("RUSTC", &builder.initial_rustc);
3194 cmd.env("TMP_DIR", &tmpdir);
3195 cmd.delay_failure().run(builder);
3196 }
3197
3198 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3199 run.path("src/tools/rust-installer")
3200 }
3201
3202 fn make_run(run: RunConfig<'_>) {
3203 run.builder.ensure(Self);
3204 }
3205}
3206
3207#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3208pub struct TestHelpers {
3209 pub target: TargetSelection,
3210}
3211
3212impl Step for TestHelpers {
3213 type Output = ();
3214
3215 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3216 run.path("tests/auxiliary/rust_test_helpers.c")
3217 }
3218
3219 fn make_run(run: RunConfig<'_>) {
3220 run.builder.ensure(TestHelpers { target: run.target })
3221 }
3222
3223 fn run(self, builder: &Builder<'_>) {
3226 if builder.config.dry_run() {
3227 return;
3228 }
3229 let target = if self.target == "x86_64-fortanix-unknown-sgx" {
3233 TargetSelection::from_user("x86_64-unknown-linux-gnu")
3234 } else {
3235 self.target
3236 };
3237 let dst = builder.test_helpers_out(target);
3238 let src = builder.src.join("tests/auxiliary/rust_test_helpers.c");
3239 if up_to_date(&src, &dst.join("librust_test_helpers.a")) {
3240 return;
3241 }
3242
3243 let _guard = builder.msg_unstaged(Kind::Build, "test helpers", target);
3244 t!(fs::create_dir_all(&dst));
3245 let mut cfg = cc::Build::new();
3246
3247 if !target.is_msvc() {
3251 if let Some(ar) = builder.ar(target) {
3252 cfg.archiver(ar);
3253 }
3254 cfg.compiler(builder.cc(target));
3255 }
3256 cfg.cargo_metadata(false)
3257 .out_dir(&dst)
3258 .target(&target.triple)
3259 .host(&builder.config.build.triple)
3260 .opt_level(0)
3261 .warnings(false)
3262 .debug(false)
3263 .file(builder.src.join("tests/auxiliary/rust_test_helpers.c"))
3264 .compile("rust_test_helpers");
3265 }
3266}
3267
3268#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3269pub struct CodegenCranelift {
3270 compiler: Compiler,
3271 target: TargetSelection,
3272}
3273
3274impl Step for CodegenCranelift {
3275 type Output = ();
3276 const DEFAULT: bool = true;
3277 const ONLY_HOSTS: bool = true;
3278
3279 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3280 run.paths(&["compiler/rustc_codegen_cranelift"])
3281 }
3282
3283 fn make_run(run: RunConfig<'_>) {
3284 let builder = run.builder;
3285 let host = run.build_triple();
3286 let compiler = run.builder.compiler_for(run.builder.top_stage, host, host);
3287
3288 if builder.doc_tests == DocTests::Only {
3289 return;
3290 }
3291
3292 if builder.download_rustc() {
3293 builder.info("CI rustc uses the default codegen backend. skipping");
3294 return;
3295 }
3296
3297 if !target_supports_cranelift_backend(run.target) {
3298 builder.info("target not supported by rustc_codegen_cranelift. skipping");
3299 return;
3300 }
3301
3302 if builder.remote_tested(run.target) {
3303 builder.info("remote testing is not supported by rustc_codegen_cranelift. skipping");
3304 return;
3305 }
3306
3307 if !builder.config.codegen_backends(run.target).contains(&"cranelift".to_owned()) {
3308 builder.info("cranelift not in rust.codegen-backends. skipping");
3309 return;
3310 }
3311
3312 builder.ensure(CodegenCranelift { compiler, target: run.target });
3313 }
3314
3315 fn run(self, builder: &Builder<'_>) {
3316 let compiler = self.compiler;
3317 let target = self.target;
3318
3319 builder.ensure(compile::Std::new(compiler, target));
3320
3321 let compiler = builder.compiler_for(compiler.stage, compiler.host, target);
3326
3327 let build_cargo = || {
3328 let mut cargo = builder::Cargo::new(
3329 builder,
3330 compiler,
3331 Mode::Codegen, SourceType::InTree,
3333 target,
3334 Kind::Run,
3335 );
3336
3337 cargo.current_dir(&builder.src.join("compiler/rustc_codegen_cranelift"));
3338 cargo
3339 .arg("--manifest-path")
3340 .arg(builder.src.join("compiler/rustc_codegen_cranelift/build_system/Cargo.toml"));
3341 compile::rustc_cargo_env(builder, &mut cargo, target, compiler.stage);
3342
3343 cargo.env("CARGO_BUILD_INCREMENTAL", "false");
3345
3346 cargo
3347 };
3348
3349 builder.info(&format!(
3350 "{} cranelift stage{} ({} -> {})",
3351 Kind::Test.description(),
3352 compiler.stage,
3353 &compiler.host,
3354 target
3355 ));
3356 let _time = helpers::timeit(builder);
3357
3358 let download_dir = builder.out.join("cg_clif_download");
3360
3361 let mut cargo = build_cargo();
3370 cargo
3371 .arg("--")
3372 .arg("test")
3373 .arg("--download-dir")
3374 .arg(&download_dir)
3375 .arg("--out-dir")
3376 .arg(builder.stage_out(compiler, Mode::ToolRustc).join("cg_clif"))
3377 .arg("--no-unstable-features")
3378 .arg("--use-backend")
3379 .arg("cranelift")
3380 .arg("--sysroot")
3382 .arg("llvm")
3383 .arg("--skip-test")
3386 .arg("testsuite.extended_sysroot");
3387
3388 cargo.into_cmd().run(builder);
3389 }
3390}
3391
3392#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3393pub struct CodegenGCC {
3394 compiler: Compiler,
3395 target: TargetSelection,
3396}
3397
3398impl Step for CodegenGCC {
3399 type Output = ();
3400 const DEFAULT: bool = true;
3401 const ONLY_HOSTS: bool = true;
3402
3403 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3404 run.paths(&["compiler/rustc_codegen_gcc"])
3405 }
3406
3407 fn make_run(run: RunConfig<'_>) {
3408 let builder = run.builder;
3409 let host = run.build_triple();
3410 let compiler = run.builder.compiler_for(run.builder.top_stage, host, host);
3411
3412 if builder.doc_tests == DocTests::Only {
3413 return;
3414 }
3415
3416 if builder.download_rustc() {
3417 builder.info("CI rustc uses the default codegen backend. skipping");
3418 return;
3419 }
3420
3421 let triple = run.target.triple;
3422 let target_supported =
3423 if triple.contains("linux") { triple.contains("x86_64") } else { false };
3424 if !target_supported {
3425 builder.info("target not supported by rustc_codegen_gcc. skipping");
3426 return;
3427 }
3428
3429 if builder.remote_tested(run.target) {
3430 builder.info("remote testing is not supported by rustc_codegen_gcc. skipping");
3431 return;
3432 }
3433
3434 if !builder.config.codegen_backends(run.target).contains(&"gcc".to_owned()) {
3435 builder.info("gcc not in rust.codegen-backends. skipping");
3436 return;
3437 }
3438
3439 builder.ensure(CodegenGCC { compiler, target: run.target });
3440 }
3441
3442 fn run(self, builder: &Builder<'_>) {
3443 let compiler = self.compiler;
3444 let target = self.target;
3445
3446 let gcc = builder.ensure(Gcc { target });
3447
3448 builder.ensure(
3449 compile::Std::new(compiler, target)
3450 .extra_rust_args(&["-Csymbol-mangling-version=v0", "-Cpanic=abort"]),
3451 );
3452
3453 let compiler = builder.compiler_for(compiler.stage, compiler.host, target);
3458
3459 let build_cargo = || {
3460 let mut cargo = builder::Cargo::new(
3461 builder,
3462 compiler,
3463 Mode::Codegen, SourceType::InTree,
3465 target,
3466 Kind::Run,
3467 );
3468
3469 cargo.current_dir(&builder.src.join("compiler/rustc_codegen_gcc"));
3470 cargo
3471 .arg("--manifest-path")
3472 .arg(builder.src.join("compiler/rustc_codegen_gcc/build_system/Cargo.toml"));
3473 compile::rustc_cargo_env(builder, &mut cargo, target, compiler.stage);
3474 add_cg_gcc_cargo_flags(&mut cargo, &gcc);
3475
3476 cargo.env("CARGO_BUILD_INCREMENTAL", "false");
3478 cargo.rustflag("-Cpanic=abort");
3479
3480 cargo
3481 };
3482
3483 builder.info(&format!(
3484 "{} GCC stage{} ({} -> {})",
3485 Kind::Test.description(),
3486 compiler.stage,
3487 &compiler.host,
3488 target
3489 ));
3490 let _time = helpers::timeit(builder);
3491
3492 let mut cargo = build_cargo();
3501
3502 cargo
3503 .env("CG_RUSTFLAGS", "-Alinker-messages")
3505 .arg("--")
3506 .arg("test")
3507 .arg("--use-backend")
3508 .arg("gcc")
3509 .arg("--gcc-path")
3510 .arg(gcc.libgccjit.parent().unwrap())
3511 .arg("--out-dir")
3512 .arg(builder.stage_out(compiler, Mode::ToolRustc).join("cg_gcc"))
3513 .arg("--release")
3514 .arg("--mini-tests")
3515 .arg("--std-tests");
3516 cargo.args(builder.config.test_args());
3517
3518 cargo.into_cmd().run(builder);
3519 }
3520}
3521
3522#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3527pub struct TestFloatParse {
3528 path: PathBuf,
3529 host: TargetSelection,
3530}
3531
3532impl Step for TestFloatParse {
3533 type Output = ();
3534 const ONLY_HOSTS: bool = true;
3535 const DEFAULT: bool = true;
3536
3537 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3538 run.path("src/etc/test-float-parse")
3539 }
3540
3541 fn make_run(run: RunConfig<'_>) {
3542 for path in run.paths {
3543 let path = path.assert_single_path().path.clone();
3544 run.builder.ensure(Self { path, host: run.target });
3545 }
3546 }
3547
3548 fn run(self, builder: &Builder<'_>) {
3549 let bootstrap_host = builder.config.build;
3550 let compiler = builder.compiler(builder.top_stage, bootstrap_host);
3551 let path = self.path.to_str().unwrap();
3552 let crate_name = self.path.iter().next_back().unwrap().to_str().unwrap();
3553
3554 builder.ensure(tool::TestFloatParse { host: self.host });
3555
3556 let cargo_test = tool::prepare_tool_cargo(
3558 builder,
3559 compiler,
3560 Mode::ToolStd,
3561 bootstrap_host,
3562 Kind::Test,
3563 path,
3564 SourceType::InTree,
3565 &[],
3566 );
3567
3568 run_cargo_test(cargo_test, &[], &[], crate_name, bootstrap_host, builder);
3569
3570 let mut cargo_run = tool::prepare_tool_cargo(
3572 builder,
3573 compiler,
3574 Mode::ToolStd,
3575 bootstrap_host,
3576 Kind::Run,
3577 path,
3578 SourceType::InTree,
3579 &[],
3580 );
3581
3582 if !matches!(env::var("FLOAT_PARSE_TESTS_NO_SKIP_HUGE").as_deref(), Ok("1") | Ok("true")) {
3583 cargo_run.args(["--", "--skip-huge"]);
3584 }
3585
3586 cargo_run.into_cmd().run(builder);
3587 }
3588}
3589
3590#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
3594pub struct CollectLicenseMetadata;
3595
3596impl Step for CollectLicenseMetadata {
3597 type Output = PathBuf;
3598 const ONLY_HOSTS: bool = true;
3599
3600 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3601 run.path("src/tools/collect-license-metadata")
3602 }
3603
3604 fn make_run(run: RunConfig<'_>) {
3605 run.builder.ensure(CollectLicenseMetadata);
3606 }
3607
3608 fn run(self, builder: &Builder<'_>) -> Self::Output {
3609 let Some(reuse) = &builder.config.reuse else {
3610 panic!("REUSE is required to collect the license metadata");
3611 };
3612
3613 let dest = builder.src.join("license-metadata.json");
3614
3615 let mut cmd = builder.tool_cmd(Tool::CollectLicenseMetadata);
3616 cmd.env("REUSE_EXE", reuse);
3617 cmd.env("DEST", &dest);
3618 cmd.env("ONLY_CHECK", "1");
3619 cmd.run(builder);
3620
3621 dest
3622 }
3623}