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}
2592
2593#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2594pub struct LlvmTools {
2595 pub target: TargetSelection,
2596}
2597
2598impl Step for LlvmTools {
2599 type Output = Option<GeneratedTarball>;
2600 const IS_HOST: bool = true;
2601
2602 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2603 let mut run = run.alias("llvm-tools");
2604 for tool in LLVM_TOOLS {
2605 run = run.alias(tool);
2606 }
2607
2608 run
2609 }
2610
2611 fn is_default_step(builder: &Builder<'_>) -> bool {
2612 should_build_extended_tool(builder, "llvm-tools")
2613 }
2614
2615 fn make_run(run: RunConfig<'_>) {
2616 run.builder.ensure(LlvmTools { target: run.target });
2617 }
2618
2619 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2620 fn tools_to_install(paths: &[PathBuf]) -> Vec<&'static str> {
2621 let mut tools = vec![];
2622
2623 for path in paths {
2624 let path = path.to_str().unwrap();
2625
2626 if path == "llvm-tools" {
2628 return LLVM_TOOLS.to_owned();
2629 }
2630
2631 for tool in LLVM_TOOLS {
2632 if path == *tool {
2633 tools.push(*tool);
2634 }
2635 }
2636 }
2637
2638 if tools.is_empty() {
2640 tools = LLVM_TOOLS.to_owned();
2641 }
2642
2643 tools
2644 }
2645
2646 let target = self.target;
2647
2648 if let Some(config) = builder.config.target_config.get(&target)
2650 && !builder.config.llvm_from_ci
2651 && config.llvm_config.is_some()
2652 {
2653 builder.info(&format!("Skipping LlvmTools ({target}): external LLVM"));
2654 return None;
2655 }
2656
2657 if !builder.config.dry_run() {
2658 builder.require_submodule("src/llvm-project", None);
2659 }
2660
2661 builder.ensure(crate::core::build_steps::llvm::Llvm { target });
2662
2663 let mut tarball = Tarball::new(builder, "llvm-tools", &target.triple);
2664 tarball.set_overlay(OverlayKind::Llvm);
2665 tarball.is_preview(true);
2666
2667 if builder.config.llvm_tools_enabled {
2668 let src_bindir = builder.llvm_out(target).join("bin");
2670 let dst_bindir = format!("lib/rustlib/{}/bin", target.triple);
2671 for tool in tools_to_install(&builder.paths) {
2672 let exe = src_bindir.join(exe(tool, target));
2673 if !exe.exists() && builder.config.llvm_from_ci {
2675 eprintln!("{} does not exist; skipping copy", exe.display());
2676 continue;
2677 }
2678
2679 tarball.add_file(&exe, &dst_bindir, FileType::Executable);
2680 }
2681 }
2682
2683 maybe_install_llvm_target(builder, target, tarball.image_dir());
2688
2689 Some(tarball.generate())
2690 }
2691}
2692
2693#[derive(Debug, Clone, Hash, PartialEq, Eq)]
2696pub struct LlvmBitcodeLinker {
2697 pub build_compiler: Compiler,
2699 pub target: TargetSelection,
2701}
2702
2703impl Step for LlvmBitcodeLinker {
2704 type Output = Option<GeneratedTarball>;
2705 const IS_HOST: bool = true;
2706
2707 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2708 run.alias("llvm-bitcode-linker")
2709 }
2710
2711 fn is_default_step(builder: &Builder<'_>) -> bool {
2712 should_build_extended_tool(builder, "llvm-bitcode-linker")
2713 }
2714
2715 fn make_run(run: RunConfig<'_>) {
2716 run.builder.ensure(LlvmBitcodeLinker {
2717 build_compiler: tool::LlvmBitcodeLinker::get_build_compiler_for_target(
2718 run.builder,
2719 run.target,
2720 ),
2721 target: run.target,
2722 });
2723 }
2724
2725 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2726 let target = self.target;
2727
2728 let llbc_linker = builder
2729 .ensure(tool::LlvmBitcodeLinker::from_build_compiler(self.build_compiler, target));
2730
2731 let self_contained_bin_dir = format!("lib/rustlib/{}/bin/self-contained", target.triple);
2732
2733 let mut tarball = Tarball::new(builder, "llvm-bitcode-linker", &target.triple);
2735 tarball.set_overlay(OverlayKind::LlvmBitcodeLinker);
2736 tarball.is_preview(true);
2737
2738 tarball.add_file(&llbc_linker.tool_path, self_contained_bin_dir, FileType::Executable);
2739
2740 Some(tarball.generate())
2741 }
2742}
2743
2744#[derive(Debug, Clone, Hash, PartialEq, Eq)]
2747pub struct Enzyme {
2748 pub target: TargetSelection,
2750}
2751
2752impl Step for Enzyme {
2753 type Output = Option<GeneratedTarball>;
2754 const IS_HOST: bool = true;
2755
2756 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2757 run.alias("enzyme")
2758 }
2759
2760 fn is_default_step(builder: &Builder<'_>) -> bool {
2761 builder.config.llvm_enzyme
2762 }
2763
2764 fn make_run(run: RunConfig<'_>) {
2765 run.builder.ensure(Enzyme { target: run.target });
2766 }
2767
2768 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2769 if !builder.build.unstable_features() {
2773 return None;
2774 }
2775
2776 let target = self.target;
2777
2778 let enzyme = builder.ensure(llvm::Enzyme { target });
2779
2780 let target_libdir = format!("lib/rustlib/{}/lib", target.triple);
2781
2782 let mut tarball = Tarball::new(builder, "enzyme", &target.triple);
2784 tarball.set_overlay(OverlayKind::Enzyme);
2785 tarball.is_preview(true);
2786
2787 tarball.add_file(enzyme.enzyme_path(), target_libdir, FileType::NativeLibrary);
2788
2789 Some(tarball.generate())
2790 }
2791}
2792
2793#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2802pub struct RustDev {
2803 pub target: TargetSelection,
2804}
2805
2806impl Step for RustDev {
2807 type Output = Option<GeneratedTarball>;
2808 const IS_HOST: bool = true;
2809
2810 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2811 run.alias("rust-dev")
2812 }
2813
2814 fn is_default_step(_builder: &Builder<'_>) -> bool {
2815 true
2816 }
2817
2818 fn make_run(run: RunConfig<'_>) {
2819 run.builder.ensure(RustDev { target: run.target });
2820 }
2821
2822 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2823 let target = self.target;
2824
2825 if let Some(config) = builder.config.target_config.get(&target)
2827 && let Some(ref _s) = config.llvm_config
2828 {
2829 builder.info(&format!("Skipping RustDev ({target}): external LLVM"));
2830 return None;
2831 }
2832
2833 if !builder.config.dry_run() {
2834 builder.require_submodule("src/llvm-project", None);
2835 }
2836
2837 let mut tarball = Tarball::new(builder, "rust-dev", &target.triple);
2838 tarball.set_overlay(OverlayKind::Llvm);
2839 tarball.permit_symlinks(true);
2841
2842 builder.ensure(crate::core::build_steps::llvm::Llvm { target });
2843
2844 let src_bindir = builder.llvm_out(target).join("bin");
2845 if src_bindir.exists() {
2851 for entry in walkdir::WalkDir::new(&src_bindir) {
2852 let entry = t!(entry);
2853 if entry.file_type().is_file() && !entry.path_is_symlink() {
2854 let name = entry.file_name().to_str().unwrap();
2855 tarball.add_file(src_bindir.join(name), "bin", FileType::Executable);
2856 }
2857 }
2858 }
2859
2860 if builder.config.lld_enabled {
2861 let lld_out = builder.ensure(crate::core::build_steps::llvm::Lld { target });
2863
2864 let lld_path = lld_out.join("bin").join(exe("lld", target));
2866 if lld_path.exists() {
2867 tarball.add_file(&lld_path, "bin", FileType::Executable);
2868 }
2869 }
2870
2871 tarball.add_file(builder.llvm_filecheck(target), "bin", FileType::Executable);
2872
2873 tarball.add_dir(builder.llvm_out(target).join("include"), "include");
2877
2878 let dst_libdir = tarball.image_dir().join("lib");
2883 maybe_install_llvm(builder, target, &dst_libdir, true);
2884 let link_type = if builder.llvm_link_shared() { "dynamic" } else { "static" };
2885 t!(std::fs::write(tarball.image_dir().join("link-type.txt"), link_type), dst_libdir);
2886
2887 copy_src_dirs(
2891 builder,
2892 &builder.src.join("src").join("llvm-project"),
2893 &["compiler-rt"],
2894 &["compiler-rt/test"],
2897 tarball.image_dir(),
2898 );
2899
2900 Some(tarball.generate())
2901 }
2902}
2903
2904#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2910pub struct Bootstrap {
2911 target: TargetSelection,
2912}
2913
2914impl Step for Bootstrap {
2915 type Output = Option<GeneratedTarball>;
2916
2917 const IS_HOST: bool = true;
2918
2919 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2920 run.alias("bootstrap")
2921 }
2922
2923 fn make_run(run: RunConfig<'_>) {
2924 run.builder.ensure(Bootstrap { target: run.target });
2925 }
2926
2927 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2928 let target = self.target;
2929
2930 let tarball = Tarball::new(builder, "bootstrap", &target.triple);
2931
2932 let bootstrap_outdir = &builder.bootstrap_out;
2933 for file in &["bootstrap", "rustc", "rustdoc"] {
2934 tarball.add_file(
2935 bootstrap_outdir.join(exe(file, target)),
2936 "bootstrap/bin",
2937 FileType::Executable,
2938 );
2939 }
2940
2941 Some(tarball.generate())
2942 }
2943
2944 fn metadata(&self) -> Option<StepMetadata> {
2945 Some(StepMetadata::dist("bootstrap", self.target))
2946 }
2947}
2948
2949#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2954pub struct BuildManifest {
2955 target: TargetSelection,
2956}
2957
2958impl Step for BuildManifest {
2959 type Output = GeneratedTarball;
2960
2961 const IS_HOST: bool = true;
2962
2963 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2964 run.alias("build-manifest")
2965 }
2966
2967 fn make_run(run: RunConfig<'_>) {
2968 run.builder.ensure(BuildManifest { target: run.target });
2969 }
2970
2971 fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
2972 let build_manifest =
2976 builder.ensure(tool::BuildManifest::new(builder, builder.config.host_target));
2977
2978 let tarball = Tarball::new(builder, "build-manifest", &self.target.triple);
2979 tarball.add_file(&build_manifest.tool_path, "bin", FileType::Executable);
2980 tarball.generate()
2981 }
2982
2983 fn metadata(&self) -> Option<StepMetadata> {
2984 Some(StepMetadata::dist("build-manifest", self.target))
2985 }
2986}
2987
2988#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2994pub struct ReproducibleArtifacts {
2995 target: TargetSelection,
2996}
2997
2998impl Step for ReproducibleArtifacts {
2999 type Output = Option<GeneratedTarball>;
3000 const IS_HOST: bool = true;
3001
3002 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3003 run.alias("reproducible-artifacts")
3004 }
3005
3006 fn is_default_step(_builder: &Builder<'_>) -> bool {
3007 true
3008 }
3009
3010 fn make_run(run: RunConfig<'_>) {
3011 run.builder.ensure(ReproducibleArtifacts { target: run.target });
3012 }
3013
3014 fn run(self, builder: &Builder<'_>) -> Self::Output {
3015 let mut added_anything = false;
3016 let tarball = Tarball::new(builder, "reproducible-artifacts", &self.target.triple);
3017 if let Some(path) = builder.config.rust_profile_use.as_ref() {
3018 tarball.add_file(path, ".", FileType::Regular);
3019 added_anything = true;
3020 }
3021 if let Some(path) = builder.config.llvm_profile_use.as_ref() {
3022 tarball.add_file(path, ".", FileType::Regular);
3023 added_anything = true;
3024 }
3025 for profile in &builder.config.reproducible_artifacts {
3026 tarball.add_file(profile, ".", FileType::Regular);
3027 added_anything = true;
3028 }
3029 if added_anything { Some(tarball.generate()) } else { None }
3030 }
3031
3032 fn metadata(&self) -> Option<StepMetadata> {
3033 Some(StepMetadata::dist("reproducible-artifacts", self.target))
3034 }
3035}
3036
3037#[derive(Clone, Debug, Eq, Hash, PartialEq)]
3043pub struct GccDev {
3044 target: TargetSelection,
3045}
3046
3047impl Step for GccDev {
3048 type Output = GeneratedTarball;
3049
3050 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3051 run.alias("gcc-dev")
3052 }
3053
3054 fn make_run(run: RunConfig<'_>) {
3055 run.builder.ensure(GccDev { target: run.target });
3056 }
3057
3058 fn run(self, builder: &Builder<'_>) -> Self::Output {
3059 let tarball = Tarball::new(builder, "gcc-dev", &self.target.triple);
3060 let output = builder
3061 .ensure(super::gcc::Gcc { target_pair: GccTargetPair::for_native_build(self.target) });
3062 tarball.add_file(output.libgccjit(), "lib", FileType::NativeLibrary);
3063 tarball.generate()
3064 }
3065
3066 fn metadata(&self) -> Option<StepMetadata> {
3067 Some(StepMetadata::dist("gcc-dev", self.target))
3068 }
3069}
3070
3071#[derive(Clone, Debug, Eq, Hash, PartialEq)]
3077pub struct Gcc {
3078 host: TargetSelection,
3079 target: TargetSelection,
3080}
3081
3082impl Step for Gcc {
3083 type Output = Option<GeneratedTarball>;
3084
3085 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3086 run.alias("gcc")
3087 }
3088
3089 fn make_run(run: RunConfig<'_>) {
3090 run.builder.ensure(Gcc { host: run.builder.host_target, target: run.target });
3094 }
3095
3096 fn run(self, builder: &Builder<'_>) -> Self::Output {
3097 if !builder.build.unstable_features() {
3101 return None;
3102 }
3103
3104 let host = self.host;
3105 let target = self.target;
3106 if host != "x86_64-unknown-linux-gnu" {
3107 builder.info(&format!("host target `{host}` not supported by gcc. skipping"));
3108 return None;
3109 }
3110
3111 if builder.config.is_running_on_ci() {
3112 assert_eq!(
3113 builder.config.gcc_ci_mode,
3114 GccCiMode::BuildLocally,
3115 "Cannot use gcc.download-ci-gcc when distributing GCC on CI"
3116 );
3117 }
3118
3119 builder.require_submodule(
3122 "src/gcc",
3123 Some("The src/gcc submodule is required for disting libgccjit"),
3124 );
3125
3126 let target_pair = GccTargetPair::for_target_pair(host, target);
3127 let libgccjit = builder.ensure(super::gcc::Gcc { target_pair });
3128
3129 let mut tarball = Tarball::new(builder, &format!("gcc-{target}"), &host.triple);
3133 tarball.set_overlay(OverlayKind::Gcc);
3134 tarball.is_preview(true);
3135 tarball.add_legal_and_readme_to("share/doc/gcc");
3136
3137 let cg_dir = PathBuf::from(format!("lib/rustlib/{host}/codegen-backends"));
3142
3143 let rel_libgccjit_path = libgccjit_path_relative_to_cg_dir(&target_pair, &libgccjit);
3145 let path = cg_dir.join(rel_libgccjit_path.parent().unwrap());
3146
3147 tarball.add_file(libgccjit.libgccjit(), path, FileType::NativeLibrary);
3148 Some(tarball.generate())
3149 }
3150
3151 fn metadata(&self) -> Option<StepMetadata> {
3152 Some(StepMetadata::dist(
3153 "gcc",
3154 TargetSelection::from_user(&format!("({}, {})", self.host, self.target)),
3155 ))
3156 }
3157}