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