1use std::collections::HashSet;
12use std::ffi::OsStr;
13use std::io::Write;
14use std::path::{Path, PathBuf};
15use std::{env, fs};
16
17use object::BinaryFormat;
18use object::read::archive::ArchiveFile;
19#[cfg(feature = "tracing")]
20use tracing::instrument;
21
22use crate::core::build_steps::compile::{
23 get_codegen_backend_file, libgccjit_path_relative_to_cg_dir, normalize_codegen_backend_name,
24};
25use crate::core::build_steps::doc::DocumentationFormat;
26use crate::core::build_steps::gcc::GccTargetPair;
27use crate::core::build_steps::tool::{
28 self, RustcPrivateCompilers, ToolTargetBuildMode, get_tool_target_compiler,
29};
30use crate::core::build_steps::vendor::Vendor;
31use crate::core::build_steps::{compile, llvm};
32use crate::core::builder::{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 version = builder.rust_info().version(builder.build, &builder.version);
640 let new_text = src_text.replace("<INSERT VERSION HERE>", &version);
641 t!(std::fs::write(&page_dst, &new_text));
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 let vendor = builder.ensure(Vendor {
1216 sync_args: vec![],
1217 versioned_dirs: true,
1218 root_dir: dst_src.clone(),
1219 output_dir: None,
1220 only_library_workspace: true,
1221 });
1222
1223 let library_cargo_config_dir = dst_src.join("library").join(".cargo");
1224 builder.create_dir(&library_cargo_config_dir);
1225 builder.create(&library_cargo_config_dir.join("config.toml"), &vendor.config_library);
1226
1227 tarball.generate()
1228 }
1229
1230 fn metadata(&self) -> Option<StepMetadata> {
1231 Some(StepMetadata::dist("src", TargetSelection::default()))
1232 }
1233}
1234
1235#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1239pub struct PlainSourceTarball;
1240
1241impl Step for PlainSourceTarball {
1242 type Output = GeneratedTarball;
1244 const IS_HOST: bool = true;
1245
1246 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1247 run.alias("rustc-src")
1248 }
1249
1250 fn is_default_step(builder: &Builder<'_>) -> bool {
1251 builder.config.rust_dist_src
1252 }
1253
1254 fn make_run(run: RunConfig<'_>) {
1255 run.builder.ensure(PlainSourceTarball);
1256 }
1257
1258 fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
1260 let tarball = prepare_source_tarball(
1261 builder,
1262 "src",
1263 &[
1264 "src/gcc",
1268 ],
1269 );
1270
1271 let plain_dst_src = tarball.image_dir();
1272 if !builder.config.dry_run() {
1277 builder.create_dir(&plain_dst_src.join("src/gcc"));
1278 t!(std::fs::write(
1279 plain_dst_src.join("src/gcc/notice.txt"),
1280 "The GCC source code is not included due to unclear licensing implications\n"
1281 ));
1282 }
1283 tarball.bare()
1284 }
1285}
1286
1287#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1289pub struct PlainSourceTarballGpl;
1290
1291impl Step for PlainSourceTarballGpl {
1292 type Output = GeneratedTarball;
1294 const IS_HOST: bool = true;
1295
1296 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1297 run.alias("rustc-src-gpl")
1298 }
1299
1300 fn is_default_step(builder: &Builder<'_>) -> bool {
1301 builder.config.rust_dist_src
1302 }
1303
1304 fn make_run(run: RunConfig<'_>) {
1305 run.builder.ensure(PlainSourceTarballGpl);
1306 }
1307
1308 fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
1310 let tarball = prepare_source_tarball(builder, "src-gpl", &[]);
1311 tarball.bare()
1312 }
1313}
1314
1315fn prepare_source_tarball<'a>(
1316 builder: &'a Builder<'a>,
1317 name: &str,
1318 exclude_dirs: &[&str],
1319) -> Tarball<'a> {
1320 let mut tarball = Tarball::new(builder, "rustc", name);
1325 tarball.permit_symlinks(true);
1326 let plain_dst_src = tarball.image_dir();
1327
1328 let src_files = [
1330 ".gitmodules",
1332 "CONTRIBUTING.md",
1333 "COPYRIGHT",
1334 "Cargo.lock",
1335 "Cargo.toml",
1336 "LICENSE-APACHE",
1337 "LICENSE-MIT",
1338 "README.md",
1339 "RELEASES.md",
1340 "REUSE.toml",
1341 "bootstrap.example.toml",
1342 "configure",
1343 "license-metadata.json",
1344 "package.json",
1345 "x",
1346 "x.ps1",
1347 "x.py",
1348 "yarn.lock",
1349 ];
1351 let src_dirs = ["src", "compiler", "library", "tests", "LICENSES"];
1352
1353 copy_src_dirs(builder, &builder.src, &src_dirs, exclude_dirs, plain_dst_src);
1354
1355 for item in &src_files {
1357 builder.copy_link(&builder.src.join(item), &plain_dst_src.join(item), FileType::Regular);
1358 }
1359
1360 builder.create(&plain_dst_src.join("version"), &builder.rust_version());
1362
1363 let write_git_info = |info: Option<&Info>, path: &Path| {
1365 if let Some(info) = info {
1366 t!(std::fs::create_dir_all(path));
1367 channel::write_commit_hash_file(path, &info.sha);
1368 channel::write_commit_info_file(path, info);
1369 }
1370 };
1371 write_git_info(builder.rust_info().info(), plain_dst_src);
1372 write_git_info(builder.cargo_info.info(), &plain_dst_src.join("./src/tools/cargo"));
1373
1374 if builder.config.dist_vendor {
1375 builder.require_and_update_all_submodules();
1376
1377 let pkgs_for_pgo_training =
1379 build_helper::LLVM_PGO_CRATES.iter().chain(build_helper::RUSTC_PGO_CRATES).map(|pkg| {
1380 let mut manifest_path =
1381 builder.src.join("./src/tools/rustc-perf/collector/compile-benchmarks");
1382 manifest_path.push(pkg);
1383 manifest_path.push("Cargo.toml");
1384 manifest_path
1385 });
1386
1387 let vendor = builder.ensure(Vendor {
1389 sync_args: pkgs_for_pgo_training.collect(),
1390 versioned_dirs: true,
1391 root_dir: plain_dst_src.into(),
1392 output_dir: None,
1393 only_library_workspace: false,
1394 });
1395
1396 let cargo_config_dir = plain_dst_src.join(".cargo");
1397 builder.create_dir(&cargo_config_dir);
1398 builder.create(&cargo_config_dir.join("config.toml"), &vendor.config);
1399
1400 let library_cargo_config_dir = plain_dst_src.join("library").join(".cargo");
1401 builder.create_dir(&library_cargo_config_dir);
1402 builder.create(&library_cargo_config_dir.join("config.toml"), &vendor.config_library);
1403 }
1404
1405 for entry in walkdir::WalkDir::new(tarball.image_dir())
1409 .follow_links(true)
1410 .into_iter()
1411 .filter_map(|e| e.ok())
1412 {
1413 if entry.path().is_dir() && entry.path().file_name() == Some(OsStr::new("__pycache__")) {
1414 t!(fs::remove_dir_all(entry.path()));
1415 }
1416 }
1417 tarball
1418}
1419
1420#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1421pub struct Cargo {
1422 pub build_compiler: Compiler,
1423 pub target: TargetSelection,
1424}
1425
1426impl Step for Cargo {
1427 type Output = Option<GeneratedTarball>;
1428 const IS_HOST: bool = true;
1429
1430 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1431 run.alias("cargo")
1432 }
1433
1434 fn is_default_step(builder: &Builder<'_>) -> bool {
1435 should_build_extended_tool(builder, "cargo")
1436 }
1437
1438 fn make_run(run: RunConfig<'_>) {
1439 run.builder.ensure(Cargo {
1440 build_compiler: get_tool_target_compiler(
1441 run.builder,
1442 ToolTargetBuildMode::Build(run.target),
1443 ),
1444 target: run.target,
1445 });
1446 }
1447
1448 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1449 let build_compiler = self.build_compiler;
1450 let target = self.target;
1451
1452 let cargo = builder.ensure(tool::Cargo::from_build_compiler(build_compiler, target));
1453 let src = builder.src.join("src/tools/cargo");
1454 let etc = src.join("src/etc");
1455
1456 let mut tarball = Tarball::new(builder, "cargo", &target.triple);
1458 tarball.set_overlay(OverlayKind::Cargo);
1459
1460 tarball.add_file(&cargo.tool_path, "bin", FileType::Executable);
1461 tarball.add_file(etc.join("_cargo"), "share/zsh/site-functions", FileType::Regular);
1462 tarball.add_renamed_file(
1463 etc.join("cargo.bashcomp.sh"),
1464 "etc/bash_completion.d",
1465 "cargo",
1466 FileType::Regular,
1467 );
1468 tarball.add_dir(etc.join("man"), "share/man/man1");
1469 tarball.add_legal_and_readme_to("share/doc/cargo");
1470
1471 Some(tarball.generate())
1472 }
1473
1474 fn metadata(&self) -> Option<StepMetadata> {
1475 Some(StepMetadata::dist("cargo", self.target).built_by(self.build_compiler))
1476 }
1477}
1478
1479#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1481pub struct RustAnalyzer {
1482 pub compilers: RustcPrivateCompilers,
1483 pub target: TargetSelection,
1484}
1485
1486impl Step for RustAnalyzer {
1487 type Output = Option<GeneratedTarball>;
1488 const IS_HOST: bool = true;
1489
1490 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1491 run.alias("rust-analyzer")
1492 }
1493
1494 fn is_default_step(builder: &Builder<'_>) -> bool {
1495 should_build_extended_tool(builder, "rust-analyzer")
1496 }
1497
1498 fn make_run(run: RunConfig<'_>) {
1499 run.builder.ensure(RustAnalyzer {
1500 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1501 target: run.target,
1502 });
1503 }
1504
1505 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1506 let target = self.target;
1507 let rust_analyzer = builder.ensure(tool::RustAnalyzer::from_compilers(self.compilers));
1508
1509 let mut tarball = Tarball::new(builder, "rust-analyzer", &target.triple);
1510 tarball.set_overlay(OverlayKind::RustAnalyzer);
1511 tarball.is_preview(true);
1512 tarball.add_file(&rust_analyzer.tool_path, "bin", FileType::Executable);
1513 tarball.add_legal_and_readme_to("share/doc/rust-analyzer");
1514 Some(tarball.generate())
1515 }
1516
1517 fn metadata(&self) -> Option<StepMetadata> {
1518 Some(
1519 StepMetadata::dist("rust-analyzer", self.target)
1520 .built_by(self.compilers.build_compiler()),
1521 )
1522 }
1523}
1524
1525#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1526pub struct Clippy {
1527 pub compilers: RustcPrivateCompilers,
1528 pub target: TargetSelection,
1529}
1530
1531impl Step for Clippy {
1532 type Output = Option<GeneratedTarball>;
1533 const IS_HOST: bool = true;
1534
1535 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1536 run.alias("clippy")
1537 }
1538
1539 fn is_default_step(builder: &Builder<'_>) -> bool {
1540 should_build_extended_tool(builder, "clippy")
1541 }
1542
1543 fn make_run(run: RunConfig<'_>) {
1544 run.builder.ensure(Clippy {
1545 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1546 target: run.target,
1547 });
1548 }
1549
1550 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1551 let target = self.target;
1552
1553 let clippy = builder.ensure(tool::Clippy::from_compilers(self.compilers));
1557 let cargoclippy = builder.ensure(tool::CargoClippy::from_compilers(self.compilers));
1558
1559 let mut tarball = Tarball::new(builder, "clippy", &target.triple);
1560 tarball.set_overlay(OverlayKind::Clippy);
1561 tarball.is_preview(true);
1562 tarball.add_file(&clippy.tool_path, "bin", FileType::Executable);
1563 tarball.add_file(&cargoclippy.tool_path, "bin", FileType::Executable);
1564 tarball.add_legal_and_readme_to("share/doc/clippy");
1565 Some(tarball.generate())
1566 }
1567
1568 fn metadata(&self) -> Option<StepMetadata> {
1569 Some(StepMetadata::dist("clippy", self.target).built_by(self.compilers.build_compiler()))
1570 }
1571}
1572
1573#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1574pub struct Miri {
1575 pub compilers: RustcPrivateCompilers,
1576 pub target: TargetSelection,
1577}
1578
1579impl Step for Miri {
1580 type Output = Option<GeneratedTarball>;
1581 const IS_HOST: bool = true;
1582
1583 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1584 run.alias("miri")
1585 }
1586
1587 fn is_default_step(builder: &Builder<'_>) -> bool {
1588 should_build_extended_tool(builder, "miri")
1589 }
1590
1591 fn make_run(run: RunConfig<'_>) {
1592 run.builder.ensure(Miri {
1593 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1594 target: run.target,
1595 });
1596 }
1597
1598 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1599 if !builder.build.unstable_features() {
1603 return None;
1604 }
1605
1606 let miri = builder.ensure(tool::Miri::from_compilers(self.compilers));
1607 let cargomiri = builder.ensure(tool::CargoMiri::from_compilers(self.compilers));
1608
1609 let mut tarball = Tarball::new(builder, "miri", &self.target.triple);
1610 tarball.set_overlay(OverlayKind::Miri);
1611 tarball.is_preview(true);
1612 tarball.add_file(&miri.tool_path, "bin", FileType::Executable);
1613 tarball.add_file(&cargomiri.tool_path, "bin", FileType::Executable);
1614 tarball.add_legal_and_readme_to("share/doc/miri");
1615 Some(tarball.generate())
1616 }
1617
1618 fn metadata(&self) -> Option<StepMetadata> {
1619 Some(StepMetadata::dist("miri", self.target).built_by(self.compilers.build_compiler()))
1620 }
1621}
1622
1623#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1624pub struct CraneliftCodegenBackend {
1625 pub compilers: RustcPrivateCompilers,
1626 pub target: TargetSelection,
1627}
1628
1629impl Step for CraneliftCodegenBackend {
1630 type Output = Option<GeneratedTarball>;
1631 const IS_HOST: bool = true;
1632
1633 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1634 run.alias("rustc_codegen_cranelift")
1635 }
1636
1637 fn is_default_step(builder: &Builder<'_>) -> bool {
1638 builder
1643 .config
1644 .enabled_codegen_backends(builder.host_target)
1645 .contains(&CodegenBackendKind::Cranelift)
1646 }
1647
1648 fn make_run(run: RunConfig<'_>) {
1649 run.builder.ensure(CraneliftCodegenBackend {
1650 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1651 target: run.target,
1652 });
1653 }
1654
1655 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1656 if !builder.build.unstable_features() {
1660 return None;
1661 }
1662
1663 let target = self.target;
1664 if !target_supports_cranelift_backend(target) {
1665 builder.info("target not supported by rustc_codegen_cranelift. skipping");
1666 return None;
1667 }
1668
1669 let mut tarball = Tarball::new(builder, "rustc-codegen-cranelift", &target.triple);
1670 tarball.set_overlay(OverlayKind::RustcCodegenCranelift);
1671 tarball.is_preview(true);
1672 tarball.add_legal_and_readme_to("share/doc/rustc_codegen_cranelift");
1673
1674 let compilers = self.compilers;
1675 let stamp = builder.ensure(compile::CraneliftCodegenBackend { compilers });
1676
1677 if builder.config.dry_run() {
1678 return None;
1679 }
1680
1681 add_codegen_backend_to_tarball(builder, &tarball, compilers.target_compiler(), &stamp);
1682
1683 Some(tarball.generate())
1684 }
1685
1686 fn metadata(&self) -> Option<StepMetadata> {
1687 Some(
1688 StepMetadata::dist("rustc_codegen_cranelift", self.target)
1689 .built_by(self.compilers.build_compiler()),
1690 )
1691 }
1692}
1693
1694#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1698pub struct GccCodegenBackend {
1699 pub compilers: RustcPrivateCompilers,
1700 pub target: TargetSelection,
1701}
1702
1703impl Step for GccCodegenBackend {
1704 type Output = Option<GeneratedTarball>;
1705 const IS_HOST: bool = true;
1706
1707 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1708 run.alias("rustc_codegen_gcc")
1709 }
1710
1711 fn is_default_step(builder: &Builder<'_>) -> bool {
1712 builder
1717 .config
1718 .enabled_codegen_backends(builder.host_target)
1719 .contains(&CodegenBackendKind::Gcc)
1720 }
1721
1722 fn make_run(run: RunConfig<'_>) {
1723 run.builder.ensure(GccCodegenBackend {
1724 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1725 target: run.target,
1726 });
1727 }
1728
1729 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1730 if !builder.build.unstable_features() {
1734 return None;
1735 }
1736
1737 let target = self.target;
1738 if target != "x86_64-unknown-linux-gnu" {
1739 builder
1740 .info(&format!("target `{target}` not supported by rustc_codegen_gcc. skipping"));
1741 return None;
1742 }
1743
1744 let mut tarball = Tarball::new(builder, "rustc-codegen-gcc", &target.triple);
1745 tarball.set_overlay(OverlayKind::RustcCodegenGcc);
1746 tarball.is_preview(true);
1747 tarball.add_legal_and_readme_to("share/doc/rustc_codegen_gcc");
1748
1749 let compilers = self.compilers;
1750 let backend = builder.ensure(compile::GccCodegenBackend::for_target(compilers, target));
1751
1752 if builder.config.dry_run() {
1753 return None;
1754 }
1755
1756 add_codegen_backend_to_tarball(
1757 builder,
1758 &tarball,
1759 compilers.target_compiler(),
1760 backend.stamp(),
1761 );
1762
1763 Some(tarball.generate())
1764 }
1765
1766 fn metadata(&self) -> Option<StepMetadata> {
1767 Some(
1768 StepMetadata::dist("rustc_codegen_gcc", self.target)
1769 .built_by(self.compilers.build_compiler()),
1770 )
1771 }
1772}
1773
1774fn add_codegen_backend_to_tarball(
1777 builder: &Builder<'_>,
1778 tarball: &Tarball<'_>,
1779 compiler: Compiler,
1780 stamp: &BuildStamp,
1781) {
1782 let backends_dst = builder.sysroot_codegen_backends(compiler);
1784 let backends_rel = backends_dst
1785 .strip_prefix(builder.sysroot(compiler))
1786 .unwrap()
1787 .strip_prefix(builder.sysroot_libdir_relative(compiler))
1788 .unwrap();
1789 let backends_dst = PathBuf::from("lib").join(backends_rel);
1791
1792 let codegen_backend_dylib = get_codegen_backend_file(stamp);
1793 tarball.add_renamed_file(
1794 &codegen_backend_dylib,
1795 &backends_dst,
1796 &normalize_codegen_backend_name(builder, &codegen_backend_dylib),
1797 FileType::NativeLibrary,
1798 );
1799}
1800
1801#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1802pub struct Rustfmt {
1803 pub compilers: RustcPrivateCompilers,
1804 pub target: TargetSelection,
1805}
1806
1807impl Step for Rustfmt {
1808 type Output = Option<GeneratedTarball>;
1809 const IS_HOST: bool = true;
1810
1811 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1812 run.alias("rustfmt")
1813 }
1814
1815 fn is_default_step(builder: &Builder<'_>) -> bool {
1816 should_build_extended_tool(builder, "rustfmt")
1817 }
1818
1819 fn make_run(run: RunConfig<'_>) {
1820 run.builder.ensure(Rustfmt {
1821 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1822 target: run.target,
1823 });
1824 }
1825
1826 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1827 let rustfmt = builder.ensure(tool::Rustfmt::from_compilers(self.compilers));
1828 let cargofmt = builder.ensure(tool::Cargofmt::from_compilers(self.compilers));
1829
1830 let mut tarball = Tarball::new(builder, "rustfmt", &self.target.triple);
1831 tarball.set_overlay(OverlayKind::Rustfmt);
1832 tarball.is_preview(true);
1833 tarball.add_file(&rustfmt.tool_path, "bin", FileType::Executable);
1834 tarball.add_file(&cargofmt.tool_path, "bin", FileType::Executable);
1835 tarball.add_legal_and_readme_to("share/doc/rustfmt");
1836 Some(tarball.generate())
1837 }
1838
1839 fn metadata(&self) -> Option<StepMetadata> {
1840 Some(StepMetadata::dist("rustfmt", self.target).built_by(self.compilers.build_compiler()))
1841 }
1842}
1843
1844#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1846pub struct Extended {
1847 build_compiler: Compiler,
1848 target: TargetSelection,
1849}
1850
1851impl Step for Extended {
1852 type Output = ();
1853 const IS_HOST: bool = true;
1854
1855 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1856 run.alias("extended")
1857 }
1858
1859 fn is_default_step(builder: &Builder<'_>) -> bool {
1860 builder.config.extended
1861 }
1862
1863 fn make_run(run: RunConfig<'_>) {
1864 run.builder.ensure(Extended {
1865 build_compiler: run
1866 .builder
1867 .compiler(run.builder.top_stage - 1, run.builder.host_target),
1868 target: run.target,
1869 });
1870 }
1871
1872 fn run(self, builder: &Builder<'_>) {
1874 let target = self.target;
1875 builder.info(&format!("Dist extended stage{} ({target})", builder.top_stage));
1876
1877 let mut tarballs = Vec::new();
1878 let mut built_tools = HashSet::new();
1879 macro_rules! add_component {
1880 ($name:expr => $step:expr) => {
1881 if let Some(Some(tarball)) = builder.ensure_if_default($step, Kind::Dist) {
1882 tarballs.push(tarball);
1883 built_tools.insert($name);
1884 }
1885 };
1886 }
1887
1888 let rustc_private_compilers =
1889 RustcPrivateCompilers::from_build_compiler(builder, self.build_compiler, target);
1890 let build_compiler = rustc_private_compilers.build_compiler();
1891 let target_compiler = rustc_private_compilers.target_compiler();
1892
1893 tarballs.push(builder.ensure(Rustc { target_compiler }));
1898 tarballs.push(builder.ensure(Std { build_compiler, target }).expect("missing std"));
1899
1900 if target.is_windows_gnu() || target.is_windows_gnullvm() {
1901 tarballs.push(builder.ensure(Mingw { target }).expect("missing mingw"));
1902 }
1903
1904 add_component!("rust-docs" => Docs { host: target });
1905 add_component!("rust-json-docs" => JsonDocs { build_compiler: target_compiler, target });
1907 add_component!("cargo" => Cargo { build_compiler, target });
1908 add_component!("rustfmt" => Rustfmt { compilers: rustc_private_compilers, target });
1909 add_component!("rust-analyzer" => RustAnalyzer { compilers: rustc_private_compilers, target });
1910 add_component!("llvm-components" => LlvmTools { target });
1911 add_component!("clippy" => Clippy { compilers: rustc_private_compilers, target });
1912 add_component!("miri" => Miri { compilers: rustc_private_compilers, target });
1913 add_component!("analysis" => Analysis { build_compiler, target });
1914 add_component!("rustc-codegen-cranelift" => CraneliftCodegenBackend {
1915 compilers: rustc_private_compilers,
1916 target
1917 });
1918 add_component!("llvm-bitcode-linker" => LlvmBitcodeLinker {
1919 build_compiler,
1920 target
1921 });
1922
1923 let etc = builder.src.join("src/etc/installer");
1924
1925 if builder.config.dry_run() {
1927 return;
1928 }
1929
1930 let tarball = Tarball::new(builder, "rust", &target.triple);
1931 let generated = tarball.combine(&tarballs);
1932
1933 let tmp = tmpdir(builder).join("combined-tarball");
1934 let work = generated.work_dir();
1935
1936 let mut license = String::new();
1937 license += &builder.read(&builder.src.join("COPYRIGHT"));
1938 license += &builder.read(&builder.src.join("LICENSE-APACHE"));
1939 license += &builder.read(&builder.src.join("LICENSE-MIT"));
1940 license.push('\n');
1941 license.push('\n');
1942
1943 let rtf = r"{\rtf1\ansi\deff0{\fonttbl{\f0\fnil\fcharset0 Arial;}}\nowwrap\fs18";
1944 let mut rtf = rtf.to_string();
1945 rtf.push('\n');
1946 for line in license.lines() {
1947 rtf.push_str(line);
1948 rtf.push_str("\\line ");
1949 }
1950 rtf.push('}');
1951
1952 fn filter(contents: &str, marker: &str) -> String {
1953 let start = format!("tool-{marker}-start");
1954 let end = format!("tool-{marker}-end");
1955 let mut lines = Vec::new();
1956 let mut omitted = false;
1957 for line in contents.lines() {
1958 if line.contains(&start) {
1959 omitted = true;
1960 } else if line.contains(&end) {
1961 omitted = false;
1962 } else if !omitted {
1963 lines.push(line);
1964 }
1965 }
1966
1967 lines.join("\n")
1968 }
1969
1970 let xform = |p: &Path| {
1971 let mut contents = t!(fs::read_to_string(p));
1972 for tool in &["miri", "rust-docs"] {
1973 if !built_tools.contains(tool) {
1974 contents = filter(&contents, tool);
1975 }
1976 }
1977 let ret = tmp.join(p.file_name().unwrap());
1978 t!(fs::write(&ret, &contents));
1979 ret
1980 };
1981
1982 if target.contains("apple-darwin") {
1983 builder.info("building pkg installer");
1984 let pkg = tmp.join("pkg");
1985 let _ = fs::remove_dir_all(&pkg);
1986
1987 let pkgbuild = |component: &str| {
1988 let mut cmd = command("pkgbuild");
1989 cmd.arg("--identifier")
1990 .arg(format!("org.rust-lang.{component}"))
1991 .arg("--scripts")
1992 .arg(pkg.join(component))
1993 .arg("--nopayload")
1994 .arg(pkg.join(component).with_extension("pkg"));
1995 cmd.run(builder);
1996 };
1997
1998 let prepare = |name: &str| {
1999 builder.create_dir(&pkg.join(name));
2000 builder.cp_link_r(
2001 &work.join(format!("{}-{}", pkgname(builder, name), target.triple)),
2002 &pkg.join(name),
2003 );
2004 builder.install(&etc.join("pkg/postinstall"), &pkg.join(name), FileType::Script);
2005 pkgbuild(name);
2006 };
2007 prepare("rustc");
2008 prepare("cargo");
2009 prepare("rust-std");
2010 prepare("rust-analysis");
2011
2012 for tool in &[
2013 "clippy",
2014 "rustfmt",
2015 "rust-analyzer",
2016 "rust-docs",
2017 "miri",
2018 "rustc-codegen-cranelift",
2019 ] {
2020 if built_tools.contains(tool) {
2021 prepare(tool);
2022 }
2023 }
2024 builder.install(&etc.join("pkg/postinstall"), &pkg.join("uninstall"), FileType::Script);
2026 pkgbuild("uninstall");
2027
2028 builder.create_dir(&pkg.join("res"));
2029 builder.create(&pkg.join("res/LICENSE.txt"), &license);
2030 builder.install(&etc.join("gfx/rust-logo.png"), &pkg.join("res"), FileType::Regular);
2031 let mut cmd = command("productbuild");
2032 cmd.arg("--distribution")
2033 .arg(xform(&etc.join("pkg/Distribution.xml")))
2034 .arg("--resources")
2035 .arg(pkg.join("res"))
2036 .arg(distdir(builder).join(format!(
2037 "{}-{}.pkg",
2038 pkgname(builder, "rust"),
2039 target.triple
2040 )))
2041 .arg("--package-path")
2042 .arg(&pkg);
2043 let _time = timeit(builder);
2044 cmd.run(builder);
2045 }
2046
2047 if target.is_windows() {
2048 let exe = tmp.join("exe");
2049 let _ = fs::remove_dir_all(&exe);
2050
2051 let prepare = |name: &str| {
2052 builder.create_dir(&exe.join(name));
2053 let dir = if name == "rust-std" || name == "rust-analysis" {
2054 format!("{}-{}", name, target.triple)
2055 } else if name == "rust-analyzer" {
2056 "rust-analyzer-preview".to_string()
2057 } else if name == "clippy" {
2058 "clippy-preview".to_string()
2059 } else if name == "rustfmt" {
2060 "rustfmt-preview".to_string()
2061 } else if name == "miri" {
2062 "miri-preview".to_string()
2063 } else if name == "rustc-codegen-cranelift" {
2064 unreachable!("cg_clif shouldn't be built for windows");
2067 } else {
2068 name.to_string()
2069 };
2070 builder.cp_link_r(
2071 &work.join(format!("{}-{}", pkgname(builder, name), target.triple)).join(dir),
2072 &exe.join(name),
2073 );
2074 builder.remove(&exe.join(name).join("manifest.in"));
2075 };
2076 prepare("rustc");
2077 prepare("cargo");
2078 prepare("rust-analysis");
2079 prepare("rust-std");
2080 for tool in &["clippy", "rustfmt", "rust-analyzer", "rust-docs", "miri"] {
2081 if built_tools.contains(tool) {
2082 prepare(tool);
2083 }
2084 }
2085 if target.is_windows_gnu() || target.is_windows_gnullvm() {
2086 prepare("rust-mingw");
2087 }
2088
2089 builder.install(&etc.join("gfx/rust-logo.ico"), &exe, FileType::Regular);
2090
2091 let wix_path = env::var_os("WIX")
2093 .expect("`WIX` environment variable must be set for generating MSI installer(s).");
2094 let wix = PathBuf::from(wix_path);
2095 let heat = wix.join("bin/heat.exe");
2096 let candle = wix.join("bin/candle.exe");
2097 let light = wix.join("bin/light.exe");
2098
2099 let heat_flags = ["-nologo", "-gg", "-sfrag", "-srd", "-sreg"];
2100 command(&heat)
2101 .current_dir(&exe)
2102 .arg("dir")
2103 .arg("rustc")
2104 .args(heat_flags)
2105 .arg("-cg")
2106 .arg("RustcGroup")
2107 .arg("-dr")
2108 .arg("Rustc")
2109 .arg("-var")
2110 .arg("var.RustcDir")
2111 .arg("-out")
2112 .arg(exe.join("RustcGroup.wxs"))
2113 .run(builder);
2114 if built_tools.contains("rust-docs") {
2115 command(&heat)
2116 .current_dir(&exe)
2117 .arg("dir")
2118 .arg("rust-docs")
2119 .args(heat_flags)
2120 .arg("-cg")
2121 .arg("DocsGroup")
2122 .arg("-dr")
2123 .arg("Docs")
2124 .arg("-var")
2125 .arg("var.DocsDir")
2126 .arg("-out")
2127 .arg(exe.join("DocsGroup.wxs"))
2128 .arg("-t")
2129 .arg(etc.join("msi/squash-components.xsl"))
2130 .run(builder);
2131 }
2132 command(&heat)
2133 .current_dir(&exe)
2134 .arg("dir")
2135 .arg("cargo")
2136 .args(heat_flags)
2137 .arg("-cg")
2138 .arg("CargoGroup")
2139 .arg("-dr")
2140 .arg("Cargo")
2141 .arg("-var")
2142 .arg("var.CargoDir")
2143 .arg("-out")
2144 .arg(exe.join("CargoGroup.wxs"))
2145 .arg("-t")
2146 .arg(etc.join("msi/remove-duplicates.xsl"))
2147 .run(builder);
2148 command(&heat)
2149 .current_dir(&exe)
2150 .arg("dir")
2151 .arg("rust-std")
2152 .args(heat_flags)
2153 .arg("-cg")
2154 .arg("StdGroup")
2155 .arg("-dr")
2156 .arg("Std")
2157 .arg("-var")
2158 .arg("var.StdDir")
2159 .arg("-out")
2160 .arg(exe.join("StdGroup.wxs"))
2161 .run(builder);
2162 if built_tools.contains("rust-analyzer") {
2163 command(&heat)
2164 .current_dir(&exe)
2165 .arg("dir")
2166 .arg("rust-analyzer")
2167 .args(heat_flags)
2168 .arg("-cg")
2169 .arg("RustAnalyzerGroup")
2170 .arg("-dr")
2171 .arg("RustAnalyzer")
2172 .arg("-var")
2173 .arg("var.RustAnalyzerDir")
2174 .arg("-out")
2175 .arg(exe.join("RustAnalyzerGroup.wxs"))
2176 .arg("-t")
2177 .arg(etc.join("msi/remove-duplicates.xsl"))
2178 .run(builder);
2179 }
2180 if built_tools.contains("clippy") {
2181 command(&heat)
2182 .current_dir(&exe)
2183 .arg("dir")
2184 .arg("clippy")
2185 .args(heat_flags)
2186 .arg("-cg")
2187 .arg("ClippyGroup")
2188 .arg("-dr")
2189 .arg("Clippy")
2190 .arg("-var")
2191 .arg("var.ClippyDir")
2192 .arg("-out")
2193 .arg(exe.join("ClippyGroup.wxs"))
2194 .arg("-t")
2195 .arg(etc.join("msi/remove-duplicates.xsl"))
2196 .run(builder);
2197 }
2198 if built_tools.contains("rustfmt") {
2199 command(&heat)
2200 .current_dir(&exe)
2201 .arg("dir")
2202 .arg("rustfmt")
2203 .args(heat_flags)
2204 .arg("-cg")
2205 .arg("RustFmtGroup")
2206 .arg("-dr")
2207 .arg("RustFmt")
2208 .arg("-var")
2209 .arg("var.RustFmtDir")
2210 .arg("-out")
2211 .arg(exe.join("RustFmtGroup.wxs"))
2212 .arg("-t")
2213 .arg(etc.join("msi/remove-duplicates.xsl"))
2214 .run(builder);
2215 }
2216 if built_tools.contains("miri") {
2217 command(&heat)
2218 .current_dir(&exe)
2219 .arg("dir")
2220 .arg("miri")
2221 .args(heat_flags)
2222 .arg("-cg")
2223 .arg("MiriGroup")
2224 .arg("-dr")
2225 .arg("Miri")
2226 .arg("-var")
2227 .arg("var.MiriDir")
2228 .arg("-out")
2229 .arg(exe.join("MiriGroup.wxs"))
2230 .arg("-t")
2231 .arg(etc.join("msi/remove-duplicates.xsl"))
2232 .run(builder);
2233 }
2234 command(&heat)
2235 .current_dir(&exe)
2236 .arg("dir")
2237 .arg("rust-analysis")
2238 .args(heat_flags)
2239 .arg("-cg")
2240 .arg("AnalysisGroup")
2241 .arg("-dr")
2242 .arg("Analysis")
2243 .arg("-var")
2244 .arg("var.AnalysisDir")
2245 .arg("-out")
2246 .arg(exe.join("AnalysisGroup.wxs"))
2247 .arg("-t")
2248 .arg(etc.join("msi/remove-duplicates.xsl"))
2249 .run(builder);
2250 if target.is_windows_gnu() || target.is_windows_gnullvm() {
2251 command(&heat)
2252 .current_dir(&exe)
2253 .arg("dir")
2254 .arg("rust-mingw")
2255 .args(heat_flags)
2256 .arg("-cg")
2257 .arg("GccGroup")
2258 .arg("-dr")
2259 .arg("Gcc")
2260 .arg("-var")
2261 .arg("var.GccDir")
2262 .arg("-out")
2263 .arg(exe.join("GccGroup.wxs"))
2264 .run(builder);
2265 }
2266
2267 let candle = |input: &Path| {
2268 let output = exe.join(input.file_stem().unwrap()).with_extension("wixobj");
2269 let arch = if target.contains("x86_64") { "x64" } else { "x86" };
2270 let mut cmd = command(&candle);
2271 cmd.current_dir(&exe)
2272 .arg("-nologo")
2273 .arg("-dRustcDir=rustc")
2274 .arg("-dCargoDir=cargo")
2275 .arg("-dStdDir=rust-std")
2276 .arg("-dAnalysisDir=rust-analysis")
2277 .arg("-arch")
2278 .arg(arch)
2279 .arg("-out")
2280 .arg(&output)
2281 .arg(input);
2282 add_env(builder, &mut cmd, target, &built_tools);
2283
2284 if built_tools.contains("clippy") {
2285 cmd.arg("-dClippyDir=clippy");
2286 }
2287 if built_tools.contains("rustfmt") {
2288 cmd.arg("-dRustFmtDir=rustfmt");
2289 }
2290 if built_tools.contains("rust-docs") {
2291 cmd.arg("-dDocsDir=rust-docs");
2292 }
2293 if built_tools.contains("rust-analyzer") {
2294 cmd.arg("-dRustAnalyzerDir=rust-analyzer");
2295 }
2296 if built_tools.contains("miri") {
2297 cmd.arg("-dMiriDir=miri");
2298 }
2299 if target.is_windows_gnu() || target.is_windows_gnullvm() {
2300 cmd.arg("-dGccDir=rust-mingw");
2301 }
2302 cmd.run(builder);
2303 };
2304 candle(&xform(&etc.join("msi/rust.wxs")));
2305 candle(&etc.join("msi/ui.wxs"));
2306 candle(&etc.join("msi/rustwelcomedlg.wxs"));
2307 candle("RustcGroup.wxs".as_ref());
2308 if built_tools.contains("rust-docs") {
2309 candle("DocsGroup.wxs".as_ref());
2310 }
2311 candle("CargoGroup.wxs".as_ref());
2312 candle("StdGroup.wxs".as_ref());
2313 if built_tools.contains("clippy") {
2314 candle("ClippyGroup.wxs".as_ref());
2315 }
2316 if built_tools.contains("rustfmt") {
2317 candle("RustFmtGroup.wxs".as_ref());
2318 }
2319 if built_tools.contains("miri") {
2320 candle("MiriGroup.wxs".as_ref());
2321 }
2322 if built_tools.contains("rust-analyzer") {
2323 candle("RustAnalyzerGroup.wxs".as_ref());
2324 }
2325 candle("AnalysisGroup.wxs".as_ref());
2326
2327 if target.is_windows_gnu() || target.is_windows_gnullvm() {
2328 candle("GccGroup.wxs".as_ref());
2329 }
2330
2331 builder.create(&exe.join("LICENSE.rtf"), &rtf);
2332 builder.install(&etc.join("gfx/banner.bmp"), &exe, FileType::Regular);
2333 builder.install(&etc.join("gfx/dialogbg.bmp"), &exe, FileType::Regular);
2334
2335 builder.info(&format!("building `msi` installer with {light:?}"));
2336 let filename = format!("{}-{}.msi", pkgname(builder, "rust"), target.triple);
2337 let mut cmd = command(&light);
2338 cmd.arg("-nologo")
2339 .arg("-ext")
2340 .arg("WixUIExtension")
2341 .arg("-ext")
2342 .arg("WixUtilExtension")
2343 .arg("-out")
2344 .arg(exe.join(&filename))
2345 .arg("rust.wixobj")
2346 .arg("ui.wixobj")
2347 .arg("rustwelcomedlg.wixobj")
2348 .arg("RustcGroup.wixobj")
2349 .arg("CargoGroup.wixobj")
2350 .arg("StdGroup.wixobj")
2351 .arg("AnalysisGroup.wixobj")
2352 .current_dir(&exe);
2353
2354 if built_tools.contains("clippy") {
2355 cmd.arg("ClippyGroup.wixobj");
2356 }
2357 if built_tools.contains("rustfmt") {
2358 cmd.arg("RustFmtGroup.wixobj");
2359 }
2360 if built_tools.contains("miri") {
2361 cmd.arg("MiriGroup.wixobj");
2362 }
2363 if built_tools.contains("rust-analyzer") {
2364 cmd.arg("RustAnalyzerGroup.wixobj");
2365 }
2366 if built_tools.contains("rust-docs") {
2367 cmd.arg("DocsGroup.wixobj");
2368 }
2369
2370 if target.is_windows_gnu() || target.is_windows_gnullvm() {
2371 cmd.arg("GccGroup.wixobj");
2372 }
2373 cmd.arg("-sice:ICE57");
2375
2376 let _time = timeit(builder);
2377 cmd.run(builder);
2378
2379 if !builder.config.dry_run() {
2380 t!(move_file(exe.join(&filename), distdir(builder).join(&filename)));
2381 }
2382 }
2383 }
2384
2385 fn metadata(&self) -> Option<StepMetadata> {
2386 Some(StepMetadata::dist("extended", self.target).built_by(self.build_compiler))
2387 }
2388}
2389
2390fn add_env(
2391 builder: &Builder<'_>,
2392 cmd: &mut BootstrapCommand,
2393 target: TargetSelection,
2394 built_tools: &HashSet<&'static str>,
2395) {
2396 let mut parts = builder.version.split('.');
2397 cmd.env("CFG_RELEASE_INFO", builder.rust_version())
2398 .env("CFG_RELEASE_NUM", &builder.version)
2399 .env("CFG_RELEASE", builder.rust_release())
2400 .env("CFG_VER_MAJOR", parts.next().unwrap())
2401 .env("CFG_VER_MINOR", parts.next().unwrap())
2402 .env("CFG_VER_PATCH", parts.next().unwrap())
2403 .env("CFG_VER_BUILD", "0") .env("CFG_PACKAGE_VERS", builder.rust_package_vers())
2405 .env("CFG_PACKAGE_NAME", pkgname(builder, "rust"))
2406 .env("CFG_BUILD", target.triple)
2407 .env("CFG_CHANNEL", &builder.config.channel);
2408
2409 if target.is_windows_gnullvm() {
2410 cmd.env("CFG_MINGW", "1").env("CFG_ABI", "LLVM");
2411 } else if target.is_windows_gnu() {
2412 cmd.env("CFG_MINGW", "1").env("CFG_ABI", "GNU");
2413 } else {
2414 cmd.env("CFG_MINGW", "0").env("CFG_ABI", "MSVC");
2415 }
2416
2417 let mut define_optional_tool = |tool_name: &str, env_name: &str| {
2419 cmd.env(env_name, if built_tools.contains(tool_name) { "1" } else { "0" });
2420 };
2421 define_optional_tool("rustfmt", "CFG_RUSTFMT");
2422 define_optional_tool("clippy", "CFG_CLIPPY");
2423 define_optional_tool("miri", "CFG_MIRI");
2424 define_optional_tool("rust-analyzer", "CFG_RA");
2425}
2426
2427fn install_llvm_file(
2428 builder: &Builder<'_>,
2429 source: &Path,
2430 destination: &Path,
2431 install_symlink: bool,
2432) {
2433 if builder.config.dry_run() {
2434 return;
2435 }
2436
2437 if source.is_symlink() {
2438 builder.install(&t!(fs::canonicalize(source)), destination, FileType::NativeLibrary);
2441
2442 let full_dest = destination.join(source.file_name().unwrap());
2443 if install_symlink {
2444 builder.copy_link(source, &full_dest, FileType::NativeLibrary);
2447 } else {
2448 let link = t!(fs::read_link(source));
2452 let mut linker_script = t!(fs::File::create(full_dest));
2453 t!(write!(linker_script, "INPUT({})\n", link.display()));
2454
2455 let meta = t!(fs::metadata(source));
2458 if let Ok(mtime) = meta.modified() {
2459 t!(linker_script.set_modified(mtime));
2460 }
2461 }
2462 } else {
2463 builder.install(source, destination, FileType::NativeLibrary);
2464 }
2465}
2466
2467#[cfg_attr(
2471 feature = "tracing",
2472 instrument(
2473 level = "trace",
2474 name = "maybe_install_llvm",
2475 skip_all,
2476 fields(target = ?target, dst_libdir = ?dst_libdir, install_symlink = install_symlink),
2477 ),
2478)]
2479fn maybe_install_llvm(
2480 builder: &Builder<'_>,
2481 target: TargetSelection,
2482 dst_libdir: &Path,
2483 install_symlink: bool,
2484) -> bool {
2485 if builder.config.is_system_llvm(target) {
2502 trace!("system LLVM requested, no install");
2503 return false;
2504 }
2505
2506 if target.contains("apple-darwin") && builder.llvm_link_shared() {
2512 let src_libdir = builder.llvm_out(target).join("lib");
2513 let llvm_dylib_path = src_libdir.join("libLLVM.dylib");
2514 if llvm_dylib_path.exists() {
2515 builder.install(&llvm_dylib_path, dst_libdir, FileType::NativeLibrary);
2516 }
2517 !builder.config.dry_run()
2518 } else if let llvm::LlvmBuildStatus::AlreadyBuilt(llvm::LlvmResult {
2519 host_llvm_config, ..
2520 }) = llvm::prebuilt_llvm_config(builder, target, true)
2521 {
2522 trace!("LLVM already built, installing LLVM files");
2523 let mut cmd = command(host_llvm_config);
2524 cmd.cached();
2525 cmd.arg("--libfiles");
2526 builder.do_if_verbose(|| println!("running {cmd:?}"));
2527 let files = cmd.run_capture_stdout(builder).stdout();
2528 let build_llvm_out = &builder.llvm_out(builder.config.host_target);
2529 let target_llvm_out = &builder.llvm_out(target);
2530 for file in files.trim_end().split(' ') {
2531 let file = if let Ok(relative_path) = Path::new(file).strip_prefix(build_llvm_out) {
2533 target_llvm_out.join(relative_path)
2534 } else {
2535 PathBuf::from(file)
2536 };
2537 install_llvm_file(builder, &file, dst_libdir, install_symlink);
2538 }
2539 !builder.config.dry_run()
2540 } else {
2541 false
2542 }
2543}
2544
2545#[cfg_attr(
2547 feature = "tracing",
2548 instrument(
2549 level = "trace",
2550 name = "maybe_install_llvm_target",
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_target(builder: &Builder<'_>, target: TargetSelection, sysroot: &Path) {
2560 let dst_libdir = sysroot.join("lib/rustlib").join(target).join("lib");
2561 if builder.llvm_link_shared() {
2565 maybe_install_llvm(builder, target, &dst_libdir, false);
2566 }
2567}
2568
2569#[cfg_attr(
2571 feature = "tracing",
2572 instrument(
2573 level = "trace",
2574 name = "maybe_install_llvm_runtime",
2575 skip_all,
2576 fields(
2577 llvm_link_shared = ?builder.llvm_link_shared(),
2578 target = ?target,
2579 sysroot = ?sysroot,
2580 ),
2581 ),
2582)]
2583pub fn maybe_install_llvm_runtime(builder: &Builder<'_>, target: TargetSelection, sysroot: &Path) {
2584 let dst_libdir = sysroot.join(builder.libdir_relative(Compiler::new(1, target)));
2585 if builder.llvm_link_shared() {
2589 maybe_install_llvm(builder, target, &dst_libdir, false);
2590
2591 if target.triple.contains("windows") {
2595 let dst_libdir = sysroot.join("lib/rustlib").join(target).join("bin");
2596 maybe_install_llvm(builder, target, &dst_libdir, false);
2597 }
2598 }
2599}
2600
2601#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2602pub struct LlvmTools {
2603 pub target: TargetSelection,
2604}
2605
2606impl Step for LlvmTools {
2607 type Output = Option<GeneratedTarball>;
2608 const IS_HOST: bool = true;
2609
2610 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2611 let mut run = run.alias("llvm-tools");
2612 for tool in LLVM_TOOLS {
2613 run = run.alias(tool);
2614 }
2615
2616 run
2617 }
2618
2619 fn is_default_step(builder: &Builder<'_>) -> bool {
2620 should_build_extended_tool(builder, "llvm-tools")
2621 }
2622
2623 fn make_run(run: RunConfig<'_>) {
2624 run.builder.ensure(LlvmTools { target: run.target });
2625 }
2626
2627 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2628 fn tools_to_install(paths: &[PathBuf]) -> Vec<&'static str> {
2629 let mut tools = vec![];
2630
2631 for path in paths {
2632 let path = path.to_str().unwrap();
2633
2634 if path == "llvm-tools" {
2636 return LLVM_TOOLS.to_owned();
2637 }
2638
2639 for tool in LLVM_TOOLS {
2640 if path == *tool {
2641 tools.push(*tool);
2642 }
2643 }
2644 }
2645
2646 if tools.is_empty() {
2648 tools = LLVM_TOOLS.to_owned();
2649 }
2650
2651 tools
2652 }
2653
2654 let target = self.target;
2655
2656 if let Some(config) = builder.config.target_config.get(&target)
2658 && !builder.config.llvm_from_ci
2659 && config.llvm_config.is_some()
2660 {
2661 builder.info(&format!("Skipping LlvmTools ({target}): external LLVM"));
2662 return None;
2663 }
2664
2665 if !builder.config.dry_run() {
2666 builder.require_submodule("src/llvm-project", None);
2667 }
2668
2669 builder.ensure(crate::core::build_steps::llvm::Llvm { target });
2670
2671 let mut tarball = Tarball::new(builder, "llvm-tools", &target.triple);
2672 tarball.set_overlay(OverlayKind::Llvm);
2673 tarball.is_preview(true);
2674
2675 if builder.config.llvm_tools_enabled {
2676 let src_bindir = builder.llvm_out(target).join("bin");
2678 let dst_bindir = format!("lib/rustlib/{}/bin", target.triple);
2679 for tool in tools_to_install(&builder.paths) {
2680 let exe = src_bindir.join(exe(tool, target));
2681 if !exe.exists() && builder.config.llvm_from_ci {
2683 eprintln!("{} does not exist; skipping copy", exe.display());
2684 continue;
2685 }
2686
2687 tarball.add_file(&exe, &dst_bindir, FileType::Executable);
2688 }
2689 }
2690
2691 maybe_install_llvm_target(builder, target, tarball.image_dir());
2696
2697 Some(tarball.generate())
2698 }
2699}
2700
2701#[derive(Debug, Clone, Hash, PartialEq, Eq)]
2704pub struct LlvmBitcodeLinker {
2705 pub build_compiler: Compiler,
2707 pub target: TargetSelection,
2709}
2710
2711impl Step for LlvmBitcodeLinker {
2712 type Output = Option<GeneratedTarball>;
2713 const IS_HOST: bool = true;
2714
2715 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2716 run.alias("llvm-bitcode-linker")
2717 }
2718
2719 fn is_default_step(builder: &Builder<'_>) -> bool {
2720 should_build_extended_tool(builder, "llvm-bitcode-linker")
2721 }
2722
2723 fn make_run(run: RunConfig<'_>) {
2724 run.builder.ensure(LlvmBitcodeLinker {
2725 build_compiler: tool::LlvmBitcodeLinker::get_build_compiler_for_target(
2726 run.builder,
2727 run.target,
2728 ),
2729 target: run.target,
2730 });
2731 }
2732
2733 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2734 let target = self.target;
2735
2736 let llbc_linker = builder
2737 .ensure(tool::LlvmBitcodeLinker::from_build_compiler(self.build_compiler, target));
2738
2739 let self_contained_bin_dir = format!("lib/rustlib/{}/bin/self-contained", target.triple);
2740
2741 let mut tarball = Tarball::new(builder, "llvm-bitcode-linker", &target.triple);
2743 tarball.set_overlay(OverlayKind::LlvmBitcodeLinker);
2744 tarball.is_preview(true);
2745
2746 tarball.add_file(&llbc_linker.tool_path, self_contained_bin_dir, FileType::Executable);
2747
2748 Some(tarball.generate())
2749 }
2750}
2751
2752#[derive(Debug, Clone, Hash, PartialEq, Eq)]
2755pub struct Enzyme {
2756 pub target: TargetSelection,
2758}
2759
2760impl Step for Enzyme {
2761 type Output = Option<GeneratedTarball>;
2762 const IS_HOST: bool = true;
2763
2764 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2765 run.alias("enzyme")
2766 }
2767
2768 fn is_default_step(builder: &Builder<'_>) -> bool {
2769 builder.config.llvm_enzyme
2770 }
2771
2772 fn make_run(run: RunConfig<'_>) {
2773 run.builder.ensure(Enzyme { target: run.target });
2774 }
2775
2776 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2777 if !builder.build.unstable_features() {
2781 return None;
2782 }
2783
2784 let target = self.target;
2785
2786 let enzyme = builder.ensure(llvm::Enzyme { target });
2787
2788 let target_libdir = format!("lib/rustlib/{}/lib", target.triple);
2789
2790 let mut tarball = Tarball::new(builder, "enzyme", &target.triple);
2792 tarball.set_overlay(OverlayKind::Enzyme);
2793 tarball.is_preview(true);
2794
2795 tarball.add_file(enzyme.enzyme_path(), target_libdir, FileType::NativeLibrary);
2796
2797 Some(tarball.generate())
2798 }
2799}
2800
2801#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2810pub struct RustDev {
2811 pub target: TargetSelection,
2812}
2813
2814impl Step for RustDev {
2815 type Output = Option<GeneratedTarball>;
2816 const IS_HOST: bool = true;
2817
2818 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2819 run.alias("rust-dev")
2820 }
2821
2822 fn is_default_step(_builder: &Builder<'_>) -> bool {
2823 true
2824 }
2825
2826 fn make_run(run: RunConfig<'_>) {
2827 run.builder.ensure(RustDev { target: run.target });
2828 }
2829
2830 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2831 let target = self.target;
2832
2833 if let Some(config) = builder.config.target_config.get(&target)
2835 && let Some(ref _s) = config.llvm_config
2836 {
2837 builder.info(&format!("Skipping RustDev ({target}): external LLVM"));
2838 return None;
2839 }
2840
2841 if !builder.config.dry_run() {
2842 builder.require_submodule("src/llvm-project", None);
2843 }
2844
2845 let mut tarball = Tarball::new(builder, "rust-dev", &target.triple);
2846 tarball.set_overlay(OverlayKind::Llvm);
2847 tarball.permit_symlinks(true);
2849
2850 builder.ensure(crate::core::build_steps::llvm::Llvm { target });
2851
2852 let src_bindir = builder.llvm_out(target).join("bin");
2853 if src_bindir.exists() {
2859 for entry in walkdir::WalkDir::new(&src_bindir) {
2860 let entry = t!(entry);
2861 if entry.file_type().is_file() && !entry.path_is_symlink() {
2862 let name = entry.file_name().to_str().unwrap();
2863 tarball.add_file(src_bindir.join(name), "bin", FileType::Executable);
2864 }
2865 }
2866 }
2867
2868 if builder.config.lld_enabled {
2869 let lld_out = builder.ensure(crate::core::build_steps::llvm::Lld { target });
2871
2872 let lld_path = lld_out.join("bin").join(exe("lld", target));
2874 if lld_path.exists() {
2875 tarball.add_file(&lld_path, "bin", FileType::Executable);
2876 }
2877 }
2878
2879 tarball.add_file(builder.llvm_filecheck(target), "bin", FileType::Executable);
2880
2881 tarball.add_dir(builder.llvm_out(target).join("include"), "include");
2885
2886 let dst_libdir = tarball.image_dir().join("lib");
2891 maybe_install_llvm(builder, target, &dst_libdir, true);
2892 let link_type = if builder.llvm_link_shared() { "dynamic" } else { "static" };
2893 t!(std::fs::write(tarball.image_dir().join("link-type.txt"), link_type), dst_libdir);
2894
2895 copy_src_dirs(
2899 builder,
2900 &builder.src.join("src").join("llvm-project"),
2901 &["compiler-rt"],
2902 &["compiler-rt/test"],
2905 tarball.image_dir(),
2906 );
2907
2908 Some(tarball.generate())
2909 }
2910}
2911
2912#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2918pub struct Bootstrap {
2919 target: TargetSelection,
2920}
2921
2922impl Step for Bootstrap {
2923 type Output = Option<GeneratedTarball>;
2924
2925 const IS_HOST: bool = true;
2926
2927 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2928 run.alias("bootstrap")
2929 }
2930
2931 fn make_run(run: RunConfig<'_>) {
2932 run.builder.ensure(Bootstrap { target: run.target });
2933 }
2934
2935 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2936 let target = self.target;
2937
2938 let tarball = Tarball::new(builder, "bootstrap", &target.triple);
2939
2940 let bootstrap_outdir = &builder.bootstrap_out;
2941 for file in &["bootstrap", "rustc", "rustdoc"] {
2942 tarball.add_file(
2943 bootstrap_outdir.join(exe(file, target)),
2944 "bootstrap/bin",
2945 FileType::Executable,
2946 );
2947 }
2948
2949 Some(tarball.generate())
2950 }
2951
2952 fn metadata(&self) -> Option<StepMetadata> {
2953 Some(StepMetadata::dist("bootstrap", self.target))
2954 }
2955}
2956
2957#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2962pub struct BuildManifest {
2963 target: TargetSelection,
2964}
2965
2966impl Step for BuildManifest {
2967 type Output = GeneratedTarball;
2968
2969 const IS_HOST: bool = true;
2970
2971 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2972 run.alias("build-manifest")
2973 }
2974
2975 fn make_run(run: RunConfig<'_>) {
2976 run.builder.ensure(BuildManifest { target: run.target });
2977 }
2978
2979 fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
2980 let build_manifest =
2984 builder.ensure(tool::BuildManifest::new(builder, builder.config.host_target));
2985
2986 let tarball = Tarball::new(builder, "build-manifest", &self.target.triple);
2987 tarball.add_file(&build_manifest.tool_path, "bin", FileType::Executable);
2988 tarball.generate()
2989 }
2990
2991 fn metadata(&self) -> Option<StepMetadata> {
2992 Some(StepMetadata::dist("build-manifest", self.target))
2993 }
2994}
2995
2996#[derive(Clone, Debug, Eq, Hash, PartialEq)]
3002pub struct ReproducibleArtifacts {
3003 target: TargetSelection,
3004}
3005
3006impl Step for ReproducibleArtifacts {
3007 type Output = Option<GeneratedTarball>;
3008 const IS_HOST: bool = true;
3009
3010 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3011 run.alias("reproducible-artifacts")
3012 }
3013
3014 fn is_default_step(_builder: &Builder<'_>) -> bool {
3015 true
3016 }
3017
3018 fn make_run(run: RunConfig<'_>) {
3019 run.builder.ensure(ReproducibleArtifacts { target: run.target });
3020 }
3021
3022 fn run(self, builder: &Builder<'_>) -> Self::Output {
3023 let mut added_anything = false;
3024 let tarball = Tarball::new(builder, "reproducible-artifacts", &self.target.triple);
3025 if let Some(path) = builder.config.rust_profile_use.as_ref() {
3026 tarball.add_file(path, ".", FileType::Regular);
3027 added_anything = true;
3028 }
3029 if let Some(path) = builder.config.llvm_profile_use.as_ref() {
3030 tarball.add_file(path, ".", FileType::Regular);
3031 added_anything = true;
3032 }
3033 for profile in &builder.config.reproducible_artifacts {
3034 tarball.add_file(profile, ".", FileType::Regular);
3035 added_anything = true;
3036 }
3037 if added_anything { Some(tarball.generate()) } else { None }
3038 }
3039
3040 fn metadata(&self) -> Option<StepMetadata> {
3041 Some(StepMetadata::dist("reproducible-artifacts", self.target))
3042 }
3043}
3044
3045#[derive(Clone, Debug, Eq, Hash, PartialEq)]
3051pub struct GccDev {
3052 target: TargetSelection,
3053}
3054
3055impl Step for GccDev {
3056 type Output = GeneratedTarball;
3057
3058 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3059 run.alias("gcc-dev")
3060 }
3061
3062 fn make_run(run: RunConfig<'_>) {
3063 run.builder.ensure(GccDev { target: run.target });
3064 }
3065
3066 fn run(self, builder: &Builder<'_>) -> Self::Output {
3067 let tarball = Tarball::new(builder, "gcc-dev", &self.target.triple);
3068 let output = builder
3069 .ensure(super::gcc::Gcc { target_pair: GccTargetPair::for_native_build(self.target) });
3070 tarball.add_file(output.libgccjit(), "lib", FileType::NativeLibrary);
3071 tarball.generate()
3072 }
3073
3074 fn metadata(&self) -> Option<StepMetadata> {
3075 Some(StepMetadata::dist("gcc-dev", self.target))
3076 }
3077}
3078
3079#[derive(Clone, Debug, Eq, Hash, PartialEq)]
3085pub struct Gcc {
3086 host: TargetSelection,
3087 target: TargetSelection,
3088}
3089
3090impl Step for Gcc {
3091 type Output = Option<GeneratedTarball>;
3092
3093 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3094 run.alias("gcc")
3095 }
3096
3097 fn make_run(run: RunConfig<'_>) {
3098 run.builder.ensure(Gcc { host: run.builder.host_target, target: run.target });
3102 }
3103
3104 fn run(self, builder: &Builder<'_>) -> Self::Output {
3105 if !builder.build.unstable_features() {
3109 return None;
3110 }
3111
3112 let host = self.host;
3113 let target = self.target;
3114 if host != "x86_64-unknown-linux-gnu" {
3115 builder.info(&format!("host target `{host}` not supported by gcc. skipping"));
3116 return None;
3117 }
3118
3119 if builder.config.is_running_on_ci() {
3120 assert_eq!(
3121 builder.config.gcc_ci_mode,
3122 GccCiMode::BuildLocally,
3123 "Cannot use gcc.download-ci-gcc when distributing GCC on CI"
3124 );
3125 }
3126
3127 builder.require_submodule(
3130 "src/gcc",
3131 Some("The src/gcc submodule is required for disting libgccjit"),
3132 );
3133
3134 let target_pair = GccTargetPair::for_target_pair(host, target);
3135 let libgccjit = builder.ensure(super::gcc::Gcc { target_pair });
3136
3137 let mut tarball = Tarball::new(builder, &format!("gcc-{target}"), &host.triple);
3141 tarball.set_overlay(OverlayKind::Gcc);
3142 tarball.is_preview(true);
3143 tarball.add_legal_and_readme_to("share/doc/gcc");
3144
3145 let cg_dir = PathBuf::from(format!("lib/rustlib/{host}/codegen-backends"));
3150
3151 let rel_libgccjit_path = libgccjit_path_relative_to_cg_dir(&target_pair, &libgccjit);
3153 let path = cg_dir.join(rel_libgccjit_path.parent().unwrap());
3154
3155 tarball.add_file(libgccjit.libgccjit(), path, FileType::NativeLibrary);
3156 Some(tarball.generate())
3157 }
3158
3159 fn metadata(&self) -> Option<StepMetadata> {
3160 Some(StepMetadata::dist(
3161 "gcc",
3162 TargetSelection::from_user(&format!("({}, {})", self.host, self.target)),
3163 ))
3164 }
3165}