1use std::collections::HashSet;
12use std::ffi::OsStr;
13use std::io::Write;
14use std::path::{Path, PathBuf};
15use std::{env, fs};
16
17use object::BinaryFormat;
18use object::read::archive::ArchiveFile;
19#[cfg(feature = "tracing")]
20use tracing::instrument;
21
22use crate::core::build_steps::compile::{get_codegen_backend_file, normalize_codegen_backend_name};
23use crate::core::build_steps::doc::DocumentationFormat;
24use crate::core::build_steps::tool::{
25 self, RustcPrivateCompilers, ToolTargetBuildMode, get_tool_target_compiler,
26};
27use crate::core::build_steps::vendor::{VENDOR_DIR, Vendor};
28use crate::core::build_steps::{compile, llvm};
29use crate::core::builder::{Builder, Kind, RunConfig, ShouldRun, Step, StepMetadata};
30use crate::core::config::TargetSelection;
31use crate::utils::build_stamp::{self, BuildStamp};
32use crate::utils::channel::{self, Info};
33use crate::utils::exec::{BootstrapCommand, command};
34use crate::utils::helpers::{
35 exe, is_dylib, move_file, t, target_supports_cranelift_backend, timeit,
36};
37use crate::utils::tarball::{GeneratedTarball, OverlayKind, Tarball};
38use crate::{CodegenBackendKind, Compiler, DependencyType, FileType, LLVM_TOOLS, Mode, trace};
39
40pub fn pkgname(builder: &Builder<'_>, component: &str) -> String {
41 format!("{}-{}", component, builder.rust_package_vers())
42}
43
44pub(crate) fn distdir(builder: &Builder<'_>) -> PathBuf {
45 builder.out.join("dist")
46}
47
48pub fn tmpdir(builder: &Builder<'_>) -> PathBuf {
49 builder.out.join("tmp/dist")
50}
51
52fn should_build_extended_tool(builder: &Builder<'_>, tool: &str) -> bool {
53 if !builder.config.extended {
54 return false;
55 }
56 builder.config.tools.as_ref().is_none_or(|tools| tools.contains(tool))
57}
58
59#[derive(Debug, Clone, Hash, PartialEq, Eq)]
60pub struct Docs {
61 pub host: TargetSelection,
62}
63
64impl Step for Docs {
65 type Output = Option<GeneratedTarball>;
66 const DEFAULT: bool = true;
67
68 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
69 let default = run.builder.config.docs;
70 run.alias("rust-docs").default_condition(default)
71 }
72
73 fn make_run(run: RunConfig<'_>) {
74 run.builder.ensure(Docs { host: run.target });
75 }
76
77 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
79 let host = self.host;
80 builder.run_default_doc_steps();
84
85 let dest = "share/doc/rust/html";
86
87 let mut tarball = Tarball::new(builder, "rust-docs", &host.triple);
88 tarball.set_product_name("Rust Documentation");
89 tarball.add_bulk_dir(builder.doc_out(host), dest);
90 tarball.add_file(builder.src.join("src/doc/robots.txt"), dest, FileType::Regular);
91 tarball.add_file(builder.src.join("src/doc/sitemap.txt"), dest, FileType::Regular);
92 Some(tarball.generate())
93 }
94
95 fn metadata(&self) -> Option<StepMetadata> {
96 Some(StepMetadata::dist("docs", self.host))
97 }
98}
99
100#[derive(Debug, Clone, Hash, PartialEq, Eq)]
103pub struct JsonDocs {
104 build_compiler: Compiler,
105 target: TargetSelection,
106}
107
108impl Step for JsonDocs {
109 type Output = Option<GeneratedTarball>;
110 const DEFAULT: bool = true;
111
112 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
113 let default = run.builder.config.docs;
114 run.alias("rust-docs-json").default_condition(default)
115 }
116
117 fn make_run(run: RunConfig<'_>) {
118 run.builder.ensure(JsonDocs {
119 build_compiler: run.builder.compiler_for_std(run.builder.top_stage),
120 target: run.target,
121 });
122 }
123
124 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
125 let target = self.target;
126 let directory = builder.ensure(crate::core::build_steps::doc::Std::from_build_compiler(
127 self.build_compiler,
128 target,
129 DocumentationFormat::Json,
130 ));
131
132 let dest = "share/doc/rust/json";
133
134 let mut tarball = Tarball::new(builder, "rust-docs-json", &target.triple);
135 tarball.set_product_name("Rust Documentation In JSON Format");
136 tarball.is_preview(true);
137 tarball.add_bulk_dir(directory, dest);
138 Some(tarball.generate())
139 }
140
141 fn metadata(&self) -> Option<StepMetadata> {
142 Some(StepMetadata::dist("json-docs", self.target).built_by(self.build_compiler))
143 }
144}
145
146#[derive(Debug, Clone, Hash, PartialEq, Eq)]
153pub struct RustcDocs {
154 target: TargetSelection,
155}
156
157impl Step for RustcDocs {
158 type Output = GeneratedTarball;
159
160 const DEFAULT: bool = true;
161 const IS_HOST: bool = true;
162
163 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
164 let builder = run.builder;
165 run.alias("rustc-docs").default_condition(builder.config.compiler_docs)
166 }
167
168 fn make_run(run: RunConfig<'_>) {
169 run.builder.ensure(RustcDocs { target: run.target });
170 }
171
172 fn run(self, builder: &Builder<'_>) -> Self::Output {
173 let target = self.target;
174 builder.run_default_doc_steps();
175
176 let mut tarball = Tarball::new(builder, "rustc-docs", &target.triple);
177 tarball.set_product_name("Rustc Documentation");
178 tarball.add_bulk_dir(builder.compiler_doc_out(target), "share/doc/rust/html/rustc");
179 tarball.generate()
180 }
181}
182
183fn find_files(files: &[&str], path: &[PathBuf]) -> Vec<PathBuf> {
184 let mut found = Vec::with_capacity(files.len());
185
186 for file in files {
187 let file_path = path.iter().map(|dir| dir.join(file)).find(|p| p.exists());
188
189 if let Some(file_path) = file_path {
190 found.push(file_path);
191 } else {
192 panic!("Could not find '{file}' in {path:?}");
193 }
194 }
195
196 found
197}
198
199fn make_win_dist(plat_root: &Path, target: TargetSelection, builder: &Builder<'_>) {
200 if builder.config.dry_run() {
201 return;
202 }
203
204 let (bin_path, lib_path) = get_cc_search_dirs(target, builder);
205
206 let compiler = if target == "i686-pc-windows-gnu" {
207 "i686-w64-mingw32-gcc.exe"
208 } else if target == "x86_64-pc-windows-gnu" {
209 "x86_64-w64-mingw32-gcc.exe"
210 } else {
211 "gcc.exe"
212 };
213 let target_tools = [compiler, "ld.exe", "dlltool.exe", "libwinpthread-1.dll"];
214
215 let target_libs = [
218 "libgcc.a",
220 "libgcc_eh.a",
221 "libgcc_s.a",
222 "libm.a",
223 "libmingw32.a",
224 "libmingwex.a",
225 "libstdc++.a",
226 "libiconv.a",
227 "libmoldname.a",
228 "libpthread.a",
229 "libadvapi32.a",
234 "libbcrypt.a",
235 "libcomctl32.a",
236 "libcomdlg32.a",
237 "libcredui.a",
238 "libcrypt32.a",
239 "libdbghelp.a",
240 "libgdi32.a",
241 "libimagehlp.a",
242 "libiphlpapi.a",
243 "libkernel32.a",
244 "libmsimg32.a",
245 "libmsvcrt.a",
246 "libntdll.a",
247 "libodbc32.a",
248 "libole32.a",
249 "liboleaut32.a",
250 "libopengl32.a",
251 "libpsapi.a",
252 "librpcrt4.a",
253 "libsecur32.a",
254 "libsetupapi.a",
255 "libshell32.a",
256 "libsynchronization.a",
257 "libuser32.a",
258 "libuserenv.a",
259 "libuuid.a",
260 "libwinhttp.a",
261 "libwinmm.a",
262 "libwinspool.a",
263 "libws2_32.a",
264 "libwsock32.a",
265 ];
266
267 let target_tools = find_files(&target_tools, &bin_path);
269 let target_libs = find_files(&target_libs, &lib_path);
270
271 let plat_target_bin_self_contained_dir =
273 plat_root.join("lib/rustlib").join(target).join("bin/self-contained");
274 fs::create_dir_all(&plat_target_bin_self_contained_dir)
275 .expect("creating plat_target_bin_self_contained_dir failed");
276 for src in target_tools {
277 builder.copy_link_to_folder(&src, &plat_target_bin_self_contained_dir);
278 }
279
280 builder.create(
282 &plat_target_bin_self_contained_dir.join("GCC-WARNING.txt"),
283 "gcc.exe contained in this folder cannot be used for compiling C files - it is only \
284 used as a linker. In order to be able to compile projects containing C code use \
285 the GCC provided by MinGW or Cygwin.",
286 );
287
288 let plat_target_lib_self_contained_dir =
290 plat_root.join("lib/rustlib").join(target).join("lib/self-contained");
291 fs::create_dir_all(&plat_target_lib_self_contained_dir)
292 .expect("creating plat_target_lib_self_contained_dir failed");
293 for src in target_libs {
294 builder.copy_link_to_folder(&src, &plat_target_lib_self_contained_dir);
295 }
296}
297
298fn make_win_llvm_dist(plat_root: &Path, target: TargetSelection, builder: &Builder<'_>) {
299 if builder.config.dry_run() {
300 return;
301 }
302
303 let (_, lib_path) = get_cc_search_dirs(target, builder);
304
305 let target_libs = [
308 "libunwind.a",
310 "libunwind.dll.a",
311 "libmingw32.a",
312 "libmingwex.a",
313 "libmsvcrt.a",
314 "libkernel32.a",
316 "libuser32.a",
317 "libntdll.a",
318 "libuserenv.a",
319 "libws2_32.a",
320 "libdbghelp.a",
321 ];
322
323 let target_libs = find_files(&target_libs, &lib_path);
325
326 let plat_target_lib_self_contained_dir =
328 plat_root.join("lib/rustlib").join(target).join("lib/self-contained");
329 fs::create_dir_all(&plat_target_lib_self_contained_dir)
330 .expect("creating plat_target_lib_self_contained_dir failed");
331 for src in target_libs {
332 builder.copy_link_to_folder(&src, &plat_target_lib_self_contained_dir);
333 }
334}
335
336fn runtime_dll_dist(rust_root: &Path, target: TargetSelection, builder: &Builder<'_>) {
337 if builder.config.dry_run() {
338 return;
339 }
340
341 let (bin_path, libs_path) = get_cc_search_dirs(target, builder);
342
343 let mut rustc_dlls = vec![];
344 if target.ends_with("windows-gnu") {
346 rustc_dlls.push("libwinpthread-1.dll");
347 if target.starts_with("i686-") {
348 rustc_dlls.push("libgcc_s_dw2-1.dll");
349 } else {
350 rustc_dlls.push("libgcc_s_seh-1.dll");
351 }
352 } else if target.ends_with("windows-gnullvm") {
353 rustc_dlls.push("libunwind.dll");
354 } else {
355 panic!("Vendoring of runtime DLLs for `{target}` is not supported`");
356 }
357 let bin_path = if target.ends_with("windows-gnullvm") && builder.host_target != target {
359 bin_path
360 .into_iter()
361 .chain(libs_path.iter().map(|path| path.with_file_name("bin")))
362 .collect()
363 } else {
364 bin_path
365 };
366 let rustc_dlls = find_files(&rustc_dlls, &bin_path);
367
368 let rust_bin_dir = rust_root.join("bin/");
370 fs::create_dir_all(&rust_bin_dir).expect("creating rust_bin_dir failed");
371 for src in &rustc_dlls {
372 builder.copy_link_to_folder(src, &rust_bin_dir);
373 }
374
375 if builder.config.lld_enabled {
376 let rust_target_bin_dir = rust_root.join("lib/rustlib").join(target).join("bin");
378 fs::create_dir_all(&rust_target_bin_dir).expect("creating rust_target_bin_dir failed");
379 for src in &rustc_dlls {
380 builder.copy_link_to_folder(src, &rust_target_bin_dir);
381 }
382 }
383}
384
385fn get_cc_search_dirs(
386 target: TargetSelection,
387 builder: &Builder<'_>,
388) -> (Vec<PathBuf>, Vec<PathBuf>) {
389 let mut cmd = command(builder.cc(target));
391 cmd.arg("-print-search-dirs");
392 let gcc_out = cmd.run_capture_stdout(builder).stdout();
393
394 let mut bin_path: Vec<_> = env::split_paths(&env::var_os("PATH").unwrap_or_default()).collect();
395 let mut lib_path = Vec::new();
396
397 for line in gcc_out.lines() {
398 let idx = line.find(':').unwrap();
399 let key = &line[..idx];
400 let trim_chars: &[_] = &[' ', '='];
401 let value = env::split_paths(line[(idx + 1)..].trim_start_matches(trim_chars));
402
403 if key == "programs" {
404 bin_path.extend(value);
405 } else if key == "libraries" {
406 lib_path.extend(value);
407 }
408 }
409 (bin_path, lib_path)
410}
411
412#[derive(Debug, Clone, Hash, PartialEq, Eq)]
417pub struct Mingw {
418 target: TargetSelection,
419}
420
421impl Step for Mingw {
422 type Output = Option<GeneratedTarball>;
423 const DEFAULT: bool = true;
424
425 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
426 run.alias("rust-mingw")
427 }
428
429 fn make_run(run: RunConfig<'_>) {
430 run.builder.ensure(Mingw { target: run.target });
431 }
432
433 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
434 let target = self.target;
435 if !target.contains("pc-windows-gnu") || !builder.config.dist_include_mingw_linker {
436 return None;
437 }
438
439 let mut tarball = Tarball::new(builder, "rust-mingw", &target.triple);
440 tarball.set_product_name("Rust MinGW");
441
442 if target.ends_with("pc-windows-gnu") {
443 make_win_dist(tarball.image_dir(), target, builder);
444 } else if target.ends_with("pc-windows-gnullvm") {
445 make_win_llvm_dist(tarball.image_dir(), target, builder);
446 } else {
447 unreachable!();
448 }
449
450 Some(tarball.generate())
451 }
452
453 fn metadata(&self) -> Option<StepMetadata> {
454 Some(StepMetadata::dist("mingw", self.target))
455 }
456}
457
458#[derive(Debug, Clone, Hash, PartialEq, Eq)]
468pub struct Rustc {
469 pub target_compiler: Compiler,
471}
472
473impl Step for Rustc {
474 type Output = GeneratedTarball;
475
476 const DEFAULT: bool = true;
477 const IS_HOST: bool = true;
478
479 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
480 run.alias("rustc")
481 }
482
483 fn make_run(run: RunConfig<'_>) {
484 run.builder.ensure(Rustc {
485 target_compiler: run.builder.compiler(run.builder.top_stage, run.target),
486 });
487 }
488
489 fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
490 let target_compiler = self.target_compiler;
491 let target = self.target_compiler.host;
492
493 let tarball = Tarball::new(builder, "rustc", &target.triple);
494
495 prepare_image(builder, target_compiler, tarball.image_dir());
497
498 if target.contains("pc-windows-gnu") && builder.config.dist_include_mingw_linker {
506 runtime_dll_dist(tarball.image_dir(), target, builder);
507 tarball.add_dir(builder.src.join("src/etc/third-party"), "share/doc");
508 }
509
510 return tarball.generate();
511
512 fn prepare_image(builder: &Builder<'_>, target_compiler: Compiler, image: &Path) {
513 let target = target_compiler.host;
514 let src = builder.sysroot(target_compiler);
515
516 t!(fs::create_dir_all(image.join("bin")));
518 builder.cp_link_r(&src.join("bin"), &image.join("bin"));
519
520 if builder
522 .config
523 .tools
524 .as_ref()
525 .is_none_or(|tools| tools.iter().any(|tool| tool == "rustdoc"))
526 {
527 let rustdoc = builder.rustdoc_for_compiler(target_compiler);
528 builder.install(&rustdoc, &image.join("bin"), FileType::Executable);
529 }
530
531 let compilers = RustcPrivateCompilers::from_target_compiler(builder, target_compiler);
532
533 if let Some(ra_proc_macro_srv) = builder.ensure_if_default(
534 tool::RustAnalyzerProcMacroSrv::from_compilers(compilers),
535 builder.kind,
536 ) {
537 let dst = image.join("libexec");
538 builder.install(&ra_proc_macro_srv.tool_path, &dst, FileType::Executable);
539 }
540
541 let libdir_relative = builder.libdir_relative(target_compiler);
542
543 if libdir_relative.to_str() != Some("bin") {
545 let libdir = builder.rustc_libdir(target_compiler);
546 for entry in builder.read_dir(&libdir) {
547 if is_dylib(&entry.path())
553 && !entry
554 .path()
555 .file_name()
556 .and_then(|n| n.to_str())
557 .map(|n| n.contains("libgccjit"))
558 .unwrap_or(false)
559 {
560 builder.install(&entry.path(), &image.join("lib"), FileType::NativeLibrary);
563 }
564 }
565 }
566
567 maybe_install_llvm_runtime(builder, target, image);
573
574 let dst_dir = image.join("lib/rustlib").join(target).join("bin");
575 t!(fs::create_dir_all(&dst_dir));
576
577 if builder.config.lld_enabled {
579 let src_dir = builder.sysroot_target_bindir(target_compiler, target);
580 let rust_lld = exe("rust-lld", target_compiler.host);
581 builder.copy_link(
582 &src_dir.join(&rust_lld),
583 &dst_dir.join(&rust_lld),
584 FileType::Executable,
585 );
586 let self_contained_lld_src_dir = src_dir.join("gcc-ld");
587 let self_contained_lld_dst_dir = dst_dir.join("gcc-ld");
588 t!(fs::create_dir(&self_contained_lld_dst_dir));
589 for name in crate::LLD_FILE_NAMES {
590 let exe_name = exe(name, target_compiler.host);
591 builder.copy_link(
592 &self_contained_lld_src_dir.join(&exe_name),
593 &self_contained_lld_dst_dir.join(&exe_name),
594 FileType::Executable,
595 );
596 }
597 }
598
599 if builder.config.llvm_enabled(target_compiler.host)
600 && builder.config.llvm_tools_enabled
601 {
602 let src_dir = builder.sysroot_target_bindir(target_compiler, target);
603 let llvm_objcopy = exe("llvm-objcopy", target_compiler.host);
604 let rust_objcopy = exe("rust-objcopy", target_compiler.host);
605 builder.copy_link(
606 &src_dir.join(&llvm_objcopy),
607 &dst_dir.join(&rust_objcopy),
608 FileType::Executable,
609 );
610 }
611
612 if builder.tool_enabled("wasm-component-ld") {
613 let src_dir = builder.sysroot_target_bindir(target_compiler, target);
614 let ld = exe("wasm-component-ld", target_compiler.host);
615 builder.copy_link(&src_dir.join(&ld), &dst_dir.join(&ld), FileType::Executable);
616 }
617
618 t!(fs::create_dir_all(image.join("share/man/man1")));
620 let man_src = builder.src.join("src/doc/man");
621 let man_dst = image.join("share/man/man1");
622
623 for file_entry in builder.read_dir(&man_src) {
626 let page_src = file_entry.path();
627 let page_dst = man_dst.join(file_entry.file_name());
628 let src_text = t!(std::fs::read_to_string(&page_src));
629 let new_text = src_text.replace("<INSERT VERSION HERE>", &builder.version);
630 t!(std::fs::write(&page_dst, &new_text));
631 t!(fs::copy(&page_src, &page_dst));
632 }
633
634 builder.ensure(DebuggerScripts { sysroot: image.to_owned(), target });
636
637 generate_target_spec_json_schema(builder, image);
638
639 let file_list = builder.ensure(super::run::GenerateCopyright);
641 for file in file_list {
642 builder.install(&file, &image.join("share/doc/rust"), FileType::Regular);
643 }
644
645 builder.install(
647 &builder.src.join("README.md"),
648 &image.join("share/doc/rust"),
649 FileType::Regular,
650 );
651
652 let license = |path: &Path| {
654 builder.install(path, &image.join("share/doc/rust/licenses"), FileType::Regular);
655 };
656 for entry in t!(std::fs::read_dir(builder.src.join("LICENSES"))).flatten() {
657 license(&entry.path());
658 }
659 }
660 }
661
662 fn metadata(&self) -> Option<StepMetadata> {
663 Some(StepMetadata::dist("rustc", self.target_compiler.host))
664 }
665}
666
667fn generate_target_spec_json_schema(builder: &Builder<'_>, sysroot: &Path) {
668 let stage1_host = builder.compiler(1, builder.host_target);
672 let mut rustc = builder.rustc_cmd(stage1_host).fail_fast();
673 rustc
674 .env("RUSTC_BOOTSTRAP", "1")
675 .args(["--print=target-spec-json-schema", "-Zunstable-options"]);
676 let schema = rustc.run_capture(builder).stdout();
677
678 let schema_dir = tmpdir(builder);
679 t!(fs::create_dir_all(&schema_dir));
680 let schema_file = schema_dir.join("target-spec-json-schema.json");
681 t!(std::fs::write(&schema_file, schema));
682
683 let dst = sysroot.join("etc");
684 t!(fs::create_dir_all(&dst));
685
686 builder.install(&schema_file, &dst, FileType::Regular);
687}
688
689#[derive(Debug, Clone, Hash, PartialEq, Eq)]
691pub struct DebuggerScripts {
692 pub sysroot: PathBuf,
694 pub target: TargetSelection,
695}
696
697impl Step for DebuggerScripts {
698 type Output = ();
699
700 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
701 run.never()
702 }
703
704 fn run(self, builder: &Builder<'_>) {
705 let target = self.target;
706 let sysroot = self.sysroot;
707 let dst = sysroot.join("lib/rustlib/etc");
708 t!(fs::create_dir_all(&dst));
709 let cp_debugger_script = |file: &str| {
710 builder.install(&builder.src.join("src/etc/").join(file), &dst, FileType::Regular);
711 };
712 if target.contains("windows-msvc") {
713 builder.install(
715 &builder.src.join("src/etc/rust-windbg.cmd"),
716 &sysroot.join("bin"),
717 FileType::Script,
718 );
719
720 cp_debugger_script("natvis/intrinsic.natvis");
721 cp_debugger_script("natvis/liballoc.natvis");
722 cp_debugger_script("natvis/libcore.natvis");
723 cp_debugger_script("natvis/libstd.natvis");
724 }
725
726 cp_debugger_script("rust_types.py");
727
728 builder.install(
730 &builder.src.join("src/etc/rust-gdb"),
731 &sysroot.join("bin"),
732 FileType::Script,
733 );
734 builder.install(
735 &builder.src.join("src/etc/rust-gdbgui"),
736 &sysroot.join("bin"),
737 FileType::Script,
738 );
739
740 cp_debugger_script("gdb_load_rust_pretty_printers.py");
741 cp_debugger_script("gdb_lookup.py");
742 cp_debugger_script("gdb_providers.py");
743
744 builder.install(
746 &builder.src.join("src/etc/rust-lldb"),
747 &sysroot.join("bin"),
748 FileType::Script,
749 );
750
751 cp_debugger_script("lldb_lookup.py");
752 cp_debugger_script("lldb_providers.py");
753 cp_debugger_script("lldb_commands")
754 }
755}
756
757fn skip_host_target_lib(builder: &Builder<'_>, compiler: Compiler) -> bool {
758 if !builder.config.is_host_target(compiler.host) {
761 builder.info("\tskipping, not a build host");
762 true
763 } else {
764 false
765 }
766}
767
768fn verify_uefi_rlib_format(builder: &Builder<'_>, target: TargetSelection, stamp: &BuildStamp) {
772 if !target.ends_with("-uefi") {
773 return;
774 }
775
776 for (path, _) in builder.read_stamp_file(stamp) {
777 if path.extension() != Some(OsStr::new("rlib")) {
778 continue;
779 }
780
781 let data = t!(fs::read(&path));
782 let data = data.as_slice();
783 let archive = t!(ArchiveFile::parse(data));
784 for member in archive.members() {
785 let member = t!(member);
786 let member_data = t!(member.data(data));
787
788 let is_coff = match object::File::parse(member_data) {
789 Ok(member_file) => member_file.format() == BinaryFormat::Coff,
790 Err(_) => false,
791 };
792
793 if !is_coff {
794 let member_name = String::from_utf8_lossy(member.name());
795 panic!("member {} in {} is not COFF", member_name, path.display());
796 }
797 }
798 }
799}
800
801fn copy_target_libs(
803 builder: &Builder<'_>,
804 target: TargetSelection,
805 image: &Path,
806 stamp: &BuildStamp,
807) {
808 let dst = image.join("lib/rustlib").join(target).join("lib");
809 let self_contained_dst = dst.join("self-contained");
810 t!(fs::create_dir_all(&dst));
811 t!(fs::create_dir_all(&self_contained_dst));
812 for (path, dependency_type) in builder.read_stamp_file(stamp) {
813 if dependency_type == DependencyType::TargetSelfContained {
814 builder.copy_link(
815 &path,
816 &self_contained_dst.join(path.file_name().unwrap()),
817 FileType::NativeLibrary,
818 );
819 } else if dependency_type == DependencyType::Target || builder.config.is_host_target(target)
820 {
821 builder.copy_link(&path, &dst.join(path.file_name().unwrap()), FileType::NativeLibrary);
822 }
823 }
824}
825
826#[derive(Debug, Clone, Hash, PartialEq, Eq)]
833pub struct Std {
834 pub build_compiler: Compiler,
836 pub target: TargetSelection,
837}
838
839impl Std {
840 pub fn new(builder: &Builder<'_>, target: TargetSelection) -> Self {
841 Std { build_compiler: builder.compiler_for_std(builder.top_stage), target }
842 }
843}
844
845impl Step for Std {
846 type Output = Option<GeneratedTarball>;
847 const DEFAULT: bool = true;
848
849 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
850 run.alias("rust-std")
851 }
852
853 fn make_run(run: RunConfig<'_>) {
854 run.builder.ensure(Std::new(run.builder, run.target));
855 }
856
857 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
858 let build_compiler = self.build_compiler;
859 let target = self.target;
860
861 if skip_host_target_lib(builder, build_compiler) {
862 return None;
863 }
864
865 let stamp =
868 builder.std(build_compiler, target).expect("Standard library has to be built for dist");
869
870 let mut tarball = Tarball::new(builder, "rust-std", &target.triple);
871 tarball.include_target_in_component_name(true);
872
873 verify_uefi_rlib_format(builder, target, &stamp);
874 copy_target_libs(builder, target, tarball.image_dir(), &stamp);
875
876 Some(tarball.generate())
877 }
878
879 fn metadata(&self) -> Option<StepMetadata> {
880 Some(StepMetadata::dist("std", self.target).built_by(self.build_compiler))
881 }
882}
883
884#[derive(Debug, Clone, Hash, PartialEq, Eq)]
889pub struct RustcDev {
890 build_compiler: Compiler,
892 target: TargetSelection,
893}
894
895impl RustcDev {
896 pub fn new(builder: &Builder<'_>, target: TargetSelection) -> Self {
897 Self {
898 build_compiler: builder.compiler(1, builder.config.host_target),
902 target,
903 }
904 }
905}
906
907impl Step for RustcDev {
908 type Output = Option<GeneratedTarball>;
909 const DEFAULT: bool = true;
910 const IS_HOST: bool = true;
911
912 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
913 run.alias("rustc-dev")
914 }
915
916 fn make_run(run: RunConfig<'_>) {
917 run.builder.ensure(RustcDev::new(run.builder, run.target));
918 }
919
920 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
921 let build_compiler = self.build_compiler;
922 let target = self.target;
923 if skip_host_target_lib(builder, build_compiler) {
924 return None;
925 }
926
927 builder.ensure(compile::Rustc::new(build_compiler, target));
929
930 let tarball = Tarball::new(builder, "rustc-dev", &target.triple);
931
932 let stamp = build_stamp::librustc_stamp(builder, build_compiler, target);
933 copy_target_libs(builder, target, tarball.image_dir(), &stamp);
934
935 let src_files = &["Cargo.lock"];
936 copy_src_dirs(
939 builder,
940 &builder.src,
941 &["compiler", "library/proc_macro"],
943 &[],
944 &tarball.image_dir().join("lib/rustlib/rustc-src/rust"),
945 );
946 for file in src_files {
947 tarball.add_file(
948 builder.src.join(file),
949 "lib/rustlib/rustc-src/rust",
950 FileType::Regular,
951 );
952 }
953
954 Some(tarball.generate())
955 }
956
957 fn metadata(&self) -> Option<StepMetadata> {
958 Some(StepMetadata::dist("rustc-dev", self.target).built_by(self.build_compiler))
959 }
960}
961
962#[derive(Debug, Clone, Hash, PartialEq, Eq)]
967pub struct Analysis {
968 build_compiler: Compiler,
969 target: TargetSelection,
970}
971
972impl Step for Analysis {
973 type Output = Option<GeneratedTarball>;
974
975 const DEFAULT: bool = true;
976
977 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
978 let default = should_build_extended_tool(run.builder, "analysis");
979 run.alias("rust-analysis").default_condition(default)
980 }
981
982 fn make_run(run: RunConfig<'_>) {
983 run.builder.ensure(Analysis {
985 build_compiler: run.builder.compiler(1, run.builder.config.host_target),
986 target: run.target,
987 });
988 }
989
990 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
991 let compiler = self.build_compiler;
992 let target = self.target;
993 if skip_host_target_lib(builder, compiler) {
994 return None;
995 }
996
997 let src = builder
998 .stage_out(compiler, Mode::Std)
999 .join(target)
1000 .join(builder.cargo_dir())
1001 .join("deps")
1002 .join("save-analysis");
1003
1004 t!(std::fs::create_dir_all(&src));
1006 let mut removed = src.clone();
1007 removed.push("removed.json");
1008 let mut f = t!(std::fs::File::create(removed));
1009 t!(write!(f, r#"{{ "warning": "The `rust-analysis` component has been removed." }}"#));
1010
1011 let mut tarball = Tarball::new(builder, "rust-analysis", &target.triple);
1012 tarball.include_target_in_component_name(true);
1013 tarball.add_dir(src, format!("lib/rustlib/{}/analysis", target.triple));
1014 Some(tarball.generate())
1015 }
1016
1017 fn metadata(&self) -> Option<StepMetadata> {
1018 Some(StepMetadata::dist("analysis", self.target).built_by(self.build_compiler))
1019 }
1020}
1021
1022fn copy_src_dirs(
1025 builder: &Builder<'_>,
1026 base: &Path,
1027 src_dirs: &[&str],
1028 exclude_dirs: &[&str],
1029 dst_dir: &Path,
1030) {
1031 for src_dir in src_dirs {
1034 assert!(Path::new(src_dir).is_relative());
1035 }
1036
1037 if builder.config.dry_run() {
1040 return;
1041 }
1042
1043 fn filter_fn(exclude_dirs: &[&str], dir: &str, path: &Path) -> bool {
1044 let spath = match path.to_str() {
1046 Some(path) => path,
1047 None => return false,
1048 };
1049 if spath.ends_with('~') || spath.ends_with(".pyc") {
1050 return false;
1051 }
1052 let spath = spath.replace("\\", "/");
1054
1055 static LLVM_PROJECTS: &[&str] = &[
1056 "llvm-project/clang",
1057 "llvm-project/libunwind",
1058 "llvm-project/lld",
1059 "llvm-project/lldb",
1060 "llvm-project/llvm",
1061 "llvm-project/compiler-rt",
1062 "llvm-project/cmake",
1063 "llvm-project/runtimes",
1064 "llvm-project/third-party",
1065 ];
1066 if spath.starts_with("llvm-project") && spath != "llvm-project" {
1067 if !LLVM_PROJECTS.iter().any(|path| spath.starts_with(path)) {
1068 return false;
1069 }
1070
1071 if spath.starts_with("llvm-project/third-party")
1073 && spath != "llvm-project/third-party"
1074 && !spath.starts_with("llvm-project/third-party/siphash")
1075 {
1076 return false;
1077 }
1078
1079 if spath.starts_with("llvm-project/llvm/test")
1080 && (spath.ends_with(".ll") || spath.ends_with(".td") || spath.ends_with(".s"))
1081 {
1082 return false;
1083 }
1084 }
1085
1086 if spath.starts_with("tools/cargo/tests") {
1088 return true;
1089 }
1090
1091 if !exclude_dirs.is_empty() {
1092 let full_path = Path::new(dir).join(path);
1093 if exclude_dirs.iter().any(|excl| full_path == Path::new(excl)) {
1094 return false;
1095 }
1096 }
1097
1098 static EXCLUDES: &[&str] = &[
1099 "CVS",
1100 "RCS",
1101 "SCCS",
1102 ".git",
1103 ".gitignore",
1104 ".gitmodules",
1105 ".gitattributes",
1106 ".cvsignore",
1107 ".svn",
1108 ".arch-ids",
1109 "{arch}",
1110 "=RELEASE-ID",
1111 "=meta-update",
1112 "=update",
1113 ".bzr",
1114 ".bzrignore",
1115 ".bzrtags",
1116 ".hg",
1117 ".hgignore",
1118 ".hgrags",
1119 "_darcs",
1120 ];
1121
1122 let last_component = path.iter().next_back().map(|s| s.to_str().unwrap()).unwrap();
1129 !EXCLUDES.contains(&last_component)
1130 }
1131
1132 for item in src_dirs {
1134 let dst = &dst_dir.join(item);
1135 t!(fs::create_dir_all(dst));
1136 builder
1137 .cp_link_filtered(&base.join(item), dst, &|path| filter_fn(exclude_dirs, item, path));
1138 }
1139}
1140
1141#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1142pub struct Src;
1143
1144impl Step for Src {
1145 type Output = GeneratedTarball;
1147 const DEFAULT: bool = true;
1148 const IS_HOST: bool = true;
1149
1150 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1151 run.alias("rust-src")
1152 }
1153
1154 fn make_run(run: RunConfig<'_>) {
1155 run.builder.ensure(Src);
1156 }
1157
1158 fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
1160 if !builder.config.dry_run() {
1161 builder.require_submodule("src/llvm-project", None);
1162 }
1163
1164 let tarball = Tarball::new_targetless(builder, "rust-src");
1165
1166 let dst_src = tarball.image_dir().join("lib/rustlib/src/rust");
1174
1175 copy_src_dirs(
1178 builder,
1179 &builder.src,
1180 &["library", "src/llvm-project/libunwind"],
1181 &[
1182 "library/backtrace/crates",
1185 "library/stdarch/Cargo.toml",
1188 "library/stdarch/crates/stdarch-verify",
1189 "library/stdarch/crates/intrinsic-test",
1190 ],
1191 &dst_src,
1192 );
1193
1194 tarball.generate()
1195 }
1196
1197 fn metadata(&self) -> Option<StepMetadata> {
1198 Some(StepMetadata::dist("src", TargetSelection::default()))
1199 }
1200}
1201
1202#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1203pub struct PlainSourceTarball;
1204
1205impl Step for PlainSourceTarball {
1206 type Output = GeneratedTarball;
1208 const DEFAULT: bool = true;
1209 const IS_HOST: bool = true;
1210
1211 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1212 let builder = run.builder;
1213 run.alias("rustc-src").default_condition(builder.config.rust_dist_src)
1214 }
1215
1216 fn make_run(run: RunConfig<'_>) {
1217 run.builder.ensure(PlainSourceTarball);
1218 }
1219
1220 fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
1222 let mut tarball = Tarball::new(builder, "rustc", "src");
1227 tarball.permit_symlinks(true);
1228 let plain_dst_src = tarball.image_dir();
1229
1230 let src_files = [
1232 ".gitmodules",
1234 "CONTRIBUTING.md",
1235 "COPYRIGHT",
1236 "Cargo.lock",
1237 "Cargo.toml",
1238 "LICENSE-APACHE",
1239 "LICENSE-MIT",
1240 "README.md",
1241 "RELEASES.md",
1242 "REUSE.toml",
1243 "bootstrap.example.toml",
1244 "configure",
1245 "license-metadata.json",
1246 "package.json",
1247 "x",
1248 "x.ps1",
1249 "x.py",
1250 "yarn.lock",
1251 ];
1253 let src_dirs = ["src", "compiler", "library", "tests", "LICENSES"];
1254
1255 copy_src_dirs(
1256 builder,
1257 &builder.src,
1258 &src_dirs,
1259 &[
1260 "src/gcc",
1264 ],
1265 plain_dst_src,
1266 );
1267 if !builder.config.dry_run() {
1272 builder.create_dir(&plain_dst_src.join("src/gcc"));
1273 t!(std::fs::write(
1274 plain_dst_src.join("src/gcc/notice.txt"),
1275 "The GCC source code is not included due to unclear licensing implications\n"
1276 ));
1277 }
1278
1279 for item in &src_files {
1281 builder.copy_link(
1282 &builder.src.join(item),
1283 &plain_dst_src.join(item),
1284 FileType::Regular,
1285 );
1286 }
1287
1288 builder.create(&plain_dst_src.join("version"), &builder.rust_version());
1290
1291 let write_git_info = |info: Option<&Info>, path: &Path| {
1293 if let Some(info) = info {
1294 t!(std::fs::create_dir_all(path));
1295 channel::write_commit_hash_file(path, &info.sha);
1296 channel::write_commit_info_file(path, info);
1297 }
1298 };
1299 write_git_info(builder.rust_info().info(), plain_dst_src);
1300 write_git_info(builder.cargo_info.info(), &plain_dst_src.join("./src/tools/cargo"));
1301
1302 if builder.config.dist_vendor {
1303 builder.require_and_update_all_submodules();
1304
1305 let pkgs_for_pgo_training = build_helper::LLVM_PGO_CRATES
1307 .iter()
1308 .chain(build_helper::RUSTC_PGO_CRATES)
1309 .map(|pkg| {
1310 let mut manifest_path =
1311 builder.src.join("./src/tools/rustc-perf/collector/compile-benchmarks");
1312 manifest_path.push(pkg);
1313 manifest_path.push("Cargo.toml");
1314 manifest_path
1315 });
1316
1317 let vendor = builder.ensure(Vendor {
1319 sync_args: pkgs_for_pgo_training.collect(),
1320 versioned_dirs: true,
1321 root_dir: plain_dst_src.into(),
1322 output_dir: VENDOR_DIR.into(),
1323 });
1324
1325 let cargo_config_dir = plain_dst_src.join(".cargo");
1326 builder.create_dir(&cargo_config_dir);
1327 builder.create(&cargo_config_dir.join("config.toml"), &vendor.config);
1328 }
1329
1330 for entry in walkdir::WalkDir::new(tarball.image_dir())
1334 .follow_links(true)
1335 .into_iter()
1336 .filter_map(|e| e.ok())
1337 {
1338 if entry.path().is_dir() && entry.path().file_name() == Some(OsStr::new("__pycache__"))
1339 {
1340 t!(fs::remove_dir_all(entry.path()));
1341 }
1342 }
1343
1344 tarball.bare()
1345 }
1346}
1347
1348#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1349pub struct Cargo {
1350 pub build_compiler: Compiler,
1351 pub target: TargetSelection,
1352}
1353
1354impl Step for Cargo {
1355 type Output = Option<GeneratedTarball>;
1356 const DEFAULT: bool = true;
1357 const IS_HOST: bool = true;
1358
1359 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1360 let default = should_build_extended_tool(run.builder, "cargo");
1361 run.alias("cargo").default_condition(default)
1362 }
1363
1364 fn make_run(run: RunConfig<'_>) {
1365 run.builder.ensure(Cargo {
1366 build_compiler: get_tool_target_compiler(
1367 run.builder,
1368 ToolTargetBuildMode::Build(run.target),
1369 ),
1370 target: run.target,
1371 });
1372 }
1373
1374 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1375 let build_compiler = self.build_compiler;
1376 let target = self.target;
1377
1378 let cargo = builder.ensure(tool::Cargo::from_build_compiler(build_compiler, target));
1379 let src = builder.src.join("src/tools/cargo");
1380 let etc = src.join("src/etc");
1381
1382 let mut tarball = Tarball::new(builder, "cargo", &target.triple);
1384 tarball.set_overlay(OverlayKind::Cargo);
1385
1386 tarball.add_file(&cargo.tool_path, "bin", FileType::Executable);
1387 tarball.add_file(etc.join("_cargo"), "share/zsh/site-functions", FileType::Regular);
1388 tarball.add_renamed_file(
1389 etc.join("cargo.bashcomp.sh"),
1390 "etc/bash_completion.d",
1391 "cargo",
1392 FileType::Regular,
1393 );
1394 tarball.add_dir(etc.join("man"), "share/man/man1");
1395 tarball.add_legal_and_readme_to("share/doc/cargo");
1396
1397 Some(tarball.generate())
1398 }
1399
1400 fn metadata(&self) -> Option<StepMetadata> {
1401 Some(StepMetadata::dist("cargo", self.target).built_by(self.build_compiler))
1402 }
1403}
1404
1405#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1407pub struct RustAnalyzer {
1408 pub compilers: RustcPrivateCompilers,
1409 pub target: TargetSelection,
1410}
1411
1412impl Step for RustAnalyzer {
1413 type Output = Option<GeneratedTarball>;
1414 const DEFAULT: bool = true;
1415 const IS_HOST: bool = true;
1416
1417 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1418 let default = should_build_extended_tool(run.builder, "rust-analyzer");
1419 run.alias("rust-analyzer").default_condition(default)
1420 }
1421
1422 fn make_run(run: RunConfig<'_>) {
1423 run.builder.ensure(RustAnalyzer {
1424 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1425 target: run.target,
1426 });
1427 }
1428
1429 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1430 let target = self.target;
1431 let rust_analyzer = builder.ensure(tool::RustAnalyzer::from_compilers(self.compilers));
1432
1433 let mut tarball = Tarball::new(builder, "rust-analyzer", &target.triple);
1434 tarball.set_overlay(OverlayKind::RustAnalyzer);
1435 tarball.is_preview(true);
1436 tarball.add_file(&rust_analyzer.tool_path, "bin", FileType::Executable);
1437 tarball.add_legal_and_readme_to("share/doc/rust-analyzer");
1438 Some(tarball.generate())
1439 }
1440
1441 fn metadata(&self) -> Option<StepMetadata> {
1442 Some(
1443 StepMetadata::dist("rust-analyzer", self.target)
1444 .built_by(self.compilers.build_compiler()),
1445 )
1446 }
1447}
1448
1449#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1450pub struct Clippy {
1451 pub compilers: RustcPrivateCompilers,
1452 pub target: TargetSelection,
1453}
1454
1455impl Step for Clippy {
1456 type Output = Option<GeneratedTarball>;
1457 const DEFAULT: bool = true;
1458 const IS_HOST: bool = true;
1459
1460 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1461 let default = should_build_extended_tool(run.builder, "clippy");
1462 run.alias("clippy").default_condition(default)
1463 }
1464
1465 fn make_run(run: RunConfig<'_>) {
1466 run.builder.ensure(Clippy {
1467 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1468 target: run.target,
1469 });
1470 }
1471
1472 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1473 let target = self.target;
1474
1475 let clippy = builder.ensure(tool::Clippy::from_compilers(self.compilers));
1479 let cargoclippy = builder.ensure(tool::CargoClippy::from_compilers(self.compilers));
1480
1481 let mut tarball = Tarball::new(builder, "clippy", &target.triple);
1482 tarball.set_overlay(OverlayKind::Clippy);
1483 tarball.is_preview(true);
1484 tarball.add_file(&clippy.tool_path, "bin", FileType::Executable);
1485 tarball.add_file(&cargoclippy.tool_path, "bin", FileType::Executable);
1486 tarball.add_legal_and_readme_to("share/doc/clippy");
1487 Some(tarball.generate())
1488 }
1489
1490 fn metadata(&self) -> Option<StepMetadata> {
1491 Some(StepMetadata::dist("clippy", self.target).built_by(self.compilers.build_compiler()))
1492 }
1493}
1494
1495#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1496pub struct Miri {
1497 pub compilers: RustcPrivateCompilers,
1498 pub target: TargetSelection,
1499}
1500
1501impl Step for Miri {
1502 type Output = Option<GeneratedTarball>;
1503 const DEFAULT: bool = true;
1504 const IS_HOST: bool = true;
1505
1506 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1507 let default = should_build_extended_tool(run.builder, "miri");
1508 run.alias("miri").default_condition(default)
1509 }
1510
1511 fn make_run(run: RunConfig<'_>) {
1512 run.builder.ensure(Miri {
1513 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1514 target: run.target,
1515 });
1516 }
1517
1518 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1519 if !builder.build.unstable_features() {
1523 return None;
1524 }
1525
1526 let miri = builder.ensure(tool::Miri::from_compilers(self.compilers));
1527 let cargomiri = builder.ensure(tool::CargoMiri::from_compilers(self.compilers));
1528
1529 let mut tarball = Tarball::new(builder, "miri", &self.target.triple);
1530 tarball.set_overlay(OverlayKind::Miri);
1531 tarball.is_preview(true);
1532 tarball.add_file(&miri.tool_path, "bin", FileType::Executable);
1533 tarball.add_file(&cargomiri.tool_path, "bin", FileType::Executable);
1534 tarball.add_legal_and_readme_to("share/doc/miri");
1535 Some(tarball.generate())
1536 }
1537
1538 fn metadata(&self) -> Option<StepMetadata> {
1539 Some(StepMetadata::dist("miri", self.target).built_by(self.compilers.build_compiler()))
1540 }
1541}
1542
1543#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1544pub struct CraneliftCodegenBackend {
1545 pub compilers: RustcPrivateCompilers,
1546 pub target: TargetSelection,
1547}
1548
1549impl Step for CraneliftCodegenBackend {
1550 type Output = Option<GeneratedTarball>;
1551 const DEFAULT: bool = true;
1552 const IS_HOST: bool = true;
1553
1554 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1555 let clif_enabled_by_default = run
1560 .builder
1561 .config
1562 .enabled_codegen_backends(run.builder.host_target)
1563 .contains(&CodegenBackendKind::Cranelift);
1564 run.alias("rustc_codegen_cranelift").default_condition(clif_enabled_by_default)
1565 }
1566
1567 fn make_run(run: RunConfig<'_>) {
1568 run.builder.ensure(CraneliftCodegenBackend {
1569 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1570 target: run.target,
1571 });
1572 }
1573
1574 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1575 if !builder.build.unstable_features() {
1579 return None;
1580 }
1581
1582 let target = self.target;
1583 if !target_supports_cranelift_backend(target) {
1584 builder.info("target not supported by rustc_codegen_cranelift. skipping");
1585 return None;
1586 }
1587
1588 let mut tarball = Tarball::new(builder, "rustc-codegen-cranelift", &target.triple);
1589 tarball.set_overlay(OverlayKind::RustcCodegenCranelift);
1590 tarball.is_preview(true);
1591 tarball.add_legal_and_readme_to("share/doc/rustc_codegen_cranelift");
1592
1593 let compilers = self.compilers;
1594 let stamp = builder.ensure(compile::CraneliftCodegenBackend { compilers });
1595
1596 if builder.config.dry_run() {
1597 return None;
1598 }
1599
1600 let backends_dst = builder.sysroot_codegen_backends(compilers.target_compiler());
1602 let backends_rel = backends_dst
1603 .strip_prefix(builder.sysroot(compilers.target_compiler()))
1604 .unwrap()
1605 .strip_prefix(builder.sysroot_libdir_relative(compilers.target_compiler()))
1606 .unwrap();
1607 let backends_dst = PathBuf::from("lib").join(backends_rel);
1609
1610 let codegen_backend_dylib = get_codegen_backend_file(&stamp);
1611 tarball.add_renamed_file(
1612 &codegen_backend_dylib,
1613 &backends_dst,
1614 &normalize_codegen_backend_name(builder, &codegen_backend_dylib),
1615 FileType::NativeLibrary,
1616 );
1617
1618 Some(tarball.generate())
1619 }
1620
1621 fn metadata(&self) -> Option<StepMetadata> {
1622 Some(
1623 StepMetadata::dist("rustc_codegen_cranelift", self.target)
1624 .built_by(self.compilers.build_compiler()),
1625 )
1626 }
1627}
1628
1629#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1630pub struct Rustfmt {
1631 pub compilers: RustcPrivateCompilers,
1632 pub target: TargetSelection,
1633}
1634
1635impl Step for Rustfmt {
1636 type Output = Option<GeneratedTarball>;
1637 const DEFAULT: bool = true;
1638 const IS_HOST: bool = true;
1639
1640 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1641 let default = should_build_extended_tool(run.builder, "rustfmt");
1642 run.alias("rustfmt").default_condition(default)
1643 }
1644
1645 fn make_run(run: RunConfig<'_>) {
1646 run.builder.ensure(Rustfmt {
1647 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1648 target: run.target,
1649 });
1650 }
1651
1652 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1653 let rustfmt = builder.ensure(tool::Rustfmt::from_compilers(self.compilers));
1654 let cargofmt = builder.ensure(tool::Cargofmt::from_compilers(self.compilers));
1655
1656 let mut tarball = Tarball::new(builder, "rustfmt", &self.target.triple);
1657 tarball.set_overlay(OverlayKind::Rustfmt);
1658 tarball.is_preview(true);
1659 tarball.add_file(&rustfmt.tool_path, "bin", FileType::Executable);
1660 tarball.add_file(&cargofmt.tool_path, "bin", FileType::Executable);
1661 tarball.add_legal_and_readme_to("share/doc/rustfmt");
1662 Some(tarball.generate())
1663 }
1664
1665 fn metadata(&self) -> Option<StepMetadata> {
1666 Some(StepMetadata::dist("rustfmt", self.target).built_by(self.compilers.build_compiler()))
1667 }
1668}
1669
1670#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1672pub struct Extended {
1673 build_compiler: Compiler,
1674 target: TargetSelection,
1675}
1676
1677impl Step for Extended {
1678 type Output = ();
1679 const DEFAULT: bool = true;
1680 const IS_HOST: bool = true;
1681
1682 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1683 let builder = run.builder;
1684 run.alias("extended").default_condition(builder.config.extended)
1685 }
1686
1687 fn make_run(run: RunConfig<'_>) {
1688 run.builder.ensure(Extended {
1689 build_compiler: run
1690 .builder
1691 .compiler(run.builder.top_stage - 1, run.builder.host_target),
1692 target: run.target,
1693 });
1694 }
1695
1696 fn run(self, builder: &Builder<'_>) {
1698 let target = self.target;
1699 builder.info(&format!("Dist extended stage{} ({target})", builder.top_stage));
1700
1701 let mut tarballs = Vec::new();
1702 let mut built_tools = HashSet::new();
1703 macro_rules! add_component {
1704 ($name:expr => $step:expr) => {
1705 if let Some(Some(tarball)) = builder.ensure_if_default($step, Kind::Dist) {
1706 tarballs.push(tarball);
1707 built_tools.insert($name);
1708 }
1709 };
1710 }
1711
1712 let rustc_private_compilers =
1713 RustcPrivateCompilers::from_build_compiler(builder, self.build_compiler, target);
1714 let build_compiler = rustc_private_compilers.build_compiler();
1715 let target_compiler = rustc_private_compilers.target_compiler();
1716
1717 tarballs.push(builder.ensure(Rustc { target_compiler }));
1722 tarballs.push(builder.ensure(Std { build_compiler, target }).expect("missing std"));
1723
1724 if target.is_windows_gnu() {
1725 tarballs.push(builder.ensure(Mingw { target }).expect("missing mingw"));
1726 }
1727
1728 add_component!("rust-docs" => Docs { host: target });
1729 add_component!("rust-json-docs" => JsonDocs { build_compiler: target_compiler, target });
1731 add_component!("cargo" => Cargo { build_compiler, target });
1732 add_component!("rustfmt" => Rustfmt { compilers: rustc_private_compilers, target });
1733 add_component!("rust-analyzer" => RustAnalyzer { compilers: rustc_private_compilers, target });
1734 add_component!("llvm-components" => LlvmTools { target });
1735 add_component!("clippy" => Clippy { compilers: rustc_private_compilers, target });
1736 add_component!("miri" => Miri { compilers: rustc_private_compilers, target });
1737 add_component!("analysis" => Analysis { build_compiler, target });
1738 add_component!("rustc-codegen-cranelift" => CraneliftCodegenBackend {
1739 compilers: rustc_private_compilers,
1740 target
1741 });
1742 add_component!("llvm-bitcode-linker" => LlvmBitcodeLinker {
1743 build_compiler,
1744 target
1745 });
1746
1747 let etc = builder.src.join("src/etc/installer");
1748
1749 if builder.config.dry_run() {
1751 return;
1752 }
1753
1754 let tarball = Tarball::new(builder, "rust", &target.triple);
1755 let generated = tarball.combine(&tarballs);
1756
1757 let tmp = tmpdir(builder).join("combined-tarball");
1758 let work = generated.work_dir();
1759
1760 let mut license = String::new();
1761 license += &builder.read(&builder.src.join("COPYRIGHT"));
1762 license += &builder.read(&builder.src.join("LICENSE-APACHE"));
1763 license += &builder.read(&builder.src.join("LICENSE-MIT"));
1764 license.push('\n');
1765 license.push('\n');
1766
1767 let rtf = r"{\rtf1\ansi\deff0{\fonttbl{\f0\fnil\fcharset0 Arial;}}\nowwrap\fs18";
1768 let mut rtf = rtf.to_string();
1769 rtf.push('\n');
1770 for line in license.lines() {
1771 rtf.push_str(line);
1772 rtf.push_str("\\line ");
1773 }
1774 rtf.push('}');
1775
1776 fn filter(contents: &str, marker: &str) -> String {
1777 let start = format!("tool-{marker}-start");
1778 let end = format!("tool-{marker}-end");
1779 let mut lines = Vec::new();
1780 let mut omitted = false;
1781 for line in contents.lines() {
1782 if line.contains(&start) {
1783 omitted = true;
1784 } else if line.contains(&end) {
1785 omitted = false;
1786 } else if !omitted {
1787 lines.push(line);
1788 }
1789 }
1790
1791 lines.join("\n")
1792 }
1793
1794 let xform = |p: &Path| {
1795 let mut contents = t!(fs::read_to_string(p));
1796 for tool in &["miri", "rust-docs"] {
1797 if !built_tools.contains(tool) {
1798 contents = filter(&contents, tool);
1799 }
1800 }
1801 let ret = tmp.join(p.file_name().unwrap());
1802 t!(fs::write(&ret, &contents));
1803 ret
1804 };
1805
1806 if target.contains("apple-darwin") {
1807 builder.info("building pkg installer");
1808 let pkg = tmp.join("pkg");
1809 let _ = fs::remove_dir_all(&pkg);
1810
1811 let pkgbuild = |component: &str| {
1812 let mut cmd = command("pkgbuild");
1813 cmd.arg("--identifier")
1814 .arg(format!("org.rust-lang.{component}"))
1815 .arg("--scripts")
1816 .arg(pkg.join(component))
1817 .arg("--nopayload")
1818 .arg(pkg.join(component).with_extension("pkg"));
1819 cmd.run(builder);
1820 };
1821
1822 let prepare = |name: &str| {
1823 builder.create_dir(&pkg.join(name));
1824 builder.cp_link_r(
1825 &work.join(format!("{}-{}", pkgname(builder, name), target.triple)),
1826 &pkg.join(name),
1827 );
1828 builder.install(&etc.join("pkg/postinstall"), &pkg.join(name), FileType::Script);
1829 pkgbuild(name);
1830 };
1831 prepare("rustc");
1832 prepare("cargo");
1833 prepare("rust-std");
1834 prepare("rust-analysis");
1835
1836 for tool in &[
1837 "clippy",
1838 "rustfmt",
1839 "rust-analyzer",
1840 "rust-docs",
1841 "miri",
1842 "rustc-codegen-cranelift",
1843 ] {
1844 if built_tools.contains(tool) {
1845 prepare(tool);
1846 }
1847 }
1848 builder.install(&etc.join("pkg/postinstall"), &pkg.join("uninstall"), FileType::Script);
1850 pkgbuild("uninstall");
1851
1852 builder.create_dir(&pkg.join("res"));
1853 builder.create(&pkg.join("res/LICENSE.txt"), &license);
1854 builder.install(&etc.join("gfx/rust-logo.png"), &pkg.join("res"), FileType::Regular);
1855 let mut cmd = command("productbuild");
1856 cmd.arg("--distribution")
1857 .arg(xform(&etc.join("pkg/Distribution.xml")))
1858 .arg("--resources")
1859 .arg(pkg.join("res"))
1860 .arg(distdir(builder).join(format!(
1861 "{}-{}.pkg",
1862 pkgname(builder, "rust"),
1863 target.triple
1864 )))
1865 .arg("--package-path")
1866 .arg(&pkg);
1867 let _time = timeit(builder);
1868 cmd.run(builder);
1869 }
1870
1871 if target.is_windows() && !target.contains("gnullvm") {
1873 let exe = tmp.join("exe");
1874 let _ = fs::remove_dir_all(&exe);
1875
1876 let prepare = |name: &str| {
1877 builder.create_dir(&exe.join(name));
1878 let dir = if name == "rust-std" || name == "rust-analysis" {
1879 format!("{}-{}", name, target.triple)
1880 } else if name == "rust-analyzer" {
1881 "rust-analyzer-preview".to_string()
1882 } else if name == "clippy" {
1883 "clippy-preview".to_string()
1884 } else if name == "rustfmt" {
1885 "rustfmt-preview".to_string()
1886 } else if name == "miri" {
1887 "miri-preview".to_string()
1888 } else if name == "rustc-codegen-cranelift" {
1889 unreachable!("cg_clif shouldn't be built for windows");
1892 } else {
1893 name.to_string()
1894 };
1895 builder.cp_link_r(
1896 &work.join(format!("{}-{}", pkgname(builder, name), target.triple)).join(dir),
1897 &exe.join(name),
1898 );
1899 builder.remove(&exe.join(name).join("manifest.in"));
1900 };
1901 prepare("rustc");
1902 prepare("cargo");
1903 prepare("rust-analysis");
1904 prepare("rust-std");
1905 for tool in &["clippy", "rustfmt", "rust-analyzer", "rust-docs", "miri"] {
1906 if built_tools.contains(tool) {
1907 prepare(tool);
1908 }
1909 }
1910 if target.is_windows_gnu() {
1911 prepare("rust-mingw");
1912 }
1913
1914 builder.install(&etc.join("gfx/rust-logo.ico"), &exe, FileType::Regular);
1915
1916 let wix_path = env::var_os("WIX")
1918 .expect("`WIX` environment variable must be set for generating MSI installer(s).");
1919 let wix = PathBuf::from(wix_path);
1920 let heat = wix.join("bin/heat.exe");
1921 let candle = wix.join("bin/candle.exe");
1922 let light = wix.join("bin/light.exe");
1923
1924 let heat_flags = ["-nologo", "-gg", "-sfrag", "-srd", "-sreg"];
1925 command(&heat)
1926 .current_dir(&exe)
1927 .arg("dir")
1928 .arg("rustc")
1929 .args(heat_flags)
1930 .arg("-cg")
1931 .arg("RustcGroup")
1932 .arg("-dr")
1933 .arg("Rustc")
1934 .arg("-var")
1935 .arg("var.RustcDir")
1936 .arg("-out")
1937 .arg(exe.join("RustcGroup.wxs"))
1938 .run(builder);
1939 if built_tools.contains("rust-docs") {
1940 command(&heat)
1941 .current_dir(&exe)
1942 .arg("dir")
1943 .arg("rust-docs")
1944 .args(heat_flags)
1945 .arg("-cg")
1946 .arg("DocsGroup")
1947 .arg("-dr")
1948 .arg("Docs")
1949 .arg("-var")
1950 .arg("var.DocsDir")
1951 .arg("-out")
1952 .arg(exe.join("DocsGroup.wxs"))
1953 .arg("-t")
1954 .arg(etc.join("msi/squash-components.xsl"))
1955 .run(builder);
1956 }
1957 command(&heat)
1958 .current_dir(&exe)
1959 .arg("dir")
1960 .arg("cargo")
1961 .args(heat_flags)
1962 .arg("-cg")
1963 .arg("CargoGroup")
1964 .arg("-dr")
1965 .arg("Cargo")
1966 .arg("-var")
1967 .arg("var.CargoDir")
1968 .arg("-out")
1969 .arg(exe.join("CargoGroup.wxs"))
1970 .arg("-t")
1971 .arg(etc.join("msi/remove-duplicates.xsl"))
1972 .run(builder);
1973 command(&heat)
1974 .current_dir(&exe)
1975 .arg("dir")
1976 .arg("rust-std")
1977 .args(heat_flags)
1978 .arg("-cg")
1979 .arg("StdGroup")
1980 .arg("-dr")
1981 .arg("Std")
1982 .arg("-var")
1983 .arg("var.StdDir")
1984 .arg("-out")
1985 .arg(exe.join("StdGroup.wxs"))
1986 .run(builder);
1987 if built_tools.contains("rust-analyzer") {
1988 command(&heat)
1989 .current_dir(&exe)
1990 .arg("dir")
1991 .arg("rust-analyzer")
1992 .args(heat_flags)
1993 .arg("-cg")
1994 .arg("RustAnalyzerGroup")
1995 .arg("-dr")
1996 .arg("RustAnalyzer")
1997 .arg("-var")
1998 .arg("var.RustAnalyzerDir")
1999 .arg("-out")
2000 .arg(exe.join("RustAnalyzerGroup.wxs"))
2001 .arg("-t")
2002 .arg(etc.join("msi/remove-duplicates.xsl"))
2003 .run(builder);
2004 }
2005 if built_tools.contains("clippy") {
2006 command(&heat)
2007 .current_dir(&exe)
2008 .arg("dir")
2009 .arg("clippy")
2010 .args(heat_flags)
2011 .arg("-cg")
2012 .arg("ClippyGroup")
2013 .arg("-dr")
2014 .arg("Clippy")
2015 .arg("-var")
2016 .arg("var.ClippyDir")
2017 .arg("-out")
2018 .arg(exe.join("ClippyGroup.wxs"))
2019 .arg("-t")
2020 .arg(etc.join("msi/remove-duplicates.xsl"))
2021 .run(builder);
2022 }
2023 if built_tools.contains("rustfmt") {
2024 command(&heat)
2025 .current_dir(&exe)
2026 .arg("dir")
2027 .arg("rustfmt")
2028 .args(heat_flags)
2029 .arg("-cg")
2030 .arg("RustFmtGroup")
2031 .arg("-dr")
2032 .arg("RustFmt")
2033 .arg("-var")
2034 .arg("var.RustFmtDir")
2035 .arg("-out")
2036 .arg(exe.join("RustFmtGroup.wxs"))
2037 .arg("-t")
2038 .arg(etc.join("msi/remove-duplicates.xsl"))
2039 .run(builder);
2040 }
2041 if built_tools.contains("miri") {
2042 command(&heat)
2043 .current_dir(&exe)
2044 .arg("dir")
2045 .arg("miri")
2046 .args(heat_flags)
2047 .arg("-cg")
2048 .arg("MiriGroup")
2049 .arg("-dr")
2050 .arg("Miri")
2051 .arg("-var")
2052 .arg("var.MiriDir")
2053 .arg("-out")
2054 .arg(exe.join("MiriGroup.wxs"))
2055 .arg("-t")
2056 .arg(etc.join("msi/remove-duplicates.xsl"))
2057 .run(builder);
2058 }
2059 command(&heat)
2060 .current_dir(&exe)
2061 .arg("dir")
2062 .arg("rust-analysis")
2063 .args(heat_flags)
2064 .arg("-cg")
2065 .arg("AnalysisGroup")
2066 .arg("-dr")
2067 .arg("Analysis")
2068 .arg("-var")
2069 .arg("var.AnalysisDir")
2070 .arg("-out")
2071 .arg(exe.join("AnalysisGroup.wxs"))
2072 .arg("-t")
2073 .arg(etc.join("msi/remove-duplicates.xsl"))
2074 .run(builder);
2075 if target.is_windows_gnu() {
2076 command(&heat)
2077 .current_dir(&exe)
2078 .arg("dir")
2079 .arg("rust-mingw")
2080 .args(heat_flags)
2081 .arg("-cg")
2082 .arg("GccGroup")
2083 .arg("-dr")
2084 .arg("Gcc")
2085 .arg("-var")
2086 .arg("var.GccDir")
2087 .arg("-out")
2088 .arg(exe.join("GccGroup.wxs"))
2089 .run(builder);
2090 }
2091
2092 let candle = |input: &Path| {
2093 let output = exe.join(input.file_stem().unwrap()).with_extension("wixobj");
2094 let arch = if target.contains("x86_64") { "x64" } else { "x86" };
2095 let mut cmd = command(&candle);
2096 cmd.current_dir(&exe)
2097 .arg("-nologo")
2098 .arg("-dRustcDir=rustc")
2099 .arg("-dCargoDir=cargo")
2100 .arg("-dStdDir=rust-std")
2101 .arg("-dAnalysisDir=rust-analysis")
2102 .arg("-arch")
2103 .arg(arch)
2104 .arg("-out")
2105 .arg(&output)
2106 .arg(input);
2107 add_env(builder, &mut cmd, target, &built_tools);
2108
2109 if built_tools.contains("clippy") {
2110 cmd.arg("-dClippyDir=clippy");
2111 }
2112 if built_tools.contains("rustfmt") {
2113 cmd.arg("-dRustFmtDir=rustfmt");
2114 }
2115 if built_tools.contains("rust-docs") {
2116 cmd.arg("-dDocsDir=rust-docs");
2117 }
2118 if built_tools.contains("rust-analyzer") {
2119 cmd.arg("-dRustAnalyzerDir=rust-analyzer");
2120 }
2121 if built_tools.contains("miri") {
2122 cmd.arg("-dMiriDir=miri");
2123 }
2124 if target.is_windows_gnu() {
2125 cmd.arg("-dGccDir=rust-mingw");
2126 }
2127 cmd.run(builder);
2128 };
2129 candle(&xform(&etc.join("msi/rust.wxs")));
2130 candle(&etc.join("msi/ui.wxs"));
2131 candle(&etc.join("msi/rustwelcomedlg.wxs"));
2132 candle("RustcGroup.wxs".as_ref());
2133 if built_tools.contains("rust-docs") {
2134 candle("DocsGroup.wxs".as_ref());
2135 }
2136 candle("CargoGroup.wxs".as_ref());
2137 candle("StdGroup.wxs".as_ref());
2138 if built_tools.contains("clippy") {
2139 candle("ClippyGroup.wxs".as_ref());
2140 }
2141 if built_tools.contains("rustfmt") {
2142 candle("RustFmtGroup.wxs".as_ref());
2143 }
2144 if built_tools.contains("miri") {
2145 candle("MiriGroup.wxs".as_ref());
2146 }
2147 if built_tools.contains("rust-analyzer") {
2148 candle("RustAnalyzerGroup.wxs".as_ref());
2149 }
2150 candle("AnalysisGroup.wxs".as_ref());
2151
2152 if target.is_windows_gnu() {
2153 candle("GccGroup.wxs".as_ref());
2154 }
2155
2156 builder.create(&exe.join("LICENSE.rtf"), &rtf);
2157 builder.install(&etc.join("gfx/banner.bmp"), &exe, FileType::Regular);
2158 builder.install(&etc.join("gfx/dialogbg.bmp"), &exe, FileType::Regular);
2159
2160 builder.info(&format!("building `msi` installer with {light:?}"));
2161 let filename = format!("{}-{}.msi", pkgname(builder, "rust"), target.triple);
2162 let mut cmd = command(&light);
2163 cmd.arg("-nologo")
2164 .arg("-ext")
2165 .arg("WixUIExtension")
2166 .arg("-ext")
2167 .arg("WixUtilExtension")
2168 .arg("-out")
2169 .arg(exe.join(&filename))
2170 .arg("rust.wixobj")
2171 .arg("ui.wixobj")
2172 .arg("rustwelcomedlg.wixobj")
2173 .arg("RustcGroup.wixobj")
2174 .arg("CargoGroup.wixobj")
2175 .arg("StdGroup.wixobj")
2176 .arg("AnalysisGroup.wixobj")
2177 .current_dir(&exe);
2178
2179 if built_tools.contains("clippy") {
2180 cmd.arg("ClippyGroup.wixobj");
2181 }
2182 if built_tools.contains("rustfmt") {
2183 cmd.arg("RustFmtGroup.wixobj");
2184 }
2185 if built_tools.contains("miri") {
2186 cmd.arg("MiriGroup.wixobj");
2187 }
2188 if built_tools.contains("rust-analyzer") {
2189 cmd.arg("RustAnalyzerGroup.wixobj");
2190 }
2191 if built_tools.contains("rust-docs") {
2192 cmd.arg("DocsGroup.wixobj");
2193 }
2194
2195 if target.is_windows_gnu() {
2196 cmd.arg("GccGroup.wixobj");
2197 }
2198 cmd.arg("-sice:ICE57");
2200
2201 let _time = timeit(builder);
2202 cmd.run(builder);
2203
2204 if !builder.config.dry_run() {
2205 t!(move_file(exe.join(&filename), distdir(builder).join(&filename)));
2206 }
2207 }
2208 }
2209
2210 fn metadata(&self) -> Option<StepMetadata> {
2211 Some(StepMetadata::dist("extended", self.target).built_by(self.build_compiler))
2212 }
2213}
2214
2215fn add_env(
2216 builder: &Builder<'_>,
2217 cmd: &mut BootstrapCommand,
2218 target: TargetSelection,
2219 built_tools: &HashSet<&'static str>,
2220) {
2221 let mut parts = builder.version.split('.');
2222 cmd.env("CFG_RELEASE_INFO", builder.rust_version())
2223 .env("CFG_RELEASE_NUM", &builder.version)
2224 .env("CFG_RELEASE", builder.rust_release())
2225 .env("CFG_VER_MAJOR", parts.next().unwrap())
2226 .env("CFG_VER_MINOR", parts.next().unwrap())
2227 .env("CFG_VER_PATCH", parts.next().unwrap())
2228 .env("CFG_VER_BUILD", "0") .env("CFG_PACKAGE_VERS", builder.rust_package_vers())
2230 .env("CFG_PACKAGE_NAME", pkgname(builder, "rust"))
2231 .env("CFG_BUILD", target.triple)
2232 .env("CFG_CHANNEL", &builder.config.channel);
2233
2234 if target.contains("windows-gnullvm") {
2235 cmd.env("CFG_MINGW", "1").env("CFG_ABI", "LLVM");
2236 } else if target.is_windows_gnu() {
2237 cmd.env("CFG_MINGW", "1").env("CFG_ABI", "GNU");
2238 } else {
2239 cmd.env("CFG_MINGW", "0").env("CFG_ABI", "MSVC");
2240 }
2241
2242 let mut define_optional_tool = |tool_name: &str, env_name: &str| {
2244 cmd.env(env_name, if built_tools.contains(tool_name) { "1" } else { "0" });
2245 };
2246 define_optional_tool("rustfmt", "CFG_RUSTFMT");
2247 define_optional_tool("clippy", "CFG_CLIPPY");
2248 define_optional_tool("miri", "CFG_MIRI");
2249 define_optional_tool("rust-analyzer", "CFG_RA");
2250}
2251
2252fn install_llvm_file(
2253 builder: &Builder<'_>,
2254 source: &Path,
2255 destination: &Path,
2256 install_symlink: bool,
2257) {
2258 if builder.config.dry_run() {
2259 return;
2260 }
2261
2262 if source.is_symlink() {
2263 builder.install(&t!(fs::canonicalize(source)), destination, FileType::NativeLibrary);
2266
2267 let full_dest = destination.join(source.file_name().unwrap());
2268 if install_symlink {
2269 builder.copy_link(source, &full_dest, FileType::NativeLibrary);
2272 } else {
2273 let link = t!(fs::read_link(source));
2277 let mut linker_script = t!(fs::File::create(full_dest));
2278 t!(write!(linker_script, "INPUT({})\n", link.display()));
2279
2280 let meta = t!(fs::metadata(source));
2283 if let Ok(mtime) = meta.modified() {
2284 t!(linker_script.set_modified(mtime));
2285 }
2286 }
2287 } else {
2288 builder.install(source, destination, FileType::NativeLibrary);
2289 }
2290}
2291
2292#[cfg_attr(
2296 feature = "tracing",
2297 instrument(
2298 level = "trace",
2299 name = "maybe_install_llvm",
2300 skip_all,
2301 fields(target = ?target, dst_libdir = ?dst_libdir, install_symlink = install_symlink),
2302 ),
2303)]
2304fn maybe_install_llvm(
2305 builder: &Builder<'_>,
2306 target: TargetSelection,
2307 dst_libdir: &Path,
2308 install_symlink: bool,
2309) -> bool {
2310 if builder.config.is_system_llvm(target) {
2327 trace!("system LLVM requested, no install");
2328 return false;
2329 }
2330
2331 if target.contains("apple-darwin") && builder.llvm_link_shared() {
2337 let src_libdir = builder.llvm_out(target).join("lib");
2338 let llvm_dylib_path = src_libdir.join("libLLVM.dylib");
2339 if llvm_dylib_path.exists() {
2340 builder.install(&llvm_dylib_path, dst_libdir, FileType::NativeLibrary);
2341 }
2342 !builder.config.dry_run()
2343 } else if let llvm::LlvmBuildStatus::AlreadyBuilt(llvm::LlvmResult {
2344 host_llvm_config, ..
2345 }) = llvm::prebuilt_llvm_config(builder, target, true)
2346 {
2347 trace!("LLVM already built, installing LLVM files");
2348 let mut cmd = command(host_llvm_config);
2349 cmd.cached();
2350 cmd.arg("--libfiles");
2351 builder.do_if_verbose(|| println!("running {cmd:?}"));
2352 let files = cmd.run_capture_stdout(builder).stdout();
2353 let build_llvm_out = &builder.llvm_out(builder.config.host_target);
2354 let target_llvm_out = &builder.llvm_out(target);
2355 for file in files.trim_end().split(' ') {
2356 let file = if let Ok(relative_path) = Path::new(file).strip_prefix(build_llvm_out) {
2358 target_llvm_out.join(relative_path)
2359 } else {
2360 PathBuf::from(file)
2361 };
2362 install_llvm_file(builder, &file, dst_libdir, install_symlink);
2363 }
2364 !builder.config.dry_run()
2365 } else {
2366 false
2367 }
2368}
2369
2370#[cfg_attr(
2372 feature = "tracing",
2373 instrument(
2374 level = "trace",
2375 name = "maybe_install_llvm_target",
2376 skip_all,
2377 fields(
2378 llvm_link_shared = ?builder.llvm_link_shared(),
2379 target = ?target,
2380 sysroot = ?sysroot,
2381 ),
2382 ),
2383)]
2384pub fn maybe_install_llvm_target(builder: &Builder<'_>, target: TargetSelection, sysroot: &Path) {
2385 let dst_libdir = sysroot.join("lib/rustlib").join(target).join("lib");
2386 if builder.llvm_link_shared() {
2390 maybe_install_llvm(builder, target, &dst_libdir, false);
2391 }
2392}
2393
2394#[cfg_attr(
2396 feature = "tracing",
2397 instrument(
2398 level = "trace",
2399 name = "maybe_install_llvm_runtime",
2400 skip_all,
2401 fields(
2402 llvm_link_shared = ?builder.llvm_link_shared(),
2403 target = ?target,
2404 sysroot = ?sysroot,
2405 ),
2406 ),
2407)]
2408pub fn maybe_install_llvm_runtime(builder: &Builder<'_>, target: TargetSelection, sysroot: &Path) {
2409 let dst_libdir = sysroot.join(builder.sysroot_libdir_relative(Compiler::new(1, target)));
2410 if builder.llvm_link_shared() {
2414 maybe_install_llvm(builder, target, &dst_libdir, false);
2415 }
2416}
2417
2418#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2419pub struct LlvmTools {
2420 pub target: TargetSelection,
2421}
2422
2423impl Step for LlvmTools {
2424 type Output = Option<GeneratedTarball>;
2425 const IS_HOST: bool = true;
2426 const DEFAULT: bool = true;
2427
2428 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2429 let default = should_build_extended_tool(run.builder, "llvm-tools");
2430
2431 let mut run = run.alias("llvm-tools");
2432 for tool in LLVM_TOOLS {
2433 run = run.alias(tool);
2434 }
2435
2436 run.default_condition(default)
2437 }
2438
2439 fn make_run(run: RunConfig<'_>) {
2440 run.builder.ensure(LlvmTools { target: run.target });
2441 }
2442
2443 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2444 fn tools_to_install(paths: &[PathBuf]) -> Vec<&'static str> {
2445 let mut tools = vec![];
2446
2447 for path in paths {
2448 let path = path.to_str().unwrap();
2449
2450 if path == "llvm-tools" {
2452 return LLVM_TOOLS.to_owned();
2453 }
2454
2455 for tool in LLVM_TOOLS {
2456 if path == *tool {
2457 tools.push(*tool);
2458 }
2459 }
2460 }
2461
2462 if tools.is_empty() {
2464 tools = LLVM_TOOLS.to_owned();
2465 }
2466
2467 tools
2468 }
2469
2470 let target = self.target;
2471
2472 if let Some(config) = builder.config.target_config.get(&target)
2474 && !builder.config.llvm_from_ci
2475 && config.llvm_config.is_some()
2476 {
2477 builder.info(&format!("Skipping LlvmTools ({target}): external LLVM"));
2478 return None;
2479 }
2480
2481 if !builder.config.dry_run() {
2482 builder.require_submodule("src/llvm-project", None);
2483 }
2484
2485 builder.ensure(crate::core::build_steps::llvm::Llvm { target });
2486
2487 let mut tarball = Tarball::new(builder, "llvm-tools", &target.triple);
2488 tarball.set_overlay(OverlayKind::Llvm);
2489 tarball.is_preview(true);
2490
2491 if builder.config.llvm_tools_enabled {
2492 let src_bindir = builder.llvm_out(target).join("bin");
2494 let dst_bindir = format!("lib/rustlib/{}/bin", target.triple);
2495 for tool in tools_to_install(&builder.paths) {
2496 let exe = src_bindir.join(exe(tool, target));
2497 if !exe.exists() && builder.config.llvm_from_ci {
2499 eprintln!("{} does not exist; skipping copy", exe.display());
2500 continue;
2501 }
2502
2503 tarball.add_file(&exe, &dst_bindir, FileType::Executable);
2504 }
2505 }
2506
2507 maybe_install_llvm_target(builder, target, tarball.image_dir());
2512
2513 Some(tarball.generate())
2514 }
2515}
2516
2517#[derive(Debug, Clone, Hash, PartialEq, Eq)]
2520pub struct LlvmBitcodeLinker {
2521 pub build_compiler: Compiler,
2523 pub target: TargetSelection,
2525}
2526
2527impl Step for LlvmBitcodeLinker {
2528 type Output = Option<GeneratedTarball>;
2529 const DEFAULT: bool = true;
2530 const IS_HOST: bool = true;
2531
2532 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2533 let default = should_build_extended_tool(run.builder, "llvm-bitcode-linker");
2534 run.alias("llvm-bitcode-linker").default_condition(default)
2535 }
2536
2537 fn make_run(run: RunConfig<'_>) {
2538 run.builder.ensure(LlvmBitcodeLinker {
2539 build_compiler: tool::LlvmBitcodeLinker::get_build_compiler_for_target(
2540 run.builder,
2541 run.target,
2542 ),
2543 target: run.target,
2544 });
2545 }
2546
2547 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2548 let target = self.target;
2549
2550 let llbc_linker = builder
2551 .ensure(tool::LlvmBitcodeLinker::from_build_compiler(self.build_compiler, target));
2552
2553 let self_contained_bin_dir = format!("lib/rustlib/{}/bin/self-contained", target.triple);
2554
2555 let mut tarball = Tarball::new(builder, "llvm-bitcode-linker", &target.triple);
2557 tarball.set_overlay(OverlayKind::LlvmBitcodeLinker);
2558 tarball.is_preview(true);
2559
2560 tarball.add_file(&llbc_linker.tool_path, self_contained_bin_dir, FileType::Executable);
2561
2562 Some(tarball.generate())
2563 }
2564}
2565
2566#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2575pub struct RustDev {
2576 pub target: TargetSelection,
2577}
2578
2579impl Step for RustDev {
2580 type Output = Option<GeneratedTarball>;
2581 const DEFAULT: bool = true;
2582 const IS_HOST: bool = true;
2583
2584 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2585 run.alias("rust-dev")
2586 }
2587
2588 fn make_run(run: RunConfig<'_>) {
2589 run.builder.ensure(RustDev { target: run.target });
2590 }
2591
2592 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2593 let target = self.target;
2594
2595 if let Some(config) = builder.config.target_config.get(&target)
2597 && let Some(ref _s) = config.llvm_config
2598 {
2599 builder.info(&format!("Skipping RustDev ({target}): external LLVM"));
2600 return None;
2601 }
2602
2603 if !builder.config.dry_run() {
2604 builder.require_submodule("src/llvm-project", None);
2605 }
2606
2607 let mut tarball = Tarball::new(builder, "rust-dev", &target.triple);
2608 tarball.set_overlay(OverlayKind::Llvm);
2609 tarball.permit_symlinks(true);
2611
2612 builder.ensure(crate::core::build_steps::llvm::Llvm { target });
2613
2614 let src_bindir = builder.llvm_out(target).join("bin");
2615 if src_bindir.exists() {
2621 for entry in walkdir::WalkDir::new(&src_bindir) {
2622 let entry = t!(entry);
2623 if entry.file_type().is_file() && !entry.path_is_symlink() {
2624 let name = entry.file_name().to_str().unwrap();
2625 tarball.add_file(src_bindir.join(name), "bin", FileType::Executable);
2626 }
2627 }
2628 }
2629
2630 if builder.config.lld_enabled {
2631 let lld_out = builder.ensure(crate::core::build_steps::llvm::Lld { target });
2633
2634 let lld_path = lld_out.join("bin").join(exe("lld", target));
2636 if lld_path.exists() {
2637 tarball.add_file(&lld_path, "bin", FileType::Executable);
2638 }
2639 }
2640
2641 tarball.add_file(builder.llvm_filecheck(target), "bin", FileType::Executable);
2642
2643 tarball.add_dir(builder.llvm_out(target).join("include"), "include");
2647
2648 let dst_libdir = tarball.image_dir().join("lib");
2653 maybe_install_llvm(builder, target, &dst_libdir, true);
2654 let link_type = if builder.llvm_link_shared() { "dynamic" } else { "static" };
2655 t!(std::fs::write(tarball.image_dir().join("link-type.txt"), link_type), dst_libdir);
2656
2657 copy_src_dirs(
2661 builder,
2662 &builder.src.join("src").join("llvm-project"),
2663 &["compiler-rt"],
2664 &["compiler-rt/test"],
2667 tarball.image_dir(),
2668 );
2669
2670 Some(tarball.generate())
2671 }
2672}
2673
2674#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2680pub struct Bootstrap {
2681 target: TargetSelection,
2682}
2683
2684impl Step for Bootstrap {
2685 type Output = Option<GeneratedTarball>;
2686
2687 const IS_HOST: bool = true;
2688
2689 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2690 run.alias("bootstrap")
2691 }
2692
2693 fn make_run(run: RunConfig<'_>) {
2694 run.builder.ensure(Bootstrap { target: run.target });
2695 }
2696
2697 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2698 let target = self.target;
2699
2700 let tarball = Tarball::new(builder, "bootstrap", &target.triple);
2701
2702 let bootstrap_outdir = &builder.bootstrap_out;
2703 for file in &["bootstrap", "rustc", "rustdoc"] {
2704 tarball.add_file(
2705 bootstrap_outdir.join(exe(file, target)),
2706 "bootstrap/bin",
2707 FileType::Executable,
2708 );
2709 }
2710
2711 Some(tarball.generate())
2712 }
2713
2714 fn metadata(&self) -> Option<StepMetadata> {
2715 Some(StepMetadata::dist("bootstrap", self.target))
2716 }
2717}
2718
2719#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2724pub struct BuildManifest {
2725 target: TargetSelection,
2726}
2727
2728impl Step for BuildManifest {
2729 type Output = GeneratedTarball;
2730
2731 const IS_HOST: bool = true;
2732
2733 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2734 run.alias("build-manifest")
2735 }
2736
2737 fn make_run(run: RunConfig<'_>) {
2738 run.builder.ensure(BuildManifest { target: run.target });
2739 }
2740
2741 fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
2742 let build_manifest =
2746 builder.ensure(tool::BuildManifest::new(builder, builder.config.host_target));
2747
2748 let tarball = Tarball::new(builder, "build-manifest", &self.target.triple);
2749 tarball.add_file(&build_manifest.tool_path, "bin", FileType::Executable);
2750 tarball.generate()
2751 }
2752
2753 fn metadata(&self) -> Option<StepMetadata> {
2754 Some(StepMetadata::dist("build-manifest", self.target))
2755 }
2756}
2757
2758#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2764pub struct ReproducibleArtifacts {
2765 target: TargetSelection,
2766}
2767
2768impl Step for ReproducibleArtifacts {
2769 type Output = Option<GeneratedTarball>;
2770 const DEFAULT: bool = true;
2771 const IS_HOST: bool = true;
2772
2773 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2774 run.alias("reproducible-artifacts")
2775 }
2776
2777 fn make_run(run: RunConfig<'_>) {
2778 run.builder.ensure(ReproducibleArtifacts { target: run.target });
2779 }
2780
2781 fn run(self, builder: &Builder<'_>) -> Self::Output {
2782 let mut added_anything = false;
2783 let tarball = Tarball::new(builder, "reproducible-artifacts", &self.target.triple);
2784 if let Some(path) = builder.config.rust_profile_use.as_ref() {
2785 tarball.add_file(path, ".", FileType::Regular);
2786 added_anything = true;
2787 }
2788 if let Some(path) = builder.config.llvm_profile_use.as_ref() {
2789 tarball.add_file(path, ".", FileType::Regular);
2790 added_anything = true;
2791 }
2792 for profile in &builder.config.reproducible_artifacts {
2793 tarball.add_file(profile, ".", FileType::Regular);
2794 added_anything = true;
2795 }
2796 if added_anything { Some(tarball.generate()) } else { None }
2797 }
2798
2799 fn metadata(&self) -> Option<StepMetadata> {
2800 Some(StepMetadata::dist("reproducible-artifacts", self.target))
2801 }
2802}
2803
2804#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2808pub struct Gcc {
2809 target: TargetSelection,
2810}
2811
2812impl Step for Gcc {
2813 type Output = GeneratedTarball;
2814
2815 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2816 run.alias("gcc")
2817 }
2818
2819 fn make_run(run: RunConfig<'_>) {
2820 run.builder.ensure(Gcc { target: run.target });
2821 }
2822
2823 fn run(self, builder: &Builder<'_>) -> Self::Output {
2824 let tarball = Tarball::new(builder, "gcc", &self.target.triple);
2825 let output = builder.ensure(super::gcc::Gcc { target: self.target });
2826 tarball.add_file(&output.libgccjit, "lib", FileType::NativeLibrary);
2827 tarball.generate()
2828 }
2829
2830 fn metadata(&self) -> Option<StepMetadata> {
2831 Some(StepMetadata::dist("gcc", self.target))
2832 }
2833}