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