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::{
23 get_codegen_backend_file, libgccjit_path_relative_to_cg_dir, normalize_codegen_backend_name,
24};
25use crate::core::build_steps::doc::DocumentationFormat;
26use crate::core::build_steps::gcc::GccTargetPair;
27use crate::core::build_steps::tool::{
28 self, RustcPrivateCompilers, ToolTargetBuildMode, get_tool_target_compiler,
29};
30use crate::core::build_steps::vendor::Vendor;
31use crate::core::build_steps::{compile, llvm};
32use crate::core::builder::{
33 Builder, CommandLineStep, Kind, RunConfig, ShouldRun, Step, StepMetadata,
34};
35use crate::core::config::{GccCiMode, TargetSelection};
36use crate::utils::build_stamp::{self, BuildStamp};
37use crate::utils::channel::{self, Info};
38use crate::utils::exec::{BootstrapCommand, command};
39use crate::utils::helpers::{
40 exe, is_dylib, move_file, t, target_supports_cranelift_backend, timeit,
41};
42use crate::utils::tarball::{GeneratedTarball, OverlayKind, Tarball};
43use crate::{CodegenBackendKind, Compiler, DependencyType, FileType, LLVM_TOOLS, Mode, trace};
44
45pub fn pkgname(builder: &Builder<'_>, component: &str) -> String {
46 format!("{}-{}", component, builder.rust_package_vers())
47}
48
49pub(crate) fn distdir(builder: &Builder<'_>) -> PathBuf {
50 builder.out.join("dist")
51}
52
53pub fn tmpdir(builder: &Builder<'_>) -> PathBuf {
54 builder.out.join("tmp/dist")
55}
56
57fn should_build_extended_tool(builder: &Builder<'_>, tool: &str) -> bool {
58 if !builder.config.extended {
59 return false;
60 }
61 builder.config.tools.as_ref().is_none_or(|tools| tools.contains(tool))
62}
63
64#[derive(Debug, Clone, Hash, PartialEq, Eq)]
65pub struct Docs {
66 pub host: TargetSelection,
67}
68
69impl CommandLineStep for Docs {
70 type Output = Option<GeneratedTarball>;
71
72 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
73 run.alias("rust-docs")
74 }
75
76 fn is_default_step(builder: &Builder<'_>) -> bool {
77 builder.config.docs
78 }
79
80 fn make_run(run: RunConfig<'_>) {
81 run.builder.ensure(Docs { host: run.target });
82 }
83
84 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
86 let host = self.host;
87 builder.run_default_doc_steps();
91
92 if !builder.config.dry_run() {
95 t!(fs::create_dir_all(builder.doc_out(host)));
96 }
97
98 let dest = "share/doc/rust/html";
99
100 let mut tarball = Tarball::new(builder, "rust-docs", &host.triple);
101 tarball.set_product_name("Rust Documentation");
102 tarball.add_bulk_dir(builder.doc_out(host), dest);
103 tarball.add_file(builder.src.join("src/doc/robots.txt"), dest, FileType::Regular);
104 tarball.add_file(builder.src.join("src/doc/sitemap.txt"), dest, FileType::Regular);
105 Some(tarball.generate())
106 }
107
108 fn metadata(&self) -> Option<StepMetadata> {
109 Some(StepMetadata::dist("docs", self.host))
110 }
111}
112
113#[derive(Debug, Clone, Hash, PartialEq, Eq)]
116pub struct JsonDocs {
117 build_compiler: Compiler,
118 target: TargetSelection,
119}
120
121impl CommandLineStep for JsonDocs {
122 type Output = Option<GeneratedTarball>;
123
124 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
125 run.alias("rust-docs-json")
126 }
127
128 fn is_default_step(builder: &Builder<'_>) -> bool {
129 builder.config.docs
130 }
131
132 fn make_run(run: RunConfig<'_>) {
133 run.builder.ensure(JsonDocs {
134 build_compiler: run.builder.compiler_for_std(run.builder.top_stage),
135 target: run.target,
136 });
137 }
138
139 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
140 let target = self.target;
141 let directory = builder.ensure(crate::core::build_steps::doc::Std::from_build_compiler(
142 self.build_compiler,
143 target,
144 DocumentationFormat::Json,
145 ));
146
147 let dest = "share/doc/rust/json";
148
149 let mut tarball = Tarball::new(builder, "rust-docs-json", &target.triple);
150 tarball.set_product_name("Rust Documentation In JSON Format");
151 tarball.is_preview(true);
152 tarball.add_bulk_dir(directory, dest);
153 Some(tarball.generate())
154 }
155
156 fn metadata(&self) -> Option<StepMetadata> {
157 Some(StepMetadata::dist("json-docs", self.target).built_by(self.build_compiler))
158 }
159}
160
161#[derive(Debug, Clone, Hash, PartialEq, Eq)]
168pub struct RustcDocs {
169 target: TargetSelection,
170}
171
172impl CommandLineStep for RustcDocs {
173 type Output = GeneratedTarball;
174 const IS_HOST: bool = true;
175
176 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
177 run.alias("rustc-docs")
178 }
179
180 fn is_default_step(builder: &Builder<'_>) -> bool {
181 builder.config.compiler_docs
182 }
183
184 fn make_run(run: RunConfig<'_>) {
185 run.builder.ensure(RustcDocs { target: run.target });
186 }
187
188 fn run(self, builder: &Builder<'_>) -> Self::Output {
189 let target = self.target;
190 builder.run_default_doc_steps();
191
192 let mut tarball = Tarball::new(builder, "rustc-docs", &target.triple);
193 tarball.set_product_name("Rustc Documentation");
194 tarball.add_bulk_dir(builder.compiler_doc_out(target), "share/doc/rust/html/rustc-docs");
195 tarball.generate()
196 }
197}
198
199fn find_files(files: &[&str], path: &[PathBuf]) -> Vec<PathBuf> {
200 let mut found = Vec::with_capacity(files.len());
201
202 for file in files {
203 let file_path = path.iter().map(|dir| dir.join(file)).find(|p| p.exists());
204
205 if let Some(file_path) = file_path {
206 found.push(file_path);
207 } else {
208 panic!("Could not find '{file}' in {path:?}");
209 }
210 }
211
212 found
213}
214
215fn make_win_dist(plat_root: &Path, target: TargetSelection, builder: &Builder<'_>) {
216 if builder.config.dry_run() {
217 return;
218 }
219
220 let (bin_path, lib_path) = get_cc_search_dirs(target, builder);
221
222 let compiler = if target == "i686-pc-windows-gnu" {
223 "i686-w64-mingw32-gcc.exe"
224 } else if target == "x86_64-pc-windows-gnu" {
225 "x86_64-w64-mingw32-gcc.exe"
226 } else {
227 "gcc.exe"
228 };
229 let target_tools = [compiler, "ld.exe", "dlltool.exe", "libwinpthread-1.dll"];
230
231 let target_libs = [
234 "libgcc.a",
236 "libgcc_eh.a",
237 "libgcc_s.a",
238 "libm.a",
239 "libmingw32.a",
240 "libmingwex.a",
241 "libstdc++.a",
242 "libiconv.a",
243 "libmoldname.a",
244 "libpthread.a",
245 "libadvapi32.a",
250 "libbcrypt.a",
251 "libcomctl32.a",
252 "libcomdlg32.a",
253 "libcredui.a",
254 "libcrypt32.a",
255 "libdbghelp.a",
256 "libgdi32.a",
257 "libimagehlp.a",
258 "libiphlpapi.a",
259 "libkernel32.a",
260 "libmsimg32.a",
261 "libmsvcrt.a",
262 "libntdll.a",
263 "libodbc32.a",
264 "libole32.a",
265 "liboleaut32.a",
266 "libopengl32.a",
267 "libpsapi.a",
268 "librpcrt4.a",
269 "libsecur32.a",
270 "libsetupapi.a",
271 "libshell32.a",
272 "libsynchronization.a",
273 "libuser32.a",
274 "libuserenv.a",
275 "libuuid.a",
276 "libwinhttp.a",
277 "libwinmm.a",
278 "libwinspool.a",
279 "libws2_32.a",
280 "libwsock32.a",
281 ];
282
283 let target_tools = find_files(&target_tools, &bin_path);
285 let target_libs = find_files(&target_libs, &lib_path);
286
287 let plat_target_bin_self_contained_dir =
289 plat_root.join("lib/rustlib").join(target).join("bin/self-contained");
290 fs::create_dir_all(&plat_target_bin_self_contained_dir)
291 .expect("creating plat_target_bin_self_contained_dir failed");
292 for src in target_tools {
293 builder.copy_link_to_folder(&src, &plat_target_bin_self_contained_dir);
294 }
295
296 builder.create(
298 &plat_target_bin_self_contained_dir.join("GCC-WARNING.txt"),
299 "gcc.exe contained in this folder cannot be used for compiling C files - it is only \
300 used as a linker. In order to be able to compile projects containing C code use \
301 the GCC provided by MinGW or Cygwin.",
302 );
303
304 let plat_target_lib_self_contained_dir =
306 plat_root.join("lib/rustlib").join(target).join("lib/self-contained");
307 fs::create_dir_all(&plat_target_lib_self_contained_dir)
308 .expect("creating plat_target_lib_self_contained_dir failed");
309 for src in target_libs {
310 builder.copy_link_to_folder(&src, &plat_target_lib_self_contained_dir);
311 }
312}
313
314fn make_win_llvm_dist(plat_root: &Path, target: TargetSelection, builder: &Builder<'_>) {
315 if builder.config.dry_run() {
316 return;
317 }
318
319 let (_, lib_path) = get_cc_search_dirs(target, builder);
320
321 let target_libs = [
324 "libunwind.a",
326 "libunwind.dll.a",
327 "libmingw32.a",
328 "libmingwex.a",
329 "libmsvcrt.a",
330 "libkernel32.a",
332 "libuser32.a",
333 "libntdll.a",
334 "libuserenv.a",
335 "libws2_32.a",
336 "libdbghelp.a",
337 ];
338
339 let target_libs = find_files(&target_libs, &lib_path);
341
342 let plat_target_lib_self_contained_dir =
344 plat_root.join("lib/rustlib").join(target).join("lib/self-contained");
345 fs::create_dir_all(&plat_target_lib_self_contained_dir)
346 .expect("creating plat_target_lib_self_contained_dir failed");
347 for src in target_libs {
348 builder.copy_link_to_folder(&src, &plat_target_lib_self_contained_dir);
349 }
350}
351
352fn runtime_dll_dist(rust_root: &Path, target: TargetSelection, builder: &Builder<'_>) {
353 if builder.config.dry_run() {
354 return;
355 }
356
357 let (bin_path, _) = get_cc_search_dirs(target, builder);
358
359 let mut rustc_dlls = vec![];
360 if target.is_windows_gnu() {
362 rustc_dlls.push("libwinpthread-1.dll");
363 if target.starts_with("i686-") {
364 rustc_dlls.push("libgcc_s_dw2-1.dll");
365 } else {
366 rustc_dlls.push("libgcc_s_seh-1.dll");
367 }
368 } else if target.is_windows_gnullvm() {
369 rustc_dlls.push("libunwind.dll");
370 } else {
371 panic!("Vendoring of runtime DLLs for `{target}` is not supported`");
372 }
373 let rustc_dlls = find_files(&rustc_dlls, &bin_path);
374
375 let rust_bin_dir = rust_root.join("bin/");
377 fs::create_dir_all(&rust_bin_dir).expect("creating rust_bin_dir failed");
378 for src in &rustc_dlls {
379 builder.copy_link_to_folder(src, &rust_bin_dir);
380 }
381
382 if builder.config.lld_enabled {
383 let rust_target_bin_dir = rust_root.join("lib/rustlib").join(target).join("bin");
385 fs::create_dir_all(&rust_target_bin_dir).expect("creating rust_target_bin_dir failed");
386 for src in &rustc_dlls {
387 builder.copy_link_to_folder(src, &rust_target_bin_dir);
388 }
389 }
390}
391
392fn get_cc_search_dirs(
393 target: TargetSelection,
394 builder: &Builder<'_>,
395) -> (Vec<PathBuf>, Vec<PathBuf>) {
396 let mut cmd = command(builder.cc(target));
398 cmd.arg("-print-search-dirs");
399 let gcc_out = cmd.run_capture_stdout(builder).stdout();
400
401 let mut bin_path: Vec<_> = env::split_paths(&env::var_os("PATH").unwrap_or_default()).collect();
402 let mut lib_path = Vec::new();
403
404 for line in gcc_out.lines() {
405 let idx = line.find(':').unwrap();
406 let key = &line[..idx];
407 let trim_chars: &[_] = &[' ', '='];
408 let value = env::split_paths(line[(idx + 1)..].trim_start_matches(trim_chars));
409
410 if key == "programs" {
411 bin_path.extend(value);
412 } else if key == "libraries" {
413 lib_path.extend(value);
414 }
415 }
416 (bin_path, lib_path)
417}
418
419#[derive(Debug, Clone, Hash, PartialEq, Eq)]
424pub struct Mingw {
425 target: TargetSelection,
426}
427
428impl CommandLineStep for Mingw {
429 type Output = Option<GeneratedTarball>;
430
431 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
432 run.alias("rust-mingw")
433 }
434
435 fn is_default_step(_builder: &Builder<'_>) -> bool {
436 true
437 }
438
439 fn make_run(run: RunConfig<'_>) {
440 run.builder.ensure(Mingw { target: run.target });
441 }
442
443 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
444 let target = self.target;
445 if !target.contains("pc-windows-gnu") || !builder.config.dist_include_mingw_linker {
446 return None;
447 }
448
449 let mut tarball = Tarball::new(builder, "rust-mingw", &target.triple);
450 tarball.set_product_name("Rust MinGW");
451
452 if target.ends_with("pc-windows-gnu") {
453 make_win_dist(tarball.image_dir(), target, builder);
454 } else if target.ends_with("pc-windows-gnullvm") {
455 make_win_llvm_dist(tarball.image_dir(), target, builder);
456 } else {
457 unreachable!();
458 }
459
460 Some(tarball.generate())
461 }
462
463 fn metadata(&self) -> Option<StepMetadata> {
464 Some(StepMetadata::dist("mingw", self.target))
465 }
466}
467
468#[derive(Debug, Clone, Hash, PartialEq, Eq)]
478pub struct Rustc {
479 pub target_compiler: Compiler,
481}
482
483impl CommandLineStep for Rustc {
484 type Output = GeneratedTarball;
485 const IS_HOST: bool = true;
486
487 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
488 run.alias("rustc")
489 }
490
491 fn is_default_step(_builder: &Builder<'_>) -> bool {
492 true
493 }
494
495 fn make_run(run: RunConfig<'_>) {
496 run.builder.ensure(Rustc {
497 target_compiler: run.builder.compiler(run.builder.top_stage, run.target),
498 });
499 }
500
501 fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
502 let target_compiler = self.target_compiler;
503 let target = self.target_compiler.host;
504
505 let tarball = Tarball::new(builder, "rustc", &target.triple);
506
507 prepare_image(builder, target_compiler, tarball.image_dir());
509
510 if target.contains("pc-windows-gnu") && builder.config.dist_include_mingw_linker {
518 runtime_dll_dist(tarball.image_dir(), target, builder);
519 tarball.add_dir(builder.src.join("src/etc/third-party"), "share/doc");
520 }
521
522 return tarball.generate();
523
524 fn prepare_image(builder: &Builder<'_>, target_compiler: Compiler, image: &Path) {
525 let target = target_compiler.host;
526 let src = builder.sysroot(target_compiler);
527
528 t!(fs::create_dir_all(image.join("bin")));
530 builder.cp_link_r(&src.join("bin"), &image.join("bin"));
531
532 if builder
534 .config
535 .tools
536 .as_ref()
537 .is_none_or(|tools| tools.iter().any(|tool| tool == "rustdoc"))
538 {
539 let rustdoc = builder.rustdoc_for_compiler(target_compiler);
540 builder.install(&rustdoc, &image.join("bin"), FileType::Executable);
541 }
542
543 let compilers = RustcPrivateCompilers::from_target_compiler(builder, target_compiler);
544
545 if let Some(ra_proc_macro_srv) = builder.ensure_if_default(
546 tool::RustAnalyzerProcMacroSrv::from_compilers(compilers),
547 builder.kind,
548 ) {
549 let dst = image.join("libexec");
550 builder.install(&ra_proc_macro_srv.tool_path, &dst, FileType::Executable);
551 }
552
553 let libdir_relative = builder.libdir_relative(target_compiler);
554
555 if libdir_relative.to_str() != Some("bin") {
557 let libdir = builder.rustc_libdir(target_compiler);
558 for entry in builder.read_dir(&libdir) {
559 if is_dylib(&entry.path())
565 && !entry
566 .path()
567 .file_name()
568 .and_then(|n| n.to_str())
569 .map(|n| n.contains("libgccjit"))
570 .unwrap_or(false)
571 {
572 builder.install(&entry.path(), &image.join("lib"), FileType::NativeLibrary);
575 }
576 }
577 }
578
579 maybe_install_llvm_runtime(builder, target, image);
585
586 let dst_dir = image.join("lib/rustlib").join(target).join("bin");
587 t!(fs::create_dir_all(&dst_dir));
588
589 if builder.config.lld_enabled {
591 let src_dir = builder.sysroot_target_bindir(target_compiler, target);
592 let rust_lld = exe("rust-lld", target_compiler.host);
593 builder.copy_link(
594 &src_dir.join(&rust_lld),
595 &dst_dir.join(&rust_lld),
596 FileType::Executable,
597 );
598 let self_contained_lld_src_dir = src_dir.join("gcc-ld");
599 let self_contained_lld_dst_dir = dst_dir.join("gcc-ld");
600 t!(fs::create_dir(&self_contained_lld_dst_dir));
601 for name in crate::LLD_FILE_NAMES {
602 let exe_name = exe(name, target_compiler.host);
603 builder.copy_link(
604 &self_contained_lld_src_dir.join(&exe_name),
605 &self_contained_lld_dst_dir.join(&exe_name),
606 FileType::Executable,
607 );
608 }
609 }
610
611 if builder.config.llvm_enabled(target_compiler.host)
612 && builder.config.llvm_tools_enabled
613 {
614 let src_dir = builder.sysroot_target_bindir(target_compiler, target);
615 let llvm_objcopy = exe("llvm-objcopy", target_compiler.host);
616 let rust_objcopy = exe("rust-objcopy", target_compiler.host);
617 builder.copy_link(
618 &src_dir.join(&llvm_objcopy),
619 &dst_dir.join(&rust_objcopy),
620 FileType::Executable,
621 );
622 }
623
624 if builder.tool_enabled("wasm-component-ld") {
625 let src_dir = builder.sysroot_target_bindir(target_compiler, target);
626 let ld = exe("wasm-component-ld", target_compiler.host);
627 builder.copy_link(&src_dir.join(&ld), &dst_dir.join(&ld), FileType::Executable);
628 }
629
630 t!(fs::create_dir_all(image.join("share/man/man1")));
632 let man_src = builder.src.join("src/doc/man");
633 let man_dst = image.join("share/man/man1");
634
635 for file_entry in builder.read_dir(&man_src) {
638 let page_src = file_entry.path();
639 let page_dst = man_dst.join(file_entry.file_name());
640 let src_text = t!(std::fs::read_to_string(&page_src));
641 let version = builder.rust_info().version(builder.build, &builder.version);
642 let new_text = src_text.replace("<INSERT VERSION HERE>", &version);
643 t!(std::fs::write(&page_dst, &new_text));
644 }
645
646 builder.ensure(DebuggerScripts { sysroot: image.to_owned(), target });
648
649 generate_target_spec_json_schema(builder, image);
650
651 let file_list = builder.ensure(super::run::GenerateCopyright);
653 for file in file_list {
654 builder.install(&file, &image.join("share/doc/rust"), FileType::Regular);
655 }
656
657 builder.install(
659 &builder.src.join("README.md"),
660 &image.join("share/doc/rust"),
661 FileType::Regular,
662 );
663
664 let license = |path: &Path| {
666 builder.install(path, &image.join("share/doc/rust/licenses"), FileType::Regular);
667 };
668 for entry in t!(std::fs::read_dir(builder.src.join("LICENSES"))).flatten() {
669 license(&entry.path());
670 }
671 }
672 }
673
674 fn metadata(&self) -> Option<StepMetadata> {
675 Some(StepMetadata::dist("rustc", self.target_compiler.host))
676 }
677}
678
679fn generate_target_spec_json_schema(builder: &Builder<'_>, sysroot: &Path) {
680 let stage1_host = builder.compiler(1, builder.host_target);
684 let mut rustc = builder.rustc_cmd(stage1_host).fail_fast();
685 rustc
686 .env("RUSTC_BOOTSTRAP", "1")
687 .args(["--print=target-spec-json-schema", "-Zunstable-options"]);
688 let schema = rustc.run_capture(builder).stdout();
689
690 let schema_dir = tmpdir(builder);
691 t!(fs::create_dir_all(&schema_dir));
692 let schema_file = schema_dir.join("target-spec-json-schema.json");
693 t!(std::fs::write(&schema_file, schema));
694
695 let dst = sysroot.join("etc");
696 t!(fs::create_dir_all(&dst));
697
698 builder.install(&schema_file, &dst, FileType::Regular);
699}
700
701#[derive(Debug, Clone, Hash, PartialEq, Eq)]
703pub struct DebuggerScripts {
704 pub sysroot: PathBuf,
706 pub target: TargetSelection,
707}
708
709impl Step for DebuggerScripts {
710 type Output = ();
711
712 fn run(self, builder: &Builder<'_>) {
713 let target = self.target;
714 let sysroot = self.sysroot;
715 let dst = sysroot.join("lib/rustlib/etc");
716 t!(fs::create_dir_all(&dst));
717 let cp_debugger_script = |file: &str| {
718 builder.install(&builder.src.join("src/etc/").join(file), &dst, FileType::Regular);
719 };
720 if target.contains("windows-msvc") {
721 builder.install(
723 &builder.src.join("src/etc/rust-windbg.cmd"),
724 &sysroot.join("bin"),
725 FileType::Script,
726 );
727
728 cp_debugger_script("natvis/intrinsic.natvis");
729 cp_debugger_script("natvis/liballoc.natvis");
730 cp_debugger_script("natvis/libcore.natvis");
731 cp_debugger_script("natvis/libstd.natvis");
732 }
733
734 cp_debugger_script("rust_types.py");
735
736 builder.install(
738 &builder.src.join("src/etc/rust-gdb"),
739 &sysroot.join("bin"),
740 FileType::Script,
741 );
742 builder.install(
743 &builder.src.join("src/etc/rust-gdbgui"),
744 &sysroot.join("bin"),
745 FileType::Script,
746 );
747
748 cp_debugger_script("gdb_load_rust_pretty_printers.py");
749 cp_debugger_script("gdb_lookup.py");
750 cp_debugger_script("gdb_providers.py");
751 if builder.build.unstable_features() {
752 cp_debugger_script("gdb_trim_paths.py");
753 }
754
755 builder.install(
757 &builder.src.join("src/etc/rust-lldb"),
758 &sysroot.join("bin"),
759 FileType::Script,
760 );
761
762 cp_debugger_script("lldb_lookup.py");
763 cp_debugger_script("lldb_providers.py");
764 }
765}
766
767fn skip_host_target_lib(builder: &Builder<'_>, compiler: Compiler) -> bool {
768 if !builder.config.is_host_target(compiler.host) {
771 builder.info("\tskipping, not a build host");
772 true
773 } else {
774 false
775 }
776}
777
778fn verify_uefi_rlib_format(builder: &Builder<'_>, target: TargetSelection, stamp: &BuildStamp) {
782 if !target.ends_with("-uefi") {
783 return;
784 }
785
786 for (path, _) in builder.read_stamp_file(stamp) {
787 if path.extension() != Some(OsStr::new("rlib")) {
788 continue;
789 }
790
791 let data = t!(fs::read(&path));
792 let data = data.as_slice();
793 let archive = t!(ArchiveFile::parse(data));
794 for member in archive.members() {
795 let member = t!(member);
796 let member_data = t!(member.data(data));
797
798 let is_coff = match object::File::parse(member_data) {
799 Ok(member_file) => member_file.format() == BinaryFormat::Coff,
800 Err(_) => false,
801 };
802
803 if !is_coff {
804 let member_name = String::from_utf8_lossy(member.name());
805 panic!("member {} in {} is not COFF", member_name, path.display());
806 }
807 }
808 }
809}
810
811fn copy_target_libs(
813 builder: &Builder<'_>,
814 target: TargetSelection,
815 image: &Path,
816 stamp: &BuildStamp,
817) {
818 let dst = image.join("lib/rustlib").join(target).join("lib");
819 let self_contained_dst = dst.join("self-contained");
820 t!(fs::create_dir_all(&dst));
821 t!(fs::create_dir_all(&self_contained_dst));
822 for (path, dependency_type) in builder.read_stamp_file(stamp) {
823 if dependency_type == DependencyType::TargetSelfContained {
824 builder.copy_link(
825 &path,
826 &self_contained_dst.join(path.file_name().unwrap()),
827 FileType::NativeLibrary,
828 );
829 } else if dependency_type == DependencyType::Target || builder.config.is_host_target(target)
830 {
831 builder.copy_link(&path, &dst.join(path.file_name().unwrap()), FileType::NativeLibrary);
832 }
833 }
834}
835
836#[derive(Debug, Clone, Hash, PartialEq, Eq)]
843pub struct Std {
844 pub build_compiler: Compiler,
846 pub target: TargetSelection,
847}
848
849impl Std {
850 pub fn new(builder: &Builder<'_>, target: TargetSelection) -> Self {
851 Std { build_compiler: builder.compiler_for_std(builder.top_stage), target }
852 }
853}
854
855impl CommandLineStep for Std {
856 type Output = Option<GeneratedTarball>;
857
858 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
859 run.alias("rust-std")
860 }
861
862 fn is_default_step(_builder: &Builder<'_>) -> bool {
863 true
864 }
865
866 fn make_run(run: RunConfig<'_>) {
867 run.builder.ensure(Std::new(run.builder, run.target));
868 }
869
870 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
871 let build_compiler = self.build_compiler;
872 let target = self.target;
873
874 if skip_host_target_lib(builder, build_compiler) {
875 return None;
876 }
877
878 let stamp =
881 builder.std(build_compiler, target).expect("Standard library has to be built for dist");
882
883 let mut tarball = Tarball::new(builder, "rust-std", &target.triple);
884 tarball.include_target_in_component_name(true);
885
886 verify_uefi_rlib_format(builder, target, &stamp);
887 copy_target_libs(builder, target, tarball.image_dir(), &stamp);
888
889 Some(tarball.generate())
890 }
891
892 fn metadata(&self) -> Option<StepMetadata> {
893 Some(StepMetadata::dist("std", self.target).built_by(self.build_compiler))
894 }
895}
896
897#[derive(Debug, Clone, Hash, PartialEq, Eq)]
902pub struct RustcDev {
903 pub build_compiler: Compiler,
905 pub target: TargetSelection,
906}
907
908impl RustcDev {
909 pub fn new(builder: &Builder<'_>, target: TargetSelection) -> Self {
910 Self {
911 build_compiler: builder.compiler(1, builder.config.host_target),
915 target,
916 }
917 }
918}
919
920impl CommandLineStep for RustcDev {
921 type Output = Option<GeneratedTarball>;
922 const IS_HOST: bool = true;
923
924 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
925 run.alias("rustc-dev")
926 }
927
928 fn is_default_step(_builder: &Builder<'_>) -> bool {
929 true
930 }
931
932 fn make_run(run: RunConfig<'_>) {
933 run.builder.ensure(RustcDev::new(run.builder, run.target));
934 }
935
936 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
937 let build_compiler = self.build_compiler;
938 let target = self.target;
939 if skip_host_target_lib(builder, build_compiler) {
940 return None;
941 }
942
943 builder.ensure(compile::Rustc::new(build_compiler, target));
945
946 let tarball = Tarball::new(builder, "rustc-dev", &target.triple);
947
948 let stamp = build_stamp::librustc_stamp(builder, build_compiler, target);
949 copy_target_libs(builder, target, tarball.image_dir(), &stamp);
950
951 let src_files = &["Cargo.lock"];
952 copy_src_dirs(
955 builder,
956 &builder.src,
957 &["compiler", "library/proc_macro"],
959 &[],
960 &tarball.image_dir().join("lib/rustlib/rustc-src/rust"),
961 );
962 for file in src_files {
963 tarball.add_file(
964 builder.src.join(file),
965 "lib/rustlib/rustc-src/rust",
966 FileType::Regular,
967 );
968 }
969
970 Some(tarball.generate())
971 }
972
973 fn metadata(&self) -> Option<StepMetadata> {
974 Some(StepMetadata::dist("rustc-dev", self.target).built_by(self.build_compiler))
975 }
976}
977
978#[derive(Debug, Clone, Hash, PartialEq, Eq)]
983pub struct Analysis {
984 build_compiler: Compiler,
985 target: TargetSelection,
986}
987
988impl CommandLineStep for Analysis {
989 type Output = Option<GeneratedTarball>;
990
991 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
992 run.alias("rust-analysis")
993 }
994
995 fn is_default_step(builder: &Builder<'_>) -> bool {
996 should_build_extended_tool(builder, "analysis")
997 }
998
999 fn make_run(run: RunConfig<'_>) {
1000 run.builder.ensure(Analysis {
1002 build_compiler: run.builder.compiler(1, run.builder.config.host_target),
1003 target: run.target,
1004 });
1005 }
1006
1007 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1008 let compiler = self.build_compiler;
1009 let target = self.target;
1010 if skip_host_target_lib(builder, compiler) {
1011 return None;
1012 }
1013
1014 let src = builder
1015 .stage_out(compiler, Mode::Std)
1016 .join(target)
1017 .join(builder.cargo_dir(Mode::Std))
1018 .join("deps")
1019 .join("save-analysis");
1020
1021 t!(std::fs::create_dir_all(&src));
1023 let mut removed = src.clone();
1024 removed.push("removed.json");
1025 let mut f = t!(std::fs::File::create(removed));
1026 t!(write!(f, r#"{{ "warning": "The `rust-analysis` component has been removed." }}"#));
1027
1028 let mut tarball = Tarball::new(builder, "rust-analysis", &target.triple);
1029 tarball.include_target_in_component_name(true);
1030 tarball.add_dir(src, format!("lib/rustlib/{}/analysis", target.triple));
1031 Some(tarball.generate())
1032 }
1033
1034 fn metadata(&self) -> Option<StepMetadata> {
1035 Some(StepMetadata::dist("analysis", self.target).built_by(self.build_compiler))
1036 }
1037}
1038
1039fn copy_src_dirs(
1042 builder: &Builder<'_>,
1043 base: &Path,
1044 src_dirs: &[&str],
1045 exclude_dirs: &[&str],
1046 dst_dir: &Path,
1047) {
1048 for src_dir in src_dirs {
1051 assert!(Path::new(src_dir).is_relative());
1052 }
1053
1054 if builder.config.dry_run() {
1057 return;
1058 }
1059
1060 fn filter_fn(exclude_dirs: &[&str], dir: &str, path: &Path) -> bool {
1061 let spath = match path.to_str() {
1063 Some(path) => path,
1064 None => return false,
1065 };
1066 if spath.ends_with('~') || spath.ends_with(".pyc") {
1067 return false;
1068 }
1069 let spath = spath.replace("\\", "/");
1071
1072 static LLVM_PROJECTS: &[&str] = &[
1073 "llvm-project/clang",
1074 "llvm-project/libc",
1075 "llvm-project/libunwind",
1076 "llvm-project/lld",
1077 "llvm-project/lldb",
1078 "llvm-project/llvm",
1079 "llvm-project/compiler-rt",
1080 "llvm-project/cmake",
1081 "llvm-project/runtimes",
1082 "llvm-project/third-party",
1083 ];
1084 if spath.starts_with("llvm-project") && spath != "llvm-project" {
1085 if !LLVM_PROJECTS.iter().any(|path| spath.starts_with(path)) {
1086 return false;
1087 }
1088
1089 if spath.starts_with("llvm-project/third-party")
1091 && spath != "llvm-project/third-party"
1092 && !spath.starts_with("llvm-project/third-party/siphash")
1093 {
1094 return false;
1095 }
1096
1097 if spath.starts_with("llvm-project/llvm/test")
1098 && (spath.ends_with(".ll") || spath.ends_with(".td") || spath.ends_with(".s"))
1099 {
1100 return false;
1101 }
1102 }
1103
1104 if spath.starts_with("tools/cargo/tests") {
1106 return true;
1107 }
1108
1109 if !exclude_dirs.is_empty() {
1110 let full_path = Path::new(dir).join(path);
1111 if exclude_dirs.iter().any(|excl| full_path == Path::new(excl)) {
1112 return false;
1113 }
1114 }
1115
1116 static EXCLUDES: &[&str] = &[
1117 "CVS",
1118 "RCS",
1119 "SCCS",
1120 ".git",
1121 ".gitignore",
1122 ".gitmodules",
1123 ".gitattributes",
1124 ".cvsignore",
1125 ".svn",
1126 ".arch-ids",
1127 "{arch}",
1128 "=RELEASE-ID",
1129 "=meta-update",
1130 "=update",
1131 ".bzr",
1132 ".bzrignore",
1133 ".bzrtags",
1134 ".hg",
1135 ".hgignore",
1136 ".hgrags",
1137 "_darcs",
1138 ];
1139
1140 let last_component = path.iter().next_back().map(|s| s.to_str().unwrap()).unwrap();
1147 !EXCLUDES.contains(&last_component)
1148 }
1149
1150 for item in src_dirs {
1152 let dst = &dst_dir.join(item);
1153 t!(fs::create_dir_all(dst));
1154 builder
1155 .cp_link_filtered(&base.join(item), dst, &|path| filter_fn(exclude_dirs, item, path));
1156 }
1157}
1158
1159#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1160pub struct Src;
1161
1162impl CommandLineStep for Src {
1163 type Output = GeneratedTarball;
1165 const IS_HOST: bool = true;
1166
1167 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1168 run.alias("rust-src")
1169 }
1170
1171 fn is_default_step(_builder: &Builder<'_>) -> bool {
1172 true
1173 }
1174
1175 fn make_run(run: RunConfig<'_>) {
1176 run.builder.ensure(Src);
1177 }
1178
1179 fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
1181 if !builder.config.dry_run() {
1182 builder.require_submodule("src/llvm-project", None);
1183 }
1184
1185 let tarball = Tarball::new_targetless(builder, "rust-src");
1186
1187 let dst_src = tarball.image_dir().join("lib/rustlib/src/rust");
1195
1196 copy_src_dirs(
1199 builder,
1200 &builder.src,
1201 &["library", "src/llvm-project/libunwind"],
1202 &[
1203 "library/backtrace/crates",
1206 ],
1207 &dst_src,
1208 );
1209
1210 let vendor = builder.ensure(Vendor {
1212 sync_args: vec![],
1213 versioned_dirs: true,
1214 root_dir: dst_src.clone(),
1215 output_dir: None,
1216 only_library_workspace: true,
1217 });
1218
1219 let library_cargo_config_dir = dst_src.join("library").join(".cargo");
1220 builder.create_dir(&library_cargo_config_dir);
1221 builder.create(&library_cargo_config_dir.join("config.toml"), &vendor.config_library);
1222
1223 tarball.generate()
1224 }
1225
1226 fn metadata(&self) -> Option<StepMetadata> {
1227 Some(StepMetadata::dist("src", TargetSelection::default()))
1228 }
1229}
1230
1231#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1235pub struct PlainSourceTarball;
1236
1237impl CommandLineStep for PlainSourceTarball {
1238 type Output = GeneratedTarball;
1240 const IS_HOST: bool = true;
1241
1242 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1243 run.alias("rustc-src")
1244 }
1245
1246 fn is_default_step(builder: &Builder<'_>) -> bool {
1247 builder.config.rust_dist_src
1248 }
1249
1250 fn make_run(run: RunConfig<'_>) {
1251 run.builder.ensure(PlainSourceTarball);
1252 }
1253
1254 fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
1256 let tarball = prepare_source_tarball(
1257 builder,
1258 "src",
1259 &[
1260 "src/gcc",
1264 ],
1265 );
1266
1267 let plain_dst_src = tarball.image_dir();
1268 if !builder.config.dry_run() {
1273 builder.create_dir(&plain_dst_src.join("src/gcc"));
1274 t!(std::fs::write(
1275 plain_dst_src.join("src/gcc/notice.txt"),
1276 "The GCC source code is not included due to unclear licensing implications\n"
1277 ));
1278 }
1279 tarball.bare()
1280 }
1281}
1282
1283#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1285pub struct PlainSourceTarballGpl;
1286
1287impl CommandLineStep for PlainSourceTarballGpl {
1288 type Output = GeneratedTarball;
1290 const IS_HOST: bool = true;
1291
1292 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1293 run.alias("rustc-src-gpl")
1294 }
1295
1296 fn is_default_step(builder: &Builder<'_>) -> bool {
1297 builder.config.rust_dist_src
1298 }
1299
1300 fn make_run(run: RunConfig<'_>) {
1301 run.builder.ensure(PlainSourceTarballGpl);
1302 }
1303
1304 fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
1306 let tarball = prepare_source_tarball(builder, "src-gpl", &[]);
1307 tarball.bare()
1308 }
1309}
1310
1311fn prepare_source_tarball<'a>(
1312 builder: &'a Builder<'a>,
1313 name: &str,
1314 exclude_dirs: &[&str],
1315) -> Tarball<'a> {
1316 let mut tarball = Tarball::new(builder, "rustc", name);
1321 tarball.permit_symlinks(true);
1322 let plain_dst_src = tarball.image_dir();
1323
1324 let src_files = [
1326 ".gitmodules",
1328 "CONTRIBUTING.md",
1329 "COPYRIGHT",
1330 "Cargo.lock",
1331 "Cargo.toml",
1332 "LICENSE-APACHE",
1333 "LICENSE-MIT",
1334 "README.md",
1335 "RELEASES.md",
1336 "REUSE.toml",
1337 "bootstrap.example.toml",
1338 "configure",
1339 "license-metadata.json",
1340 "package.json",
1341 "x",
1342 "x.ps1",
1343 "x.py",
1344 "yarn.lock",
1345 ];
1347 let src_dirs = ["src", "compiler", "library", "tests", "LICENSES"];
1348
1349 copy_src_dirs(builder, &builder.src, &src_dirs, exclude_dirs, plain_dst_src);
1350
1351 for item in &src_files {
1353 builder.copy_link(&builder.src.join(item), &plain_dst_src.join(item), FileType::Regular);
1354 }
1355
1356 builder.create(&plain_dst_src.join("version"), &builder.rust_version());
1358
1359 let write_git_info = |info: Option<&Info>, path: &Path| {
1361 if let Some(info) = info {
1362 t!(std::fs::create_dir_all(path));
1363 channel::write_commit_hash_file(path, &info.sha);
1364 channel::write_commit_info_file(path, info);
1365 }
1366 };
1367 write_git_info(builder.rust_info().info(), plain_dst_src);
1368 write_git_info(builder.cargo_info.info(), &plain_dst_src.join("./src/tools/cargo"));
1369
1370 if builder.config.dist_vendor {
1371 builder.require_and_update_all_submodules();
1372
1373 let pkgs_for_pgo_training =
1375 build_helper::LLVM_PGO_CRATES.iter().chain(build_helper::RUSTC_PGO_CRATES).map(|pkg| {
1376 let mut manifest_path =
1377 builder.src.join("./src/tools/rustc-perf/collector/compile-benchmarks");
1378 manifest_path.push(pkg);
1379 manifest_path.push("Cargo.toml");
1380 manifest_path
1381 });
1382
1383 let vendor = builder.ensure(Vendor {
1385 sync_args: pkgs_for_pgo_training.collect(),
1386 versioned_dirs: true,
1387 root_dir: plain_dst_src.into(),
1388 output_dir: None,
1389 only_library_workspace: false,
1390 });
1391
1392 let cargo_config_dir = plain_dst_src.join(".cargo");
1393 builder.create_dir(&cargo_config_dir);
1394 builder.create(&cargo_config_dir.join("config.toml"), &vendor.config);
1395
1396 let library_cargo_config_dir = plain_dst_src.join("library").join(".cargo");
1397 builder.create_dir(&library_cargo_config_dir);
1398 builder.create(&library_cargo_config_dir.join("config.toml"), &vendor.config_library);
1399 }
1400
1401 for entry in walkdir::WalkDir::new(tarball.image_dir())
1405 .follow_links(true)
1406 .into_iter()
1407 .filter_map(|e| e.ok())
1408 {
1409 if entry.path().is_dir() && entry.path().file_name() == Some(OsStr::new("__pycache__")) {
1410 t!(fs::remove_dir_all(entry.path()));
1411 }
1412 }
1413 tarball
1414}
1415
1416#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1417pub struct Cargo {
1418 pub build_compiler: Compiler,
1419 pub target: TargetSelection,
1420}
1421
1422impl CommandLineStep for Cargo {
1423 type Output = Option<GeneratedTarball>;
1424 const IS_HOST: bool = true;
1425
1426 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1427 run.alias("cargo")
1428 }
1429
1430 fn is_default_step(builder: &Builder<'_>) -> bool {
1431 should_build_extended_tool(builder, "cargo")
1432 }
1433
1434 fn make_run(run: RunConfig<'_>) {
1435 run.builder.ensure(Cargo {
1436 build_compiler: get_tool_target_compiler(
1437 run.builder,
1438 ToolTargetBuildMode::Build(run.target),
1439 ),
1440 target: run.target,
1441 });
1442 }
1443
1444 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1445 let build_compiler = self.build_compiler;
1446 let target = self.target;
1447
1448 let cargo = builder.ensure(tool::Cargo::from_build_compiler(build_compiler, target));
1449 let src = builder.src.join("src/tools/cargo");
1450 let etc = src.join("etc");
1451
1452 let mut tarball = Tarball::new(builder, "cargo", &target.triple);
1454 tarball.set_overlay(OverlayKind::Cargo);
1455
1456 tarball.add_file(&cargo.tool_path, "bin", FileType::Executable);
1457 tarball.add_file(etc.join("_cargo"), "share/zsh/site-functions", FileType::Regular);
1458 tarball.add_renamed_file(
1459 etc.join("cargo.bashcomp.sh"),
1460 "etc/bash_completion.d",
1461 "cargo",
1462 FileType::Regular,
1463 );
1464 tarball.add_dir(etc.join("man"), "share/man/man1");
1465 tarball.add_legal_and_readme_to("share/doc/cargo");
1466
1467 Some(tarball.generate())
1468 }
1469
1470 fn metadata(&self) -> Option<StepMetadata> {
1471 Some(StepMetadata::dist("cargo", self.target).built_by(self.build_compiler))
1472 }
1473}
1474
1475#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1477pub struct RustAnalyzer {
1478 pub compilers: RustcPrivateCompilers,
1479 pub target: TargetSelection,
1480}
1481
1482impl CommandLineStep for RustAnalyzer {
1483 type Output = Option<GeneratedTarball>;
1484 const IS_HOST: bool = true;
1485
1486 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1487 run.alias("rust-analyzer")
1488 }
1489
1490 fn is_default_step(builder: &Builder<'_>) -> bool {
1491 should_build_extended_tool(builder, "rust-analyzer")
1492 }
1493
1494 fn make_run(run: RunConfig<'_>) {
1495 run.builder.ensure(RustAnalyzer {
1496 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1497 target: run.target,
1498 });
1499 }
1500
1501 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1502 let target = self.target;
1503 let rust_analyzer = builder.ensure(tool::RustAnalyzer::from_compilers(self.compilers));
1504
1505 let mut tarball = Tarball::new(builder, "rust-analyzer", &target.triple);
1506 tarball.set_overlay(OverlayKind::RustAnalyzer);
1507 tarball.is_preview(true);
1508 tarball.add_file(&rust_analyzer.tool_path, "bin", FileType::Executable);
1509 tarball.add_legal_and_readme_to("share/doc/rust-analyzer");
1510 Some(tarball.generate())
1511 }
1512
1513 fn metadata(&self) -> Option<StepMetadata> {
1514 Some(
1515 StepMetadata::dist("rust-analyzer", self.target)
1516 .built_by(self.compilers.build_compiler()),
1517 )
1518 }
1519}
1520
1521#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1522pub struct Clippy {
1523 pub compilers: RustcPrivateCompilers,
1524 pub target: TargetSelection,
1525}
1526
1527impl CommandLineStep for Clippy {
1528 type Output = Option<GeneratedTarball>;
1529 const IS_HOST: bool = true;
1530
1531 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1532 run.alias("clippy")
1533 }
1534
1535 fn is_default_step(builder: &Builder<'_>) -> bool {
1536 should_build_extended_tool(builder, "clippy")
1537 }
1538
1539 fn make_run(run: RunConfig<'_>) {
1540 run.builder.ensure(Clippy {
1541 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1542 target: run.target,
1543 });
1544 }
1545
1546 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1547 let target = self.target;
1548
1549 let clippy = builder.ensure(tool::Clippy::from_compilers(self.compilers));
1553 let cargoclippy = builder.ensure(tool::CargoClippy::from_compilers(self.compilers));
1554
1555 let mut tarball = Tarball::new(builder, "clippy", &target.triple);
1556 tarball.set_overlay(OverlayKind::Clippy);
1557 tarball.is_preview(true);
1558 tarball.add_file(&clippy.tool_path, "bin", FileType::Executable);
1559 tarball.add_file(&cargoclippy.tool_path, "bin", FileType::Executable);
1560 tarball.add_legal_and_readme_to("share/doc/clippy");
1561 Some(tarball.generate())
1562 }
1563
1564 fn metadata(&self) -> Option<StepMetadata> {
1565 Some(StepMetadata::dist("clippy", self.target).built_by(self.compilers.build_compiler()))
1566 }
1567}
1568
1569#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1570pub struct Miri {
1571 pub compilers: RustcPrivateCompilers,
1572 pub target: TargetSelection,
1573}
1574
1575impl CommandLineStep for Miri {
1576 type Output = Option<GeneratedTarball>;
1577 const IS_HOST: bool = true;
1578
1579 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1580 run.alias("miri")
1581 }
1582
1583 fn is_default_step(builder: &Builder<'_>) -> bool {
1584 should_build_extended_tool(builder, "miri")
1585 }
1586
1587 fn make_run(run: RunConfig<'_>) {
1588 run.builder.ensure(Miri {
1589 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1590 target: run.target,
1591 });
1592 }
1593
1594 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1595 if !builder.build.unstable_features() {
1599 return None;
1600 }
1601
1602 let miri = builder.ensure(tool::Miri::from_compilers(self.compilers));
1603 let cargomiri = builder.ensure(tool::CargoMiri::from_compilers(self.compilers));
1604
1605 let mut tarball = Tarball::new(builder, "miri", &self.target.triple);
1606 tarball.set_overlay(OverlayKind::Miri);
1607 tarball.is_preview(true);
1608 tarball.add_file(&miri.tool_path, "bin", FileType::Executable);
1609 tarball.add_file(&cargomiri.tool_path, "bin", FileType::Executable);
1610 tarball.add_legal_and_readme_to("share/doc/miri");
1611 Some(tarball.generate())
1612 }
1613
1614 fn metadata(&self) -> Option<StepMetadata> {
1615 Some(StepMetadata::dist("miri", self.target).built_by(self.compilers.build_compiler()))
1616 }
1617}
1618
1619#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1620pub struct CraneliftCodegenBackend {
1621 pub compilers: RustcPrivateCompilers,
1622 pub target: TargetSelection,
1623}
1624
1625impl CommandLineStep for CraneliftCodegenBackend {
1626 type Output = Option<GeneratedTarball>;
1627 const IS_HOST: bool = true;
1628
1629 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1630 run.alias("rustc_codegen_cranelift")
1631 }
1632
1633 fn is_default_step(builder: &Builder<'_>) -> bool {
1634 builder
1639 .config
1640 .enabled_codegen_backends(builder.host_target)
1641 .contains(&CodegenBackendKind::Cranelift)
1642 }
1643
1644 fn make_run(run: RunConfig<'_>) {
1645 run.builder.ensure(CraneliftCodegenBackend {
1646 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1647 target: run.target,
1648 });
1649 }
1650
1651 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1652 if !builder.build.unstable_features() {
1656 return None;
1657 }
1658
1659 let target = self.target;
1660 if !target_supports_cranelift_backend(target) {
1661 builder.info("target not supported by rustc_codegen_cranelift. skipping");
1662 return None;
1663 }
1664
1665 let mut tarball = Tarball::new(builder, "rustc-codegen-cranelift", &target.triple);
1666 tarball.set_overlay(OverlayKind::RustcCodegenCranelift);
1667 tarball.is_preview(true);
1668 tarball.add_legal_and_readme_to("share/doc/rustc_codegen_cranelift");
1669
1670 let compilers = self.compilers;
1671 let stamp = builder.ensure(compile::CraneliftCodegenBackend { compilers });
1672
1673 if builder.config.dry_run() {
1674 return None;
1675 }
1676
1677 add_codegen_backend_to_tarball(builder, &tarball, compilers.target_compiler(), &stamp);
1678
1679 Some(tarball.generate())
1680 }
1681
1682 fn metadata(&self) -> Option<StepMetadata> {
1683 Some(
1684 StepMetadata::dist("rustc_codegen_cranelift", self.target)
1685 .built_by(self.compilers.build_compiler()),
1686 )
1687 }
1688}
1689
1690#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1694pub struct GccCodegenBackend {
1695 pub compilers: RustcPrivateCompilers,
1696 pub target: TargetSelection,
1697}
1698
1699impl CommandLineStep for GccCodegenBackend {
1700 type Output = Option<GeneratedTarball>;
1701 const IS_HOST: bool = true;
1702
1703 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1704 run.alias("rustc_codegen_gcc")
1705 }
1706
1707 fn is_default_step(builder: &Builder<'_>) -> bool {
1708 builder
1713 .config
1714 .enabled_codegen_backends(builder.host_target)
1715 .contains(&CodegenBackendKind::Gcc)
1716 }
1717
1718 fn make_run(run: RunConfig<'_>) {
1719 run.builder.ensure(GccCodegenBackend {
1720 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1721 target: run.target,
1722 });
1723 }
1724
1725 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1726 if !builder.build.unstable_features() {
1730 return None;
1731 }
1732
1733 let target = self.target;
1734 if target != "x86_64-unknown-linux-gnu" {
1735 builder
1736 .info(&format!("target `{target}` not supported by rustc_codegen_gcc. skipping"));
1737 return None;
1738 }
1739
1740 let mut tarball = Tarball::new(builder, "rustc-codegen-gcc", &target.triple);
1741 tarball.set_overlay(OverlayKind::RustcCodegenGcc);
1742 tarball.is_preview(true);
1743 tarball.add_legal_and_readme_to("share/doc/rustc_codegen_gcc");
1744
1745 let compilers = self.compilers;
1746 let backend = builder.ensure(compile::GccCodegenBackend::for_target(compilers, target));
1747
1748 if builder.config.dry_run() {
1749 return None;
1750 }
1751
1752 add_codegen_backend_to_tarball(
1753 builder,
1754 &tarball,
1755 compilers.target_compiler(),
1756 backend.stamp(),
1757 );
1758
1759 Some(tarball.generate())
1760 }
1761
1762 fn metadata(&self) -> Option<StepMetadata> {
1763 Some(
1764 StepMetadata::dist("rustc_codegen_gcc", self.target)
1765 .built_by(self.compilers.build_compiler()),
1766 )
1767 }
1768}
1769
1770fn add_codegen_backend_to_tarball(
1773 builder: &Builder<'_>,
1774 tarball: &Tarball<'_>,
1775 compiler: Compiler,
1776 stamp: &BuildStamp,
1777) {
1778 let backends_dst = builder.sysroot_codegen_backends(compiler);
1780 let backends_rel = backends_dst
1781 .strip_prefix(builder.sysroot(compiler))
1782 .unwrap()
1783 .strip_prefix(builder.sysroot_libdir_relative(compiler))
1784 .unwrap();
1785 let backends_dst = PathBuf::from("lib").join(backends_rel);
1787
1788 let codegen_backend_dylib = get_codegen_backend_file(stamp);
1789 tarball.add_renamed_file(
1790 &codegen_backend_dylib,
1791 &backends_dst,
1792 &normalize_codegen_backend_name(builder, &codegen_backend_dylib),
1793 FileType::NativeLibrary,
1794 );
1795}
1796
1797#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1798pub struct Rustfmt {
1799 pub compilers: RustcPrivateCompilers,
1800 pub target: TargetSelection,
1801}
1802
1803impl CommandLineStep for Rustfmt {
1804 type Output = Option<GeneratedTarball>;
1805 const IS_HOST: bool = true;
1806
1807 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1808 run.alias("rustfmt")
1809 }
1810
1811 fn is_default_step(builder: &Builder<'_>) -> bool {
1812 should_build_extended_tool(builder, "rustfmt")
1813 }
1814
1815 fn make_run(run: RunConfig<'_>) {
1816 run.builder.ensure(Rustfmt {
1817 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1818 target: run.target,
1819 });
1820 }
1821
1822 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1823 let rustfmt = builder.ensure(tool::Rustfmt::from_compilers(self.compilers));
1824 let cargofmt = builder.ensure(tool::Cargofmt::from_compilers(self.compilers));
1825
1826 let mut tarball = Tarball::new(builder, "rustfmt", &self.target.triple);
1827 tarball.set_overlay(OverlayKind::Rustfmt);
1828 tarball.is_preview(true);
1829 tarball.add_file(&rustfmt.tool_path, "bin", FileType::Executable);
1830 tarball.add_file(&cargofmt.tool_path, "bin", FileType::Executable);
1831 tarball.add_legal_and_readme_to("share/doc/rustfmt");
1832 Some(tarball.generate())
1833 }
1834
1835 fn metadata(&self) -> Option<StepMetadata> {
1836 Some(StepMetadata::dist("rustfmt", self.target).built_by(self.compilers.build_compiler()))
1837 }
1838}
1839
1840#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1842pub struct Extended {
1843 build_compiler: Compiler,
1844 target: TargetSelection,
1845}
1846
1847impl CommandLineStep for Extended {
1848 type Output = ();
1849 const IS_HOST: bool = true;
1850
1851 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1852 run.alias("extended")
1853 }
1854
1855 fn is_default_step(builder: &Builder<'_>) -> bool {
1856 builder.config.extended
1857 }
1858
1859 fn make_run(run: RunConfig<'_>) {
1860 run.builder.ensure(Extended {
1861 build_compiler: run
1862 .builder
1863 .compiler(run.builder.top_stage - 1, run.builder.host_target),
1864 target: run.target,
1865 });
1866 }
1867
1868 fn run(self, builder: &Builder<'_>) {
1870 let target = self.target;
1871 builder.info(&format!("Dist extended stage{} ({target})", builder.top_stage));
1872
1873 let mut tarballs = Vec::new();
1874 let mut built_tools = HashSet::new();
1875 macro_rules! add_component {
1876 ($name:expr => $step:expr) => {
1877 if let Some(Some(tarball)) = builder.ensure_if_default($step, Kind::Dist) {
1878 tarballs.push(tarball);
1879 built_tools.insert($name);
1880 }
1881 };
1882 }
1883
1884 let rustc_private_compilers =
1885 RustcPrivateCompilers::from_build_compiler(builder, self.build_compiler, target);
1886 let build_compiler = rustc_private_compilers.build_compiler();
1887 let target_compiler = rustc_private_compilers.target_compiler();
1888
1889 tarballs.push(builder.ensure(Rustc { target_compiler }));
1894 tarballs.push(builder.ensure(Std { build_compiler, target }).expect("missing std"));
1895
1896 if target.is_windows_gnu() || target.is_windows_gnullvm() {
1897 tarballs.push(builder.ensure(Mingw { target }).expect("missing mingw"));
1898 }
1899
1900 add_component!("rust-docs" => Docs { host: target });
1901 add_component!("rust-json-docs" => JsonDocs { build_compiler: target_compiler, target });
1903 add_component!("cargo" => Cargo { build_compiler, target });
1904 add_component!("rustfmt" => Rustfmt { compilers: rustc_private_compilers, target });
1905 add_component!("rust-analyzer" => RustAnalyzer { compilers: rustc_private_compilers, target });
1906 add_component!("llvm-components" => LlvmTools { target });
1907 add_component!("clippy" => Clippy { compilers: rustc_private_compilers, target });
1908 add_component!("miri" => Miri { compilers: rustc_private_compilers, target });
1909 add_component!("analysis" => Analysis { build_compiler, target });
1910 add_component!("rustc-codegen-cranelift" => CraneliftCodegenBackend {
1911 compilers: rustc_private_compilers,
1912 target
1913 });
1914 add_component!("llvm-bitcode-linker" => LlvmBitcodeLinker {
1915 build_compiler,
1916 target
1917 });
1918
1919 let etc = builder.src.join("src/etc/installer");
1920
1921 if builder.config.dry_run() {
1923 return;
1924 }
1925
1926 let tarball = Tarball::new(builder, "rust", &target.triple);
1927 let generated = tarball.combine(&tarballs);
1928
1929 let tmp = tmpdir(builder).join("combined-tarball");
1930 let work = generated.work_dir();
1931
1932 let mut license = String::new();
1933 license += &builder.read(&builder.src.join("COPYRIGHT"));
1934 license += &builder.read(&builder.src.join("LICENSE-APACHE"));
1935 license += &builder.read(&builder.src.join("LICENSE-MIT"));
1936 license.push('\n');
1937 license.push('\n');
1938
1939 let rtf = r"{\rtf1\ansi\deff0{\fonttbl{\f0\fnil\fcharset0 Arial;}}\nowwrap\fs18";
1940 let mut rtf = rtf.to_string();
1941 rtf.push('\n');
1942 for line in license.lines() {
1943 rtf.push_str(line);
1944 rtf.push_str("\\line ");
1945 }
1946 rtf.push('}');
1947
1948 fn filter(contents: &str, marker: &str) -> String {
1949 let start = format!("tool-{marker}-start");
1950 let end = format!("tool-{marker}-end");
1951 let mut lines = Vec::new();
1952 let mut omitted = false;
1953 for line in contents.lines() {
1954 if line.contains(&start) {
1955 omitted = true;
1956 } else if line.contains(&end) {
1957 omitted = false;
1958 } else if !omitted {
1959 lines.push(line);
1960 }
1961 }
1962
1963 lines.join("\n")
1964 }
1965
1966 let xform = |p: &Path| {
1967 let mut contents = t!(fs::read_to_string(p));
1968 for tool in &["miri", "rust-docs"] {
1969 if !built_tools.contains(tool) {
1970 contents = filter(&contents, tool);
1971 }
1972 }
1973 let ret = tmp.join(p.file_name().unwrap());
1974 t!(fs::write(&ret, &contents));
1975 ret
1976 };
1977
1978 if target.contains("apple-darwin") {
1979 builder.info("building pkg installer");
1980 let pkg = tmp.join("pkg");
1981 let _ = fs::remove_dir_all(&pkg);
1982
1983 let pkgbuild = |component: &str| {
1984 let mut cmd = command("pkgbuild");
1985 cmd.arg("--identifier")
1986 .arg(format!("org.rust-lang.{component}"))
1987 .arg("--scripts")
1988 .arg(pkg.join(component))
1989 .arg("--nopayload")
1990 .arg(pkg.join(component).with_extension("pkg"));
1991 cmd.run(builder);
1992 };
1993
1994 let prepare = |name: &str| {
1995 builder.create_dir(&pkg.join(name));
1996 builder.cp_link_r(
1997 &work.join(format!("{}-{}", pkgname(builder, name), target.triple)),
1998 &pkg.join(name),
1999 );
2000 builder.install(&etc.join("pkg/postinstall"), &pkg.join(name), FileType::Script);
2001 pkgbuild(name);
2002 };
2003 prepare("rustc");
2004 prepare("cargo");
2005 prepare("rust-std");
2006 prepare("rust-analysis");
2007
2008 for tool in &[
2009 "clippy",
2010 "rustfmt",
2011 "rust-analyzer",
2012 "rust-docs",
2013 "miri",
2014 "rustc-codegen-cranelift",
2015 ] {
2016 if built_tools.contains(tool) {
2017 prepare(tool);
2018 }
2019 }
2020 builder.install(&etc.join("pkg/postinstall"), &pkg.join("uninstall"), FileType::Script);
2022 pkgbuild("uninstall");
2023
2024 builder.create_dir(&pkg.join("res"));
2025 builder.create(&pkg.join("res/LICENSE.txt"), &license);
2026 builder.install(&etc.join("gfx/rust-logo.png"), &pkg.join("res"), FileType::Regular);
2027 let mut cmd = command("productbuild");
2028 cmd.arg("--distribution")
2029 .arg(xform(&etc.join("pkg/Distribution.xml")))
2030 .arg("--resources")
2031 .arg(pkg.join("res"))
2032 .arg(distdir(builder).join(format!(
2033 "{}-{}.pkg",
2034 pkgname(builder, "rust"),
2035 target.triple
2036 )))
2037 .arg("--package-path")
2038 .arg(&pkg);
2039 let _time = timeit(builder);
2040 cmd.run(builder);
2041 }
2042
2043 if target.is_windows() {
2044 let exe = tmp.join("exe");
2045 let _ = fs::remove_dir_all(&exe);
2046
2047 let prepare = |name: &str| {
2048 builder.create_dir(&exe.join(name));
2049 let dir = if name == "rust-std" || name == "rust-analysis" {
2050 format!("{}-{}", name, target.triple)
2051 } else if name == "rust-analyzer" {
2052 "rust-analyzer-preview".to_string()
2053 } else if name == "clippy" {
2054 "clippy-preview".to_string()
2055 } else if name == "rustfmt" {
2056 "rustfmt-preview".to_string()
2057 } else if name == "miri" {
2058 "miri-preview".to_string()
2059 } else if name == "rustc-codegen-cranelift" {
2060 unreachable!("cg_clif shouldn't be built for windows");
2063 } else {
2064 name.to_string()
2065 };
2066 builder.cp_link_r(
2067 &work.join(format!("{}-{}", pkgname(builder, name), target.triple)).join(dir),
2068 &exe.join(name),
2069 );
2070 builder.remove(&exe.join(name).join("manifest.in"));
2071 };
2072 prepare("rustc");
2073 prepare("cargo");
2074 prepare("rust-analysis");
2075 prepare("rust-std");
2076 for tool in &["clippy", "rustfmt", "rust-analyzer", "rust-docs", "miri"] {
2077 if built_tools.contains(tool) {
2078 prepare(tool);
2079 }
2080 }
2081 if target.is_windows_gnu() || target.is_windows_gnullvm() {
2082 prepare("rust-mingw");
2083 }
2084
2085 builder.install(&etc.join("gfx/rust-logo.ico"), &exe, FileType::Regular);
2086
2087 let wix_path = env::var_os("WIX")
2089 .expect("`WIX` environment variable must be set for generating MSI installer(s).");
2090 let wix = PathBuf::from(wix_path);
2091 let heat = wix.join("bin/heat.exe");
2092 let candle = wix.join("bin/candle.exe");
2093 let light = wix.join("bin/light.exe");
2094
2095 let heat_flags = ["-nologo", "-gg", "-sfrag", "-srd", "-sreg"];
2096 command(&heat)
2097 .current_dir(&exe)
2098 .arg("dir")
2099 .arg("rustc")
2100 .args(heat_flags)
2101 .arg("-cg")
2102 .arg("RustcGroup")
2103 .arg("-dr")
2104 .arg("Rustc")
2105 .arg("-var")
2106 .arg("var.RustcDir")
2107 .arg("-out")
2108 .arg(exe.join("RustcGroup.wxs"))
2109 .run(builder);
2110 if built_tools.contains("rust-docs") {
2111 command(&heat)
2112 .current_dir(&exe)
2113 .arg("dir")
2114 .arg("rust-docs")
2115 .args(heat_flags)
2116 .arg("-cg")
2117 .arg("DocsGroup")
2118 .arg("-dr")
2119 .arg("Docs")
2120 .arg("-var")
2121 .arg("var.DocsDir")
2122 .arg("-out")
2123 .arg(exe.join("DocsGroup.wxs"))
2124 .arg("-t")
2125 .arg(etc.join("msi/squash-components.xsl"))
2126 .run(builder);
2127 }
2128 command(&heat)
2129 .current_dir(&exe)
2130 .arg("dir")
2131 .arg("cargo")
2132 .args(heat_flags)
2133 .arg("-cg")
2134 .arg("CargoGroup")
2135 .arg("-dr")
2136 .arg("Cargo")
2137 .arg("-var")
2138 .arg("var.CargoDir")
2139 .arg("-out")
2140 .arg(exe.join("CargoGroup.wxs"))
2141 .arg("-t")
2142 .arg(etc.join("msi/remove-duplicates.xsl"))
2143 .run(builder);
2144 command(&heat)
2145 .current_dir(&exe)
2146 .arg("dir")
2147 .arg("rust-std")
2148 .args(heat_flags)
2149 .arg("-cg")
2150 .arg("StdGroup")
2151 .arg("-dr")
2152 .arg("Std")
2153 .arg("-var")
2154 .arg("var.StdDir")
2155 .arg("-out")
2156 .arg(exe.join("StdGroup.wxs"))
2157 .run(builder);
2158 if built_tools.contains("rust-analyzer") {
2159 command(&heat)
2160 .current_dir(&exe)
2161 .arg("dir")
2162 .arg("rust-analyzer")
2163 .args(heat_flags)
2164 .arg("-cg")
2165 .arg("RustAnalyzerGroup")
2166 .arg("-dr")
2167 .arg("RustAnalyzer")
2168 .arg("-var")
2169 .arg("var.RustAnalyzerDir")
2170 .arg("-out")
2171 .arg(exe.join("RustAnalyzerGroup.wxs"))
2172 .arg("-t")
2173 .arg(etc.join("msi/remove-duplicates.xsl"))
2174 .run(builder);
2175 }
2176 if built_tools.contains("clippy") {
2177 command(&heat)
2178 .current_dir(&exe)
2179 .arg("dir")
2180 .arg("clippy")
2181 .args(heat_flags)
2182 .arg("-cg")
2183 .arg("ClippyGroup")
2184 .arg("-dr")
2185 .arg("Clippy")
2186 .arg("-var")
2187 .arg("var.ClippyDir")
2188 .arg("-out")
2189 .arg(exe.join("ClippyGroup.wxs"))
2190 .arg("-t")
2191 .arg(etc.join("msi/remove-duplicates.xsl"))
2192 .run(builder);
2193 }
2194 if built_tools.contains("rustfmt") {
2195 command(&heat)
2196 .current_dir(&exe)
2197 .arg("dir")
2198 .arg("rustfmt")
2199 .args(heat_flags)
2200 .arg("-cg")
2201 .arg("RustFmtGroup")
2202 .arg("-dr")
2203 .arg("RustFmt")
2204 .arg("-var")
2205 .arg("var.RustFmtDir")
2206 .arg("-out")
2207 .arg(exe.join("RustFmtGroup.wxs"))
2208 .arg("-t")
2209 .arg(etc.join("msi/remove-duplicates.xsl"))
2210 .run(builder);
2211 }
2212 if built_tools.contains("miri") {
2213 command(&heat)
2214 .current_dir(&exe)
2215 .arg("dir")
2216 .arg("miri")
2217 .args(heat_flags)
2218 .arg("-cg")
2219 .arg("MiriGroup")
2220 .arg("-dr")
2221 .arg("Miri")
2222 .arg("-var")
2223 .arg("var.MiriDir")
2224 .arg("-out")
2225 .arg(exe.join("MiriGroup.wxs"))
2226 .arg("-t")
2227 .arg(etc.join("msi/remove-duplicates.xsl"))
2228 .run(builder);
2229 }
2230 command(&heat)
2231 .current_dir(&exe)
2232 .arg("dir")
2233 .arg("rust-analysis")
2234 .args(heat_flags)
2235 .arg("-cg")
2236 .arg("AnalysisGroup")
2237 .arg("-dr")
2238 .arg("Analysis")
2239 .arg("-var")
2240 .arg("var.AnalysisDir")
2241 .arg("-out")
2242 .arg(exe.join("AnalysisGroup.wxs"))
2243 .arg("-t")
2244 .arg(etc.join("msi/remove-duplicates.xsl"))
2245 .run(builder);
2246 if target.is_windows_gnu() || target.is_windows_gnullvm() {
2247 command(&heat)
2248 .current_dir(&exe)
2249 .arg("dir")
2250 .arg("rust-mingw")
2251 .args(heat_flags)
2252 .arg("-cg")
2253 .arg("GccGroup")
2254 .arg("-dr")
2255 .arg("Gcc")
2256 .arg("-var")
2257 .arg("var.GccDir")
2258 .arg("-out")
2259 .arg(exe.join("GccGroup.wxs"))
2260 .run(builder);
2261 }
2262
2263 let candle = |input: &Path| {
2264 let output = exe.join(input.file_stem().unwrap()).with_extension("wixobj");
2265 let arch = if target.contains("x86_64") { "x64" } else { "x86" };
2266 let mut cmd = command(&candle);
2267 cmd.current_dir(&exe)
2268 .arg("-nologo")
2269 .arg("-dRustcDir=rustc")
2270 .arg("-dCargoDir=cargo")
2271 .arg("-dStdDir=rust-std")
2272 .arg("-dAnalysisDir=rust-analysis")
2273 .arg("-arch")
2274 .arg(arch)
2275 .arg("-out")
2276 .arg(&output)
2277 .arg(input);
2278 add_env(builder, &mut cmd, target, &built_tools);
2279
2280 if built_tools.contains("clippy") {
2281 cmd.arg("-dClippyDir=clippy");
2282 }
2283 if built_tools.contains("rustfmt") {
2284 cmd.arg("-dRustFmtDir=rustfmt");
2285 }
2286 if built_tools.contains("rust-docs") {
2287 cmd.arg("-dDocsDir=rust-docs");
2288 }
2289 if built_tools.contains("rust-analyzer") {
2290 cmd.arg("-dRustAnalyzerDir=rust-analyzer");
2291 }
2292 if built_tools.contains("miri") {
2293 cmd.arg("-dMiriDir=miri");
2294 }
2295 if target.is_windows_gnu() || target.is_windows_gnullvm() {
2296 cmd.arg("-dGccDir=rust-mingw");
2297 }
2298 cmd.run(builder);
2299 };
2300 candle(&xform(&etc.join("msi/rust.wxs")));
2301 candle(&etc.join("msi/ui.wxs"));
2302 candle(&etc.join("msi/rustwelcomedlg.wxs"));
2303 candle("RustcGroup.wxs".as_ref());
2304 if built_tools.contains("rust-docs") {
2305 candle("DocsGroup.wxs".as_ref());
2306 }
2307 candle("CargoGroup.wxs".as_ref());
2308 candle("StdGroup.wxs".as_ref());
2309 if built_tools.contains("clippy") {
2310 candle("ClippyGroup.wxs".as_ref());
2311 }
2312 if built_tools.contains("rustfmt") {
2313 candle("RustFmtGroup.wxs".as_ref());
2314 }
2315 if built_tools.contains("miri") {
2316 candle("MiriGroup.wxs".as_ref());
2317 }
2318 if built_tools.contains("rust-analyzer") {
2319 candle("RustAnalyzerGroup.wxs".as_ref());
2320 }
2321 candle("AnalysisGroup.wxs".as_ref());
2322
2323 if target.is_windows_gnu() || target.is_windows_gnullvm() {
2324 candle("GccGroup.wxs".as_ref());
2325 }
2326
2327 builder.create(&exe.join("LICENSE.rtf"), &rtf);
2328 builder.install(&etc.join("gfx/banner.bmp"), &exe, FileType::Regular);
2329 builder.install(&etc.join("gfx/dialogbg.bmp"), &exe, FileType::Regular);
2330
2331 builder.info(&format!("building `msi` installer with {light:?}"));
2332 let filename = format!("{}-{}.msi", pkgname(builder, "rust"), target.triple);
2333 let mut cmd = command(&light);
2334 cmd.arg("-nologo")
2335 .arg("-ext")
2336 .arg("WixUIExtension")
2337 .arg("-ext")
2338 .arg("WixUtilExtension")
2339 .arg("-out")
2340 .arg(exe.join(&filename))
2341 .arg("rust.wixobj")
2342 .arg("ui.wixobj")
2343 .arg("rustwelcomedlg.wixobj")
2344 .arg("RustcGroup.wixobj")
2345 .arg("CargoGroup.wixobj")
2346 .arg("StdGroup.wixobj")
2347 .arg("AnalysisGroup.wixobj")
2348 .current_dir(&exe);
2349
2350 if built_tools.contains("clippy") {
2351 cmd.arg("ClippyGroup.wixobj");
2352 }
2353 if built_tools.contains("rustfmt") {
2354 cmd.arg("RustFmtGroup.wixobj");
2355 }
2356 if built_tools.contains("miri") {
2357 cmd.arg("MiriGroup.wixobj");
2358 }
2359 if built_tools.contains("rust-analyzer") {
2360 cmd.arg("RustAnalyzerGroup.wixobj");
2361 }
2362 if built_tools.contains("rust-docs") {
2363 cmd.arg("DocsGroup.wixobj");
2364 }
2365
2366 if target.is_windows_gnu() || target.is_windows_gnullvm() {
2367 cmd.arg("GccGroup.wixobj");
2368 }
2369 cmd.arg("-sice:ICE57");
2371
2372 let _time = timeit(builder);
2373 cmd.run(builder);
2374
2375 if !builder.config.dry_run() {
2376 t!(move_file(exe.join(&filename), distdir(builder).join(&filename)));
2377 }
2378 }
2379 }
2380
2381 fn metadata(&self) -> Option<StepMetadata> {
2382 Some(StepMetadata::dist("extended", self.target).built_by(self.build_compiler))
2383 }
2384}
2385
2386fn add_env(
2387 builder: &Builder<'_>,
2388 cmd: &mut BootstrapCommand,
2389 target: TargetSelection,
2390 built_tools: &HashSet<&'static str>,
2391) {
2392 let mut parts = builder.version.split('.');
2393 cmd.env("CFG_RELEASE_INFO", builder.rust_version())
2394 .env("CFG_RELEASE_NUM", &builder.version)
2395 .env("CFG_RELEASE", builder.rust_release())
2396 .env("CFG_VER_MAJOR", parts.next().unwrap())
2397 .env("CFG_VER_MINOR", parts.next().unwrap())
2398 .env("CFG_VER_PATCH", parts.next().unwrap())
2399 .env("CFG_VER_BUILD", "0") .env("CFG_PACKAGE_VERS", builder.rust_package_vers())
2401 .env("CFG_PACKAGE_NAME", pkgname(builder, "rust"))
2402 .env("CFG_BUILD", target.triple)
2403 .env("CFG_CHANNEL", &builder.config.channel);
2404
2405 if target.is_windows_gnullvm() {
2406 cmd.env("CFG_MINGW", "1").env("CFG_ABI", "LLVM");
2407 } else if target.is_windows_gnu() {
2408 cmd.env("CFG_MINGW", "1").env("CFG_ABI", "GNU");
2409 } else {
2410 cmd.env("CFG_MINGW", "0").env("CFG_ABI", "MSVC");
2411 }
2412
2413 let mut define_optional_tool = |tool_name: &str, env_name: &str| {
2415 cmd.env(env_name, if built_tools.contains(tool_name) { "1" } else { "0" });
2416 };
2417 define_optional_tool("rustfmt", "CFG_RUSTFMT");
2418 define_optional_tool("clippy", "CFG_CLIPPY");
2419 define_optional_tool("miri", "CFG_MIRI");
2420 define_optional_tool("rust-analyzer", "CFG_RA");
2421}
2422
2423fn install_llvm_file(
2424 builder: &Builder<'_>,
2425 source: &Path,
2426 destination: &Path,
2427 install_symlink: bool,
2428) {
2429 if builder.config.dry_run() {
2430 return;
2431 }
2432
2433 if source.is_symlink() {
2434 builder.install(&t!(fs::canonicalize(source)), destination, FileType::NativeLibrary);
2437
2438 let full_dest = destination.join(source.file_name().unwrap());
2439 if install_symlink {
2440 builder.copy_link(source, &full_dest, FileType::NativeLibrary);
2443 } else {
2444 let link = t!(fs::read_link(source));
2448 let mut linker_script = t!(fs::File::create(full_dest));
2449 t!(write!(linker_script, "INPUT({})\n", link.display()));
2450
2451 let meta = t!(fs::metadata(source));
2454 if let Ok(mtime) = meta.modified() {
2455 t!(linker_script.set_modified(mtime));
2456 }
2457 }
2458 } else {
2459 builder.install(source, destination, FileType::NativeLibrary);
2460 }
2461}
2462
2463#[cfg_attr(
2467 feature = "tracing",
2468 instrument(
2469 level = "trace",
2470 name = "maybe_install_llvm",
2471 skip_all,
2472 fields(target = ?target, dst_libdir = ?dst_libdir, install_symlink = install_symlink),
2473 ),
2474)]
2475fn maybe_install_llvm(
2476 builder: &Builder<'_>,
2477 target: TargetSelection,
2478 dst_libdir: &Path,
2479 install_symlink: bool,
2480) -> bool {
2481 if builder.config.is_system_llvm(target) {
2498 trace!("system LLVM requested, no install");
2499 return false;
2500 }
2501
2502 if target.contains("apple-darwin") && builder.llvm_link_shared() {
2508 let src_libdir = builder.llvm_out(target).join("lib");
2509 let llvm_dylib_path = src_libdir.join("libLLVM.dylib");
2510 if llvm_dylib_path.exists() {
2511 builder.install(&llvm_dylib_path, dst_libdir, FileType::NativeLibrary);
2512
2513 if install_symlink && let Some(llvm_config_path) = &builder.llvm_config(target) {
2514 let major = llvm::get_llvm_version_major(builder, llvm_config_path);
2515 let versioned_name = match &builder.config.llvm_version_suffix {
2516 Some(version_suffix) => format!("libLLVM-{major}{version_suffix}.dylib"),
2517 None => {
2518 if builder.config.channel == "dev" {
2520 format!("libLLVM-{major}-rust-dev.dylib")
2521 } else {
2522 format!(
2523 "libLLVM-{major}-rust-{}-{}.dylib",
2524 builder.version, builder.config.channel
2525 )
2526 }
2527 }
2528 };
2529 t!(builder.symlink_file("libLLVM.dylib", dst_libdir.join(versioned_name)));
2530 }
2531 }
2532 !builder.config.dry_run()
2533 } else if let llvm::LlvmBuildStatus::AlreadyBuilt(llvm::LlvmOutput {
2534 host_llvm_config, ..
2535 }) = llvm::prebuilt_llvm_config(builder, target, true)
2536 {
2537 trace!("LLVM already built, installing LLVM files");
2538 let mut cmd = command(host_llvm_config);
2539 cmd.cached();
2540 cmd.arg("--libfiles");
2541 builder.do_if_verbose(|| println!("running {cmd:?}"));
2542 let files = cmd.run_capture_stdout(builder).stdout();
2543 let build_llvm_out = &builder.llvm_out(builder.config.host_target);
2544 let target_llvm_out = &builder.llvm_out(target);
2545 for file in files.trim_end().split(' ') {
2546 let file = if let Ok(relative_path) = Path::new(file).strip_prefix(build_llvm_out) {
2548 target_llvm_out.join(relative_path)
2549 } else {
2550 PathBuf::from(file)
2551 };
2552 install_llvm_file(builder, &file, dst_libdir, install_symlink);
2553 }
2554 !builder.config.dry_run()
2555 } else {
2556 false
2557 }
2558}
2559
2560#[cfg_attr(
2562 feature = "tracing",
2563 instrument(
2564 level = "trace",
2565 name = "maybe_install_llvm_target",
2566 skip_all,
2567 fields(
2568 llvm_link_shared = ?builder.llvm_link_shared(),
2569 target = ?target,
2570 sysroot = ?sysroot,
2571 ),
2572 ),
2573)]
2574pub fn maybe_install_llvm_target(builder: &Builder<'_>, target: TargetSelection, sysroot: &Path) {
2575 let dst_libdir = sysroot.join("lib/rustlib").join(target).join("lib");
2576 if builder.llvm_link_shared() {
2580 maybe_install_llvm(builder, target, &dst_libdir, false);
2581 }
2582}
2583
2584#[cfg_attr(
2586 feature = "tracing",
2587 instrument(
2588 level = "trace",
2589 name = "maybe_install_llvm_runtime",
2590 skip_all,
2591 fields(
2592 llvm_link_shared = ?builder.llvm_link_shared(),
2593 target = ?target,
2594 sysroot = ?sysroot,
2595 ),
2596 ),
2597)]
2598pub fn maybe_install_llvm_runtime(builder: &Builder<'_>, target: TargetSelection, sysroot: &Path) {
2599 let dst_libdir = sysroot.join(builder.libdir_relative(Compiler::new(1, target)));
2600 if builder.llvm_link_shared() {
2604 maybe_install_llvm(builder, target, &dst_libdir, false);
2605
2606 if target.triple.contains("windows") {
2610 let dst_libdir = sysroot.join("lib/rustlib").join(target).join("bin");
2611 maybe_install_llvm(builder, target, &dst_libdir, false);
2612 }
2613 }
2614}
2615
2616#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2617pub struct LlvmTools {
2618 pub target: TargetSelection,
2619}
2620
2621impl CommandLineStep for LlvmTools {
2622 type Output = Option<GeneratedTarball>;
2623 const IS_HOST: bool = true;
2624
2625 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2626 let mut run = run.alias("llvm-tools");
2627 for tool in LLVM_TOOLS {
2628 run = run.alias(tool);
2629 }
2630
2631 run
2632 }
2633
2634 fn is_default_step(builder: &Builder<'_>) -> bool {
2635 should_build_extended_tool(builder, "llvm-tools")
2636 }
2637
2638 fn make_run(run: RunConfig<'_>) {
2639 run.builder.ensure(LlvmTools { target: run.target });
2640 }
2641
2642 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2643 fn tools_to_install(paths: &[PathBuf]) -> Vec<&'static str> {
2644 let mut tools = vec![];
2645
2646 for path in paths {
2647 let path = path.to_str().unwrap();
2648
2649 if path == "llvm-tools" {
2651 return LLVM_TOOLS.to_owned();
2652 }
2653
2654 for tool in LLVM_TOOLS {
2655 if path == *tool {
2656 tools.push(*tool);
2657 }
2658 }
2659 }
2660
2661 if tools.is_empty() {
2663 tools = LLVM_TOOLS.to_owned();
2664 }
2665
2666 tools
2667 }
2668
2669 let target = self.target;
2670
2671 if let Some(config) = builder.config.target_config.get(&target)
2673 && !builder.config.llvm_from_ci
2674 && config.llvm_config.is_some()
2675 {
2676 builder.info(&format!("Skipping LlvmTools ({target}): external LLVM"));
2677 return None;
2678 }
2679
2680 if !builder.config.dry_run() {
2681 builder.require_submodule("src/llvm-project", None);
2682 }
2683
2684 let llvm_output = builder.ensure(crate::core::build_steps::llvm::Llvm { target });
2685
2686 let mut tarball = Tarball::new(builder, "llvm-tools", &target.triple);
2687 tarball.set_overlay(OverlayKind::Llvm);
2688 tarball.is_preview(true);
2689
2690 if builder.config.llvm_tools_enabled {
2691 let src_bindir = llvm_output.root_dir().join("bin");
2693 let dst_bindir = format!("lib/rustlib/{}/bin", target.triple);
2694 for tool in tools_to_install(&builder.paths) {
2695 let exe = src_bindir.join(exe(tool, target));
2696 if !exe.exists() && builder.config.llvm_from_ci {
2698 eprintln!("{} does not exist; skipping copy", exe.display());
2699 continue;
2700 }
2701
2702 tarball.add_file(&exe, &dst_bindir, FileType::Executable);
2703 }
2704 }
2705
2706 maybe_install_llvm_target(builder, target, tarball.image_dir());
2711
2712 Some(tarball.generate())
2713 }
2714}
2715
2716#[derive(Debug, Clone, Hash, PartialEq, Eq)]
2719pub struct LlvmBitcodeLinker {
2720 pub build_compiler: Compiler,
2722 pub target: TargetSelection,
2724}
2725
2726impl CommandLineStep for LlvmBitcodeLinker {
2727 type Output = Option<GeneratedTarball>;
2728 const IS_HOST: bool = true;
2729
2730 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2731 run.alias("llvm-bitcode-linker")
2732 }
2733
2734 fn is_default_step(builder: &Builder<'_>) -> bool {
2735 should_build_extended_tool(builder, "llvm-bitcode-linker")
2736 }
2737
2738 fn make_run(run: RunConfig<'_>) {
2739 run.builder.ensure(LlvmBitcodeLinker {
2740 build_compiler: tool::LlvmBitcodeLinker::get_build_compiler_for_target(
2741 run.builder,
2742 run.target,
2743 ),
2744 target: run.target,
2745 });
2746 }
2747
2748 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2749 let target = self.target;
2750
2751 let llbc_linker = builder
2752 .ensure(tool::LlvmBitcodeLinker::from_build_compiler(self.build_compiler, target));
2753
2754 let self_contained_bin_dir = format!("lib/rustlib/{}/bin/self-contained", target.triple);
2755
2756 let mut tarball = Tarball::new(builder, "llvm-bitcode-linker", &target.triple);
2758 tarball.set_overlay(OverlayKind::LlvmBitcodeLinker);
2759 tarball.is_preview(true);
2760
2761 tarball.add_file(&llbc_linker.tool_path, self_contained_bin_dir, FileType::Executable);
2762
2763 Some(tarball.generate())
2764 }
2765}
2766
2767#[derive(Debug, Clone, Hash, PartialEq, Eq)]
2770pub struct Enzyme {
2771 pub target: TargetSelection,
2773}
2774
2775impl CommandLineStep for Enzyme {
2776 type Output = Option<GeneratedTarball>;
2777 const IS_HOST: bool = true;
2778
2779 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2780 run.alias("enzyme")
2781 }
2782
2783 fn is_default_step(builder: &Builder<'_>) -> bool {
2784 builder.config.llvm_enzyme
2785 }
2786
2787 fn make_run(run: RunConfig<'_>) {
2788 run.builder.ensure(Enzyme { target: run.target });
2789 }
2790
2791 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2792 if !builder.build.unstable_features() {
2796 return None;
2797 }
2798
2799 let target = self.target;
2800
2801 let enzyme = builder.ensure(llvm::Enzyme { target });
2802
2803 let target_libdir = format!("lib/rustlib/{}/lib", target.triple);
2804
2805 let mut tarball = Tarball::new(builder, "enzyme", &target.triple);
2807 tarball.set_overlay(OverlayKind::Enzyme);
2808 tarball.is_preview(true);
2809
2810 tarball.add_file(enzyme.enzyme_path(), target_libdir, FileType::NativeLibrary);
2811
2812 Some(tarball.generate())
2813 }
2814}
2815
2816#[derive(Debug, Clone, Hash, PartialEq, Eq)]
2817pub struct Offload {
2818 pub target: TargetSelection,
2819}
2820
2821impl CommandLineStep for Offload {
2822 type Output = Option<GeneratedTarball>;
2823 const IS_HOST: bool = true;
2824
2825 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2826 run.alias("offload")
2827 }
2828
2829 fn is_default_step(builder: &Builder<'_>) -> bool {
2830 builder.config.llvm_offload
2831 }
2832
2833 fn make_run(run: RunConfig<'_>) {
2834 run.builder.ensure(Offload { target: run.target });
2835 }
2836
2837 fn run(self, builder: &Builder<'_>) -> Self::Output {
2838 if !builder.unstable_features() {
2839 return None;
2840 }
2841
2842 let target = self.target;
2843
2844 let omp_offload = builder.ensure(llvm::OmpOffload { target });
2845 let rust_offload = builder.ensure(llvm::RustOffload { target });
2846
2847 if builder.config.dry_run() {
2848 return None;
2849 }
2850
2851 let target_libdir = PathBuf::from(format!("lib/rustlib/{}/lib", target.triple));
2852
2853 let mut tarball = Tarball::new(builder, "offload", &target.triple);
2854 tarball.set_overlay(OverlayKind::Offload);
2855 tarball.is_preview(true);
2856
2857 let omp_offload_libdir = builder.out.join(target).join("offload").join("lib");
2858
2859 for path in omp_offload.artifact_paths_with_symlink_targets() {
2860 let relative = t!(path.strip_prefix(&omp_offload_libdir));
2861 let destdir = target_libdir.join(relative.parent().unwrap());
2862
2863 tarball.add_file(path, destdir, FileType::NativeLibrary);
2864 }
2865
2866 tarball.add_file(rust_offload.rust_offload_path(), target_libdir, FileType::NativeLibrary);
2867
2868 Some(tarball.generate())
2869 }
2870}
2871
2872#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2881pub struct RustDev {
2882 pub target: TargetSelection,
2883}
2884
2885impl CommandLineStep for RustDev {
2886 type Output = Option<GeneratedTarball>;
2887 const IS_HOST: bool = true;
2888
2889 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2890 run.alias("rust-dev")
2891 }
2892
2893 fn is_default_step(_builder: &Builder<'_>) -> bool {
2894 true
2895 }
2896
2897 fn make_run(run: RunConfig<'_>) {
2898 run.builder.ensure(RustDev { target: run.target });
2899 }
2900
2901 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2902 let target = self.target;
2903
2904 if let Some(config) = builder.config.target_config.get(&target)
2906 && let Some(ref _s) = config.llvm_config
2907 {
2908 builder.info(&format!("Skipping RustDev ({target}): external LLVM"));
2909 return None;
2910 }
2911
2912 if !builder.config.dry_run() {
2913 builder.require_submodule("src/llvm-project", None);
2914 }
2915
2916 let mut tarball = Tarball::new(builder, "rust-dev", &target.triple);
2917 tarball.set_overlay(OverlayKind::Llvm);
2918 tarball.permit_symlinks(true);
2920
2921 let llvm_output = builder.ensure(crate::core::build_steps::llvm::Llvm { target });
2922
2923 let src_bindir = llvm_output.root_dir().join("bin");
2924 if src_bindir.exists() {
2930 for entry in walkdir::WalkDir::new(&src_bindir) {
2931 let entry = t!(entry);
2932 if entry.file_type().is_file() && !entry.path_is_symlink() {
2933 let name = entry.file_name().to_str().unwrap();
2934 tarball.add_file(src_bindir.join(name), "bin", FileType::Executable);
2935 }
2936 }
2937 }
2938
2939 if builder.config.lld_enabled {
2940 let lld_out = builder.ensure(crate::core::build_steps::llvm::Lld { target });
2942
2943 let lld_path = lld_out.join("bin").join(exe("lld", target));
2945 if lld_path.exists() {
2946 tarball.add_file(&lld_path, "bin", FileType::Executable);
2947 }
2948 }
2949
2950 let filecheck = builder.ensure(llvm::FileCheck { target });
2951 tarball.add_file(filecheck, "bin", FileType::Executable);
2952
2953 tarball.add_dir(llvm_output.root_dir().join("include"), "include");
2957
2958 let dst_libdir = tarball.image_dir().join("lib");
2963 maybe_install_llvm(builder, target, &dst_libdir, true);
2964 let link_type = if builder.llvm_link_shared() { "dynamic" } else { "static" };
2965 t!(std::fs::write(tarball.image_dir().join("link-type.txt"), link_type), dst_libdir);
2966
2967 copy_src_dirs(
2971 builder,
2972 &builder.src.join("src").join("llvm-project"),
2973 &["compiler-rt"],
2974 &["compiler-rt/test"],
2977 tarball.image_dir(),
2978 );
2979
2980 Some(tarball.generate())
2981 }
2982}
2983
2984#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2990pub struct Bootstrap {
2991 target: TargetSelection,
2992}
2993
2994impl CommandLineStep for Bootstrap {
2995 type Output = Option<GeneratedTarball>;
2996
2997 const IS_HOST: bool = true;
2998
2999 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3000 run.alias("bootstrap")
3001 }
3002
3003 fn make_run(run: RunConfig<'_>) {
3004 run.builder.ensure(Bootstrap { target: run.target });
3005 }
3006
3007 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
3008 let target = self.target;
3009
3010 let tarball = Tarball::new(builder, "bootstrap", &target.triple);
3011
3012 let bootstrap_outdir = &builder.bootstrap_out;
3013 for file in &["bootstrap", "rustc", "rustdoc"] {
3014 tarball.add_file(
3015 bootstrap_outdir.join(exe(file, target)),
3016 "bootstrap/bin",
3017 FileType::Executable,
3018 );
3019 }
3020
3021 Some(tarball.generate())
3022 }
3023
3024 fn metadata(&self) -> Option<StepMetadata> {
3025 Some(StepMetadata::dist("bootstrap", self.target))
3026 }
3027}
3028
3029#[derive(Clone, Debug, Eq, Hash, PartialEq)]
3034pub struct BuildManifest {
3035 target: TargetSelection,
3036}
3037
3038impl CommandLineStep for BuildManifest {
3039 type Output = GeneratedTarball;
3040
3041 const IS_HOST: bool = true;
3042
3043 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3044 run.alias("build-manifest")
3045 }
3046
3047 fn make_run(run: RunConfig<'_>) {
3048 run.builder.ensure(BuildManifest { target: run.target });
3049 }
3050
3051 fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
3052 let build_manifest =
3056 builder.ensure(tool::BuildManifest::new(builder, builder.config.host_target));
3057
3058 let tarball = Tarball::new(builder, "build-manifest", &self.target.triple);
3059 tarball.add_file(&build_manifest.tool_path, "bin", FileType::Executable);
3060 tarball.generate()
3061 }
3062
3063 fn metadata(&self) -> Option<StepMetadata> {
3064 Some(StepMetadata::dist("build-manifest", self.target))
3065 }
3066}
3067
3068#[derive(Clone, Debug, Eq, Hash, PartialEq)]
3074pub struct ReproducibleArtifacts {
3075 target: TargetSelection,
3076}
3077
3078impl CommandLineStep for ReproducibleArtifacts {
3079 type Output = Option<GeneratedTarball>;
3080 const IS_HOST: bool = true;
3081
3082 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3083 run.alias("reproducible-artifacts")
3084 }
3085
3086 fn is_default_step(_builder: &Builder<'_>) -> bool {
3087 true
3088 }
3089
3090 fn make_run(run: RunConfig<'_>) {
3091 run.builder.ensure(ReproducibleArtifacts { target: run.target });
3092 }
3093
3094 fn run(self, builder: &Builder<'_>) -> Self::Output {
3095 let mut added_anything = false;
3096 let tarball = Tarball::new(builder, "reproducible-artifacts", &self.target.triple);
3097
3098 let pgo_profiles = [
3099 &builder.config.rust_pgo.use_profile,
3100 &builder.config.llvm_pgo.use_profile,
3101 &builder.config.rustdoc_pgo.use_profile,
3102 &builder.config.cargo_pgo.use_profile,
3103 ];
3104 for profile in pgo_profiles {
3105 if let Some(path) = profile.as_ref() {
3106 tarball.add_file(path, ".", FileType::Regular);
3107 added_anything = true;
3108 }
3109 }
3110 for profile in &builder.config.reproducible_artifacts {
3111 tarball.add_file(profile, ".", FileType::Regular);
3112 added_anything = true;
3113 }
3114 if added_anything { Some(tarball.generate()) } else { None }
3115 }
3116
3117 fn metadata(&self) -> Option<StepMetadata> {
3118 Some(StepMetadata::dist("reproducible-artifacts", self.target))
3119 }
3120}
3121
3122#[derive(Clone, Debug, Eq, Hash, PartialEq)]
3128pub struct GccDev {
3129 target: TargetSelection,
3130}
3131
3132impl CommandLineStep for GccDev {
3133 type Output = GeneratedTarball;
3134
3135 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3136 run.alias("gcc-dev")
3137 }
3138
3139 fn make_run(run: RunConfig<'_>) {
3140 run.builder.ensure(GccDev { target: run.target });
3141 }
3142
3143 fn run(self, builder: &Builder<'_>) -> Self::Output {
3144 let tarball = Tarball::new(builder, "gcc-dev", &self.target.triple);
3145 let output = builder
3146 .ensure(super::gcc::Gcc { target_pair: GccTargetPair::for_native_build(self.target) });
3147 tarball.add_file(output.libgccjit(), "lib", FileType::NativeLibrary);
3148 tarball.generate()
3149 }
3150
3151 fn metadata(&self) -> Option<StepMetadata> {
3152 Some(StepMetadata::dist("gcc-dev", self.target))
3153 }
3154}
3155
3156#[derive(Clone, Debug, Eq, Hash, PartialEq)]
3162pub struct Gcc {
3163 host: TargetSelection,
3164 target: TargetSelection,
3165}
3166
3167impl CommandLineStep for Gcc {
3168 type Output = Option<GeneratedTarball>;
3169
3170 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3171 run.alias("gcc")
3172 }
3173
3174 fn make_run(run: RunConfig<'_>) {
3175 run.builder.ensure(Gcc { host: run.builder.host_target, target: run.target });
3179 }
3180
3181 fn run(self, builder: &Builder<'_>) -> Self::Output {
3182 if !builder.build.unstable_features() {
3186 return None;
3187 }
3188
3189 let host = self.host;
3190 let target = self.target;
3191 if host != "x86_64-unknown-linux-gnu" {
3192 builder.info(&format!("host target `{host}` not supported by gcc. skipping"));
3193 return None;
3194 }
3195
3196 if builder.config.is_running_on_ci() {
3197 assert_eq!(
3198 builder.config.gcc_ci_mode,
3199 GccCiMode::BuildLocally,
3200 "Cannot use gcc.download-ci-gcc when distributing GCC on CI"
3201 );
3202 }
3203
3204 builder.require_submodule(
3207 "src/gcc",
3208 Some("The src/gcc submodule is required for disting libgccjit"),
3209 );
3210
3211 let target_pair = GccTargetPair::for_target_pair(host, target);
3212 let libgccjit = builder.ensure(super::gcc::Gcc { target_pair });
3213
3214 let mut tarball = Tarball::new(builder, &format!("gcc-{target}"), &host.triple);
3218 tarball.set_overlay(OverlayKind::Gcc);
3219 tarball.is_preview(true);
3220 tarball.add_legal_and_readme_to("share/doc/gcc");
3221
3222 let cg_dir = PathBuf::from(format!("lib/rustlib/{host}/codegen-backends"));
3227
3228 let rel_libgccjit_path = libgccjit_path_relative_to_cg_dir(&target_pair, &libgccjit);
3230 let path = cg_dir.join(rel_libgccjit_path.parent().unwrap());
3231
3232 tarball.add_file(libgccjit.libgccjit(), path, FileType::NativeLibrary);
3233 Some(tarball.generate())
3234 }
3235
3236 fn metadata(&self) -> Option<StepMetadata> {
3237 Some(StepMetadata::dist(
3238 "gcc",
3239 TargetSelection::from_user(&format!("({}, {})", self.host, self.target)),
3240 ))
3241 }
3242}