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