1use std::ffi::OsStr;
13use std::path::{Path, PathBuf};
14use std::{env, fs};
15
16use crate::core::build_steps::compile::{CargoMessage, is_lto_stage};
17use crate::core::build_steps::dist::LLD_FILE_NAMES;
18use crate::core::build_steps::toolstate::ToolState;
19use crate::core::build_steps::{compile, llvm};
20use crate::core::builder::{
21 self, Builder, Cargo as CargoCommand, CommandLineStep, Kind, RunConfig, ShouldRun, Step,
22 StepMetadata, apply_pgo, cargo_profile_var,
23};
24use crate::core::compiler::Compiler;
25use crate::core::config::{Allocator, DebuginfoLevel, RustcLto, TargetSelection};
26use crate::core::session::{FileType, Mode};
27use crate::utils::exec::{BootstrapCommand, command};
28use crate::utils::helpers::{self, add_dylib_path, exe, t};
29
30#[derive(Debug, Clone, Hash, PartialEq, Eq)]
31pub enum SourceType {
32 InTree,
33 Submodule,
34}
35
36#[derive(Debug, Clone, Hash, PartialEq, Eq)]
37pub enum ToolArtifactKind {
38 Binary,
39 Library,
40}
41
42#[derive(Debug, Clone, Hash, PartialEq, Eq)]
43struct ToolBuild {
44 build_compiler: Compiler,
46 target: TargetSelection,
47 tool: &'static str,
48 path: &'static str,
49 mode: Mode,
50 source_type: SourceType,
51 extra_features: Vec<String>,
52 allow_features: &'static str,
54 cargo_args: Vec<String>,
56 artifact_kind: ToolArtifactKind,
58}
59
60#[derive(Clone)]
63pub struct ToolBuildResult {
64 pub tool_path: PathBuf,
66 pub build_compiler: Compiler,
68 pub artifacts: Vec<PathBuf>,
70}
71
72impl Step for ToolBuild {
73 type Output = ToolBuildResult;
74
75 fn run(self, builder: &Builder<'_>) -> ToolBuildResult {
80 let target = self.target;
81 let mut tool = self.tool;
82 let path = self.path;
83
84 match self.mode {
85 Mode::ToolRustcPrivate => {
86 if !self.build_compiler.is_forced_compiler() && builder.download_rustc() {
88 builder.std(self.build_compiler, self.build_compiler.host);
89 builder.ensure(compile::Rustc::new(self.build_compiler, target));
90 }
91 }
92 Mode::ToolStd => {
93 if !self.build_compiler.is_forced_compiler() {
95 builder.std(self.build_compiler, target);
96 }
97 }
98 Mode::ToolBootstrap | Mode::ToolTarget => {} _ => panic!("unexpected Mode for tool build"),
100 }
101
102 let mut cargo = prepare_tool_cargo(
103 builder,
104 self.build_compiler,
105 self.mode,
106 target,
107 Kind::Build,
108 path,
109 self.source_type,
110 &self.extra_features,
111 );
112
113 if let Some(ref ccache) = builder.config.ccache
118 && matches!(self.mode, Mode::ToolBootstrap)
119 && !builder.config.incremental
120 {
121 cargo.env("RUSTC_WRAPPER", ccache);
122 }
123
124 if is_lto_stage(&self.build_compiler)
127 && (self.mode == Mode::ToolRustcPrivate || self.path == "src/tools/cargo")
128 {
129 let lto = match builder.config.rust_lto {
130 RustcLto::Off => Some("off"),
131 RustcLto::Thin => Some("thin"),
132 RustcLto::Fat => Some("fat"),
133 RustcLto::ThinLocal => None,
134 };
135 if let Some(lto) = lto {
136 cargo.env(cargo_profile_var("LTO", &builder.config, self.mode), lto);
137 }
138 }
139
140 let pgo_config = match self.path {
141 "src/tools/rustdoc" => Some(&builder.config.rustdoc_pgo),
142 "src/tools/cargo" => Some(&builder.config.cargo_pgo),
143 "src/tools/clippy" => Some(&builder.config.clippy_pgo),
144 _ => None,
145 };
146 if let Some(pgo_config) = pgo_config {
147 apply_pgo(builder, &mut cargo, self.build_compiler, pgo_config);
148 }
149
150 if !self.allow_features.is_empty() {
151 cargo.allow_features(self.allow_features);
152 }
153
154 cargo.args(self.cargo_args);
155
156 let _guard =
157 builder.msg(Kind::Build, self.tool, self.mode, self.build_compiler, self.target);
158
159 let mut artifacts = vec![];
161 let build_success = compile::stream_cargo(builder, cargo, vec![], &mut |msg| match msg {
162 CargoMessage::CompilerArtifact { filenames, .. } => {
163 artifacts.extend(filenames.into_iter().map(|p| PathBuf::from(p.as_ref())));
164 }
165 CargoMessage::BuildScriptExecuted => {}
166 CargoMessage::BuildFinished => {}
167 });
168
169 builder.save_toolstate(
170 tool,
171 if build_success { ToolState::TestFail } else { ToolState::BuildFail },
172 );
173
174 if !build_success {
175 helpers::exit_process(1);
176 } else {
177 if tool == "tidy" {
181 tool = "rust-tidy";
182 }
183 let tool_path = match self.artifact_kind {
184 ToolArtifactKind::Binary => {
185 copy_link_tool_bin(builder, self.build_compiler, self.target, self.mode, tool)
186 }
187 ToolArtifactKind::Library => builder
188 .cargo_out(self.build_compiler, self.mode, self.target)
189 .join(format!("lib{tool}.rlib")),
190 };
191
192 ToolBuildResult { tool_path, build_compiler: self.build_compiler, artifacts }
193 }
194 }
195}
196
197#[expect(clippy::too_many_arguments)] pub fn prepare_tool_cargo(
199 builder: &Builder<'_>,
200 compiler: Compiler,
201 mode: Mode,
202 target: TargetSelection,
203 cmd_kind: Kind,
204 path: &str,
205 source_type: SourceType,
206 extra_features: &[String],
207) -> CargoCommand {
208 let mut cargo = builder::Cargo::new(builder, compiler, mode, source_type, target, cmd_kind);
209
210 let path = PathBuf::from(path);
211 let dir = builder.src.join(&path);
212 cargo.arg("--manifest-path").arg(dir.join("Cargo.toml"));
213
214 let mut features = extra_features.to_vec();
215 if builder.sess.config.cargo_native_static {
216 if path.ends_with("cargo")
217 || path.ends_with("clippy")
218 || path.ends_with("miri")
219 || path.ends_with("rustfmt")
220 {
221 cargo.env("LIBZ_SYS_STATIC", "1");
222 }
223 if path.ends_with("cargo") {
224 features.push("all-static".to_string());
225 }
226 }
227
228 builder
234 .config
235 .tool
236 .iter()
237 .filter(|(tool_name, _)| path.file_name().and_then(OsStr::to_str) == Some(tool_name))
238 .for_each(|(_, tool)| features.extend(tool.features.clone().unwrap_or_default()));
239
240 cargo.env("SYSROOT", builder.sysroot(compiler));
243
244 if mode == Mode::ToolRustcPrivate {
247 cargo.add_rustc_lib_path(builder);
248 }
249
250 cargo.env("LZMA_API_STATIC", "1");
253
254 if builder.config.allocator(target) == Allocator::Jemalloc
256 && env::var_os("JEMALLOC_SYS_WITH_LG_PAGE").is_none()
257 {
258 if target.starts_with("aarch64") {
261 cargo.env("JEMALLOC_SYS_WITH_LG_PAGE", "16");
262 }
263 else if target.starts_with("loongarch") {
265 cargo.env("JEMALLOC_SYS_WITH_LG_PAGE", "14");
266 }
267 }
268
269 cargo.env("CFG_RELEASE", builder.rust_release());
273 cargo.env("CFG_RELEASE_CHANNEL", &builder.config.channel);
274 cargo.env("CFG_VERSION", builder.rust_version());
275 cargo.env("CFG_RELEASE_NUM", &builder.version);
276 cargo.env("DOC_RUST_LANG_ORG_CHANNEL", builder.doc_rust_lang_org_channel());
277
278 if let Some(ref ver_date) = builder.rust_info().commit_date() {
279 cargo.env("CFG_VER_DATE", ver_date);
280 }
281
282 if let Some(ref ver_hash) = builder.rust_info().sha() {
283 cargo.env("CFG_VER_HASH", ver_hash);
284 }
285
286 if let Some(description) = &builder.config.description {
287 cargo.env("CFG_VER_DESCRIPTION", description);
288 }
289
290 let info = builder.config.git_info(builder.config.omit_git_hash, &dir);
291 if let Some(sha) = info.sha() {
292 cargo.env("CFG_COMMIT_HASH", sha);
293 }
294
295 if let Some(sha_short) = info.sha_short() {
296 cargo.env("CFG_SHORT_COMMIT_HASH", sha_short);
297 }
298
299 if let Some(date) = info.commit_date() {
300 cargo.env("CFG_COMMIT_DATE", date);
301 }
302
303 if !features.is_empty() {
304 cargo.arg("--features").arg(features.join(", "));
305 }
306
307 cargo.rustflag("-Zunstable-options");
315
316 if !path.ends_with("cargo") {
333 cargo.env("FORCE_ON_BROKEN_PIPE_KILL", "-Zon-broken-pipe=kill");
338 }
339
340 cargo
341}
342
343pub enum ToolTargetBuildMode {
346 Build(TargetSelection),
349 Dist(Compiler),
353}
354
355pub(crate) fn get_tool_target_compiler(
357 builder: &Builder<'_>,
358 mode: ToolTargetBuildMode,
359) -> Compiler {
360 let (target, build_compiler_stage) = match mode {
361 ToolTargetBuildMode::Build(target) => {
362 assert!(builder.top_stage > 0);
363 (target, builder.top_stage - 1)
365 }
366 ToolTargetBuildMode::Dist(target_compiler) => {
367 assert!(target_compiler.stage > 0);
368 (target_compiler.host, target_compiler.stage - 1)
371 }
372 };
373
374 let compiler = if builder.host_target == target {
375 builder.compiler(build_compiler_stage, builder.host_target)
376 } else {
377 let build_compiler = builder.compiler(build_compiler_stage.max(1), builder.host_target);
380 builder.std(build_compiler, builder.host_target);
382 build_compiler
383 };
384 builder.std(compiler, target);
385 compiler
386}
387
388fn copy_link_tool_bin(
391 builder: &Builder<'_>,
392 build_compiler: Compiler,
393 target: TargetSelection,
394 mode: Mode,
395 name: &str,
396) -> PathBuf {
397 let cargo_out = builder.cargo_out(build_compiler, mode, target).join(exe(name, target));
398 let bin = builder.tools_dir(build_compiler).join(exe(name, target));
399 builder.copy_link(&cargo_out, &bin, FileType::Executable);
400 bin
401}
402
403macro_rules! bootstrap_tool {
404 ($(
405 $name:ident, $path:expr, $tool_name:expr
406 $(,is_external_tool = $external:expr)*
407 $(,allow_features = $allow_features:expr)?
408 $(,submodules = $submodules:expr)?
409 $(,artifact_kind = $artifact_kind:expr)?
410 ;
411 )+) => {
412 #[derive(PartialEq, Eq, Clone)]
413 pub(crate) enum Tool {
414 $(
415 #[allow(dead_code, reason = "not all bootstrap-tools need a variant")]
416 $name,
417 )+
418 }
419
420 impl<'a> Builder<'a> {
421 pub(crate) fn tool_exe(&self, tool: Tool) -> PathBuf {
425 self.tool(tool).tool_path
426 }
427
428 pub(crate) fn tool(&self, tool: Tool) -> ToolBuildResult {
432 match tool {
433 $(Tool::$name =>
434 self.ensure($name {
435 compiler: self.compiler(0, self.config.host_target),
436 target: self.config.host_target,
437 }),
438 )+
439 }
440 }
441 }
442
443 $(
444 #[derive(Debug, Clone, Hash, PartialEq, Eq)]
445 pub struct $name {
446 pub compiler: Compiler,
447 pub target: TargetSelection,
448 }
449
450 impl CommandLineStep for $name {
451 type Output = ToolBuildResult;
452
453 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
454 run.path($path)
455 }
456
457 fn make_run(run: RunConfig<'_>) {
458 run.builder.ensure($name {
459 compiler: run.builder.compiler(0, run.builder.config.host_target),
461 target: run.target,
462 });
463 }
464
465 fn run(self, builder: &Builder<'_>) -> ToolBuildResult {
466 $(
467 for submodule in $submodules {
468 builder.require_submodule(submodule, None);
469 }
470 )*
471
472 builder.ensure(ToolBuild {
473 build_compiler: self.compiler,
474 target: self.target,
475 tool: $tool_name,
476 mode: Mode::ToolBootstrap,
477 path: $path,
478 source_type: if false $(|| $external)* {
479 SourceType::Submodule
480 } else {
481 SourceType::InTree
482 },
483 extra_features: vec![],
484 allow_features: {
485 let mut _value = "";
486 $( _value = $allow_features; )?
487 _value
488 },
489 cargo_args: vec![],
490 artifact_kind: if false $(|| $artifact_kind == ToolArtifactKind::Library)* {
491 ToolArtifactKind::Library
492 } else {
493 ToolArtifactKind::Binary
494 }
495 })
496 }
497
498 fn metadata(&self) -> Option<StepMetadata> {
499 Some(
500 StepMetadata::build(stringify!($name), self.target)
501 .built_by(self.compiler)
502 )
503 }
504 }
505 )+
506 }
507}
508
509bootstrap_tool!(
510 Rustbook, "src/tools/rustbook", "rustbook", is_external_tool = true, submodules = SUBMODULES_FOR_RUSTBOOK;
515 UnstableBookGen, "src/tools/unstable-book-gen", "unstable-book-gen";
516 Tidy, "src/tools/tidy", "tidy";
517 Linkchecker, "src/tools/linkchecker", "linkchecker";
518 CargoTest, "src/tools/cargotest", "cargotest";
519 Compiletest, "src/tools/compiletest", "compiletest";
520 RemoteTestClient, "src/tools/remote-test-client", "remote-test-client";
521 RustInstaller, "src/tools/rust-installer", "rust-installer";
522 RustdocTheme, "src/tools/rustdoc-themes", "rustdoc-themes";
523 LintDocs, "src/tools/lint-docs", "lint-docs";
524 JsonDocCk, "src/tools/jsondocck", "jsondocck";
525 JsonDocLint, "src/tools/jsondoclint", "jsondoclint";
526 HtmlChecker, "src/tools/html-checker", "html-checker";
527 BumpStage0, "src/tools/bump-stage0", "bump-stage0";
528 ReplaceVersionPlaceholder, "src/tools/replace-version-placeholder", "replace-version-placeholder";
529 CollectLicenseMetadata, "src/tools/collect-license-metadata", "collect-license-metadata";
530 GenerateCopyright, "src/tools/generate-copyright", "generate-copyright";
531 GenerateWindowsSys, "src/tools/generate-windows-sys", "generate-windows-sys";
532 RustdocGUITest, "src/tools/rustdoc-gui-test", "rustdoc-gui-test";
533 CoverageDump, "src/tools/coverage-dump", "coverage-dump";
534 UnicodeTableGenerator, "src/tools/unicode-table-generator", "unicode-table-generator";
535 FeaturesStatusDump, "src/tools/features-status-dump", "features-status-dump";
536 OptimizedDist, "src/tools/opt-dist", "opt-dist", submodules = &["src/tools/rustc-perf"];
537 RunMakeSupport, "src/tools/run-make-support", "run_make_support", artifact_kind = ToolArtifactKind::Library;
538 IntrinsicTest, "library/stdarch/crates/intrinsic-test", "intrinsic-test";
539);
540
541pub static SUBMODULES_FOR_RUSTBOOK: &[&str] = &["src/doc/book", "src/doc/reference"];
544
545#[derive(Debug, Clone, Hash, PartialEq, Eq)]
548pub struct RustcPerf {
549 pub compiler: Compiler,
550 pub target: TargetSelection,
551}
552
553impl CommandLineStep for RustcPerf {
554 type Output = ToolBuildResult;
556
557 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
558 run.path("src/tools/rustc-perf")
559 }
560
561 fn make_run(run: RunConfig<'_>) {
562 run.builder.ensure(RustcPerf {
563 compiler: run.builder.compiler(0, run.builder.config.host_target),
564 target: run.target,
565 });
566 }
567
568 fn run(self, builder: &Builder<'_>) -> ToolBuildResult {
569 builder.require_submodule("src/tools/rustc-perf", None);
571
572 let tool = ToolBuild {
573 build_compiler: self.compiler,
574 target: self.target,
575 tool: "collector",
576 mode: Mode::ToolBootstrap,
577 path: "src/tools/rustc-perf",
578 source_type: SourceType::Submodule,
579 extra_features: Vec::new(),
580 allow_features: "",
581 cargo_args: vec!["-p".to_string(), "collector".to_string()],
584 artifact_kind: ToolArtifactKind::Binary,
585 };
586 let res = builder.ensure(tool.clone());
587 copy_link_tool_bin(builder, tool.build_compiler, tool.target, tool.mode, "rustc-fake");
590
591 res
592 }
593}
594
595#[derive(Debug, Clone, Hash, PartialEq, Eq)]
596pub struct ErrorIndex {
597 compilers: RustcPrivateCompilers,
598}
599
600impl ErrorIndex {
601 pub fn command(builder: &Builder<'_>, compilers: RustcPrivateCompilers) -> BootstrapCommand {
602 let mut cmd = command(builder.ensure(ErrorIndex { compilers }).tool_path);
605
606 let target_compiler = compilers.target_compiler();
607 let mut dylib_paths = builder.rustc_lib_paths(target_compiler);
608 dylib_paths.push(builder.sysroot_target_libdir(target_compiler, target_compiler.host));
609 add_dylib_path(dylib_paths, &mut cmd);
610 cmd
611 }
612}
613
614impl CommandLineStep for ErrorIndex {
615 type Output = ToolBuildResult;
616
617 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
618 run.path("src/tools/error_index_generator")
619 }
620
621 fn make_run(run: RunConfig<'_>) {
622 run.builder.ensure(ErrorIndex {
628 compilers: RustcPrivateCompilers::new(
629 run.builder,
630 run.builder.top_stage,
631 run.builder.host_target,
632 ),
633 });
634 }
635
636 fn run(self, builder: &Builder<'_>) -> ToolBuildResult {
637 builder.require_submodule(
638 "src/doc/reference",
639 Some("error_index_generator requires mdbook-spec"),
640 );
641 builder
642 .require_submodule("src/doc/book", Some("error_index_generator requires mdbook-trpl"));
643 builder.ensure(ToolBuild {
644 build_compiler: self.compilers.build_compiler,
645 target: self.compilers.target(),
646 tool: "error_index_generator",
647 mode: Mode::ToolRustcPrivate,
648 path: "src/tools/error_index_generator",
649 source_type: SourceType::InTree,
650 extra_features: Vec::new(),
651 allow_features: "",
652 cargo_args: Vec::new(),
653 artifact_kind: ToolArtifactKind::Binary,
654 })
655 }
656
657 fn metadata(&self) -> Option<StepMetadata> {
658 Some(
659 StepMetadata::build("error-index", self.compilers.target())
660 .built_by(self.compilers.build_compiler),
661 )
662 }
663}
664
665#[derive(Debug, Clone, Hash, PartialEq, Eq)]
666pub struct RemoteTestServer {
667 pub build_compiler: Compiler,
668 pub target: TargetSelection,
669}
670
671impl CommandLineStep for RemoteTestServer {
672 type Output = ToolBuildResult;
673
674 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
675 run.path("src/tools/remote-test-server")
676 }
677
678 fn make_run(run: RunConfig<'_>) {
679 run.builder.ensure(RemoteTestServer {
680 build_compiler: get_tool_target_compiler(
681 run.builder,
682 ToolTargetBuildMode::Build(run.target),
683 ),
684 target: run.target,
685 });
686 }
687
688 fn run(self, builder: &Builder<'_>) -> ToolBuildResult {
689 builder.ensure(ToolBuild {
690 build_compiler: self.build_compiler,
691 target: self.target,
692 tool: "remote-test-server",
693 mode: Mode::ToolTarget,
694 path: "src/tools/remote-test-server",
695 source_type: SourceType::InTree,
696 extra_features: Vec::new(),
697 allow_features: "",
698 cargo_args: Vec::new(),
699 artifact_kind: ToolArtifactKind::Binary,
700 })
701 }
702
703 fn metadata(&self) -> Option<StepMetadata> {
704 Some(StepMetadata::build("remote-test-server", self.target).built_by(self.build_compiler))
705 }
706}
707
708#[derive(Debug, Clone, Hash, PartialEq, Eq)]
713pub struct Rustdoc {
714 pub target_compiler: Compiler,
717}
718
719impl CommandLineStep for Rustdoc {
720 type Output = PathBuf;
722
723 const IS_HOST: bool = true;
724
725 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
726 run.multi_path(&["src/tools/rustdoc", "src/librustdoc"])
727 }
728
729 fn is_default_step(_builder: &Builder<'_>) -> bool {
730 true
731 }
732
733 fn make_run(run: RunConfig<'_>) {
734 run.builder.ensure(Rustdoc {
735 target_compiler: run.builder.compiler(run.builder.top_stage, run.target),
736 });
737 }
738
739 fn run(self, builder: &Builder<'_>) -> Self::Output {
740 let target_compiler = self.target_compiler;
741 let target = target_compiler.host;
742
743 if target_compiler.stage == 0 {
745 if !target_compiler.is_snapshot(builder) {
746 panic!("rustdoc in stage 0 must be snapshot rustdoc");
747 }
748
749 return builder.initial_rustdoc.clone();
750 }
751
752 let bin_rustdoc = || {
754 let sysroot = builder.sysroot(target_compiler);
755 let bindir = sysroot.join("bin");
756 t!(fs::create_dir_all(&bindir));
757 let bin_rustdoc = bindir.join(exe("rustdoc", target_compiler.host));
758 let _ = fs::remove_file(&bin_rustdoc);
759 bin_rustdoc
760 };
761
762 if builder.download_rustc() && builder.rust_info().is_managed_git_subrepository() {
765 let files_to_track = &["src/librustdoc", "src/tools/rustdoc", "src/rustdoc-json-types"];
766
767 if !builder.config.has_changes_from_upstream(files_to_track) {
769 let precompiled_rustdoc = builder
770 .config
771 .ci_rustc_dir()
772 .join("bin")
773 .join(exe("rustdoc", target_compiler.host));
774
775 let bin_rustdoc = bin_rustdoc();
776 builder.copy_link(&precompiled_rustdoc, &bin_rustdoc, FileType::Executable);
777 return bin_rustdoc;
778 }
779 }
780
781 let mut extra_features = Vec::new();
788 if !builder.config.rust_debug_logging {
789 extra_features.push("max_level_info".to_string())
790 }
791
792 let compilers = RustcPrivateCompilers::from_target_compiler(builder, target_compiler);
793 let tool_path = builder
794 .ensure(ToolBuild {
795 build_compiler: compilers.build_compiler,
796 target,
797 tool: "rustdoc-tool-binary",
801 mode: Mode::ToolRustcPrivate,
802 path: "src/tools/rustdoc",
803 source_type: SourceType::InTree,
804 extra_features,
805 allow_features: "",
806 cargo_args: Vec::new(),
807 artifact_kind: ToolArtifactKind::Binary,
808 })
809 .tool_path;
810
811 if builder.config.rust_debuginfo_level_tools == DebuginfoLevel::None {
812 compile::strip_debug(builder, target, &tool_path);
815 }
816 let bin_rustdoc = bin_rustdoc();
817 builder.copy_link(&tool_path, &bin_rustdoc, FileType::Executable);
818 bin_rustdoc
819 }
820
821 fn metadata(&self) -> Option<StepMetadata> {
822 Some(
823 StepMetadata::build("rustdoc", self.target_compiler.host)
824 .stage(self.target_compiler.stage),
825 )
826 }
827}
828
829#[derive(Debug, Clone, Hash, PartialEq, Eq)]
832pub struct Cargo {
833 build_compiler: Compiler,
834 target: TargetSelection,
835}
836
837impl Cargo {
838 pub fn from_build_compiler(build_compiler: Compiler, target: TargetSelection) -> Self {
841 Self { build_compiler, target }
842 }
843}
844
845impl CommandLineStep for Cargo {
846 type Output = ToolBuildResult;
847 const IS_HOST: bool = true;
848
849 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
850 run.path("src/tools/cargo")
851 }
852
853 fn is_default_step(builder: &Builder<'_>) -> bool {
854 builder.tool_enabled("cargo")
855 }
856
857 fn make_run(run: RunConfig<'_>) {
858 run.builder.ensure(Cargo {
859 build_compiler: get_tool_target_compiler(
860 run.builder,
861 ToolTargetBuildMode::Build(run.target),
862 ),
863 target: run.target,
864 });
865 }
866
867 fn run(self, builder: &Builder<'_>) -> ToolBuildResult {
868 builder.sess.require_submodule("src/tools/cargo", None);
869
870 builder.std(self.build_compiler, builder.host_target);
871 builder.std(self.build_compiler, self.target);
872
873 builder.ensure(ToolBuild {
874 build_compiler: self.build_compiler,
875 target: self.target,
876 tool: "cargo",
877 mode: Mode::ToolTarget,
878 path: "src/tools/cargo",
879 source_type: SourceType::Submodule,
880 extra_features: Vec::new(),
881 allow_features: "min_specialization,specialization",
886 cargo_args: Vec::new(),
887 artifact_kind: ToolArtifactKind::Binary,
888 })
889 }
890
891 fn metadata(&self) -> Option<StepMetadata> {
892 Some(StepMetadata::build("cargo", self.target).built_by(self.build_compiler))
893 }
894}
895
896#[derive(Clone)]
899pub struct BuiltLldWrapper {
900 tool: ToolBuildResult,
901 lld_dir: PathBuf,
902}
903
904#[derive(Debug, Clone, Hash, PartialEq, Eq)]
905pub struct LldWrapper {
906 pub build_compiler: Compiler,
907 pub target: TargetSelection,
908}
909
910impl LldWrapper {
911 pub fn for_use_by_compiler(builder: &Builder<'_>, target_compiler: Compiler) -> Self {
913 Self {
914 build_compiler: get_tool_target_compiler(
915 builder,
916 ToolTargetBuildMode::Dist(target_compiler),
917 ),
918 target: target_compiler.host,
919 }
920 }
921}
922
923impl CommandLineStep for LldWrapper {
924 type Output = BuiltLldWrapper;
925
926 const IS_HOST: bool = true;
927
928 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
929 run.path("src/tools/lld-wrapper")
930 }
931
932 fn make_run(run: RunConfig<'_>) {
933 run.builder.ensure(LldWrapper {
934 build_compiler: get_tool_target_compiler(
935 run.builder,
936 ToolTargetBuildMode::Build(run.target),
937 ),
938 target: run.target,
939 });
940 }
941
942 fn run(self, builder: &Builder<'_>) -> Self::Output {
943 let lld_dir = builder.ensure(llvm::Lld { target: self.target });
944 let tool = builder.ensure(ToolBuild {
945 build_compiler: self.build_compiler,
946 target: self.target,
947 tool: "lld-wrapper",
948 mode: Mode::ToolTarget,
949 path: "src/tools/lld-wrapper",
950 source_type: SourceType::InTree,
951 extra_features: Vec::new(),
952 allow_features: "",
953 cargo_args: Vec::new(),
954 artifact_kind: ToolArtifactKind::Binary,
955 });
956 BuiltLldWrapper { tool, lld_dir }
957 }
958
959 fn metadata(&self) -> Option<StepMetadata> {
960 Some(StepMetadata::build("LldWrapper", self.target).built_by(self.build_compiler))
961 }
962}
963
964pub(crate) fn copy_lld_artifacts(
965 builder: &Builder<'_>,
966 lld_wrapper: BuiltLldWrapper,
967 target_compiler: Compiler,
968) {
969 let target = target_compiler.host;
970
971 let libdir_bin = builder.sysroot_target_bindir(target_compiler, target);
972 t!(fs::create_dir_all(&libdir_bin));
973
974 let src_exe = exe("lld", target);
975 let dst_exe = exe("rust-lld", target);
976
977 builder.copy_link(
978 &lld_wrapper.lld_dir.join("bin").join(src_exe),
979 &libdir_bin.join(dst_exe),
980 FileType::Executable,
981 );
982 let self_contained_lld_dir = libdir_bin.join("gcc-ld");
983 t!(fs::create_dir_all(&self_contained_lld_dir));
984
985 for name in LLD_FILE_NAMES {
986 builder.copy_link(
987 &lld_wrapper.tool.tool_path,
988 &self_contained_lld_dir.join(exe(name, target)),
989 FileType::Executable,
990 );
991 }
992}
993
994#[derive(Debug, Clone, Hash, PartialEq, Eq)]
997pub struct WasmComponentLd {
998 build_compiler: Compiler,
999 target: TargetSelection,
1000}
1001
1002impl WasmComponentLd {
1003 pub fn for_use_by_compiler(builder: &Builder<'_>, target_compiler: Compiler) -> Self {
1005 Self {
1006 build_compiler: get_tool_target_compiler(
1007 builder,
1008 ToolTargetBuildMode::Dist(target_compiler),
1009 ),
1010 target: target_compiler.host,
1011 }
1012 }
1013}
1014
1015impl CommandLineStep for WasmComponentLd {
1016 type Output = ToolBuildResult;
1017
1018 const IS_HOST: bool = true;
1019
1020 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1021 run.path("src/tools/wasm-component-ld")
1022 }
1023
1024 fn make_run(run: RunConfig<'_>) {
1025 run.builder.ensure(WasmComponentLd {
1026 build_compiler: get_tool_target_compiler(
1027 run.builder,
1028 ToolTargetBuildMode::Build(run.target),
1029 ),
1030 target: run.target,
1031 });
1032 }
1033
1034 fn run(self, builder: &Builder<'_>) -> ToolBuildResult {
1035 builder.ensure(ToolBuild {
1036 build_compiler: self.build_compiler,
1037 target: self.target,
1038 tool: "wasm-component-ld",
1039 mode: Mode::ToolTarget,
1040 path: "src/tools/wasm-component-ld",
1041 source_type: SourceType::InTree,
1042 extra_features: vec![],
1043 allow_features: "",
1044 cargo_args: vec![],
1045 artifact_kind: ToolArtifactKind::Binary,
1046 })
1047 }
1048
1049 fn metadata(&self) -> Option<StepMetadata> {
1050 Some(StepMetadata::build("WasmComponentLd", self.target).built_by(self.build_compiler))
1051 }
1052}
1053
1054#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1055pub struct RustAnalyzer {
1056 compilers: RustcPrivateCompilers,
1057}
1058
1059impl RustAnalyzer {
1060 pub fn from_compilers(compilers: RustcPrivateCompilers) -> Self {
1061 Self { compilers }
1062 }
1063}
1064
1065impl RustAnalyzer {
1066 pub const ALLOW_FEATURES: &'static str = "rustc_private,proc_macro_internals,proc_macro_diagnostic,proc_macro_span,proc_macro_span_shrink,proc_macro_def_site,new_zeroed_alloc";
1067}
1068
1069impl CommandLineStep for RustAnalyzer {
1070 type Output = ToolBuildResult;
1071 const IS_HOST: bool = true;
1072
1073 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1074 run.path("src/tools/rust-analyzer")
1075 }
1076
1077 fn is_default_step(builder: &Builder<'_>) -> bool {
1078 builder.tool_enabled("rust-analyzer")
1079 }
1080
1081 fn make_run(run: RunConfig<'_>) {
1082 run.builder.ensure(RustAnalyzer {
1083 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1084 });
1085 }
1086
1087 fn run(self, builder: &Builder<'_>) -> ToolBuildResult {
1088 let build_compiler = self.compilers.build_compiler;
1089 let target = self.compilers.target();
1090 builder.ensure(ToolBuild {
1091 build_compiler,
1092 target,
1093 tool: "rust-analyzer",
1094 mode: Mode::ToolRustcPrivate,
1095 path: "src/tools/rust-analyzer",
1096 extra_features: vec!["in-rust-tree".to_owned()],
1097 source_type: SourceType::InTree,
1098 allow_features: RustAnalyzer::ALLOW_FEATURES,
1099 cargo_args: Vec::new(),
1100 artifact_kind: ToolArtifactKind::Binary,
1101 })
1102 }
1103
1104 fn metadata(&self) -> Option<StepMetadata> {
1105 Some(
1106 StepMetadata::build("rust-analyzer", self.compilers.target())
1107 .built_by(self.compilers.build_compiler),
1108 )
1109 }
1110}
1111
1112#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1113pub struct RustAnalyzerProcMacroSrv {
1114 compilers: RustcPrivateCompilers,
1115}
1116
1117impl RustAnalyzerProcMacroSrv {
1118 pub fn from_compilers(compilers: RustcPrivateCompilers) -> Self {
1119 Self { compilers }
1120 }
1121}
1122
1123impl CommandLineStep for RustAnalyzerProcMacroSrv {
1124 type Output = ToolBuildResult;
1125 const IS_HOST: bool = true;
1126
1127 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1128 run.path("src/tools/rust-analyzer").path_with_alias(
1131 "src/tools/rust-analyzer/crates/proc-macro-srv-cli",
1132 "rust-analyzer-proc-macro-srv",
1133 )
1134 }
1135
1136 fn is_default_step(builder: &Builder<'_>) -> bool {
1137 builder.tool_enabled("rust-analyzer")
1138 || builder.tool_enabled("rust-analyzer-proc-macro-srv")
1139 }
1140
1141 fn make_run(run: RunConfig<'_>) {
1142 run.builder.ensure(RustAnalyzerProcMacroSrv {
1143 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1144 });
1145 }
1146
1147 fn run(self, builder: &Builder<'_>) -> Self::Output {
1148 let tool_result = builder.ensure(ToolBuild {
1149 build_compiler: self.compilers.build_compiler,
1150 target: self.compilers.target(),
1151 tool: "rust-analyzer-proc-macro-srv",
1152 mode: Mode::ToolRustcPrivate,
1153 path: "src/tools/rust-analyzer/crates/proc-macro-srv-cli",
1154 extra_features: vec!["in-rust-tree".to_owned()],
1155 source_type: SourceType::InTree,
1156 allow_features: RustAnalyzer::ALLOW_FEATURES,
1157 cargo_args: Vec::new(),
1158 artifact_kind: ToolArtifactKind::Binary,
1159 });
1160
1161 let libexec_path = builder.sysroot(self.compilers.target_compiler).join("libexec");
1164 t!(fs::create_dir_all(&libexec_path));
1165 builder.copy_link(
1166 &tool_result.tool_path,
1167 &libexec_path.join("rust-analyzer-proc-macro-srv"),
1168 FileType::Executable,
1169 );
1170
1171 tool_result
1172 }
1173
1174 fn metadata(&self) -> Option<StepMetadata> {
1175 Some(
1176 StepMetadata::build("rust-analyzer-proc-macro-srv", self.compilers.target())
1177 .built_by(self.compilers.build_compiler),
1178 )
1179 }
1180}
1181
1182#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1183pub struct LlvmBitcodeLinker {
1184 build_compiler: Compiler,
1185 target: TargetSelection,
1186}
1187
1188impl LlvmBitcodeLinker {
1189 pub fn from_build_compiler(build_compiler: Compiler, target: TargetSelection) -> Self {
1192 Self { build_compiler, target }
1193 }
1194
1195 pub fn from_target_compiler(builder: &Builder<'_>, target_compiler: Compiler) -> Self {
1197 Self {
1198 build_compiler: get_tool_target_compiler(
1199 builder,
1200 ToolTargetBuildMode::Dist(target_compiler),
1201 ),
1202 target: target_compiler.host,
1203 }
1204 }
1205
1206 pub fn get_build_compiler_for_target(
1208 builder: &Builder<'_>,
1209 target: TargetSelection,
1210 ) -> Compiler {
1211 get_tool_target_compiler(builder, ToolTargetBuildMode::Build(target))
1212 }
1213}
1214
1215impl CommandLineStep for LlvmBitcodeLinker {
1216 type Output = ToolBuildResult;
1217 const IS_HOST: bool = true;
1218
1219 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1220 run.path("src/tools/llvm-bitcode-linker")
1221 }
1222
1223 fn is_default_step(builder: &Builder<'_>) -> bool {
1224 builder.tool_enabled("llvm-bitcode-linker")
1225 }
1226
1227 fn make_run(run: RunConfig<'_>) {
1228 run.builder.ensure(LlvmBitcodeLinker {
1229 build_compiler: Self::get_build_compiler_for_target(run.builder, run.target),
1230 target: run.target,
1231 });
1232 }
1233
1234 fn run(self, builder: &Builder<'_>) -> ToolBuildResult {
1235 builder.ensure(ToolBuild {
1236 build_compiler: self.build_compiler,
1237 target: self.target,
1238 tool: "llvm-bitcode-linker",
1239 mode: Mode::ToolTarget,
1240 path: "src/tools/llvm-bitcode-linker",
1241 source_type: SourceType::InTree,
1242 extra_features: vec![],
1243 allow_features: "",
1244 cargo_args: Vec::new(),
1245 artifact_kind: ToolArtifactKind::Binary,
1246 })
1247 }
1248
1249 fn metadata(&self) -> Option<StepMetadata> {
1250 Some(StepMetadata::build("LlvmBitcodeLinker", self.target).built_by(self.build_compiler))
1251 }
1252}
1253
1254#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1255pub struct LibcxxVersionTool {
1256 pub target: TargetSelection,
1257}
1258
1259#[expect(dead_code)]
1260#[derive(Debug, Clone)]
1261pub enum LibcxxVersion {
1262 Gnu(usize),
1263 Llvm(usize),
1264}
1265
1266impl Step for LibcxxVersionTool {
1267 type Output = LibcxxVersion;
1268
1269 fn run(self, builder: &Builder<'_>) -> LibcxxVersion {
1270 let out_dir = builder.out.join(self.target.to_string()).join("libcxx-version");
1271 let executable = out_dir.join(exe("libcxx-version", self.target));
1272
1273 if !executable.exists() {
1278 if !out_dir.exists() {
1279 t!(fs::create_dir_all(&out_dir));
1280 }
1281
1282 let compiler = builder.cxx(self.target).unwrap();
1283 let mut cmd = command(compiler);
1284
1285 cmd.arg("-o")
1286 .arg(&executable)
1287 .arg(builder.src.join("src/tools/libcxx-version/main.cpp"));
1288
1289 cmd.run(builder);
1290
1291 if !executable.exists() {
1292 panic!("Something went wrong. {} is not present", executable.display());
1293 }
1294 }
1295
1296 let version_output = command(executable).run_capture_stdout(builder).stdout();
1297
1298 let version_str = version_output.split_once("version:").unwrap().1;
1299 let version = version_str.trim().parse::<usize>().unwrap();
1300
1301 if version_output.starts_with("libstdc++") {
1302 LibcxxVersion::Gnu(version)
1303 } else if version_output.starts_with("libc++") {
1304 LibcxxVersion::Llvm(version)
1305 } else {
1306 panic!("Coudln't recognize the standard library version.");
1307 }
1308 }
1309}
1310
1311#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1312pub struct BuildManifest {
1313 compiler: Compiler,
1314 target: TargetSelection,
1315}
1316
1317impl BuildManifest {
1318 pub fn new(builder: &Builder<'_>, target: TargetSelection) -> Self {
1319 BuildManifest { compiler: builder.compiler(1, builder.config.host_target), target }
1320 }
1321}
1322
1323impl CommandLineStep for BuildManifest {
1324 type Output = ToolBuildResult;
1325
1326 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1327 run.path("src/tools/build-manifest")
1328 }
1329
1330 fn make_run(run: RunConfig<'_>) {
1331 run.builder.ensure(BuildManifest::new(run.builder, run.target));
1332 }
1333
1334 fn run(self, builder: &Builder<'_>) -> ToolBuildResult {
1335 assert!(self.compiler.stage != 0);
1338 builder.ensure(ToolBuild {
1339 build_compiler: self.compiler,
1340 target: self.target,
1341 tool: "build-manifest",
1342 mode: Mode::ToolStd,
1343 path: "src/tools/build-manifest",
1344 source_type: SourceType::InTree,
1345 extra_features: vec![],
1346 allow_features: "",
1347 cargo_args: vec![],
1348 artifact_kind: ToolArtifactKind::Binary,
1349 })
1350 }
1351
1352 fn metadata(&self) -> Option<StepMetadata> {
1353 Some(StepMetadata::build("build-manifest", self.target).built_by(self.compiler))
1354 }
1355}
1356
1357#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
1369pub struct RustcPrivateCompilers {
1370 build_compiler: Compiler,
1372 target_compiler: Compiler,
1375}
1376
1377impl RustcPrivateCompilers {
1378 pub fn new(builder: &Builder<'_>, stage: u32, target: TargetSelection) -> Self {
1381 let build_compiler = Self::build_compiler_from_stage(builder, stage);
1382
1383 let target_compiler = builder.compiler(build_compiler.stage + 1, target);
1386
1387 Self { build_compiler, target_compiler }
1388 }
1389
1390 pub fn from_build_and_target_compiler(
1391 build_compiler: Compiler,
1392 target_compiler: Compiler,
1393 ) -> Self {
1394 Self { build_compiler, target_compiler }
1395 }
1396
1397 pub fn from_build_compiler(
1399 builder: &Builder<'_>,
1400 build_compiler: Compiler,
1401 target: TargetSelection,
1402 ) -> Self {
1403 let target_compiler = builder.compiler(build_compiler.stage + 1, target);
1404 Self { build_compiler, target_compiler }
1405 }
1406
1407 pub fn from_target_compiler(builder: &Builder<'_>, target_compiler: Compiler) -> Self {
1409 Self {
1410 build_compiler: Self::build_compiler_from_stage(builder, target_compiler.stage),
1411 target_compiler,
1412 }
1413 }
1414
1415 fn build_compiler_from_stage(builder: &Builder<'_>, stage: u32) -> Compiler {
1416 assert!(stage > 0);
1417
1418 if builder.download_rustc() && stage == 1 {
1419 builder.compiler(1, builder.config.host_target)
1421 } else {
1422 builder.compiler(stage - 1, builder.config.host_target)
1423 }
1424 }
1425
1426 pub fn build_compiler(&self) -> Compiler {
1427 self.build_compiler
1428 }
1429
1430 pub fn target_compiler(&self) -> Compiler {
1431 self.target_compiler
1432 }
1433
1434 pub fn target(&self) -> TargetSelection {
1436 self.target_compiler.host
1437 }
1438}
1439
1440macro_rules! tool_rustc_extended {
1443 (
1444 $name:ident {
1445 path: $path:expr,
1446 tool_name: $tool_name:expr,
1447 stable: $stable:expr
1448 $( , add_bins_to_sysroot: $add_bins_to_sysroot:expr )?
1449 $( , cargo_args: $cargo_args:expr )?
1450 $( , )?
1451 }
1452 ) => {
1453 #[derive(Debug, Clone, Hash, PartialEq, Eq)]
1454 pub struct $name {
1455 compilers: RustcPrivateCompilers,
1456 }
1457
1458 impl $name {
1459 pub fn from_compilers(compilers: RustcPrivateCompilers) -> Self {
1460 Self {
1461 compilers,
1462 }
1463 }
1464 }
1465
1466 impl CommandLineStep for $name {
1467 type Output = ToolBuildResult;
1468 const IS_HOST: bool = true;
1469
1470 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1471 should_run_extended_rustc_tool(
1472 run,
1473 $path,
1474 )
1475 }
1476
1477 fn is_default_step(builder: &Builder<'_>) -> bool {
1478 extended_rustc_tool_is_default_step(
1479 builder,
1480 $tool_name,
1481 $stable,
1482 )
1483 }
1484
1485 fn make_run(run: RunConfig<'_>) {
1486 run.builder.ensure($name {
1487 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1488 });
1489 }
1490
1491 fn run(self, builder: &Builder<'_>) -> ToolBuildResult {
1492 let Self { compilers } = self;
1493 build_extended_rustc_tool(
1494 builder,
1495 compilers,
1496 $tool_name,
1497 $path,
1498 None $( .or(Some(&$add_bins_to_sysroot)) )?,
1499 None $( .or(Some($cargo_args)) )?,
1500 )
1501 }
1502
1503 fn metadata(&self) -> Option<StepMetadata> {
1504 Some(
1505 StepMetadata::build($tool_name, self.compilers.target())
1506 .built_by(self.compilers.build_compiler)
1507 )
1508 }
1509 }
1510 }
1511}
1512
1513fn should_run_extended_rustc_tool<'a>(run: ShouldRun<'a>, path: &'static str) -> ShouldRun<'a> {
1514 run.path(path)
1515}
1516
1517fn extended_rustc_tool_is_default_step(
1518 builder: &Builder<'_>,
1519 tool_name: &'static str,
1520 stable: bool,
1521) -> bool {
1522 builder.config.extended
1523 && builder.config.tools.as_ref().map_or(
1524 stable || builder.sess.unstable_features(),
1527 |tools| {
1529 tools.iter().any(|tool| match tool.as_ref() {
1530 "clippy" => tool_name == "clippy-driver",
1531 x => tool_name == x,
1532 })
1533 },
1534 )
1535}
1536
1537fn build_extended_rustc_tool(
1538 builder: &Builder<'_>,
1539 compilers: RustcPrivateCompilers,
1540 tool_name: &'static str,
1541 path: &'static str,
1542 add_bins_to_sysroot: Option<&[&str]>,
1543 cargo_args: Option<&[&'static str]>,
1544) -> ToolBuildResult {
1545 let target = compilers.target();
1546 let build_compiler = compilers.build_compiler;
1547 let ToolBuildResult { tool_path, artifacts, .. } = builder.ensure(ToolBuild {
1548 build_compiler,
1549 target,
1550 tool: tool_name,
1551 mode: Mode::ToolRustcPrivate,
1552 path,
1553 extra_features: Vec::new(),
1554 source_type: SourceType::InTree,
1555 allow_features: "",
1556 cargo_args: cargo_args.unwrap_or_default().iter().map(|s| String::from(*s)).collect(),
1557 artifact_kind: ToolArtifactKind::Binary,
1558 });
1559
1560 let target_compiler = compilers.target_compiler;
1561 if let Some(add_bins_to_sysroot) = add_bins_to_sysroot
1562 && !add_bins_to_sysroot.is_empty()
1563 {
1564 let bindir = builder.sysroot(target_compiler).join("bin");
1565 t!(fs::create_dir_all(&bindir));
1566
1567 for add_bin in add_bins_to_sysroot {
1568 let bin_destination = bindir.join(exe(add_bin, target_compiler.host));
1569 builder.copy_link(&tool_path, &bin_destination, FileType::Executable);
1570 }
1571
1572 let path = bindir.join(exe(tool_name, target_compiler.host));
1574 ToolBuildResult { tool_path: path, build_compiler, artifacts }
1575 } else {
1576 ToolBuildResult { tool_path, build_compiler, artifacts }
1577 }
1578}
1579
1580tool_rustc_extended!(Cargofmt {
1581 path: "src/tools/rustfmt",
1582 tool_name: "cargo-fmt",
1583 stable: true,
1584 add_bins_to_sysroot: ["cargo-fmt"]
1585});
1586tool_rustc_extended!(CargoClippy {
1587 path: "src/tools/clippy",
1588 tool_name: "cargo-clippy",
1589 stable: true,
1590 add_bins_to_sysroot: ["cargo-clippy"]
1591});
1592tool_rustc_extended!(Clippy {
1593 path: "src/tools/clippy",
1594 tool_name: "clippy-driver",
1595 stable: true,
1596 add_bins_to_sysroot: ["clippy-driver"]
1597});
1598tool_rustc_extended!(Miri {
1599 path: "src/tools/miri",
1600 tool_name: "miri",
1601 stable: false,
1602 add_bins_to_sysroot: ["miri"],
1603 cargo_args: &["--all-targets"],
1605});
1606tool_rustc_extended!(CargoMiri {
1607 path: "src/tools/miri/cargo-miri",
1608 tool_name: "cargo-miri",
1609 stable: false,
1610 add_bins_to_sysroot: ["cargo-miri"]
1611});
1612tool_rustc_extended!(Rustfmt {
1613 path: "src/tools/rustfmt",
1614 tool_name: "rustfmt",
1615 stable: true,
1616 add_bins_to_sysroot: ["rustfmt"]
1617});
1618
1619pub const TEST_FLOAT_PARSE_ALLOW_FEATURES: &str = "f16,cfg_target_has_reliable_f16_f128";
1620
1621impl Builder<'_> {
1622 pub(crate) fn tool_cmd(&self, tool: Tool) -> BootstrapCommand {
1627 let mut cmd = command(self.tool_exe(tool));
1628 let compiler = self.compiler(0, self.config.host_target);
1629 let host = &compiler.host;
1630 let mut lib_paths: Vec<PathBuf> = discover_out_dirs_with_dylibs(
1635 self.cargo_out(compiler, Mode::ToolBootstrap, *host).join("build"),
1636 );
1637
1638 if compiler.host.is_msvc() {
1642 let curpaths = env::var_os("PATH").unwrap_or_default();
1643 let curpaths = env::split_paths(&curpaths).collect::<Vec<_>>();
1644 for (k, v) in self.cc[&compiler.host].env() {
1645 if k != "PATH" {
1646 continue;
1647 }
1648 for path in env::split_paths(v) {
1649 if !curpaths.contains(&path) {
1650 lib_paths.push(path);
1651 }
1652 }
1653 }
1654 }
1655
1656 add_dylib_path(lib_paths, &mut cmd);
1657
1658 cmd.env("RUSTC", &self.initial_rustc);
1660
1661 cmd
1662 }
1663}
1664
1665fn discover_out_dirs_with_dylibs(dir: PathBuf) -> Vec<PathBuf> {
1667 if !dir.exists() {
1668 return Vec::new();
1669 }
1670 let read_dir = |path: &Path| path.read_dir().ok().into_iter().flatten().filter_map(Result::ok);
1671 let has_dylib = |path: &Path| {
1672 read_dir(path)
1673 .any(|e| e.path().extension().is_some_and(|ext| ext == std::env::consts::DLL_EXTENSION))
1674 };
1675 dir.read_dir()
1676 .unwrap_or_else(|e| panic!("Couldn't read {}: {}", dir.display(), e))
1677 .map(|e| e.unwrap())
1678 .flat_map(|e| read_dir(&e.path()))
1679 .flat_map(|e| read_dir(&e.path()))
1680 .map(|e| e.path())
1681 .filter(|path| path.ends_with("out") && has_dylib(path))
1682 .collect::<Vec<_>>()
1683}