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_DIR, Vendor};
31use crate::core::build_steps::{compile, llvm};
32use crate::core::builder::{Builder, Kind, RunConfig, ShouldRun, Step, StepMetadata};
33use crate::core::config::{GccCiMode, TargetSelection};
34use crate::utils::build_stamp::{self, BuildStamp};
35use crate::utils::channel::{self, Info};
36use crate::utils::exec::{BootstrapCommand, command};
37use crate::utils::helpers::{
38 exe, is_dylib, move_file, t, target_supports_cranelift_backend, timeit,
39};
40use crate::utils::tarball::{GeneratedTarball, OverlayKind, Tarball};
41use crate::{CodegenBackendKind, Compiler, DependencyType, FileType, LLVM_TOOLS, Mode, trace};
42
43pub fn pkgname(builder: &Builder<'_>, component: &str) -> String {
44 format!("{}-{}", component, builder.rust_package_vers())
45}
46
47pub(crate) fn distdir(builder: &Builder<'_>) -> PathBuf {
48 builder.out.join("dist")
49}
50
51pub fn tmpdir(builder: &Builder<'_>) -> PathBuf {
52 builder.out.join("tmp/dist")
53}
54
55fn should_build_extended_tool(builder: &Builder<'_>, tool: &str) -> bool {
56 if !builder.config.extended {
57 return false;
58 }
59 builder.config.tools.as_ref().is_none_or(|tools| tools.contains(tool))
60}
61
62#[derive(Debug, Clone, Hash, PartialEq, Eq)]
63pub struct Docs {
64 pub host: TargetSelection,
65}
66
67impl Step for Docs {
68 type Output = Option<GeneratedTarball>;
69
70 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
71 run.alias("rust-docs")
72 }
73
74 fn is_default_step(builder: &Builder<'_>) -> bool {
75 builder.config.docs
76 }
77
78 fn make_run(run: RunConfig<'_>) {
79 run.builder.ensure(Docs { host: run.target });
80 }
81
82 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
84 let host = self.host;
85 builder.run_default_doc_steps();
89
90 if !builder.config.dry_run() {
93 t!(fs::create_dir_all(builder.doc_out(host)));
94 }
95
96 let dest = "share/doc/rust/html";
97
98 let mut tarball = Tarball::new(builder, "rust-docs", &host.triple);
99 tarball.set_product_name("Rust Documentation");
100 tarball.add_bulk_dir(builder.doc_out(host), dest);
101 tarball.add_file(builder.src.join("src/doc/robots.txt"), dest, FileType::Regular);
102 tarball.add_file(builder.src.join("src/doc/sitemap.txt"), dest, FileType::Regular);
103 Some(tarball.generate())
104 }
105
106 fn metadata(&self) -> Option<StepMetadata> {
107 Some(StepMetadata::dist("docs", self.host))
108 }
109}
110
111#[derive(Debug, Clone, Hash, PartialEq, Eq)]
114pub struct JsonDocs {
115 build_compiler: Compiler,
116 target: TargetSelection,
117}
118
119impl Step for JsonDocs {
120 type Output = Option<GeneratedTarball>;
121
122 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
123 run.alias("rust-docs-json")
124 }
125
126 fn is_default_step(builder: &Builder<'_>) -> bool {
127 builder.config.docs
128 }
129
130 fn make_run(run: RunConfig<'_>) {
131 run.builder.ensure(JsonDocs {
132 build_compiler: run.builder.compiler_for_std(run.builder.top_stage),
133 target: run.target,
134 });
135 }
136
137 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
138 let target = self.target;
139 let directory = builder.ensure(crate::core::build_steps::doc::Std::from_build_compiler(
140 self.build_compiler,
141 target,
142 DocumentationFormat::Json,
143 ));
144
145 let dest = "share/doc/rust/json";
146
147 let mut tarball = Tarball::new(builder, "rust-docs-json", &target.triple);
148 tarball.set_product_name("Rust Documentation In JSON Format");
149 tarball.is_preview(true);
150 tarball.add_bulk_dir(directory, dest);
151 Some(tarball.generate())
152 }
153
154 fn metadata(&self) -> Option<StepMetadata> {
155 Some(StepMetadata::dist("json-docs", self.target).built_by(self.build_compiler))
156 }
157}
158
159#[derive(Debug, Clone, Hash, PartialEq, Eq)]
166pub struct RustcDocs {
167 target: TargetSelection,
168}
169
170impl Step for RustcDocs {
171 type Output = GeneratedTarball;
172 const IS_HOST: bool = true;
173
174 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
175 run.alias("rustc-docs")
176 }
177
178 fn is_default_step(builder: &Builder<'_>) -> bool {
179 builder.config.compiler_docs
180 }
181
182 fn make_run(run: RunConfig<'_>) {
183 run.builder.ensure(RustcDocs { target: run.target });
184 }
185
186 fn run(self, builder: &Builder<'_>) -> Self::Output {
187 let target = self.target;
188 builder.run_default_doc_steps();
189
190 let mut tarball = Tarball::new(builder, "rustc-docs", &target.triple);
191 tarball.set_product_name("Rustc Documentation");
192 tarball.add_bulk_dir(builder.compiler_doc_out(target), "share/doc/rust/html/rustc-docs");
193 tarball.generate()
194 }
195}
196
197fn find_files(files: &[&str], path: &[PathBuf]) -> Vec<PathBuf> {
198 let mut found = Vec::with_capacity(files.len());
199
200 for file in files {
201 let file_path = path.iter().map(|dir| dir.join(file)).find(|p| p.exists());
202
203 if let Some(file_path) = file_path {
204 found.push(file_path);
205 } else {
206 panic!("Could not find '{file}' in {path:?}");
207 }
208 }
209
210 found
211}
212
213fn make_win_dist(plat_root: &Path, target: TargetSelection, builder: &Builder<'_>) {
214 if builder.config.dry_run() {
215 return;
216 }
217
218 let (bin_path, lib_path) = get_cc_search_dirs(target, builder);
219
220 let compiler = if target == "i686-pc-windows-gnu" {
221 "i686-w64-mingw32-gcc.exe"
222 } else if target == "x86_64-pc-windows-gnu" {
223 "x86_64-w64-mingw32-gcc.exe"
224 } else {
225 "gcc.exe"
226 };
227 let target_tools = [compiler, "ld.exe", "dlltool.exe", "libwinpthread-1.dll"];
228
229 let target_libs = [
232 "libgcc.a",
234 "libgcc_eh.a",
235 "libgcc_s.a",
236 "libm.a",
237 "libmingw32.a",
238 "libmingwex.a",
239 "libstdc++.a",
240 "libiconv.a",
241 "libmoldname.a",
242 "libpthread.a",
243 "libadvapi32.a",
248 "libbcrypt.a",
249 "libcomctl32.a",
250 "libcomdlg32.a",
251 "libcredui.a",
252 "libcrypt32.a",
253 "libdbghelp.a",
254 "libgdi32.a",
255 "libimagehlp.a",
256 "libiphlpapi.a",
257 "libkernel32.a",
258 "libmsimg32.a",
259 "libmsvcrt.a",
260 "libntdll.a",
261 "libodbc32.a",
262 "libole32.a",
263 "liboleaut32.a",
264 "libopengl32.a",
265 "libpsapi.a",
266 "librpcrt4.a",
267 "libsecur32.a",
268 "libsetupapi.a",
269 "libshell32.a",
270 "libsynchronization.a",
271 "libuser32.a",
272 "libuserenv.a",
273 "libuuid.a",
274 "libwinhttp.a",
275 "libwinmm.a",
276 "libwinspool.a",
277 "libws2_32.a",
278 "libwsock32.a",
279 ];
280
281 let target_tools = find_files(&target_tools, &bin_path);
283 let target_libs = find_files(&target_libs, &lib_path);
284
285 let plat_target_bin_self_contained_dir =
287 plat_root.join("lib/rustlib").join(target).join("bin/self-contained");
288 fs::create_dir_all(&plat_target_bin_self_contained_dir)
289 .expect("creating plat_target_bin_self_contained_dir failed");
290 for src in target_tools {
291 builder.copy_link_to_folder(&src, &plat_target_bin_self_contained_dir);
292 }
293
294 builder.create(
296 &plat_target_bin_self_contained_dir.join("GCC-WARNING.txt"),
297 "gcc.exe contained in this folder cannot be used for compiling C files - it is only \
298 used as a linker. In order to be able to compile projects containing C code use \
299 the GCC provided by MinGW or Cygwin.",
300 );
301
302 let plat_target_lib_self_contained_dir =
304 plat_root.join("lib/rustlib").join(target).join("lib/self-contained");
305 fs::create_dir_all(&plat_target_lib_self_contained_dir)
306 .expect("creating plat_target_lib_self_contained_dir failed");
307 for src in target_libs {
308 builder.copy_link_to_folder(&src, &plat_target_lib_self_contained_dir);
309 }
310}
311
312fn make_win_llvm_dist(plat_root: &Path, target: TargetSelection, builder: &Builder<'_>) {
313 if builder.config.dry_run() {
314 return;
315 }
316
317 let (_, lib_path) = get_cc_search_dirs(target, builder);
318
319 let target_libs = [
322 "libunwind.a",
324 "libunwind.dll.a",
325 "libmingw32.a",
326 "libmingwex.a",
327 "libmsvcrt.a",
328 "libkernel32.a",
330 "libuser32.a",
331 "libntdll.a",
332 "libuserenv.a",
333 "libws2_32.a",
334 "libdbghelp.a",
335 ];
336
337 let target_libs = find_files(&target_libs, &lib_path);
339
340 let plat_target_lib_self_contained_dir =
342 plat_root.join("lib/rustlib").join(target).join("lib/self-contained");
343 fs::create_dir_all(&plat_target_lib_self_contained_dir)
344 .expect("creating plat_target_lib_self_contained_dir failed");
345 for src in target_libs {
346 builder.copy_link_to_folder(&src, &plat_target_lib_self_contained_dir);
347 }
348}
349
350fn runtime_dll_dist(rust_root: &Path, target: TargetSelection, builder: &Builder<'_>) {
351 if builder.config.dry_run() {
352 return;
353 }
354
355 let (bin_path, _) = get_cc_search_dirs(target, builder);
356
357 let mut rustc_dlls = vec![];
358 if target.is_windows_gnu() {
360 rustc_dlls.push("libwinpthread-1.dll");
361 if target.starts_with("i686-") {
362 rustc_dlls.push("libgcc_s_dw2-1.dll");
363 } else {
364 rustc_dlls.push("libgcc_s_seh-1.dll");
365 }
366 } else if target.is_windows_gnullvm() {
367 rustc_dlls.push("libunwind.dll");
368 } else {
369 panic!("Vendoring of runtime DLLs for `{target}` is not supported`");
370 }
371 let rustc_dlls = find_files(&rustc_dlls, &bin_path);
372
373 let rust_bin_dir = rust_root.join("bin/");
375 fs::create_dir_all(&rust_bin_dir).expect("creating rust_bin_dir failed");
376 for src in &rustc_dlls {
377 builder.copy_link_to_folder(src, &rust_bin_dir);
378 }
379
380 if builder.config.lld_enabled {
381 let rust_target_bin_dir = rust_root.join("lib/rustlib").join(target).join("bin");
383 fs::create_dir_all(&rust_target_bin_dir).expect("creating rust_target_bin_dir failed");
384 for src in &rustc_dlls {
385 builder.copy_link_to_folder(src, &rust_target_bin_dir);
386 }
387 }
388}
389
390fn get_cc_search_dirs(
391 target: TargetSelection,
392 builder: &Builder<'_>,
393) -> (Vec<PathBuf>, Vec<PathBuf>) {
394 let mut cmd = command(builder.cc(target));
396 cmd.arg("-print-search-dirs");
397 let gcc_out = cmd.run_capture_stdout(builder).stdout();
398
399 let mut bin_path: Vec<_> = env::split_paths(&env::var_os("PATH").unwrap_or_default()).collect();
400 let mut lib_path = Vec::new();
401
402 for line in gcc_out.lines() {
403 let idx = line.find(':').unwrap();
404 let key = &line[..idx];
405 let trim_chars: &[_] = &[' ', '='];
406 let value = env::split_paths(line[(idx + 1)..].trim_start_matches(trim_chars));
407
408 if key == "programs" {
409 bin_path.extend(value);
410 } else if key == "libraries" {
411 lib_path.extend(value);
412 }
413 }
414 (bin_path, lib_path)
415}
416
417#[derive(Debug, Clone, Hash, PartialEq, Eq)]
422pub struct Mingw {
423 target: TargetSelection,
424}
425
426impl Step for Mingw {
427 type Output = Option<GeneratedTarball>;
428
429 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
430 run.alias("rust-mingw")
431 }
432
433 fn is_default_step(_builder: &Builder<'_>) -> bool {
434 true
435 }
436
437 fn make_run(run: RunConfig<'_>) {
438 run.builder.ensure(Mingw { target: run.target });
439 }
440
441 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
442 let target = self.target;
443 if !target.contains("pc-windows-gnu") || !builder.config.dist_include_mingw_linker {
444 return None;
445 }
446
447 let mut tarball = Tarball::new(builder, "rust-mingw", &target.triple);
448 tarball.set_product_name("Rust MinGW");
449
450 if target.ends_with("pc-windows-gnu") {
451 make_win_dist(tarball.image_dir(), target, builder);
452 } else if target.ends_with("pc-windows-gnullvm") {
453 make_win_llvm_dist(tarball.image_dir(), target, builder);
454 } else {
455 unreachable!();
456 }
457
458 Some(tarball.generate())
459 }
460
461 fn metadata(&self) -> Option<StepMetadata> {
462 Some(StepMetadata::dist("mingw", self.target))
463 }
464}
465
466#[derive(Debug, Clone, Hash, PartialEq, Eq)]
476pub struct Rustc {
477 pub target_compiler: Compiler,
479}
480
481impl Step for Rustc {
482 type Output = GeneratedTarball;
483 const IS_HOST: bool = true;
484
485 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
486 run.alias("rustc")
487 }
488
489 fn is_default_step(_builder: &Builder<'_>) -> bool {
490 true
491 }
492
493 fn make_run(run: RunConfig<'_>) {
494 run.builder.ensure(Rustc {
495 target_compiler: run.builder.compiler(run.builder.top_stage, run.target),
496 });
497 }
498
499 fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
500 let target_compiler = self.target_compiler;
501 let target = self.target_compiler.host;
502
503 let tarball = Tarball::new(builder, "rustc", &target.triple);
504
505 prepare_image(builder, target_compiler, tarball.image_dir());
507
508 if target.contains("pc-windows-gnu") && builder.config.dist_include_mingw_linker {
516 runtime_dll_dist(tarball.image_dir(), target, builder);
517 tarball.add_dir(builder.src.join("src/etc/third-party"), "share/doc");
518 }
519
520 return tarball.generate();
521
522 fn prepare_image(builder: &Builder<'_>, target_compiler: Compiler, image: &Path) {
523 let target = target_compiler.host;
524 let src = builder.sysroot(target_compiler);
525
526 t!(fs::create_dir_all(image.join("bin")));
528 builder.cp_link_r(&src.join("bin"), &image.join("bin"));
529
530 if builder
532 .config
533 .tools
534 .as_ref()
535 .is_none_or(|tools| tools.iter().any(|tool| tool == "rustdoc"))
536 {
537 let rustdoc = builder.rustdoc_for_compiler(target_compiler);
538 builder.install(&rustdoc, &image.join("bin"), FileType::Executable);
539 }
540
541 let compilers = RustcPrivateCompilers::from_target_compiler(builder, target_compiler);
542
543 if let Some(ra_proc_macro_srv) = builder.ensure_if_default(
544 tool::RustAnalyzerProcMacroSrv::from_compilers(compilers),
545 builder.kind,
546 ) {
547 let dst = image.join("libexec");
548 builder.install(&ra_proc_macro_srv.tool_path, &dst, FileType::Executable);
549 }
550
551 let libdir_relative = builder.libdir_relative(target_compiler);
552
553 if libdir_relative.to_str() != Some("bin") {
555 let libdir = builder.rustc_libdir(target_compiler);
556 for entry in builder.read_dir(&libdir) {
557 if is_dylib(&entry.path())
563 && !entry
564 .path()
565 .file_name()
566 .and_then(|n| n.to_str())
567 .map(|n| n.contains("libgccjit"))
568 .unwrap_or(false)
569 {
570 builder.install(&entry.path(), &image.join("lib"), FileType::NativeLibrary);
573 }
574 }
575 }
576
577 maybe_install_llvm_runtime(builder, target, image);
583
584 let dst_dir = image.join("lib/rustlib").join(target).join("bin");
585 t!(fs::create_dir_all(&dst_dir));
586
587 if builder.config.lld_enabled {
589 let src_dir = builder.sysroot_target_bindir(target_compiler, target);
590 let rust_lld = exe("rust-lld", target_compiler.host);
591 builder.copy_link(
592 &src_dir.join(&rust_lld),
593 &dst_dir.join(&rust_lld),
594 FileType::Executable,
595 );
596 let self_contained_lld_src_dir = src_dir.join("gcc-ld");
597 let self_contained_lld_dst_dir = dst_dir.join("gcc-ld");
598 t!(fs::create_dir(&self_contained_lld_dst_dir));
599 for name in crate::LLD_FILE_NAMES {
600 let exe_name = exe(name, target_compiler.host);
601 builder.copy_link(
602 &self_contained_lld_src_dir.join(&exe_name),
603 &self_contained_lld_dst_dir.join(&exe_name),
604 FileType::Executable,
605 );
606 }
607 }
608
609 if builder.config.llvm_enabled(target_compiler.host)
610 && builder.config.llvm_tools_enabled
611 {
612 let src_dir = builder.sysroot_target_bindir(target_compiler, target);
613 let llvm_objcopy = exe("llvm-objcopy", target_compiler.host);
614 let rust_objcopy = exe("rust-objcopy", target_compiler.host);
615 builder.copy_link(
616 &src_dir.join(&llvm_objcopy),
617 &dst_dir.join(&rust_objcopy),
618 FileType::Executable,
619 );
620 }
621
622 if builder.tool_enabled("wasm-component-ld") {
623 let src_dir = builder.sysroot_target_bindir(target_compiler, target);
624 let ld = exe("wasm-component-ld", target_compiler.host);
625 builder.copy_link(&src_dir.join(&ld), &dst_dir.join(&ld), FileType::Executable);
626 }
627
628 t!(fs::create_dir_all(image.join("share/man/man1")));
630 let man_src = builder.src.join("src/doc/man");
631 let man_dst = image.join("share/man/man1");
632
633 for file_entry in builder.read_dir(&man_src) {
636 let page_src = file_entry.path();
637 let page_dst = man_dst.join(file_entry.file_name());
638 let src_text = t!(std::fs::read_to_string(&page_src));
639 let new_text = src_text.replace("<INSERT VERSION HERE>", &builder.version);
640 t!(std::fs::write(&page_dst, &new_text));
641 t!(fs::copy(&page_src, &page_dst));
642 }
643
644 builder.ensure(DebuggerScripts { sysroot: image.to_owned(), target });
646
647 generate_target_spec_json_schema(builder, image);
648
649 let file_list = builder.ensure(super::run::GenerateCopyright);
651 for file in file_list {
652 builder.install(&file, &image.join("share/doc/rust"), FileType::Regular);
653 }
654
655 builder.install(
657 &builder.src.join("README.md"),
658 &image.join("share/doc/rust"),
659 FileType::Regular,
660 );
661
662 let license = |path: &Path| {
664 builder.install(path, &image.join("share/doc/rust/licenses"), FileType::Regular);
665 };
666 for entry in t!(std::fs::read_dir(builder.src.join("LICENSES"))).flatten() {
667 license(&entry.path());
668 }
669 }
670 }
671
672 fn metadata(&self) -> Option<StepMetadata> {
673 Some(StepMetadata::dist("rustc", self.target_compiler.host))
674 }
675}
676
677fn generate_target_spec_json_schema(builder: &Builder<'_>, sysroot: &Path) {
678 let stage1_host = builder.compiler(1, builder.host_target);
682 let mut rustc = builder.rustc_cmd(stage1_host).fail_fast();
683 rustc
684 .env("RUSTC_BOOTSTRAP", "1")
685 .args(["--print=target-spec-json-schema", "-Zunstable-options"]);
686 let schema = rustc.run_capture(builder).stdout();
687
688 let schema_dir = tmpdir(builder);
689 t!(fs::create_dir_all(&schema_dir));
690 let schema_file = schema_dir.join("target-spec-json-schema.json");
691 t!(std::fs::write(&schema_file, schema));
692
693 let dst = sysroot.join("etc");
694 t!(fs::create_dir_all(&dst));
695
696 builder.install(&schema_file, &dst, FileType::Regular);
697}
698
699#[derive(Debug, Clone, Hash, PartialEq, Eq)]
701pub struct DebuggerScripts {
702 pub sysroot: PathBuf,
704 pub target: TargetSelection,
705}
706
707impl Step for DebuggerScripts {
708 type Output = ();
709
710 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
711 run.never()
712 }
713
714 fn run(self, builder: &Builder<'_>) {
715 let target = self.target;
716 let sysroot = self.sysroot;
717 let dst = sysroot.join("lib/rustlib/etc");
718 t!(fs::create_dir_all(&dst));
719 let cp_debugger_script = |file: &str| {
720 builder.install(&builder.src.join("src/etc/").join(file), &dst, FileType::Regular);
721 };
722 if target.contains("windows-msvc") {
723 builder.install(
725 &builder.src.join("src/etc/rust-windbg.cmd"),
726 &sysroot.join("bin"),
727 FileType::Script,
728 );
729
730 cp_debugger_script("natvis/intrinsic.natvis");
731 cp_debugger_script("natvis/liballoc.natvis");
732 cp_debugger_script("natvis/libcore.natvis");
733 cp_debugger_script("natvis/libstd.natvis");
734 }
735
736 cp_debugger_script("rust_types.py");
737
738 builder.install(
740 &builder.src.join("src/etc/rust-gdb"),
741 &sysroot.join("bin"),
742 FileType::Script,
743 );
744 builder.install(
745 &builder.src.join("src/etc/rust-gdbgui"),
746 &sysroot.join("bin"),
747 FileType::Script,
748 );
749
750 cp_debugger_script("gdb_load_rust_pretty_printers.py");
751 cp_debugger_script("gdb_lookup.py");
752 cp_debugger_script("gdb_providers.py");
753
754 builder.install(
756 &builder.src.join("src/etc/rust-lldb"),
757 &sysroot.join("bin"),
758 FileType::Script,
759 );
760
761 cp_debugger_script("lldb_lookup.py");
762 cp_debugger_script("lldb_providers.py");
763 cp_debugger_script("lldb_commands")
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 Step 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 Step 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 Step 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/libunwind",
1075 "llvm-project/lld",
1076 "llvm-project/lldb",
1077 "llvm-project/llvm",
1078 "llvm-project/compiler-rt",
1079 "llvm-project/cmake",
1080 "llvm-project/runtimes",
1081 "llvm-project/third-party",
1082 ];
1083 if spath.starts_with("llvm-project") && spath != "llvm-project" {
1084 if !LLVM_PROJECTS.iter().any(|path| spath.starts_with(path)) {
1085 return false;
1086 }
1087
1088 if spath.starts_with("llvm-project/third-party")
1090 && spath != "llvm-project/third-party"
1091 && !spath.starts_with("llvm-project/third-party/siphash")
1092 {
1093 return false;
1094 }
1095
1096 if spath.starts_with("llvm-project/llvm/test")
1097 && (spath.ends_with(".ll") || spath.ends_with(".td") || spath.ends_with(".s"))
1098 {
1099 return false;
1100 }
1101 }
1102
1103 if spath.starts_with("tools/cargo/tests") {
1105 return true;
1106 }
1107
1108 if !exclude_dirs.is_empty() {
1109 let full_path = Path::new(dir).join(path);
1110 if exclude_dirs.iter().any(|excl| full_path == Path::new(excl)) {
1111 return false;
1112 }
1113 }
1114
1115 static EXCLUDES: &[&str] = &[
1116 "CVS",
1117 "RCS",
1118 "SCCS",
1119 ".git",
1120 ".gitignore",
1121 ".gitmodules",
1122 ".gitattributes",
1123 ".cvsignore",
1124 ".svn",
1125 ".arch-ids",
1126 "{arch}",
1127 "=RELEASE-ID",
1128 "=meta-update",
1129 "=update",
1130 ".bzr",
1131 ".bzrignore",
1132 ".bzrtags",
1133 ".hg",
1134 ".hgignore",
1135 ".hgrags",
1136 "_darcs",
1137 ];
1138
1139 let last_component = path.iter().next_back().map(|s| s.to_str().unwrap()).unwrap();
1146 !EXCLUDES.contains(&last_component)
1147 }
1148
1149 for item in src_dirs {
1151 let dst = &dst_dir.join(item);
1152 t!(fs::create_dir_all(dst));
1153 builder
1154 .cp_link_filtered(&base.join(item), dst, &|path| filter_fn(exclude_dirs, item, path));
1155 }
1156}
1157
1158#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1159pub struct Src;
1160
1161impl Step for Src {
1162 type Output = GeneratedTarball;
1164 const IS_HOST: bool = true;
1165
1166 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1167 run.alias("rust-src")
1168 }
1169
1170 fn is_default_step(_builder: &Builder<'_>) -> bool {
1171 true
1172 }
1173
1174 fn make_run(run: RunConfig<'_>) {
1175 run.builder.ensure(Src);
1176 }
1177
1178 fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
1180 if !builder.config.dry_run() {
1181 builder.require_submodule("src/llvm-project", None);
1182 }
1183
1184 let tarball = Tarball::new_targetless(builder, "rust-src");
1185
1186 let dst_src = tarball.image_dir().join("lib/rustlib/src/rust");
1194
1195 copy_src_dirs(
1198 builder,
1199 &builder.src,
1200 &["library", "src/llvm-project/libunwind"],
1201 &[
1202 "library/backtrace/crates",
1205 "library/stdarch/Cargo.toml",
1208 "library/stdarch/crates/stdarch-verify",
1209 "library/stdarch/crates/intrinsic-test",
1210 ],
1211 &dst_src,
1212 );
1213
1214 tarball.generate()
1215 }
1216
1217 fn metadata(&self) -> Option<StepMetadata> {
1218 Some(StepMetadata::dist("src", TargetSelection::default()))
1219 }
1220}
1221
1222#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1226pub struct PlainSourceTarball;
1227
1228impl Step for PlainSourceTarball {
1229 type Output = GeneratedTarball;
1231 const IS_HOST: bool = true;
1232
1233 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1234 run.alias("rustc-src")
1235 }
1236
1237 fn is_default_step(builder: &Builder<'_>) -> bool {
1238 builder.config.rust_dist_src
1239 }
1240
1241 fn make_run(run: RunConfig<'_>) {
1242 run.builder.ensure(PlainSourceTarball);
1243 }
1244
1245 fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
1247 let tarball = prepare_source_tarball(
1248 builder,
1249 "src",
1250 &[
1251 "src/gcc",
1255 ],
1256 );
1257
1258 let plain_dst_src = tarball.image_dir();
1259 if !builder.config.dry_run() {
1264 builder.create_dir(&plain_dst_src.join("src/gcc"));
1265 t!(std::fs::write(
1266 plain_dst_src.join("src/gcc/notice.txt"),
1267 "The GCC source code is not included due to unclear licensing implications\n"
1268 ));
1269 }
1270 tarball.bare()
1271 }
1272}
1273
1274#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1276pub struct PlainSourceTarballGpl;
1277
1278impl Step for PlainSourceTarballGpl {
1279 type Output = GeneratedTarball;
1281 const IS_HOST: bool = true;
1282
1283 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1284 run.alias("rustc-src-gpl")
1285 }
1286
1287 fn is_default_step(builder: &Builder<'_>) -> bool {
1288 builder.config.rust_dist_src
1289 }
1290
1291 fn make_run(run: RunConfig<'_>) {
1292 run.builder.ensure(PlainSourceTarballGpl);
1293 }
1294
1295 fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
1297 let tarball = prepare_source_tarball(builder, "src-gpl", &[]);
1298 tarball.bare()
1299 }
1300}
1301
1302fn prepare_source_tarball<'a>(
1303 builder: &'a Builder<'a>,
1304 name: &str,
1305 exclude_dirs: &[&str],
1306) -> Tarball<'a> {
1307 let mut tarball = Tarball::new(builder, "rustc", name);
1312 tarball.permit_symlinks(true);
1313 let plain_dst_src = tarball.image_dir();
1314
1315 let src_files = [
1317 ".gitmodules",
1319 "CONTRIBUTING.md",
1320 "COPYRIGHT",
1321 "Cargo.lock",
1322 "Cargo.toml",
1323 "LICENSE-APACHE",
1324 "LICENSE-MIT",
1325 "README.md",
1326 "RELEASES.md",
1327 "REUSE.toml",
1328 "bootstrap.example.toml",
1329 "configure",
1330 "license-metadata.json",
1331 "package.json",
1332 "x",
1333 "x.ps1",
1334 "x.py",
1335 "yarn.lock",
1336 ];
1338 let src_dirs = ["src", "compiler", "library", "tests", "LICENSES"];
1339
1340 copy_src_dirs(builder, &builder.src, &src_dirs, exclude_dirs, plain_dst_src);
1341
1342 for item in &src_files {
1344 builder.copy_link(&builder.src.join(item), &plain_dst_src.join(item), FileType::Regular);
1345 }
1346
1347 builder.create(&plain_dst_src.join("version"), &builder.rust_version());
1349
1350 let write_git_info = |info: Option<&Info>, path: &Path| {
1352 if let Some(info) = info {
1353 t!(std::fs::create_dir_all(path));
1354 channel::write_commit_hash_file(path, &info.sha);
1355 channel::write_commit_info_file(path, info);
1356 }
1357 };
1358 write_git_info(builder.rust_info().info(), plain_dst_src);
1359 write_git_info(builder.cargo_info.info(), &plain_dst_src.join("./src/tools/cargo"));
1360
1361 if builder.config.dist_vendor {
1362 builder.require_and_update_all_submodules();
1363
1364 let pkgs_for_pgo_training =
1366 build_helper::LLVM_PGO_CRATES.iter().chain(build_helper::RUSTC_PGO_CRATES).map(|pkg| {
1367 let mut manifest_path =
1368 builder.src.join("./src/tools/rustc-perf/collector/compile-benchmarks");
1369 manifest_path.push(pkg);
1370 manifest_path.push("Cargo.toml");
1371 manifest_path
1372 });
1373
1374 let vendor = builder.ensure(Vendor {
1376 sync_args: pkgs_for_pgo_training.collect(),
1377 versioned_dirs: true,
1378 root_dir: plain_dst_src.into(),
1379 output_dir: VENDOR_DIR.into(),
1380 });
1381
1382 let cargo_config_dir = plain_dst_src.join(".cargo");
1383 builder.create_dir(&cargo_config_dir);
1384 builder.create(&cargo_config_dir.join("config.toml"), &vendor.config);
1385 }
1386
1387 for entry in walkdir::WalkDir::new(tarball.image_dir())
1391 .follow_links(true)
1392 .into_iter()
1393 .filter_map(|e| e.ok())
1394 {
1395 if entry.path().is_dir() && entry.path().file_name() == Some(OsStr::new("__pycache__")) {
1396 t!(fs::remove_dir_all(entry.path()));
1397 }
1398 }
1399 tarball
1400}
1401
1402#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1403pub struct Cargo {
1404 pub build_compiler: Compiler,
1405 pub target: TargetSelection,
1406}
1407
1408impl Step for Cargo {
1409 type Output = Option<GeneratedTarball>;
1410 const IS_HOST: bool = true;
1411
1412 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1413 run.alias("cargo")
1414 }
1415
1416 fn is_default_step(builder: &Builder<'_>) -> bool {
1417 should_build_extended_tool(builder, "cargo")
1418 }
1419
1420 fn make_run(run: RunConfig<'_>) {
1421 run.builder.ensure(Cargo {
1422 build_compiler: get_tool_target_compiler(
1423 run.builder,
1424 ToolTargetBuildMode::Build(run.target),
1425 ),
1426 target: run.target,
1427 });
1428 }
1429
1430 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1431 let build_compiler = self.build_compiler;
1432 let target = self.target;
1433
1434 let cargo = builder.ensure(tool::Cargo::from_build_compiler(build_compiler, target));
1435 let src = builder.src.join("src/tools/cargo");
1436 let etc = src.join("src/etc");
1437
1438 let mut tarball = Tarball::new(builder, "cargo", &target.triple);
1440 tarball.set_overlay(OverlayKind::Cargo);
1441
1442 tarball.add_file(&cargo.tool_path, "bin", FileType::Executable);
1443 tarball.add_file(etc.join("_cargo"), "share/zsh/site-functions", FileType::Regular);
1444 tarball.add_renamed_file(
1445 etc.join("cargo.bashcomp.sh"),
1446 "etc/bash_completion.d",
1447 "cargo",
1448 FileType::Regular,
1449 );
1450 tarball.add_dir(etc.join("man"), "share/man/man1");
1451 tarball.add_legal_and_readme_to("share/doc/cargo");
1452
1453 Some(tarball.generate())
1454 }
1455
1456 fn metadata(&self) -> Option<StepMetadata> {
1457 Some(StepMetadata::dist("cargo", self.target).built_by(self.build_compiler))
1458 }
1459}
1460
1461#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1463pub struct RustAnalyzer {
1464 pub compilers: RustcPrivateCompilers,
1465 pub target: TargetSelection,
1466}
1467
1468impl Step for RustAnalyzer {
1469 type Output = Option<GeneratedTarball>;
1470 const IS_HOST: bool = true;
1471
1472 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1473 run.alias("rust-analyzer")
1474 }
1475
1476 fn is_default_step(builder: &Builder<'_>) -> bool {
1477 should_build_extended_tool(builder, "rust-analyzer")
1478 }
1479
1480 fn make_run(run: RunConfig<'_>) {
1481 run.builder.ensure(RustAnalyzer {
1482 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1483 target: run.target,
1484 });
1485 }
1486
1487 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1488 let target = self.target;
1489 let rust_analyzer = builder.ensure(tool::RustAnalyzer::from_compilers(self.compilers));
1490
1491 let mut tarball = Tarball::new(builder, "rust-analyzer", &target.triple);
1492 tarball.set_overlay(OverlayKind::RustAnalyzer);
1493 tarball.is_preview(true);
1494 tarball.add_file(&rust_analyzer.tool_path, "bin", FileType::Executable);
1495 tarball.add_legal_and_readme_to("share/doc/rust-analyzer");
1496 Some(tarball.generate())
1497 }
1498
1499 fn metadata(&self) -> Option<StepMetadata> {
1500 Some(
1501 StepMetadata::dist("rust-analyzer", self.target)
1502 .built_by(self.compilers.build_compiler()),
1503 )
1504 }
1505}
1506
1507#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1508pub struct Clippy {
1509 pub compilers: RustcPrivateCompilers,
1510 pub target: TargetSelection,
1511}
1512
1513impl Step for Clippy {
1514 type Output = Option<GeneratedTarball>;
1515 const IS_HOST: bool = true;
1516
1517 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1518 run.alias("clippy")
1519 }
1520
1521 fn is_default_step(builder: &Builder<'_>) -> bool {
1522 should_build_extended_tool(builder, "clippy")
1523 }
1524
1525 fn make_run(run: RunConfig<'_>) {
1526 run.builder.ensure(Clippy {
1527 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1528 target: run.target,
1529 });
1530 }
1531
1532 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1533 let target = self.target;
1534
1535 let clippy = builder.ensure(tool::Clippy::from_compilers(self.compilers));
1539 let cargoclippy = builder.ensure(tool::CargoClippy::from_compilers(self.compilers));
1540
1541 let mut tarball = Tarball::new(builder, "clippy", &target.triple);
1542 tarball.set_overlay(OverlayKind::Clippy);
1543 tarball.is_preview(true);
1544 tarball.add_file(&clippy.tool_path, "bin", FileType::Executable);
1545 tarball.add_file(&cargoclippy.tool_path, "bin", FileType::Executable);
1546 tarball.add_legal_and_readme_to("share/doc/clippy");
1547 Some(tarball.generate())
1548 }
1549
1550 fn metadata(&self) -> Option<StepMetadata> {
1551 Some(StepMetadata::dist("clippy", self.target).built_by(self.compilers.build_compiler()))
1552 }
1553}
1554
1555#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1556pub struct Miri {
1557 pub compilers: RustcPrivateCompilers,
1558 pub target: TargetSelection,
1559}
1560
1561impl Step for Miri {
1562 type Output = Option<GeneratedTarball>;
1563 const IS_HOST: bool = true;
1564
1565 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1566 run.alias("miri")
1567 }
1568
1569 fn is_default_step(builder: &Builder<'_>) -> bool {
1570 should_build_extended_tool(builder, "miri")
1571 }
1572
1573 fn make_run(run: RunConfig<'_>) {
1574 run.builder.ensure(Miri {
1575 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1576 target: run.target,
1577 });
1578 }
1579
1580 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1581 if !builder.build.unstable_features() {
1585 return None;
1586 }
1587
1588 let miri = builder.ensure(tool::Miri::from_compilers(self.compilers));
1589 let cargomiri = builder.ensure(tool::CargoMiri::from_compilers(self.compilers));
1590
1591 let mut tarball = Tarball::new(builder, "miri", &self.target.triple);
1592 tarball.set_overlay(OverlayKind::Miri);
1593 tarball.is_preview(true);
1594 tarball.add_file(&miri.tool_path, "bin", FileType::Executable);
1595 tarball.add_file(&cargomiri.tool_path, "bin", FileType::Executable);
1596 tarball.add_legal_and_readme_to("share/doc/miri");
1597 Some(tarball.generate())
1598 }
1599
1600 fn metadata(&self) -> Option<StepMetadata> {
1601 Some(StepMetadata::dist("miri", self.target).built_by(self.compilers.build_compiler()))
1602 }
1603}
1604
1605#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1606pub struct CraneliftCodegenBackend {
1607 pub compilers: RustcPrivateCompilers,
1608 pub target: TargetSelection,
1609}
1610
1611impl Step for CraneliftCodegenBackend {
1612 type Output = Option<GeneratedTarball>;
1613 const IS_HOST: bool = true;
1614
1615 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1616 run.alias("rustc_codegen_cranelift")
1617 }
1618
1619 fn is_default_step(builder: &Builder<'_>) -> bool {
1620 builder
1625 .config
1626 .enabled_codegen_backends(builder.host_target)
1627 .contains(&CodegenBackendKind::Cranelift)
1628 }
1629
1630 fn make_run(run: RunConfig<'_>) {
1631 run.builder.ensure(CraneliftCodegenBackend {
1632 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1633 target: run.target,
1634 });
1635 }
1636
1637 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1638 if !builder.build.unstable_features() {
1642 return None;
1643 }
1644
1645 let target = self.target;
1646 if !target_supports_cranelift_backend(target) {
1647 builder.info("target not supported by rustc_codegen_cranelift. skipping");
1648 return None;
1649 }
1650
1651 let mut tarball = Tarball::new(builder, "rustc-codegen-cranelift", &target.triple);
1652 tarball.set_overlay(OverlayKind::RustcCodegenCranelift);
1653 tarball.is_preview(true);
1654 tarball.add_legal_and_readme_to("share/doc/rustc_codegen_cranelift");
1655
1656 let compilers = self.compilers;
1657 let stamp = builder.ensure(compile::CraneliftCodegenBackend { compilers });
1658
1659 if builder.config.dry_run() {
1660 return None;
1661 }
1662
1663 add_codegen_backend_to_tarball(builder, &tarball, compilers.target_compiler(), &stamp);
1664
1665 Some(tarball.generate())
1666 }
1667
1668 fn metadata(&self) -> Option<StepMetadata> {
1669 Some(
1670 StepMetadata::dist("rustc_codegen_cranelift", self.target)
1671 .built_by(self.compilers.build_compiler()),
1672 )
1673 }
1674}
1675
1676#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1680pub struct GccCodegenBackend {
1681 pub compilers: RustcPrivateCompilers,
1682 pub target: TargetSelection,
1683}
1684
1685impl Step for GccCodegenBackend {
1686 type Output = Option<GeneratedTarball>;
1687 const IS_HOST: bool = true;
1688
1689 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1690 run.alias("rustc_codegen_gcc")
1691 }
1692
1693 fn is_default_step(builder: &Builder<'_>) -> bool {
1694 builder
1699 .config
1700 .enabled_codegen_backends(builder.host_target)
1701 .contains(&CodegenBackendKind::Gcc)
1702 }
1703
1704 fn make_run(run: RunConfig<'_>) {
1705 run.builder.ensure(GccCodegenBackend {
1706 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1707 target: run.target,
1708 });
1709 }
1710
1711 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1712 if !builder.build.unstable_features() {
1716 return None;
1717 }
1718
1719 let target = self.target;
1720 if target != "x86_64-unknown-linux-gnu" {
1721 builder
1722 .info(&format!("target `{target}` not supported by rustc_codegen_gcc. skipping"));
1723 return None;
1724 }
1725
1726 let mut tarball = Tarball::new(builder, "rustc-codegen-gcc", &target.triple);
1727 tarball.set_overlay(OverlayKind::RustcCodegenGcc);
1728 tarball.is_preview(true);
1729 tarball.add_legal_and_readme_to("share/doc/rustc_codegen_gcc");
1730
1731 let compilers = self.compilers;
1732 let backend = builder.ensure(compile::GccCodegenBackend::for_target(compilers, target));
1733
1734 if builder.config.dry_run() {
1735 return None;
1736 }
1737
1738 add_codegen_backend_to_tarball(
1739 builder,
1740 &tarball,
1741 compilers.target_compiler(),
1742 backend.stamp(),
1743 );
1744
1745 Some(tarball.generate())
1746 }
1747
1748 fn metadata(&self) -> Option<StepMetadata> {
1749 Some(
1750 StepMetadata::dist("rustc_codegen_gcc", self.target)
1751 .built_by(self.compilers.build_compiler()),
1752 )
1753 }
1754}
1755
1756fn add_codegen_backend_to_tarball(
1759 builder: &Builder<'_>,
1760 tarball: &Tarball<'_>,
1761 compiler: Compiler,
1762 stamp: &BuildStamp,
1763) {
1764 let backends_dst = builder.sysroot_codegen_backends(compiler);
1766 let backends_rel = backends_dst
1767 .strip_prefix(builder.sysroot(compiler))
1768 .unwrap()
1769 .strip_prefix(builder.sysroot_libdir_relative(compiler))
1770 .unwrap();
1771 let backends_dst = PathBuf::from("lib").join(backends_rel);
1773
1774 let codegen_backend_dylib = get_codegen_backend_file(stamp);
1775 tarball.add_renamed_file(
1776 &codegen_backend_dylib,
1777 &backends_dst,
1778 &normalize_codegen_backend_name(builder, &codegen_backend_dylib),
1779 FileType::NativeLibrary,
1780 );
1781}
1782
1783#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1784pub struct Rustfmt {
1785 pub compilers: RustcPrivateCompilers,
1786 pub target: TargetSelection,
1787}
1788
1789impl Step for Rustfmt {
1790 type Output = Option<GeneratedTarball>;
1791 const IS_HOST: bool = true;
1792
1793 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1794 run.alias("rustfmt")
1795 }
1796
1797 fn is_default_step(builder: &Builder<'_>) -> bool {
1798 should_build_extended_tool(builder, "rustfmt")
1799 }
1800
1801 fn make_run(run: RunConfig<'_>) {
1802 run.builder.ensure(Rustfmt {
1803 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1804 target: run.target,
1805 });
1806 }
1807
1808 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1809 let rustfmt = builder.ensure(tool::Rustfmt::from_compilers(self.compilers));
1810 let cargofmt = builder.ensure(tool::Cargofmt::from_compilers(self.compilers));
1811
1812 let mut tarball = Tarball::new(builder, "rustfmt", &self.target.triple);
1813 tarball.set_overlay(OverlayKind::Rustfmt);
1814 tarball.is_preview(true);
1815 tarball.add_file(&rustfmt.tool_path, "bin", FileType::Executable);
1816 tarball.add_file(&cargofmt.tool_path, "bin", FileType::Executable);
1817 tarball.add_legal_and_readme_to("share/doc/rustfmt");
1818 Some(tarball.generate())
1819 }
1820
1821 fn metadata(&self) -> Option<StepMetadata> {
1822 Some(StepMetadata::dist("rustfmt", self.target).built_by(self.compilers.build_compiler()))
1823 }
1824}
1825
1826#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1828pub struct Extended {
1829 build_compiler: Compiler,
1830 target: TargetSelection,
1831}
1832
1833impl Step for Extended {
1834 type Output = ();
1835 const IS_HOST: bool = true;
1836
1837 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1838 run.alias("extended")
1839 }
1840
1841 fn is_default_step(builder: &Builder<'_>) -> bool {
1842 builder.config.extended
1843 }
1844
1845 fn make_run(run: RunConfig<'_>) {
1846 run.builder.ensure(Extended {
1847 build_compiler: run
1848 .builder
1849 .compiler(run.builder.top_stage - 1, run.builder.host_target),
1850 target: run.target,
1851 });
1852 }
1853
1854 fn run(self, builder: &Builder<'_>) {
1856 let target = self.target;
1857 builder.info(&format!("Dist extended stage{} ({target})", builder.top_stage));
1858
1859 let mut tarballs = Vec::new();
1860 let mut built_tools = HashSet::new();
1861 macro_rules! add_component {
1862 ($name:expr => $step:expr) => {
1863 if let Some(Some(tarball)) = builder.ensure_if_default($step, Kind::Dist) {
1864 tarballs.push(tarball);
1865 built_tools.insert($name);
1866 }
1867 };
1868 }
1869
1870 let rustc_private_compilers =
1871 RustcPrivateCompilers::from_build_compiler(builder, self.build_compiler, target);
1872 let build_compiler = rustc_private_compilers.build_compiler();
1873 let target_compiler = rustc_private_compilers.target_compiler();
1874
1875 tarballs.push(builder.ensure(Rustc { target_compiler }));
1880 tarballs.push(builder.ensure(Std { build_compiler, target }).expect("missing std"));
1881
1882 if target.is_windows_gnu() || target.is_windows_gnullvm() {
1883 tarballs.push(builder.ensure(Mingw { target }).expect("missing mingw"));
1884 }
1885
1886 add_component!("rust-docs" => Docs { host: target });
1887 add_component!("rust-json-docs" => JsonDocs { build_compiler: target_compiler, target });
1889 add_component!("cargo" => Cargo { build_compiler, target });
1890 add_component!("rustfmt" => Rustfmt { compilers: rustc_private_compilers, target });
1891 add_component!("rust-analyzer" => RustAnalyzer { compilers: rustc_private_compilers, target });
1892 add_component!("llvm-components" => LlvmTools { target });
1893 add_component!("clippy" => Clippy { compilers: rustc_private_compilers, target });
1894 add_component!("miri" => Miri { compilers: rustc_private_compilers, target });
1895 add_component!("analysis" => Analysis { build_compiler, target });
1896 add_component!("rustc-codegen-cranelift" => CraneliftCodegenBackend {
1897 compilers: rustc_private_compilers,
1898 target
1899 });
1900 add_component!("llvm-bitcode-linker" => LlvmBitcodeLinker {
1901 build_compiler,
1902 target
1903 });
1904
1905 let etc = builder.src.join("src/etc/installer");
1906
1907 if builder.config.dry_run() {
1909 return;
1910 }
1911
1912 let tarball = Tarball::new(builder, "rust", &target.triple);
1913 let generated = tarball.combine(&tarballs);
1914
1915 let tmp = tmpdir(builder).join("combined-tarball");
1916 let work = generated.work_dir();
1917
1918 let mut license = String::new();
1919 license += &builder.read(&builder.src.join("COPYRIGHT"));
1920 license += &builder.read(&builder.src.join("LICENSE-APACHE"));
1921 license += &builder.read(&builder.src.join("LICENSE-MIT"));
1922 license.push('\n');
1923 license.push('\n');
1924
1925 let rtf = r"{\rtf1\ansi\deff0{\fonttbl{\f0\fnil\fcharset0 Arial;}}\nowwrap\fs18";
1926 let mut rtf = rtf.to_string();
1927 rtf.push('\n');
1928 for line in license.lines() {
1929 rtf.push_str(line);
1930 rtf.push_str("\\line ");
1931 }
1932 rtf.push('}');
1933
1934 fn filter(contents: &str, marker: &str) -> String {
1935 let start = format!("tool-{marker}-start");
1936 let end = format!("tool-{marker}-end");
1937 let mut lines = Vec::new();
1938 let mut omitted = false;
1939 for line in contents.lines() {
1940 if line.contains(&start) {
1941 omitted = true;
1942 } else if line.contains(&end) {
1943 omitted = false;
1944 } else if !omitted {
1945 lines.push(line);
1946 }
1947 }
1948
1949 lines.join("\n")
1950 }
1951
1952 let xform = |p: &Path| {
1953 let mut contents = t!(fs::read_to_string(p));
1954 for tool in &["miri", "rust-docs"] {
1955 if !built_tools.contains(tool) {
1956 contents = filter(&contents, tool);
1957 }
1958 }
1959 let ret = tmp.join(p.file_name().unwrap());
1960 t!(fs::write(&ret, &contents));
1961 ret
1962 };
1963
1964 if target.contains("apple-darwin") {
1965 builder.info("building pkg installer");
1966 let pkg = tmp.join("pkg");
1967 let _ = fs::remove_dir_all(&pkg);
1968
1969 let pkgbuild = |component: &str| {
1970 let mut cmd = command("pkgbuild");
1971 cmd.arg("--identifier")
1972 .arg(format!("org.rust-lang.{component}"))
1973 .arg("--scripts")
1974 .arg(pkg.join(component))
1975 .arg("--nopayload")
1976 .arg(pkg.join(component).with_extension("pkg"));
1977 cmd.run(builder);
1978 };
1979
1980 let prepare = |name: &str| {
1981 builder.create_dir(&pkg.join(name));
1982 builder.cp_link_r(
1983 &work.join(format!("{}-{}", pkgname(builder, name), target.triple)),
1984 &pkg.join(name),
1985 );
1986 builder.install(&etc.join("pkg/postinstall"), &pkg.join(name), FileType::Script);
1987 pkgbuild(name);
1988 };
1989 prepare("rustc");
1990 prepare("cargo");
1991 prepare("rust-std");
1992 prepare("rust-analysis");
1993
1994 for tool in &[
1995 "clippy",
1996 "rustfmt",
1997 "rust-analyzer",
1998 "rust-docs",
1999 "miri",
2000 "rustc-codegen-cranelift",
2001 ] {
2002 if built_tools.contains(tool) {
2003 prepare(tool);
2004 }
2005 }
2006 builder.install(&etc.join("pkg/postinstall"), &pkg.join("uninstall"), FileType::Script);
2008 pkgbuild("uninstall");
2009
2010 builder.create_dir(&pkg.join("res"));
2011 builder.create(&pkg.join("res/LICENSE.txt"), &license);
2012 builder.install(&etc.join("gfx/rust-logo.png"), &pkg.join("res"), FileType::Regular);
2013 let mut cmd = command("productbuild");
2014 cmd.arg("--distribution")
2015 .arg(xform(&etc.join("pkg/Distribution.xml")))
2016 .arg("--resources")
2017 .arg(pkg.join("res"))
2018 .arg(distdir(builder).join(format!(
2019 "{}-{}.pkg",
2020 pkgname(builder, "rust"),
2021 target.triple
2022 )))
2023 .arg("--package-path")
2024 .arg(&pkg);
2025 let _time = timeit(builder);
2026 cmd.run(builder);
2027 }
2028
2029 if target.is_windows() {
2030 let exe = tmp.join("exe");
2031 let _ = fs::remove_dir_all(&exe);
2032
2033 let prepare = |name: &str| {
2034 builder.create_dir(&exe.join(name));
2035 let dir = if name == "rust-std" || name == "rust-analysis" {
2036 format!("{}-{}", name, target.triple)
2037 } else if name == "rust-analyzer" {
2038 "rust-analyzer-preview".to_string()
2039 } else if name == "clippy" {
2040 "clippy-preview".to_string()
2041 } else if name == "rustfmt" {
2042 "rustfmt-preview".to_string()
2043 } else if name == "miri" {
2044 "miri-preview".to_string()
2045 } else if name == "rustc-codegen-cranelift" {
2046 unreachable!("cg_clif shouldn't be built for windows");
2049 } else {
2050 name.to_string()
2051 };
2052 builder.cp_link_r(
2053 &work.join(format!("{}-{}", pkgname(builder, name), target.triple)).join(dir),
2054 &exe.join(name),
2055 );
2056 builder.remove(&exe.join(name).join("manifest.in"));
2057 };
2058 prepare("rustc");
2059 prepare("cargo");
2060 prepare("rust-analysis");
2061 prepare("rust-std");
2062 for tool in &["clippy", "rustfmt", "rust-analyzer", "rust-docs", "miri"] {
2063 if built_tools.contains(tool) {
2064 prepare(tool);
2065 }
2066 }
2067 if target.is_windows_gnu() || target.is_windows_gnullvm() {
2068 prepare("rust-mingw");
2069 }
2070
2071 builder.install(&etc.join("gfx/rust-logo.ico"), &exe, FileType::Regular);
2072
2073 let wix_path = env::var_os("WIX")
2075 .expect("`WIX` environment variable must be set for generating MSI installer(s).");
2076 let wix = PathBuf::from(wix_path);
2077 let heat = wix.join("bin/heat.exe");
2078 let candle = wix.join("bin/candle.exe");
2079 let light = wix.join("bin/light.exe");
2080
2081 let heat_flags = ["-nologo", "-gg", "-sfrag", "-srd", "-sreg"];
2082 command(&heat)
2083 .current_dir(&exe)
2084 .arg("dir")
2085 .arg("rustc")
2086 .args(heat_flags)
2087 .arg("-cg")
2088 .arg("RustcGroup")
2089 .arg("-dr")
2090 .arg("Rustc")
2091 .arg("-var")
2092 .arg("var.RustcDir")
2093 .arg("-out")
2094 .arg(exe.join("RustcGroup.wxs"))
2095 .run(builder);
2096 if built_tools.contains("rust-docs") {
2097 command(&heat)
2098 .current_dir(&exe)
2099 .arg("dir")
2100 .arg("rust-docs")
2101 .args(heat_flags)
2102 .arg("-cg")
2103 .arg("DocsGroup")
2104 .arg("-dr")
2105 .arg("Docs")
2106 .arg("-var")
2107 .arg("var.DocsDir")
2108 .arg("-out")
2109 .arg(exe.join("DocsGroup.wxs"))
2110 .arg("-t")
2111 .arg(etc.join("msi/squash-components.xsl"))
2112 .run(builder);
2113 }
2114 command(&heat)
2115 .current_dir(&exe)
2116 .arg("dir")
2117 .arg("cargo")
2118 .args(heat_flags)
2119 .arg("-cg")
2120 .arg("CargoGroup")
2121 .arg("-dr")
2122 .arg("Cargo")
2123 .arg("-var")
2124 .arg("var.CargoDir")
2125 .arg("-out")
2126 .arg(exe.join("CargoGroup.wxs"))
2127 .arg("-t")
2128 .arg(etc.join("msi/remove-duplicates.xsl"))
2129 .run(builder);
2130 command(&heat)
2131 .current_dir(&exe)
2132 .arg("dir")
2133 .arg("rust-std")
2134 .args(heat_flags)
2135 .arg("-cg")
2136 .arg("StdGroup")
2137 .arg("-dr")
2138 .arg("Std")
2139 .arg("-var")
2140 .arg("var.StdDir")
2141 .arg("-out")
2142 .arg(exe.join("StdGroup.wxs"))
2143 .run(builder);
2144 if built_tools.contains("rust-analyzer") {
2145 command(&heat)
2146 .current_dir(&exe)
2147 .arg("dir")
2148 .arg("rust-analyzer")
2149 .args(heat_flags)
2150 .arg("-cg")
2151 .arg("RustAnalyzerGroup")
2152 .arg("-dr")
2153 .arg("RustAnalyzer")
2154 .arg("-var")
2155 .arg("var.RustAnalyzerDir")
2156 .arg("-out")
2157 .arg(exe.join("RustAnalyzerGroup.wxs"))
2158 .arg("-t")
2159 .arg(etc.join("msi/remove-duplicates.xsl"))
2160 .run(builder);
2161 }
2162 if built_tools.contains("clippy") {
2163 command(&heat)
2164 .current_dir(&exe)
2165 .arg("dir")
2166 .arg("clippy")
2167 .args(heat_flags)
2168 .arg("-cg")
2169 .arg("ClippyGroup")
2170 .arg("-dr")
2171 .arg("Clippy")
2172 .arg("-var")
2173 .arg("var.ClippyDir")
2174 .arg("-out")
2175 .arg(exe.join("ClippyGroup.wxs"))
2176 .arg("-t")
2177 .arg(etc.join("msi/remove-duplicates.xsl"))
2178 .run(builder);
2179 }
2180 if built_tools.contains("rustfmt") {
2181 command(&heat)
2182 .current_dir(&exe)
2183 .arg("dir")
2184 .arg("rustfmt")
2185 .args(heat_flags)
2186 .arg("-cg")
2187 .arg("RustFmtGroup")
2188 .arg("-dr")
2189 .arg("RustFmt")
2190 .arg("-var")
2191 .arg("var.RustFmtDir")
2192 .arg("-out")
2193 .arg(exe.join("RustFmtGroup.wxs"))
2194 .arg("-t")
2195 .arg(etc.join("msi/remove-duplicates.xsl"))
2196 .run(builder);
2197 }
2198 if built_tools.contains("miri") {
2199 command(&heat)
2200 .current_dir(&exe)
2201 .arg("dir")
2202 .arg("miri")
2203 .args(heat_flags)
2204 .arg("-cg")
2205 .arg("MiriGroup")
2206 .arg("-dr")
2207 .arg("Miri")
2208 .arg("-var")
2209 .arg("var.MiriDir")
2210 .arg("-out")
2211 .arg(exe.join("MiriGroup.wxs"))
2212 .arg("-t")
2213 .arg(etc.join("msi/remove-duplicates.xsl"))
2214 .run(builder);
2215 }
2216 command(&heat)
2217 .current_dir(&exe)
2218 .arg("dir")
2219 .arg("rust-analysis")
2220 .args(heat_flags)
2221 .arg("-cg")
2222 .arg("AnalysisGroup")
2223 .arg("-dr")
2224 .arg("Analysis")
2225 .arg("-var")
2226 .arg("var.AnalysisDir")
2227 .arg("-out")
2228 .arg(exe.join("AnalysisGroup.wxs"))
2229 .arg("-t")
2230 .arg(etc.join("msi/remove-duplicates.xsl"))
2231 .run(builder);
2232 if target.is_windows_gnu() || target.is_windows_gnullvm() {
2233 command(&heat)
2234 .current_dir(&exe)
2235 .arg("dir")
2236 .arg("rust-mingw")
2237 .args(heat_flags)
2238 .arg("-cg")
2239 .arg("GccGroup")
2240 .arg("-dr")
2241 .arg("Gcc")
2242 .arg("-var")
2243 .arg("var.GccDir")
2244 .arg("-out")
2245 .arg(exe.join("GccGroup.wxs"))
2246 .run(builder);
2247 }
2248
2249 let candle = |input: &Path| {
2250 let output = exe.join(input.file_stem().unwrap()).with_extension("wixobj");
2251 let arch = if target.contains("x86_64") { "x64" } else { "x86" };
2252 let mut cmd = command(&candle);
2253 cmd.current_dir(&exe)
2254 .arg("-nologo")
2255 .arg("-dRustcDir=rustc")
2256 .arg("-dCargoDir=cargo")
2257 .arg("-dStdDir=rust-std")
2258 .arg("-dAnalysisDir=rust-analysis")
2259 .arg("-arch")
2260 .arg(arch)
2261 .arg("-out")
2262 .arg(&output)
2263 .arg(input);
2264 add_env(builder, &mut cmd, target, &built_tools);
2265
2266 if built_tools.contains("clippy") {
2267 cmd.arg("-dClippyDir=clippy");
2268 }
2269 if built_tools.contains("rustfmt") {
2270 cmd.arg("-dRustFmtDir=rustfmt");
2271 }
2272 if built_tools.contains("rust-docs") {
2273 cmd.arg("-dDocsDir=rust-docs");
2274 }
2275 if built_tools.contains("rust-analyzer") {
2276 cmd.arg("-dRustAnalyzerDir=rust-analyzer");
2277 }
2278 if built_tools.contains("miri") {
2279 cmd.arg("-dMiriDir=miri");
2280 }
2281 if target.is_windows_gnu() || target.is_windows_gnullvm() {
2282 cmd.arg("-dGccDir=rust-mingw");
2283 }
2284 cmd.run(builder);
2285 };
2286 candle(&xform(&etc.join("msi/rust.wxs")));
2287 candle(&etc.join("msi/ui.wxs"));
2288 candle(&etc.join("msi/rustwelcomedlg.wxs"));
2289 candle("RustcGroup.wxs".as_ref());
2290 if built_tools.contains("rust-docs") {
2291 candle("DocsGroup.wxs".as_ref());
2292 }
2293 candle("CargoGroup.wxs".as_ref());
2294 candle("StdGroup.wxs".as_ref());
2295 if built_tools.contains("clippy") {
2296 candle("ClippyGroup.wxs".as_ref());
2297 }
2298 if built_tools.contains("rustfmt") {
2299 candle("RustFmtGroup.wxs".as_ref());
2300 }
2301 if built_tools.contains("miri") {
2302 candle("MiriGroup.wxs".as_ref());
2303 }
2304 if built_tools.contains("rust-analyzer") {
2305 candle("RustAnalyzerGroup.wxs".as_ref());
2306 }
2307 candle("AnalysisGroup.wxs".as_ref());
2308
2309 if target.is_windows_gnu() || target.is_windows_gnullvm() {
2310 candle("GccGroup.wxs".as_ref());
2311 }
2312
2313 builder.create(&exe.join("LICENSE.rtf"), &rtf);
2314 builder.install(&etc.join("gfx/banner.bmp"), &exe, FileType::Regular);
2315 builder.install(&etc.join("gfx/dialogbg.bmp"), &exe, FileType::Regular);
2316
2317 builder.info(&format!("building `msi` installer with {light:?}"));
2318 let filename = format!("{}-{}.msi", pkgname(builder, "rust"), target.triple);
2319 let mut cmd = command(&light);
2320 cmd.arg("-nologo")
2321 .arg("-ext")
2322 .arg("WixUIExtension")
2323 .arg("-ext")
2324 .arg("WixUtilExtension")
2325 .arg("-out")
2326 .arg(exe.join(&filename))
2327 .arg("rust.wixobj")
2328 .arg("ui.wixobj")
2329 .arg("rustwelcomedlg.wixobj")
2330 .arg("RustcGroup.wixobj")
2331 .arg("CargoGroup.wixobj")
2332 .arg("StdGroup.wixobj")
2333 .arg("AnalysisGroup.wixobj")
2334 .current_dir(&exe);
2335
2336 if built_tools.contains("clippy") {
2337 cmd.arg("ClippyGroup.wixobj");
2338 }
2339 if built_tools.contains("rustfmt") {
2340 cmd.arg("RustFmtGroup.wixobj");
2341 }
2342 if built_tools.contains("miri") {
2343 cmd.arg("MiriGroup.wixobj");
2344 }
2345 if built_tools.contains("rust-analyzer") {
2346 cmd.arg("RustAnalyzerGroup.wixobj");
2347 }
2348 if built_tools.contains("rust-docs") {
2349 cmd.arg("DocsGroup.wixobj");
2350 }
2351
2352 if target.is_windows_gnu() || target.is_windows_gnullvm() {
2353 cmd.arg("GccGroup.wixobj");
2354 }
2355 cmd.arg("-sice:ICE57");
2357
2358 let _time = timeit(builder);
2359 cmd.run(builder);
2360
2361 if !builder.config.dry_run() {
2362 t!(move_file(exe.join(&filename), distdir(builder).join(&filename)));
2363 }
2364 }
2365 }
2366
2367 fn metadata(&self) -> Option<StepMetadata> {
2368 Some(StepMetadata::dist("extended", self.target).built_by(self.build_compiler))
2369 }
2370}
2371
2372fn add_env(
2373 builder: &Builder<'_>,
2374 cmd: &mut BootstrapCommand,
2375 target: TargetSelection,
2376 built_tools: &HashSet<&'static str>,
2377) {
2378 let mut parts = builder.version.split('.');
2379 cmd.env("CFG_RELEASE_INFO", builder.rust_version())
2380 .env("CFG_RELEASE_NUM", &builder.version)
2381 .env("CFG_RELEASE", builder.rust_release())
2382 .env("CFG_VER_MAJOR", parts.next().unwrap())
2383 .env("CFG_VER_MINOR", parts.next().unwrap())
2384 .env("CFG_VER_PATCH", parts.next().unwrap())
2385 .env("CFG_VER_BUILD", "0") .env("CFG_PACKAGE_VERS", builder.rust_package_vers())
2387 .env("CFG_PACKAGE_NAME", pkgname(builder, "rust"))
2388 .env("CFG_BUILD", target.triple)
2389 .env("CFG_CHANNEL", &builder.config.channel);
2390
2391 if target.is_windows_gnullvm() {
2392 cmd.env("CFG_MINGW", "1").env("CFG_ABI", "LLVM");
2393 } else if target.is_windows_gnu() {
2394 cmd.env("CFG_MINGW", "1").env("CFG_ABI", "GNU");
2395 } else {
2396 cmd.env("CFG_MINGW", "0").env("CFG_ABI", "MSVC");
2397 }
2398
2399 let mut define_optional_tool = |tool_name: &str, env_name: &str| {
2401 cmd.env(env_name, if built_tools.contains(tool_name) { "1" } else { "0" });
2402 };
2403 define_optional_tool("rustfmt", "CFG_RUSTFMT");
2404 define_optional_tool("clippy", "CFG_CLIPPY");
2405 define_optional_tool("miri", "CFG_MIRI");
2406 define_optional_tool("rust-analyzer", "CFG_RA");
2407}
2408
2409fn install_llvm_file(
2410 builder: &Builder<'_>,
2411 source: &Path,
2412 destination: &Path,
2413 install_symlink: bool,
2414) {
2415 if builder.config.dry_run() {
2416 return;
2417 }
2418
2419 if source.is_symlink() {
2420 builder.install(&t!(fs::canonicalize(source)), destination, FileType::NativeLibrary);
2423
2424 let full_dest = destination.join(source.file_name().unwrap());
2425 if install_symlink {
2426 builder.copy_link(source, &full_dest, FileType::NativeLibrary);
2429 } else {
2430 let link = t!(fs::read_link(source));
2434 let mut linker_script = t!(fs::File::create(full_dest));
2435 t!(write!(linker_script, "INPUT({})\n", link.display()));
2436
2437 let meta = t!(fs::metadata(source));
2440 if let Ok(mtime) = meta.modified() {
2441 t!(linker_script.set_modified(mtime));
2442 }
2443 }
2444 } else {
2445 builder.install(source, destination, FileType::NativeLibrary);
2446 }
2447}
2448
2449#[cfg_attr(
2453 feature = "tracing",
2454 instrument(
2455 level = "trace",
2456 name = "maybe_install_llvm",
2457 skip_all,
2458 fields(target = ?target, dst_libdir = ?dst_libdir, install_symlink = install_symlink),
2459 ),
2460)]
2461fn maybe_install_llvm(
2462 builder: &Builder<'_>,
2463 target: TargetSelection,
2464 dst_libdir: &Path,
2465 install_symlink: bool,
2466) -> bool {
2467 if builder.config.is_system_llvm(target) {
2484 trace!("system LLVM requested, no install");
2485 return false;
2486 }
2487
2488 if target.contains("apple-darwin") && builder.llvm_link_shared() {
2494 let src_libdir = builder.llvm_out(target).join("lib");
2495 let llvm_dylib_path = src_libdir.join("libLLVM.dylib");
2496 if llvm_dylib_path.exists() {
2497 builder.install(&llvm_dylib_path, dst_libdir, FileType::NativeLibrary);
2498 }
2499 !builder.config.dry_run()
2500 } else if let llvm::LlvmBuildStatus::AlreadyBuilt(llvm::LlvmResult {
2501 host_llvm_config, ..
2502 }) = llvm::prebuilt_llvm_config(builder, target, true)
2503 {
2504 trace!("LLVM already built, installing LLVM files");
2505 let mut cmd = command(host_llvm_config);
2506 cmd.cached();
2507 cmd.arg("--libfiles");
2508 builder.do_if_verbose(|| println!("running {cmd:?}"));
2509 let files = cmd.run_capture_stdout(builder).stdout();
2510 let build_llvm_out = &builder.llvm_out(builder.config.host_target);
2511 let target_llvm_out = &builder.llvm_out(target);
2512 for file in files.trim_end().split(' ') {
2513 let file = if let Ok(relative_path) = Path::new(file).strip_prefix(build_llvm_out) {
2515 target_llvm_out.join(relative_path)
2516 } else {
2517 PathBuf::from(file)
2518 };
2519 install_llvm_file(builder, &file, dst_libdir, install_symlink);
2520 }
2521 !builder.config.dry_run()
2522 } else {
2523 false
2524 }
2525}
2526
2527#[cfg_attr(
2529 feature = "tracing",
2530 instrument(
2531 level = "trace",
2532 name = "maybe_install_llvm_target",
2533 skip_all,
2534 fields(
2535 llvm_link_shared = ?builder.llvm_link_shared(),
2536 target = ?target,
2537 sysroot = ?sysroot,
2538 ),
2539 ),
2540)]
2541pub fn maybe_install_llvm_target(builder: &Builder<'_>, target: TargetSelection, sysroot: &Path) {
2542 let dst_libdir = sysroot.join("lib/rustlib").join(target).join("lib");
2543 if builder.llvm_link_shared() {
2547 maybe_install_llvm(builder, target, &dst_libdir, false);
2548 }
2549}
2550
2551#[cfg_attr(
2553 feature = "tracing",
2554 instrument(
2555 level = "trace",
2556 name = "maybe_install_llvm_runtime",
2557 skip_all,
2558 fields(
2559 llvm_link_shared = ?builder.llvm_link_shared(),
2560 target = ?target,
2561 sysroot = ?sysroot,
2562 ),
2563 ),
2564)]
2565pub fn maybe_install_llvm_runtime(builder: &Builder<'_>, target: TargetSelection, sysroot: &Path) {
2566 let dst_libdir = sysroot.join(builder.libdir_relative(Compiler::new(1, target)));
2567 if builder.llvm_link_shared() {
2571 maybe_install_llvm(builder, target, &dst_libdir, false);
2572 }
2573}
2574
2575#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2576pub struct LlvmTools {
2577 pub target: TargetSelection,
2578}
2579
2580impl Step for LlvmTools {
2581 type Output = Option<GeneratedTarball>;
2582 const IS_HOST: bool = true;
2583
2584 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2585 let mut run = run.alias("llvm-tools");
2586 for tool in LLVM_TOOLS {
2587 run = run.alias(tool);
2588 }
2589
2590 run
2591 }
2592
2593 fn is_default_step(builder: &Builder<'_>) -> bool {
2594 should_build_extended_tool(builder, "llvm-tools")
2595 }
2596
2597 fn make_run(run: RunConfig<'_>) {
2598 run.builder.ensure(LlvmTools { target: run.target });
2599 }
2600
2601 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2602 fn tools_to_install(paths: &[PathBuf]) -> Vec<&'static str> {
2603 let mut tools = vec![];
2604
2605 for path in paths {
2606 let path = path.to_str().unwrap();
2607
2608 if path == "llvm-tools" {
2610 return LLVM_TOOLS.to_owned();
2611 }
2612
2613 for tool in LLVM_TOOLS {
2614 if path == *tool {
2615 tools.push(*tool);
2616 }
2617 }
2618 }
2619
2620 if tools.is_empty() {
2622 tools = LLVM_TOOLS.to_owned();
2623 }
2624
2625 tools
2626 }
2627
2628 let target = self.target;
2629
2630 if let Some(config) = builder.config.target_config.get(&target)
2632 && !builder.config.llvm_from_ci
2633 && config.llvm_config.is_some()
2634 {
2635 builder.info(&format!("Skipping LlvmTools ({target}): external LLVM"));
2636 return None;
2637 }
2638
2639 if !builder.config.dry_run() {
2640 builder.require_submodule("src/llvm-project", None);
2641 }
2642
2643 builder.ensure(crate::core::build_steps::llvm::Llvm { target });
2644
2645 let mut tarball = Tarball::new(builder, "llvm-tools", &target.triple);
2646 tarball.set_overlay(OverlayKind::Llvm);
2647 tarball.is_preview(true);
2648
2649 if builder.config.llvm_tools_enabled {
2650 let src_bindir = builder.llvm_out(target).join("bin");
2652 let dst_bindir = format!("lib/rustlib/{}/bin", target.triple);
2653 for tool in tools_to_install(&builder.paths) {
2654 let exe = src_bindir.join(exe(tool, target));
2655 if !exe.exists() && builder.config.llvm_from_ci {
2657 eprintln!("{} does not exist; skipping copy", exe.display());
2658 continue;
2659 }
2660
2661 tarball.add_file(&exe, &dst_bindir, FileType::Executable);
2662 }
2663 }
2664
2665 maybe_install_llvm_target(builder, target, tarball.image_dir());
2670
2671 Some(tarball.generate())
2672 }
2673}
2674
2675#[derive(Debug, Clone, Hash, PartialEq, Eq)]
2678pub struct LlvmBitcodeLinker {
2679 pub build_compiler: Compiler,
2681 pub target: TargetSelection,
2683}
2684
2685impl Step for LlvmBitcodeLinker {
2686 type Output = Option<GeneratedTarball>;
2687 const IS_HOST: bool = true;
2688
2689 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2690 run.alias("llvm-bitcode-linker")
2691 }
2692
2693 fn is_default_step(builder: &Builder<'_>) -> bool {
2694 should_build_extended_tool(builder, "llvm-bitcode-linker")
2695 }
2696
2697 fn make_run(run: RunConfig<'_>) {
2698 run.builder.ensure(LlvmBitcodeLinker {
2699 build_compiler: tool::LlvmBitcodeLinker::get_build_compiler_for_target(
2700 run.builder,
2701 run.target,
2702 ),
2703 target: run.target,
2704 });
2705 }
2706
2707 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2708 let target = self.target;
2709
2710 let llbc_linker = builder
2711 .ensure(tool::LlvmBitcodeLinker::from_build_compiler(self.build_compiler, target));
2712
2713 let self_contained_bin_dir = format!("lib/rustlib/{}/bin/self-contained", target.triple);
2714
2715 let mut tarball = Tarball::new(builder, "llvm-bitcode-linker", &target.triple);
2717 tarball.set_overlay(OverlayKind::LlvmBitcodeLinker);
2718 tarball.is_preview(true);
2719
2720 tarball.add_file(&llbc_linker.tool_path, self_contained_bin_dir, FileType::Executable);
2721
2722 Some(tarball.generate())
2723 }
2724}
2725
2726#[derive(Debug, Clone, Hash, PartialEq, Eq)]
2729pub struct Enzyme {
2730 pub target: TargetSelection,
2732}
2733
2734impl Step for Enzyme {
2735 type Output = Option<GeneratedTarball>;
2736 const IS_HOST: bool = true;
2737
2738 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2739 run.alias("enzyme")
2740 }
2741
2742 fn is_default_step(builder: &Builder<'_>) -> bool {
2743 builder.config.llvm_enzyme
2744 }
2745
2746 fn make_run(run: RunConfig<'_>) {
2747 run.builder.ensure(Enzyme { target: run.target });
2748 }
2749
2750 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2751 if !builder.build.unstable_features() {
2755 return None;
2756 }
2757
2758 let target = self.target;
2759
2760 let enzyme = builder.ensure(llvm::Enzyme { target });
2761
2762 let target_libdir = format!("lib/rustlib/{}/lib", target.triple);
2763
2764 let mut tarball = Tarball::new(builder, "enzyme", &target.triple);
2766 tarball.set_overlay(OverlayKind::Enzyme);
2767 tarball.is_preview(true);
2768
2769 tarball.add_file(enzyme.enzyme_path(), target_libdir, FileType::NativeLibrary);
2770
2771 Some(tarball.generate())
2772 }
2773}
2774
2775#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2784pub struct RustDev {
2785 pub target: TargetSelection,
2786}
2787
2788impl Step for RustDev {
2789 type Output = Option<GeneratedTarball>;
2790 const IS_HOST: bool = true;
2791
2792 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2793 run.alias("rust-dev")
2794 }
2795
2796 fn is_default_step(_builder: &Builder<'_>) -> bool {
2797 true
2798 }
2799
2800 fn make_run(run: RunConfig<'_>) {
2801 run.builder.ensure(RustDev { target: run.target });
2802 }
2803
2804 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2805 let target = self.target;
2806
2807 if let Some(config) = builder.config.target_config.get(&target)
2809 && let Some(ref _s) = config.llvm_config
2810 {
2811 builder.info(&format!("Skipping RustDev ({target}): external LLVM"));
2812 return None;
2813 }
2814
2815 if !builder.config.dry_run() {
2816 builder.require_submodule("src/llvm-project", None);
2817 }
2818
2819 let mut tarball = Tarball::new(builder, "rust-dev", &target.triple);
2820 tarball.set_overlay(OverlayKind::Llvm);
2821 tarball.permit_symlinks(true);
2823
2824 builder.ensure(crate::core::build_steps::llvm::Llvm { target });
2825
2826 let src_bindir = builder.llvm_out(target).join("bin");
2827 if src_bindir.exists() {
2833 for entry in walkdir::WalkDir::new(&src_bindir) {
2834 let entry = t!(entry);
2835 if entry.file_type().is_file() && !entry.path_is_symlink() {
2836 let name = entry.file_name().to_str().unwrap();
2837 tarball.add_file(src_bindir.join(name), "bin", FileType::Executable);
2838 }
2839 }
2840 }
2841
2842 if builder.config.lld_enabled {
2843 let lld_out = builder.ensure(crate::core::build_steps::llvm::Lld { target });
2845
2846 let lld_path = lld_out.join("bin").join(exe("lld", target));
2848 if lld_path.exists() {
2849 tarball.add_file(&lld_path, "bin", FileType::Executable);
2850 }
2851 }
2852
2853 tarball.add_file(builder.llvm_filecheck(target), "bin", FileType::Executable);
2854
2855 tarball.add_dir(builder.llvm_out(target).join("include"), "include");
2859
2860 let dst_libdir = tarball.image_dir().join("lib");
2865 maybe_install_llvm(builder, target, &dst_libdir, true);
2866 let link_type = if builder.llvm_link_shared() { "dynamic" } else { "static" };
2867 t!(std::fs::write(tarball.image_dir().join("link-type.txt"), link_type), dst_libdir);
2868
2869 copy_src_dirs(
2873 builder,
2874 &builder.src.join("src").join("llvm-project"),
2875 &["compiler-rt"],
2876 &["compiler-rt/test"],
2879 tarball.image_dir(),
2880 );
2881
2882 Some(tarball.generate())
2883 }
2884}
2885
2886#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2892pub struct Bootstrap {
2893 target: TargetSelection,
2894}
2895
2896impl Step for Bootstrap {
2897 type Output = Option<GeneratedTarball>;
2898
2899 const IS_HOST: bool = true;
2900
2901 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2902 run.alias("bootstrap")
2903 }
2904
2905 fn make_run(run: RunConfig<'_>) {
2906 run.builder.ensure(Bootstrap { target: run.target });
2907 }
2908
2909 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2910 let target = self.target;
2911
2912 let tarball = Tarball::new(builder, "bootstrap", &target.triple);
2913
2914 let bootstrap_outdir = &builder.bootstrap_out;
2915 for file in &["bootstrap", "rustc", "rustdoc"] {
2916 tarball.add_file(
2917 bootstrap_outdir.join(exe(file, target)),
2918 "bootstrap/bin",
2919 FileType::Executable,
2920 );
2921 }
2922
2923 Some(tarball.generate())
2924 }
2925
2926 fn metadata(&self) -> Option<StepMetadata> {
2927 Some(StepMetadata::dist("bootstrap", self.target))
2928 }
2929}
2930
2931#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2936pub struct BuildManifest {
2937 target: TargetSelection,
2938}
2939
2940impl Step for BuildManifest {
2941 type Output = GeneratedTarball;
2942
2943 const IS_HOST: bool = true;
2944
2945 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2946 run.alias("build-manifest")
2947 }
2948
2949 fn make_run(run: RunConfig<'_>) {
2950 run.builder.ensure(BuildManifest { target: run.target });
2951 }
2952
2953 fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
2954 let build_manifest =
2958 builder.ensure(tool::BuildManifest::new(builder, builder.config.host_target));
2959
2960 let tarball = Tarball::new(builder, "build-manifest", &self.target.triple);
2961 tarball.add_file(&build_manifest.tool_path, "bin", FileType::Executable);
2962 tarball.generate()
2963 }
2964
2965 fn metadata(&self) -> Option<StepMetadata> {
2966 Some(StepMetadata::dist("build-manifest", self.target))
2967 }
2968}
2969
2970#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2976pub struct ReproducibleArtifacts {
2977 target: TargetSelection,
2978}
2979
2980impl Step for ReproducibleArtifacts {
2981 type Output = Option<GeneratedTarball>;
2982 const IS_HOST: bool = true;
2983
2984 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2985 run.alias("reproducible-artifacts")
2986 }
2987
2988 fn is_default_step(_builder: &Builder<'_>) -> bool {
2989 true
2990 }
2991
2992 fn make_run(run: RunConfig<'_>) {
2993 run.builder.ensure(ReproducibleArtifacts { target: run.target });
2994 }
2995
2996 fn run(self, builder: &Builder<'_>) -> Self::Output {
2997 let mut added_anything = false;
2998 let tarball = Tarball::new(builder, "reproducible-artifacts", &self.target.triple);
2999 if let Some(path) = builder.config.rust_profile_use.as_ref() {
3000 tarball.add_file(path, ".", FileType::Regular);
3001 added_anything = true;
3002 }
3003 if let Some(path) = builder.config.llvm_profile_use.as_ref() {
3004 tarball.add_file(path, ".", FileType::Regular);
3005 added_anything = true;
3006 }
3007 for profile in &builder.config.reproducible_artifacts {
3008 tarball.add_file(profile, ".", FileType::Regular);
3009 added_anything = true;
3010 }
3011 if added_anything { Some(tarball.generate()) } else { None }
3012 }
3013
3014 fn metadata(&self) -> Option<StepMetadata> {
3015 Some(StepMetadata::dist("reproducible-artifacts", self.target))
3016 }
3017}
3018
3019#[derive(Clone, Debug, Eq, Hash, PartialEq)]
3025pub struct GccDev {
3026 target: TargetSelection,
3027}
3028
3029impl Step for GccDev {
3030 type Output = GeneratedTarball;
3031
3032 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3033 run.alias("gcc-dev")
3034 }
3035
3036 fn make_run(run: RunConfig<'_>) {
3037 run.builder.ensure(GccDev { target: run.target });
3038 }
3039
3040 fn run(self, builder: &Builder<'_>) -> Self::Output {
3041 let tarball = Tarball::new(builder, "gcc-dev", &self.target.triple);
3042 let output = builder
3043 .ensure(super::gcc::Gcc { target_pair: GccTargetPair::for_native_build(self.target) });
3044 tarball.add_file(output.libgccjit(), "lib", FileType::NativeLibrary);
3045 tarball.generate()
3046 }
3047
3048 fn metadata(&self) -> Option<StepMetadata> {
3049 Some(StepMetadata::dist("gcc-dev", self.target))
3050 }
3051}
3052
3053#[derive(Clone, Debug, Eq, Hash, PartialEq)]
3059pub struct Gcc {
3060 host: TargetSelection,
3061 target: TargetSelection,
3062}
3063
3064impl Step for Gcc {
3065 type Output = Option<GeneratedTarball>;
3066
3067 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3068 run.alias("gcc")
3069 }
3070
3071 fn make_run(run: RunConfig<'_>) {
3072 run.builder.ensure(Gcc { host: run.builder.host_target, target: run.target });
3076 }
3077
3078 fn run(self, builder: &Builder<'_>) -> Self::Output {
3079 if !builder.build.unstable_features() {
3083 return None;
3084 }
3085
3086 let host = self.host;
3087 let target = self.target;
3088 if host != "x86_64-unknown-linux-gnu" {
3089 builder.info(&format!("host target `{host}` not supported by gcc. skipping"));
3090 return None;
3091 }
3092
3093 if builder.config.is_running_on_ci() {
3094 assert_eq!(
3095 builder.config.gcc_ci_mode,
3096 GccCiMode::BuildLocally,
3097 "Cannot use gcc.download-ci-gcc when distributing GCC on CI"
3098 );
3099 }
3100
3101 builder.require_submodule(
3104 "src/gcc",
3105 Some("The src/gcc submodule is required for disting libgccjit"),
3106 );
3107
3108 let target_pair = GccTargetPair::for_target_pair(host, target);
3109 let libgccjit = builder.ensure(super::gcc::Gcc { target_pair });
3110
3111 let mut tarball = Tarball::new(builder, &format!("gcc-{target}"), &host.triple);
3115 tarball.set_overlay(OverlayKind::Gcc);
3116 tarball.is_preview(true);
3117 tarball.add_legal_and_readme_to("share/doc/gcc");
3118
3119 let cg_dir = PathBuf::from(format!("lib/rustlib/{host}/codegen-backends"));
3124
3125 let rel_libgccjit_path = libgccjit_path_relative_to_cg_dir(&target_pair, &libgccjit);
3127 let path = cg_dir.join(rel_libgccjit_path.parent().unwrap());
3128
3129 tarball.add_file(libgccjit.libgccjit(), path, FileType::NativeLibrary);
3130 Some(tarball.generate())
3131 }
3132
3133 fn metadata(&self) -> Option<StepMetadata> {
3134 Some(StepMetadata::dist(
3135 "gcc",
3136 TargetSelection::from_user(&format!("({}, {})", self.host, self.target)),
3137 ))
3138 }
3139}