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