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 }
764}
765
766fn skip_host_target_lib(builder: &Builder<'_>, compiler: Compiler) -> bool {
767 if !builder.config.is_host_target(compiler.host) {
770 builder.info("\tskipping, not a build host");
771 true
772 } else {
773 false
774 }
775}
776
777fn verify_uefi_rlib_format(builder: &Builder<'_>, target: TargetSelection, stamp: &BuildStamp) {
781 if !target.ends_with("-uefi") {
782 return;
783 }
784
785 for (path, _) in builder.read_stamp_file(stamp) {
786 if path.extension() != Some(OsStr::new("rlib")) {
787 continue;
788 }
789
790 let data = t!(fs::read(&path));
791 let data = data.as_slice();
792 let archive = t!(ArchiveFile::parse(data));
793 for member in archive.members() {
794 let member = t!(member);
795 let member_data = t!(member.data(data));
796
797 let is_coff = match object::File::parse(member_data) {
798 Ok(member_file) => member_file.format() == BinaryFormat::Coff,
799 Err(_) => false,
800 };
801
802 if !is_coff {
803 let member_name = String::from_utf8_lossy(member.name());
804 panic!("member {} in {} is not COFF", member_name, path.display());
805 }
806 }
807 }
808}
809
810fn copy_target_libs(
812 builder: &Builder<'_>,
813 target: TargetSelection,
814 image: &Path,
815 stamp: &BuildStamp,
816) {
817 let dst = image.join("lib/rustlib").join(target).join("lib");
818 let self_contained_dst = dst.join("self-contained");
819 t!(fs::create_dir_all(&dst));
820 t!(fs::create_dir_all(&self_contained_dst));
821 for (path, dependency_type) in builder.read_stamp_file(stamp) {
822 if dependency_type == DependencyType::TargetSelfContained {
823 builder.copy_link(
824 &path,
825 &self_contained_dst.join(path.file_name().unwrap()),
826 FileType::NativeLibrary,
827 );
828 } else if dependency_type == DependencyType::Target || builder.config.is_host_target(target)
829 {
830 builder.copy_link(&path, &dst.join(path.file_name().unwrap()), FileType::NativeLibrary);
831 }
832 }
833}
834
835#[derive(Debug, Clone, Hash, PartialEq, Eq)]
842pub struct Std {
843 pub build_compiler: Compiler,
845 pub target: TargetSelection,
846}
847
848impl Std {
849 pub fn new(builder: &Builder<'_>, target: TargetSelection) -> Self {
850 Std { build_compiler: builder.compiler_for_std(builder.top_stage), target }
851 }
852}
853
854impl Step for Std {
855 type Output = Option<GeneratedTarball>;
856
857 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
858 run.alias("rust-std")
859 }
860
861 fn is_default_step(_builder: &Builder<'_>) -> bool {
862 true
863 }
864
865 fn make_run(run: RunConfig<'_>) {
866 run.builder.ensure(Std::new(run.builder, run.target));
867 }
868
869 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
870 let build_compiler = self.build_compiler;
871 let target = self.target;
872
873 if skip_host_target_lib(builder, build_compiler) {
874 return None;
875 }
876
877 let stamp =
880 builder.std(build_compiler, target).expect("Standard library has to be built for dist");
881
882 let mut tarball = Tarball::new(builder, "rust-std", &target.triple);
883 tarball.include_target_in_component_name(true);
884
885 verify_uefi_rlib_format(builder, target, &stamp);
886 copy_target_libs(builder, target, tarball.image_dir(), &stamp);
887
888 Some(tarball.generate())
889 }
890
891 fn metadata(&self) -> Option<StepMetadata> {
892 Some(StepMetadata::dist("std", self.target).built_by(self.build_compiler))
893 }
894}
895
896#[derive(Debug, Clone, Hash, PartialEq, Eq)]
901pub struct RustcDev {
902 pub build_compiler: Compiler,
904 pub target: TargetSelection,
905}
906
907impl RustcDev {
908 pub fn new(builder: &Builder<'_>, target: TargetSelection) -> Self {
909 Self {
910 build_compiler: builder.compiler(1, builder.config.host_target),
914 target,
915 }
916 }
917}
918
919impl Step for RustcDev {
920 type Output = Option<GeneratedTarball>;
921 const IS_HOST: bool = true;
922
923 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
924 run.alias("rustc-dev")
925 }
926
927 fn is_default_step(_builder: &Builder<'_>) -> bool {
928 true
929 }
930
931 fn make_run(run: RunConfig<'_>) {
932 run.builder.ensure(RustcDev::new(run.builder, run.target));
933 }
934
935 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
936 let build_compiler = self.build_compiler;
937 let target = self.target;
938 if skip_host_target_lib(builder, build_compiler) {
939 return None;
940 }
941
942 builder.ensure(compile::Rustc::new(build_compiler, target));
944
945 let tarball = Tarball::new(builder, "rustc-dev", &target.triple);
946
947 let stamp = build_stamp::librustc_stamp(builder, build_compiler, target);
948 copy_target_libs(builder, target, tarball.image_dir(), &stamp);
949
950 let src_files = &["Cargo.lock"];
951 copy_src_dirs(
954 builder,
955 &builder.src,
956 &["compiler", "library/proc_macro"],
958 &[],
959 &tarball.image_dir().join("lib/rustlib/rustc-src/rust"),
960 );
961 for file in src_files {
962 tarball.add_file(
963 builder.src.join(file),
964 "lib/rustlib/rustc-src/rust",
965 FileType::Regular,
966 );
967 }
968
969 Some(tarball.generate())
970 }
971
972 fn metadata(&self) -> Option<StepMetadata> {
973 Some(StepMetadata::dist("rustc-dev", self.target).built_by(self.build_compiler))
974 }
975}
976
977#[derive(Debug, Clone, Hash, PartialEq, Eq)]
982pub struct Analysis {
983 build_compiler: Compiler,
984 target: TargetSelection,
985}
986
987impl Step for Analysis {
988 type Output = Option<GeneratedTarball>;
989
990 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
991 run.alias("rust-analysis")
992 }
993
994 fn is_default_step(builder: &Builder<'_>) -> bool {
995 should_build_extended_tool(builder, "analysis")
996 }
997
998 fn make_run(run: RunConfig<'_>) {
999 run.builder.ensure(Analysis {
1001 build_compiler: run.builder.compiler(1, run.builder.config.host_target),
1002 target: run.target,
1003 });
1004 }
1005
1006 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1007 let compiler = self.build_compiler;
1008 let target = self.target;
1009 if skip_host_target_lib(builder, compiler) {
1010 return None;
1011 }
1012
1013 let src = builder
1014 .stage_out(compiler, Mode::Std)
1015 .join(target)
1016 .join(builder.cargo_dir(Mode::Std))
1017 .join("deps")
1018 .join("save-analysis");
1019
1020 t!(std::fs::create_dir_all(&src));
1022 let mut removed = src.clone();
1023 removed.push("removed.json");
1024 let mut f = t!(std::fs::File::create(removed));
1025 t!(write!(f, r#"{{ "warning": "The `rust-analysis` component has been removed." }}"#));
1026
1027 let mut tarball = Tarball::new(builder, "rust-analysis", &target.triple);
1028 tarball.include_target_in_component_name(true);
1029 tarball.add_dir(src, format!("lib/rustlib/{}/analysis", target.triple));
1030 Some(tarball.generate())
1031 }
1032
1033 fn metadata(&self) -> Option<StepMetadata> {
1034 Some(StepMetadata::dist("analysis", self.target).built_by(self.build_compiler))
1035 }
1036}
1037
1038fn copy_src_dirs(
1041 builder: &Builder<'_>,
1042 base: &Path,
1043 src_dirs: &[&str],
1044 exclude_dirs: &[&str],
1045 dst_dir: &Path,
1046) {
1047 for src_dir in src_dirs {
1050 assert!(Path::new(src_dir).is_relative());
1051 }
1052
1053 if builder.config.dry_run() {
1056 return;
1057 }
1058
1059 fn filter_fn(exclude_dirs: &[&str], dir: &str, path: &Path) -> bool {
1060 let spath = match path.to_str() {
1062 Some(path) => path,
1063 None => return false,
1064 };
1065 if spath.ends_with('~') || spath.ends_with(".pyc") {
1066 return false;
1067 }
1068 let spath = spath.replace("\\", "/");
1070
1071 static LLVM_PROJECTS: &[&str] = &[
1072 "llvm-project/clang",
1073 "llvm-project/libunwind",
1074 "llvm-project/lld",
1075 "llvm-project/lldb",
1076 "llvm-project/llvm",
1077 "llvm-project/compiler-rt",
1078 "llvm-project/cmake",
1079 "llvm-project/runtimes",
1080 "llvm-project/third-party",
1081 ];
1082 if spath.starts_with("llvm-project") && spath != "llvm-project" {
1083 if !LLVM_PROJECTS.iter().any(|path| spath.starts_with(path)) {
1084 return false;
1085 }
1086
1087 if spath.starts_with("llvm-project/third-party")
1089 && spath != "llvm-project/third-party"
1090 && !spath.starts_with("llvm-project/third-party/siphash")
1091 {
1092 return false;
1093 }
1094
1095 if spath.starts_with("llvm-project/llvm/test")
1096 && (spath.ends_with(".ll") || spath.ends_with(".td") || spath.ends_with(".s"))
1097 {
1098 return false;
1099 }
1100 }
1101
1102 if spath.starts_with("tools/cargo/tests") {
1104 return true;
1105 }
1106
1107 if !exclude_dirs.is_empty() {
1108 let full_path = Path::new(dir).join(path);
1109 if exclude_dirs.iter().any(|excl| full_path == Path::new(excl)) {
1110 return false;
1111 }
1112 }
1113
1114 static EXCLUDES: &[&str] = &[
1115 "CVS",
1116 "RCS",
1117 "SCCS",
1118 ".git",
1119 ".gitignore",
1120 ".gitmodules",
1121 ".gitattributes",
1122 ".cvsignore",
1123 ".svn",
1124 ".arch-ids",
1125 "{arch}",
1126 "=RELEASE-ID",
1127 "=meta-update",
1128 "=update",
1129 ".bzr",
1130 ".bzrignore",
1131 ".bzrtags",
1132 ".hg",
1133 ".hgignore",
1134 ".hgrags",
1135 "_darcs",
1136 ];
1137
1138 let last_component = path.iter().next_back().map(|s| s.to_str().unwrap()).unwrap();
1145 !EXCLUDES.contains(&last_component)
1146 }
1147
1148 for item in src_dirs {
1150 let dst = &dst_dir.join(item);
1151 t!(fs::create_dir_all(dst));
1152 builder
1153 .cp_link_filtered(&base.join(item), dst, &|path| filter_fn(exclude_dirs, item, path));
1154 }
1155}
1156
1157#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1158pub struct Src;
1159
1160impl Step for Src {
1161 type Output = GeneratedTarball;
1163 const IS_HOST: bool = true;
1164
1165 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1166 run.alias("rust-src")
1167 }
1168
1169 fn is_default_step(_builder: &Builder<'_>) -> bool {
1170 true
1171 }
1172
1173 fn make_run(run: RunConfig<'_>) {
1174 run.builder.ensure(Src);
1175 }
1176
1177 fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
1179 if !builder.config.dry_run() {
1180 builder.require_submodule("src/llvm-project", None);
1181 }
1182
1183 let tarball = Tarball::new_targetless(builder, "rust-src");
1184
1185 let dst_src = tarball.image_dir().join("lib/rustlib/src/rust");
1193
1194 copy_src_dirs(
1197 builder,
1198 &builder.src,
1199 &["library", "src/llvm-project/libunwind"],
1200 &[
1201 "library/backtrace/crates",
1204 ],
1205 &dst_src,
1206 );
1207
1208 let vendor = builder.ensure(Vendor {
1210 sync_args: vec![],
1211 versioned_dirs: true,
1212 root_dir: dst_src.clone(),
1213 output_dir: None,
1214 only_library_workspace: true,
1215 });
1216
1217 let library_cargo_config_dir = dst_src.join("library").join(".cargo");
1218 builder.create_dir(&library_cargo_config_dir);
1219 builder.create(&library_cargo_config_dir.join("config.toml"), &vendor.config_library);
1220
1221 tarball.generate()
1222 }
1223
1224 fn metadata(&self) -> Option<StepMetadata> {
1225 Some(StepMetadata::dist("src", TargetSelection::default()))
1226 }
1227}
1228
1229#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1233pub struct PlainSourceTarball;
1234
1235impl Step for PlainSourceTarball {
1236 type Output = GeneratedTarball;
1238 const IS_HOST: bool = true;
1239
1240 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1241 run.alias("rustc-src")
1242 }
1243
1244 fn is_default_step(builder: &Builder<'_>) -> bool {
1245 builder.config.rust_dist_src
1246 }
1247
1248 fn make_run(run: RunConfig<'_>) {
1249 run.builder.ensure(PlainSourceTarball);
1250 }
1251
1252 fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
1254 let tarball = prepare_source_tarball(
1255 builder,
1256 "src",
1257 &[
1258 "src/gcc",
1262 ],
1263 );
1264
1265 let plain_dst_src = tarball.image_dir();
1266 if !builder.config.dry_run() {
1271 builder.create_dir(&plain_dst_src.join("src/gcc"));
1272 t!(std::fs::write(
1273 plain_dst_src.join("src/gcc/notice.txt"),
1274 "The GCC source code is not included due to unclear licensing implications\n"
1275 ));
1276 }
1277 tarball.bare()
1278 }
1279}
1280
1281#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1283pub struct PlainSourceTarballGpl;
1284
1285impl Step for PlainSourceTarballGpl {
1286 type Output = GeneratedTarball;
1288 const IS_HOST: bool = true;
1289
1290 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1291 run.alias("rustc-src-gpl")
1292 }
1293
1294 fn is_default_step(builder: &Builder<'_>) -> bool {
1295 builder.config.rust_dist_src
1296 }
1297
1298 fn make_run(run: RunConfig<'_>) {
1299 run.builder.ensure(PlainSourceTarballGpl);
1300 }
1301
1302 fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
1304 let tarball = prepare_source_tarball(builder, "src-gpl", &[]);
1305 tarball.bare()
1306 }
1307}
1308
1309fn prepare_source_tarball<'a>(
1310 builder: &'a Builder<'a>,
1311 name: &str,
1312 exclude_dirs: &[&str],
1313) -> Tarball<'a> {
1314 let mut tarball = Tarball::new(builder, "rustc", name);
1319 tarball.permit_symlinks(true);
1320 let plain_dst_src = tarball.image_dir();
1321
1322 let src_files = [
1324 ".gitmodules",
1326 "CONTRIBUTING.md",
1327 "COPYRIGHT",
1328 "Cargo.lock",
1329 "Cargo.toml",
1330 "LICENSE-APACHE",
1331 "LICENSE-MIT",
1332 "README.md",
1333 "RELEASES.md",
1334 "REUSE.toml",
1335 "bootstrap.example.toml",
1336 "configure",
1337 "license-metadata.json",
1338 "package.json",
1339 "x",
1340 "x.ps1",
1341 "x.py",
1342 "yarn.lock",
1343 ];
1345 let src_dirs = ["src", "compiler", "library", "tests", "LICENSES"];
1346
1347 copy_src_dirs(builder, &builder.src, &src_dirs, exclude_dirs, plain_dst_src);
1348
1349 for item in &src_files {
1351 builder.copy_link(&builder.src.join(item), &plain_dst_src.join(item), FileType::Regular);
1352 }
1353
1354 builder.create(&plain_dst_src.join("version"), &builder.rust_version());
1356
1357 let write_git_info = |info: Option<&Info>, path: &Path| {
1359 if let Some(info) = info {
1360 t!(std::fs::create_dir_all(path));
1361 channel::write_commit_hash_file(path, &info.sha);
1362 channel::write_commit_info_file(path, info);
1363 }
1364 };
1365 write_git_info(builder.rust_info().info(), plain_dst_src);
1366 write_git_info(builder.cargo_info.info(), &plain_dst_src.join("./src/tools/cargo"));
1367
1368 if builder.config.dist_vendor {
1369 builder.require_and_update_all_submodules();
1370
1371 let pkgs_for_pgo_training =
1373 build_helper::LLVM_PGO_CRATES.iter().chain(build_helper::RUSTC_PGO_CRATES).map(|pkg| {
1374 let mut manifest_path =
1375 builder.src.join("./src/tools/rustc-perf/collector/compile-benchmarks");
1376 manifest_path.push(pkg);
1377 manifest_path.push("Cargo.toml");
1378 manifest_path
1379 });
1380
1381 let vendor = builder.ensure(Vendor {
1383 sync_args: pkgs_for_pgo_training.collect(),
1384 versioned_dirs: true,
1385 root_dir: plain_dst_src.into(),
1386 output_dir: None,
1387 only_library_workspace: false,
1388 });
1389
1390 let cargo_config_dir = plain_dst_src.join(".cargo");
1391 builder.create_dir(&cargo_config_dir);
1392 builder.create(&cargo_config_dir.join("config.toml"), &vendor.config);
1393
1394 let library_cargo_config_dir = plain_dst_src.join("library").join(".cargo");
1395 builder.create_dir(&library_cargo_config_dir);
1396 builder.create(&library_cargo_config_dir.join("config.toml"), &vendor.config_library);
1397 }
1398
1399 for entry in walkdir::WalkDir::new(tarball.image_dir())
1403 .follow_links(true)
1404 .into_iter()
1405 .filter_map(|e| e.ok())
1406 {
1407 if entry.path().is_dir() && entry.path().file_name() == Some(OsStr::new("__pycache__")) {
1408 t!(fs::remove_dir_all(entry.path()));
1409 }
1410 }
1411 tarball
1412}
1413
1414#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1415pub struct Cargo {
1416 pub build_compiler: Compiler,
1417 pub target: TargetSelection,
1418}
1419
1420impl Step for Cargo {
1421 type Output = Option<GeneratedTarball>;
1422 const IS_HOST: bool = true;
1423
1424 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1425 run.alias("cargo")
1426 }
1427
1428 fn is_default_step(builder: &Builder<'_>) -> bool {
1429 should_build_extended_tool(builder, "cargo")
1430 }
1431
1432 fn make_run(run: RunConfig<'_>) {
1433 run.builder.ensure(Cargo {
1434 build_compiler: get_tool_target_compiler(
1435 run.builder,
1436 ToolTargetBuildMode::Build(run.target),
1437 ),
1438 target: run.target,
1439 });
1440 }
1441
1442 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1443 let build_compiler = self.build_compiler;
1444 let target = self.target;
1445
1446 let cargo = builder.ensure(tool::Cargo::from_build_compiler(build_compiler, target));
1447 let src = builder.src.join("src/tools/cargo");
1448 let etc = src.join("src/etc");
1449
1450 let mut tarball = Tarball::new(builder, "cargo", &target.triple);
1452 tarball.set_overlay(OverlayKind::Cargo);
1453
1454 tarball.add_file(&cargo.tool_path, "bin", FileType::Executable);
1455 tarball.add_file(etc.join("_cargo"), "share/zsh/site-functions", FileType::Regular);
1456 tarball.add_renamed_file(
1457 etc.join("cargo.bashcomp.sh"),
1458 "etc/bash_completion.d",
1459 "cargo",
1460 FileType::Regular,
1461 );
1462 tarball.add_dir(etc.join("man"), "share/man/man1");
1463 tarball.add_legal_and_readme_to("share/doc/cargo");
1464
1465 Some(tarball.generate())
1466 }
1467
1468 fn metadata(&self) -> Option<StepMetadata> {
1469 Some(StepMetadata::dist("cargo", self.target).built_by(self.build_compiler))
1470 }
1471}
1472
1473#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1475pub struct RustAnalyzer {
1476 pub compilers: RustcPrivateCompilers,
1477 pub target: TargetSelection,
1478}
1479
1480impl Step for RustAnalyzer {
1481 type Output = Option<GeneratedTarball>;
1482 const IS_HOST: bool = true;
1483
1484 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1485 run.alias("rust-analyzer")
1486 }
1487
1488 fn is_default_step(builder: &Builder<'_>) -> bool {
1489 should_build_extended_tool(builder, "rust-analyzer")
1490 }
1491
1492 fn make_run(run: RunConfig<'_>) {
1493 run.builder.ensure(RustAnalyzer {
1494 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1495 target: run.target,
1496 });
1497 }
1498
1499 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1500 let target = self.target;
1501 let rust_analyzer = builder.ensure(tool::RustAnalyzer::from_compilers(self.compilers));
1502
1503 let mut tarball = Tarball::new(builder, "rust-analyzer", &target.triple);
1504 tarball.set_overlay(OverlayKind::RustAnalyzer);
1505 tarball.is_preview(true);
1506 tarball.add_file(&rust_analyzer.tool_path, "bin", FileType::Executable);
1507 tarball.add_legal_and_readme_to("share/doc/rust-analyzer");
1508 Some(tarball.generate())
1509 }
1510
1511 fn metadata(&self) -> Option<StepMetadata> {
1512 Some(
1513 StepMetadata::dist("rust-analyzer", self.target)
1514 .built_by(self.compilers.build_compiler()),
1515 )
1516 }
1517}
1518
1519#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1520pub struct Clippy {
1521 pub compilers: RustcPrivateCompilers,
1522 pub target: TargetSelection,
1523}
1524
1525impl Step for Clippy {
1526 type Output = Option<GeneratedTarball>;
1527 const IS_HOST: bool = true;
1528
1529 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1530 run.alias("clippy")
1531 }
1532
1533 fn is_default_step(builder: &Builder<'_>) -> bool {
1534 should_build_extended_tool(builder, "clippy")
1535 }
1536
1537 fn make_run(run: RunConfig<'_>) {
1538 run.builder.ensure(Clippy {
1539 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1540 target: run.target,
1541 });
1542 }
1543
1544 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1545 let target = self.target;
1546
1547 let clippy = builder.ensure(tool::Clippy::from_compilers(self.compilers));
1551 let cargoclippy = builder.ensure(tool::CargoClippy::from_compilers(self.compilers));
1552
1553 let mut tarball = Tarball::new(builder, "clippy", &target.triple);
1554 tarball.set_overlay(OverlayKind::Clippy);
1555 tarball.is_preview(true);
1556 tarball.add_file(&clippy.tool_path, "bin", FileType::Executable);
1557 tarball.add_file(&cargoclippy.tool_path, "bin", FileType::Executable);
1558 tarball.add_legal_and_readme_to("share/doc/clippy");
1559 Some(tarball.generate())
1560 }
1561
1562 fn metadata(&self) -> Option<StepMetadata> {
1563 Some(StepMetadata::dist("clippy", self.target).built_by(self.compilers.build_compiler()))
1564 }
1565}
1566
1567#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1568pub struct Miri {
1569 pub compilers: RustcPrivateCompilers,
1570 pub target: TargetSelection,
1571}
1572
1573impl Step for Miri {
1574 type Output = Option<GeneratedTarball>;
1575 const IS_HOST: bool = true;
1576
1577 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1578 run.alias("miri")
1579 }
1580
1581 fn is_default_step(builder: &Builder<'_>) -> bool {
1582 should_build_extended_tool(builder, "miri")
1583 }
1584
1585 fn make_run(run: RunConfig<'_>) {
1586 run.builder.ensure(Miri {
1587 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1588 target: run.target,
1589 });
1590 }
1591
1592 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1593 if !builder.build.unstable_features() {
1597 return None;
1598 }
1599
1600 let miri = builder.ensure(tool::Miri::from_compilers(self.compilers));
1601 let cargomiri = builder.ensure(tool::CargoMiri::from_compilers(self.compilers));
1602
1603 let mut tarball = Tarball::new(builder, "miri", &self.target.triple);
1604 tarball.set_overlay(OverlayKind::Miri);
1605 tarball.is_preview(true);
1606 tarball.add_file(&miri.tool_path, "bin", FileType::Executable);
1607 tarball.add_file(&cargomiri.tool_path, "bin", FileType::Executable);
1608 tarball.add_legal_and_readme_to("share/doc/miri");
1609 Some(tarball.generate())
1610 }
1611
1612 fn metadata(&self) -> Option<StepMetadata> {
1613 Some(StepMetadata::dist("miri", self.target).built_by(self.compilers.build_compiler()))
1614 }
1615}
1616
1617#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1618pub struct CraneliftCodegenBackend {
1619 pub compilers: RustcPrivateCompilers,
1620 pub target: TargetSelection,
1621}
1622
1623impl Step for CraneliftCodegenBackend {
1624 type Output = Option<GeneratedTarball>;
1625 const IS_HOST: bool = true;
1626
1627 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1628 run.alias("rustc_codegen_cranelift")
1629 }
1630
1631 fn is_default_step(builder: &Builder<'_>) -> bool {
1632 builder
1637 .config
1638 .enabled_codegen_backends(builder.host_target)
1639 .contains(&CodegenBackendKind::Cranelift)
1640 }
1641
1642 fn make_run(run: RunConfig<'_>) {
1643 run.builder.ensure(CraneliftCodegenBackend {
1644 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1645 target: run.target,
1646 });
1647 }
1648
1649 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1650 if !builder.build.unstable_features() {
1654 return None;
1655 }
1656
1657 let target = self.target;
1658 if !target_supports_cranelift_backend(target) {
1659 builder.info("target not supported by rustc_codegen_cranelift. skipping");
1660 return None;
1661 }
1662
1663 let mut tarball = Tarball::new(builder, "rustc-codegen-cranelift", &target.triple);
1664 tarball.set_overlay(OverlayKind::RustcCodegenCranelift);
1665 tarball.is_preview(true);
1666 tarball.add_legal_and_readme_to("share/doc/rustc_codegen_cranelift");
1667
1668 let compilers = self.compilers;
1669 let stamp = builder.ensure(compile::CraneliftCodegenBackend { compilers });
1670
1671 if builder.config.dry_run() {
1672 return None;
1673 }
1674
1675 add_codegen_backend_to_tarball(builder, &tarball, compilers.target_compiler(), &stamp);
1676
1677 Some(tarball.generate())
1678 }
1679
1680 fn metadata(&self) -> Option<StepMetadata> {
1681 Some(
1682 StepMetadata::dist("rustc_codegen_cranelift", self.target)
1683 .built_by(self.compilers.build_compiler()),
1684 )
1685 }
1686}
1687
1688#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1692pub struct GccCodegenBackend {
1693 pub compilers: RustcPrivateCompilers,
1694 pub target: TargetSelection,
1695}
1696
1697impl Step for GccCodegenBackend {
1698 type Output = Option<GeneratedTarball>;
1699 const IS_HOST: bool = true;
1700
1701 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1702 run.alias("rustc_codegen_gcc")
1703 }
1704
1705 fn is_default_step(builder: &Builder<'_>) -> bool {
1706 builder
1711 .config
1712 .enabled_codegen_backends(builder.host_target)
1713 .contains(&CodegenBackendKind::Gcc)
1714 }
1715
1716 fn make_run(run: RunConfig<'_>) {
1717 run.builder.ensure(GccCodegenBackend {
1718 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1719 target: run.target,
1720 });
1721 }
1722
1723 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1724 if !builder.build.unstable_features() {
1728 return None;
1729 }
1730
1731 let target = self.target;
1732 if target != "x86_64-unknown-linux-gnu" {
1733 builder
1734 .info(&format!("target `{target}` not supported by rustc_codegen_gcc. skipping"));
1735 return None;
1736 }
1737
1738 let mut tarball = Tarball::new(builder, "rustc-codegen-gcc", &target.triple);
1739 tarball.set_overlay(OverlayKind::RustcCodegenGcc);
1740 tarball.is_preview(true);
1741 tarball.add_legal_and_readme_to("share/doc/rustc_codegen_gcc");
1742
1743 let compilers = self.compilers;
1744 let backend = builder.ensure(compile::GccCodegenBackend::for_target(compilers, target));
1745
1746 if builder.config.dry_run() {
1747 return None;
1748 }
1749
1750 add_codegen_backend_to_tarball(
1751 builder,
1752 &tarball,
1753 compilers.target_compiler(),
1754 backend.stamp(),
1755 );
1756
1757 Some(tarball.generate())
1758 }
1759
1760 fn metadata(&self) -> Option<StepMetadata> {
1761 Some(
1762 StepMetadata::dist("rustc_codegen_gcc", self.target)
1763 .built_by(self.compilers.build_compiler()),
1764 )
1765 }
1766}
1767
1768fn add_codegen_backend_to_tarball(
1771 builder: &Builder<'_>,
1772 tarball: &Tarball<'_>,
1773 compiler: Compiler,
1774 stamp: &BuildStamp,
1775) {
1776 let backends_dst = builder.sysroot_codegen_backends(compiler);
1778 let backends_rel = backends_dst
1779 .strip_prefix(builder.sysroot(compiler))
1780 .unwrap()
1781 .strip_prefix(builder.sysroot_libdir_relative(compiler))
1782 .unwrap();
1783 let backends_dst = PathBuf::from("lib").join(backends_rel);
1785
1786 let codegen_backend_dylib = get_codegen_backend_file(stamp);
1787 tarball.add_renamed_file(
1788 &codegen_backend_dylib,
1789 &backends_dst,
1790 &normalize_codegen_backend_name(builder, &codegen_backend_dylib),
1791 FileType::NativeLibrary,
1792 );
1793}
1794
1795#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1796pub struct Rustfmt {
1797 pub compilers: RustcPrivateCompilers,
1798 pub target: TargetSelection,
1799}
1800
1801impl Step for Rustfmt {
1802 type Output = Option<GeneratedTarball>;
1803 const IS_HOST: bool = true;
1804
1805 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1806 run.alias("rustfmt")
1807 }
1808
1809 fn is_default_step(builder: &Builder<'_>) -> bool {
1810 should_build_extended_tool(builder, "rustfmt")
1811 }
1812
1813 fn make_run(run: RunConfig<'_>) {
1814 run.builder.ensure(Rustfmt {
1815 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1816 target: run.target,
1817 });
1818 }
1819
1820 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1821 let rustfmt = builder.ensure(tool::Rustfmt::from_compilers(self.compilers));
1822 let cargofmt = builder.ensure(tool::Cargofmt::from_compilers(self.compilers));
1823
1824 let mut tarball = Tarball::new(builder, "rustfmt", &self.target.triple);
1825 tarball.set_overlay(OverlayKind::Rustfmt);
1826 tarball.is_preview(true);
1827 tarball.add_file(&rustfmt.tool_path, "bin", FileType::Executable);
1828 tarball.add_file(&cargofmt.tool_path, "bin", FileType::Executable);
1829 tarball.add_legal_and_readme_to("share/doc/rustfmt");
1830 Some(tarball.generate())
1831 }
1832
1833 fn metadata(&self) -> Option<StepMetadata> {
1834 Some(StepMetadata::dist("rustfmt", self.target).built_by(self.compilers.build_compiler()))
1835 }
1836}
1837
1838#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1840pub struct Extended {
1841 build_compiler: Compiler,
1842 target: TargetSelection,
1843}
1844
1845impl Step for Extended {
1846 type Output = ();
1847 const IS_HOST: bool = true;
1848
1849 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1850 run.alias("extended")
1851 }
1852
1853 fn is_default_step(builder: &Builder<'_>) -> bool {
1854 builder.config.extended
1855 }
1856
1857 fn make_run(run: RunConfig<'_>) {
1858 run.builder.ensure(Extended {
1859 build_compiler: run
1860 .builder
1861 .compiler(run.builder.top_stage - 1, run.builder.host_target),
1862 target: run.target,
1863 });
1864 }
1865
1866 fn run(self, builder: &Builder<'_>) {
1868 let target = self.target;
1869 builder.info(&format!("Dist extended stage{} ({target})", builder.top_stage));
1870
1871 let mut tarballs = Vec::new();
1872 let mut built_tools = HashSet::new();
1873 macro_rules! add_component {
1874 ($name:expr => $step:expr) => {
1875 if let Some(Some(tarball)) = builder.ensure_if_default($step, Kind::Dist) {
1876 tarballs.push(tarball);
1877 built_tools.insert($name);
1878 }
1879 };
1880 }
1881
1882 let rustc_private_compilers =
1883 RustcPrivateCompilers::from_build_compiler(builder, self.build_compiler, target);
1884 let build_compiler = rustc_private_compilers.build_compiler();
1885 let target_compiler = rustc_private_compilers.target_compiler();
1886
1887 tarballs.push(builder.ensure(Rustc { target_compiler }));
1892 tarballs.push(builder.ensure(Std { build_compiler, target }).expect("missing std"));
1893
1894 if target.is_windows_gnu() || target.is_windows_gnullvm() {
1895 tarballs.push(builder.ensure(Mingw { target }).expect("missing mingw"));
1896 }
1897
1898 add_component!("rust-docs" => Docs { host: target });
1899 add_component!("rust-json-docs" => JsonDocs { build_compiler: target_compiler, target });
1901 add_component!("cargo" => Cargo { build_compiler, target });
1902 add_component!("rustfmt" => Rustfmt { compilers: rustc_private_compilers, target });
1903 add_component!("rust-analyzer" => RustAnalyzer { compilers: rustc_private_compilers, target });
1904 add_component!("llvm-components" => LlvmTools { target });
1905 add_component!("clippy" => Clippy { compilers: rustc_private_compilers, target });
1906 add_component!("miri" => Miri { compilers: rustc_private_compilers, target });
1907 add_component!("analysis" => Analysis { build_compiler, target });
1908 add_component!("rustc-codegen-cranelift" => CraneliftCodegenBackend {
1909 compilers: rustc_private_compilers,
1910 target
1911 });
1912 add_component!("llvm-bitcode-linker" => LlvmBitcodeLinker {
1913 build_compiler,
1914 target
1915 });
1916
1917 let etc = builder.src.join("src/etc/installer");
1918
1919 if builder.config.dry_run() {
1921 return;
1922 }
1923
1924 let tarball = Tarball::new(builder, "rust", &target.triple);
1925 let generated = tarball.combine(&tarballs);
1926
1927 let tmp = tmpdir(builder).join("combined-tarball");
1928 let work = generated.work_dir();
1929
1930 let mut license = String::new();
1931 license += &builder.read(&builder.src.join("COPYRIGHT"));
1932 license += &builder.read(&builder.src.join("LICENSE-APACHE"));
1933 license += &builder.read(&builder.src.join("LICENSE-MIT"));
1934 license.push('\n');
1935 license.push('\n');
1936
1937 let rtf = r"{\rtf1\ansi\deff0{\fonttbl{\f0\fnil\fcharset0 Arial;}}\nowwrap\fs18";
1938 let mut rtf = rtf.to_string();
1939 rtf.push('\n');
1940 for line in license.lines() {
1941 rtf.push_str(line);
1942 rtf.push_str("\\line ");
1943 }
1944 rtf.push('}');
1945
1946 fn filter(contents: &str, marker: &str) -> String {
1947 let start = format!("tool-{marker}-start");
1948 let end = format!("tool-{marker}-end");
1949 let mut lines = Vec::new();
1950 let mut omitted = false;
1951 for line in contents.lines() {
1952 if line.contains(&start) {
1953 omitted = true;
1954 } else if line.contains(&end) {
1955 omitted = false;
1956 } else if !omitted {
1957 lines.push(line);
1958 }
1959 }
1960
1961 lines.join("\n")
1962 }
1963
1964 let xform = |p: &Path| {
1965 let mut contents = t!(fs::read_to_string(p));
1966 for tool in &["miri", "rust-docs"] {
1967 if !built_tools.contains(tool) {
1968 contents = filter(&contents, tool);
1969 }
1970 }
1971 let ret = tmp.join(p.file_name().unwrap());
1972 t!(fs::write(&ret, &contents));
1973 ret
1974 };
1975
1976 if target.contains("apple-darwin") {
1977 builder.info("building pkg installer");
1978 let pkg = tmp.join("pkg");
1979 let _ = fs::remove_dir_all(&pkg);
1980
1981 let pkgbuild = |component: &str| {
1982 let mut cmd = command("pkgbuild");
1983 cmd.arg("--identifier")
1984 .arg(format!("org.rust-lang.{component}"))
1985 .arg("--scripts")
1986 .arg(pkg.join(component))
1987 .arg("--nopayload")
1988 .arg(pkg.join(component).with_extension("pkg"));
1989 cmd.run(builder);
1990 };
1991
1992 let prepare = |name: &str| {
1993 builder.create_dir(&pkg.join(name));
1994 builder.cp_link_r(
1995 &work.join(format!("{}-{}", pkgname(builder, name), target.triple)),
1996 &pkg.join(name),
1997 );
1998 builder.install(&etc.join("pkg/postinstall"), &pkg.join(name), FileType::Script);
1999 pkgbuild(name);
2000 };
2001 prepare("rustc");
2002 prepare("cargo");
2003 prepare("rust-std");
2004 prepare("rust-analysis");
2005
2006 for tool in &[
2007 "clippy",
2008 "rustfmt",
2009 "rust-analyzer",
2010 "rust-docs",
2011 "miri",
2012 "rustc-codegen-cranelift",
2013 ] {
2014 if built_tools.contains(tool) {
2015 prepare(tool);
2016 }
2017 }
2018 builder.install(&etc.join("pkg/postinstall"), &pkg.join("uninstall"), FileType::Script);
2020 pkgbuild("uninstall");
2021
2022 builder.create_dir(&pkg.join("res"));
2023 builder.create(&pkg.join("res/LICENSE.txt"), &license);
2024 builder.install(&etc.join("gfx/rust-logo.png"), &pkg.join("res"), FileType::Regular);
2025 let mut cmd = command("productbuild");
2026 cmd.arg("--distribution")
2027 .arg(xform(&etc.join("pkg/Distribution.xml")))
2028 .arg("--resources")
2029 .arg(pkg.join("res"))
2030 .arg(distdir(builder).join(format!(
2031 "{}-{}.pkg",
2032 pkgname(builder, "rust"),
2033 target.triple
2034 )))
2035 .arg("--package-path")
2036 .arg(&pkg);
2037 let _time = timeit(builder);
2038 cmd.run(builder);
2039 }
2040
2041 if target.is_windows() {
2042 let exe = tmp.join("exe");
2043 let _ = fs::remove_dir_all(&exe);
2044
2045 let prepare = |name: &str| {
2046 builder.create_dir(&exe.join(name));
2047 let dir = if name == "rust-std" || name == "rust-analysis" {
2048 format!("{}-{}", name, target.triple)
2049 } else if name == "rust-analyzer" {
2050 "rust-analyzer-preview".to_string()
2051 } else if name == "clippy" {
2052 "clippy-preview".to_string()
2053 } else if name == "rustfmt" {
2054 "rustfmt-preview".to_string()
2055 } else if name == "miri" {
2056 "miri-preview".to_string()
2057 } else if name == "rustc-codegen-cranelift" {
2058 unreachable!("cg_clif shouldn't be built for windows");
2061 } else {
2062 name.to_string()
2063 };
2064 builder.cp_link_r(
2065 &work.join(format!("{}-{}", pkgname(builder, name), target.triple)).join(dir),
2066 &exe.join(name),
2067 );
2068 builder.remove(&exe.join(name).join("manifest.in"));
2069 };
2070 prepare("rustc");
2071 prepare("cargo");
2072 prepare("rust-analysis");
2073 prepare("rust-std");
2074 for tool in &["clippy", "rustfmt", "rust-analyzer", "rust-docs", "miri"] {
2075 if built_tools.contains(tool) {
2076 prepare(tool);
2077 }
2078 }
2079 if target.is_windows_gnu() || target.is_windows_gnullvm() {
2080 prepare("rust-mingw");
2081 }
2082
2083 builder.install(&etc.join("gfx/rust-logo.ico"), &exe, FileType::Regular);
2084
2085 let wix_path = env::var_os("WIX")
2087 .expect("`WIX` environment variable must be set for generating MSI installer(s).");
2088 let wix = PathBuf::from(wix_path);
2089 let heat = wix.join("bin/heat.exe");
2090 let candle = wix.join("bin/candle.exe");
2091 let light = wix.join("bin/light.exe");
2092
2093 let heat_flags = ["-nologo", "-gg", "-sfrag", "-srd", "-sreg"];
2094 command(&heat)
2095 .current_dir(&exe)
2096 .arg("dir")
2097 .arg("rustc")
2098 .args(heat_flags)
2099 .arg("-cg")
2100 .arg("RustcGroup")
2101 .arg("-dr")
2102 .arg("Rustc")
2103 .arg("-var")
2104 .arg("var.RustcDir")
2105 .arg("-out")
2106 .arg(exe.join("RustcGroup.wxs"))
2107 .run(builder);
2108 if built_tools.contains("rust-docs") {
2109 command(&heat)
2110 .current_dir(&exe)
2111 .arg("dir")
2112 .arg("rust-docs")
2113 .args(heat_flags)
2114 .arg("-cg")
2115 .arg("DocsGroup")
2116 .arg("-dr")
2117 .arg("Docs")
2118 .arg("-var")
2119 .arg("var.DocsDir")
2120 .arg("-out")
2121 .arg(exe.join("DocsGroup.wxs"))
2122 .arg("-t")
2123 .arg(etc.join("msi/squash-components.xsl"))
2124 .run(builder);
2125 }
2126 command(&heat)
2127 .current_dir(&exe)
2128 .arg("dir")
2129 .arg("cargo")
2130 .args(heat_flags)
2131 .arg("-cg")
2132 .arg("CargoGroup")
2133 .arg("-dr")
2134 .arg("Cargo")
2135 .arg("-var")
2136 .arg("var.CargoDir")
2137 .arg("-out")
2138 .arg(exe.join("CargoGroup.wxs"))
2139 .arg("-t")
2140 .arg(etc.join("msi/remove-duplicates.xsl"))
2141 .run(builder);
2142 command(&heat)
2143 .current_dir(&exe)
2144 .arg("dir")
2145 .arg("rust-std")
2146 .args(heat_flags)
2147 .arg("-cg")
2148 .arg("StdGroup")
2149 .arg("-dr")
2150 .arg("Std")
2151 .arg("-var")
2152 .arg("var.StdDir")
2153 .arg("-out")
2154 .arg(exe.join("StdGroup.wxs"))
2155 .run(builder);
2156 if built_tools.contains("rust-analyzer") {
2157 command(&heat)
2158 .current_dir(&exe)
2159 .arg("dir")
2160 .arg("rust-analyzer")
2161 .args(heat_flags)
2162 .arg("-cg")
2163 .arg("RustAnalyzerGroup")
2164 .arg("-dr")
2165 .arg("RustAnalyzer")
2166 .arg("-var")
2167 .arg("var.RustAnalyzerDir")
2168 .arg("-out")
2169 .arg(exe.join("RustAnalyzerGroup.wxs"))
2170 .arg("-t")
2171 .arg(etc.join("msi/remove-duplicates.xsl"))
2172 .run(builder);
2173 }
2174 if built_tools.contains("clippy") {
2175 command(&heat)
2176 .current_dir(&exe)
2177 .arg("dir")
2178 .arg("clippy")
2179 .args(heat_flags)
2180 .arg("-cg")
2181 .arg("ClippyGroup")
2182 .arg("-dr")
2183 .arg("Clippy")
2184 .arg("-var")
2185 .arg("var.ClippyDir")
2186 .arg("-out")
2187 .arg(exe.join("ClippyGroup.wxs"))
2188 .arg("-t")
2189 .arg(etc.join("msi/remove-duplicates.xsl"))
2190 .run(builder);
2191 }
2192 if built_tools.contains("rustfmt") {
2193 command(&heat)
2194 .current_dir(&exe)
2195 .arg("dir")
2196 .arg("rustfmt")
2197 .args(heat_flags)
2198 .arg("-cg")
2199 .arg("RustFmtGroup")
2200 .arg("-dr")
2201 .arg("RustFmt")
2202 .arg("-var")
2203 .arg("var.RustFmtDir")
2204 .arg("-out")
2205 .arg(exe.join("RustFmtGroup.wxs"))
2206 .arg("-t")
2207 .arg(etc.join("msi/remove-duplicates.xsl"))
2208 .run(builder);
2209 }
2210 if built_tools.contains("miri") {
2211 command(&heat)
2212 .current_dir(&exe)
2213 .arg("dir")
2214 .arg("miri")
2215 .args(heat_flags)
2216 .arg("-cg")
2217 .arg("MiriGroup")
2218 .arg("-dr")
2219 .arg("Miri")
2220 .arg("-var")
2221 .arg("var.MiriDir")
2222 .arg("-out")
2223 .arg(exe.join("MiriGroup.wxs"))
2224 .arg("-t")
2225 .arg(etc.join("msi/remove-duplicates.xsl"))
2226 .run(builder);
2227 }
2228 command(&heat)
2229 .current_dir(&exe)
2230 .arg("dir")
2231 .arg("rust-analysis")
2232 .args(heat_flags)
2233 .arg("-cg")
2234 .arg("AnalysisGroup")
2235 .arg("-dr")
2236 .arg("Analysis")
2237 .arg("-var")
2238 .arg("var.AnalysisDir")
2239 .arg("-out")
2240 .arg(exe.join("AnalysisGroup.wxs"))
2241 .arg("-t")
2242 .arg(etc.join("msi/remove-duplicates.xsl"))
2243 .run(builder);
2244 if target.is_windows_gnu() || target.is_windows_gnullvm() {
2245 command(&heat)
2246 .current_dir(&exe)
2247 .arg("dir")
2248 .arg("rust-mingw")
2249 .args(heat_flags)
2250 .arg("-cg")
2251 .arg("GccGroup")
2252 .arg("-dr")
2253 .arg("Gcc")
2254 .arg("-var")
2255 .arg("var.GccDir")
2256 .arg("-out")
2257 .arg(exe.join("GccGroup.wxs"))
2258 .run(builder);
2259 }
2260
2261 let candle = |input: &Path| {
2262 let output = exe.join(input.file_stem().unwrap()).with_extension("wixobj");
2263 let arch = if target.contains("x86_64") { "x64" } else { "x86" };
2264 let mut cmd = command(&candle);
2265 cmd.current_dir(&exe)
2266 .arg("-nologo")
2267 .arg("-dRustcDir=rustc")
2268 .arg("-dCargoDir=cargo")
2269 .arg("-dStdDir=rust-std")
2270 .arg("-dAnalysisDir=rust-analysis")
2271 .arg("-arch")
2272 .arg(arch)
2273 .arg("-out")
2274 .arg(&output)
2275 .arg(input);
2276 add_env(builder, &mut cmd, target, &built_tools);
2277
2278 if built_tools.contains("clippy") {
2279 cmd.arg("-dClippyDir=clippy");
2280 }
2281 if built_tools.contains("rustfmt") {
2282 cmd.arg("-dRustFmtDir=rustfmt");
2283 }
2284 if built_tools.contains("rust-docs") {
2285 cmd.arg("-dDocsDir=rust-docs");
2286 }
2287 if built_tools.contains("rust-analyzer") {
2288 cmd.arg("-dRustAnalyzerDir=rust-analyzer");
2289 }
2290 if built_tools.contains("miri") {
2291 cmd.arg("-dMiriDir=miri");
2292 }
2293 if target.is_windows_gnu() || target.is_windows_gnullvm() {
2294 cmd.arg("-dGccDir=rust-mingw");
2295 }
2296 cmd.run(builder);
2297 };
2298 candle(&xform(&etc.join("msi/rust.wxs")));
2299 candle(&etc.join("msi/ui.wxs"));
2300 candle(&etc.join("msi/rustwelcomedlg.wxs"));
2301 candle("RustcGroup.wxs".as_ref());
2302 if built_tools.contains("rust-docs") {
2303 candle("DocsGroup.wxs".as_ref());
2304 }
2305 candle("CargoGroup.wxs".as_ref());
2306 candle("StdGroup.wxs".as_ref());
2307 if built_tools.contains("clippy") {
2308 candle("ClippyGroup.wxs".as_ref());
2309 }
2310 if built_tools.contains("rustfmt") {
2311 candle("RustFmtGroup.wxs".as_ref());
2312 }
2313 if built_tools.contains("miri") {
2314 candle("MiriGroup.wxs".as_ref());
2315 }
2316 if built_tools.contains("rust-analyzer") {
2317 candle("RustAnalyzerGroup.wxs".as_ref());
2318 }
2319 candle("AnalysisGroup.wxs".as_ref());
2320
2321 if target.is_windows_gnu() || target.is_windows_gnullvm() {
2322 candle("GccGroup.wxs".as_ref());
2323 }
2324
2325 builder.create(&exe.join("LICENSE.rtf"), &rtf);
2326 builder.install(&etc.join("gfx/banner.bmp"), &exe, FileType::Regular);
2327 builder.install(&etc.join("gfx/dialogbg.bmp"), &exe, FileType::Regular);
2328
2329 builder.info(&format!("building `msi` installer with {light:?}"));
2330 let filename = format!("{}-{}.msi", pkgname(builder, "rust"), target.triple);
2331 let mut cmd = command(&light);
2332 cmd.arg("-nologo")
2333 .arg("-ext")
2334 .arg("WixUIExtension")
2335 .arg("-ext")
2336 .arg("WixUtilExtension")
2337 .arg("-out")
2338 .arg(exe.join(&filename))
2339 .arg("rust.wixobj")
2340 .arg("ui.wixobj")
2341 .arg("rustwelcomedlg.wixobj")
2342 .arg("RustcGroup.wixobj")
2343 .arg("CargoGroup.wixobj")
2344 .arg("StdGroup.wixobj")
2345 .arg("AnalysisGroup.wixobj")
2346 .current_dir(&exe);
2347
2348 if built_tools.contains("clippy") {
2349 cmd.arg("ClippyGroup.wixobj");
2350 }
2351 if built_tools.contains("rustfmt") {
2352 cmd.arg("RustFmtGroup.wixobj");
2353 }
2354 if built_tools.contains("miri") {
2355 cmd.arg("MiriGroup.wixobj");
2356 }
2357 if built_tools.contains("rust-analyzer") {
2358 cmd.arg("RustAnalyzerGroup.wixobj");
2359 }
2360 if built_tools.contains("rust-docs") {
2361 cmd.arg("DocsGroup.wixobj");
2362 }
2363
2364 if target.is_windows_gnu() || target.is_windows_gnullvm() {
2365 cmd.arg("GccGroup.wixobj");
2366 }
2367 cmd.arg("-sice:ICE57");
2369
2370 let _time = timeit(builder);
2371 cmd.run(builder);
2372
2373 if !builder.config.dry_run() {
2374 t!(move_file(exe.join(&filename), distdir(builder).join(&filename)));
2375 }
2376 }
2377 }
2378
2379 fn metadata(&self) -> Option<StepMetadata> {
2380 Some(StepMetadata::dist("extended", self.target).built_by(self.build_compiler))
2381 }
2382}
2383
2384fn add_env(
2385 builder: &Builder<'_>,
2386 cmd: &mut BootstrapCommand,
2387 target: TargetSelection,
2388 built_tools: &HashSet<&'static str>,
2389) {
2390 let mut parts = builder.version.split('.');
2391 cmd.env("CFG_RELEASE_INFO", builder.rust_version())
2392 .env("CFG_RELEASE_NUM", &builder.version)
2393 .env("CFG_RELEASE", builder.rust_release())
2394 .env("CFG_VER_MAJOR", parts.next().unwrap())
2395 .env("CFG_VER_MINOR", parts.next().unwrap())
2396 .env("CFG_VER_PATCH", parts.next().unwrap())
2397 .env("CFG_VER_BUILD", "0") .env("CFG_PACKAGE_VERS", builder.rust_package_vers())
2399 .env("CFG_PACKAGE_NAME", pkgname(builder, "rust"))
2400 .env("CFG_BUILD", target.triple)
2401 .env("CFG_CHANNEL", &builder.config.channel);
2402
2403 if target.is_windows_gnullvm() {
2404 cmd.env("CFG_MINGW", "1").env("CFG_ABI", "LLVM");
2405 } else if target.is_windows_gnu() {
2406 cmd.env("CFG_MINGW", "1").env("CFG_ABI", "GNU");
2407 } else {
2408 cmd.env("CFG_MINGW", "0").env("CFG_ABI", "MSVC");
2409 }
2410
2411 let mut define_optional_tool = |tool_name: &str, env_name: &str| {
2413 cmd.env(env_name, if built_tools.contains(tool_name) { "1" } else { "0" });
2414 };
2415 define_optional_tool("rustfmt", "CFG_RUSTFMT");
2416 define_optional_tool("clippy", "CFG_CLIPPY");
2417 define_optional_tool("miri", "CFG_MIRI");
2418 define_optional_tool("rust-analyzer", "CFG_RA");
2419}
2420
2421fn install_llvm_file(
2422 builder: &Builder<'_>,
2423 source: &Path,
2424 destination: &Path,
2425 install_symlink: bool,
2426) {
2427 if builder.config.dry_run() {
2428 return;
2429 }
2430
2431 if source.is_symlink() {
2432 builder.install(&t!(fs::canonicalize(source)), destination, FileType::NativeLibrary);
2435
2436 let full_dest = destination.join(source.file_name().unwrap());
2437 if install_symlink {
2438 builder.copy_link(source, &full_dest, FileType::NativeLibrary);
2441 } else {
2442 let link = t!(fs::read_link(source));
2446 let mut linker_script = t!(fs::File::create(full_dest));
2447 t!(write!(linker_script, "INPUT({})\n", link.display()));
2448
2449 let meta = t!(fs::metadata(source));
2452 if let Ok(mtime) = meta.modified() {
2453 t!(linker_script.set_modified(mtime));
2454 }
2455 }
2456 } else {
2457 builder.install(source, destination, FileType::NativeLibrary);
2458 }
2459}
2460
2461#[cfg_attr(
2465 feature = "tracing",
2466 instrument(
2467 level = "trace",
2468 name = "maybe_install_llvm",
2469 skip_all,
2470 fields(target = ?target, dst_libdir = ?dst_libdir, install_symlink = install_symlink),
2471 ),
2472)]
2473fn maybe_install_llvm(
2474 builder: &Builder<'_>,
2475 target: TargetSelection,
2476 dst_libdir: &Path,
2477 install_symlink: bool,
2478) -> bool {
2479 if builder.config.is_system_llvm(target) {
2496 trace!("system LLVM requested, no install");
2497 return false;
2498 }
2499
2500 if target.contains("apple-darwin") && builder.llvm_link_shared() {
2506 let src_libdir = builder.llvm_out(target).join("lib");
2507 let llvm_dylib_path = src_libdir.join("libLLVM.dylib");
2508 if llvm_dylib_path.exists() {
2509 builder.install(&llvm_dylib_path, dst_libdir, FileType::NativeLibrary);
2510
2511 if install_symlink && let Some(llvm_config_path) = &builder.llvm_config(target) {
2512 let major = llvm::get_llvm_version_major(builder, llvm_config_path);
2513 let versioned_name = match &builder.config.llvm_version_suffix {
2514 Some(version_suffix) => format!("libLLVM-{major}{version_suffix}.dylib"),
2515 None => {
2516 if builder.config.channel == "dev" {
2518 format!("libLLVM-{major}-rust-dev.dylib")
2519 } else {
2520 format!(
2521 "libLLVM-{major}-rust-{}-{}.dylib",
2522 builder.version, builder.config.channel
2523 )
2524 }
2525 }
2526 };
2527 t!(builder.symlink_file("libLLVM.dylib", dst_libdir.join(versioned_name)));
2528 }
2529 }
2530 !builder.config.dry_run()
2531 } else if let llvm::LlvmBuildStatus::AlreadyBuilt(llvm::LlvmResult {
2532 host_llvm_config, ..
2533 }) = llvm::prebuilt_llvm_config(builder, target, true)
2534 {
2535 trace!("LLVM already built, installing LLVM files");
2536 let mut cmd = command(host_llvm_config);
2537 cmd.cached();
2538 cmd.arg("--libfiles");
2539 builder.do_if_verbose(|| println!("running {cmd:?}"));
2540 let files = cmd.run_capture_stdout(builder).stdout();
2541 let build_llvm_out = &builder.llvm_out(builder.config.host_target);
2542 let target_llvm_out = &builder.llvm_out(target);
2543 for file in files.trim_end().split(' ') {
2544 let file = if let Ok(relative_path) = Path::new(file).strip_prefix(build_llvm_out) {
2546 target_llvm_out.join(relative_path)
2547 } else {
2548 PathBuf::from(file)
2549 };
2550 install_llvm_file(builder, &file, dst_libdir, install_symlink);
2551 }
2552 !builder.config.dry_run()
2553 } else {
2554 false
2555 }
2556}
2557
2558#[cfg_attr(
2560 feature = "tracing",
2561 instrument(
2562 level = "trace",
2563 name = "maybe_install_llvm_target",
2564 skip_all,
2565 fields(
2566 llvm_link_shared = ?builder.llvm_link_shared(),
2567 target = ?target,
2568 sysroot = ?sysroot,
2569 ),
2570 ),
2571)]
2572pub fn maybe_install_llvm_target(builder: &Builder<'_>, target: TargetSelection, sysroot: &Path) {
2573 let dst_libdir = sysroot.join("lib/rustlib").join(target).join("lib");
2574 if builder.llvm_link_shared() {
2578 maybe_install_llvm(builder, target, &dst_libdir, false);
2579 }
2580}
2581
2582#[cfg_attr(
2584 feature = "tracing",
2585 instrument(
2586 level = "trace",
2587 name = "maybe_install_llvm_runtime",
2588 skip_all,
2589 fields(
2590 llvm_link_shared = ?builder.llvm_link_shared(),
2591 target = ?target,
2592 sysroot = ?sysroot,
2593 ),
2594 ),
2595)]
2596pub fn maybe_install_llvm_runtime(builder: &Builder<'_>, target: TargetSelection, sysroot: &Path) {
2597 let dst_libdir = sysroot.join(builder.libdir_relative(Compiler::new(1, target)));
2598 if builder.llvm_link_shared() {
2602 maybe_install_llvm(builder, target, &dst_libdir, false);
2603
2604 if target.triple.contains("windows") {
2608 let dst_libdir = sysroot.join("lib/rustlib").join(target).join("bin");
2609 maybe_install_llvm(builder, target, &dst_libdir, false);
2610 }
2611 }
2612}
2613
2614#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2615pub struct LlvmTools {
2616 pub target: TargetSelection,
2617}
2618
2619impl Step for LlvmTools {
2620 type Output = Option<GeneratedTarball>;
2621 const IS_HOST: bool = true;
2622
2623 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2624 let mut run = run.alias("llvm-tools");
2625 for tool in LLVM_TOOLS {
2626 run = run.alias(tool);
2627 }
2628
2629 run
2630 }
2631
2632 fn is_default_step(builder: &Builder<'_>) -> bool {
2633 should_build_extended_tool(builder, "llvm-tools")
2634 }
2635
2636 fn make_run(run: RunConfig<'_>) {
2637 run.builder.ensure(LlvmTools { target: run.target });
2638 }
2639
2640 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2641 fn tools_to_install(paths: &[PathBuf]) -> Vec<&'static str> {
2642 let mut tools = vec![];
2643
2644 for path in paths {
2645 let path = path.to_str().unwrap();
2646
2647 if path == "llvm-tools" {
2649 return LLVM_TOOLS.to_owned();
2650 }
2651
2652 for tool in LLVM_TOOLS {
2653 if path == *tool {
2654 tools.push(*tool);
2655 }
2656 }
2657 }
2658
2659 if tools.is_empty() {
2661 tools = LLVM_TOOLS.to_owned();
2662 }
2663
2664 tools
2665 }
2666
2667 let target = self.target;
2668
2669 if let Some(config) = builder.config.target_config.get(&target)
2671 && !builder.config.llvm_from_ci
2672 && config.llvm_config.is_some()
2673 {
2674 builder.info(&format!("Skipping LlvmTools ({target}): external LLVM"));
2675 return None;
2676 }
2677
2678 if !builder.config.dry_run() {
2679 builder.require_submodule("src/llvm-project", None);
2680 }
2681
2682 builder.ensure(crate::core::build_steps::llvm::Llvm { target });
2683
2684 let mut tarball = Tarball::new(builder, "llvm-tools", &target.triple);
2685 tarball.set_overlay(OverlayKind::Llvm);
2686 tarball.is_preview(true);
2687
2688 if builder.config.llvm_tools_enabled {
2689 let src_bindir = builder.llvm_out(target).join("bin");
2691 let dst_bindir = format!("lib/rustlib/{}/bin", target.triple);
2692 for tool in tools_to_install(&builder.paths) {
2693 let exe = src_bindir.join(exe(tool, target));
2694 if !exe.exists() && builder.config.llvm_from_ci {
2696 eprintln!("{} does not exist; skipping copy", exe.display());
2697 continue;
2698 }
2699
2700 tarball.add_file(&exe, &dst_bindir, FileType::Executable);
2701 }
2702 }
2703
2704 maybe_install_llvm_target(builder, target, tarball.image_dir());
2709
2710 Some(tarball.generate())
2711 }
2712}
2713
2714#[derive(Debug, Clone, Hash, PartialEq, Eq)]
2717pub struct LlvmBitcodeLinker {
2718 pub build_compiler: Compiler,
2720 pub target: TargetSelection,
2722}
2723
2724impl Step for LlvmBitcodeLinker {
2725 type Output = Option<GeneratedTarball>;
2726 const IS_HOST: bool = true;
2727
2728 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2729 run.alias("llvm-bitcode-linker")
2730 }
2731
2732 fn is_default_step(builder: &Builder<'_>) -> bool {
2733 should_build_extended_tool(builder, "llvm-bitcode-linker")
2734 }
2735
2736 fn make_run(run: RunConfig<'_>) {
2737 run.builder.ensure(LlvmBitcodeLinker {
2738 build_compiler: tool::LlvmBitcodeLinker::get_build_compiler_for_target(
2739 run.builder,
2740 run.target,
2741 ),
2742 target: run.target,
2743 });
2744 }
2745
2746 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2747 let target = self.target;
2748
2749 let llbc_linker = builder
2750 .ensure(tool::LlvmBitcodeLinker::from_build_compiler(self.build_compiler, target));
2751
2752 let self_contained_bin_dir = format!("lib/rustlib/{}/bin/self-contained", target.triple);
2753
2754 let mut tarball = Tarball::new(builder, "llvm-bitcode-linker", &target.triple);
2756 tarball.set_overlay(OverlayKind::LlvmBitcodeLinker);
2757 tarball.is_preview(true);
2758
2759 tarball.add_file(&llbc_linker.tool_path, self_contained_bin_dir, FileType::Executable);
2760
2761 Some(tarball.generate())
2762 }
2763}
2764
2765#[derive(Debug, Clone, Hash, PartialEq, Eq)]
2768pub struct Enzyme {
2769 pub target: TargetSelection,
2771}
2772
2773impl Step for Enzyme {
2774 type Output = Option<GeneratedTarball>;
2775 const IS_HOST: bool = true;
2776
2777 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2778 run.alias("enzyme")
2779 }
2780
2781 fn is_default_step(builder: &Builder<'_>) -> bool {
2782 builder.config.llvm_enzyme
2783 }
2784
2785 fn make_run(run: RunConfig<'_>) {
2786 run.builder.ensure(Enzyme { target: run.target });
2787 }
2788
2789 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2790 if !builder.build.unstable_features() {
2794 return None;
2795 }
2796
2797 let target = self.target;
2798
2799 let enzyme = builder.ensure(llvm::Enzyme { target });
2800
2801 let target_libdir = format!("lib/rustlib/{}/lib", target.triple);
2802
2803 let mut tarball = Tarball::new(builder, "enzyme", &target.triple);
2805 tarball.set_overlay(OverlayKind::Enzyme);
2806 tarball.is_preview(true);
2807
2808 tarball.add_file(enzyme.enzyme_path(), target_libdir, FileType::NativeLibrary);
2809
2810 Some(tarball.generate())
2811 }
2812}
2813
2814#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2823pub struct RustDev {
2824 pub target: TargetSelection,
2825}
2826
2827impl Step for RustDev {
2828 type Output = Option<GeneratedTarball>;
2829 const IS_HOST: bool = true;
2830
2831 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2832 run.alias("rust-dev")
2833 }
2834
2835 fn is_default_step(_builder: &Builder<'_>) -> bool {
2836 true
2837 }
2838
2839 fn make_run(run: RunConfig<'_>) {
2840 run.builder.ensure(RustDev { target: run.target });
2841 }
2842
2843 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2844 let target = self.target;
2845
2846 if let Some(config) = builder.config.target_config.get(&target)
2848 && let Some(ref _s) = config.llvm_config
2849 {
2850 builder.info(&format!("Skipping RustDev ({target}): external LLVM"));
2851 return None;
2852 }
2853
2854 if !builder.config.dry_run() {
2855 builder.require_submodule("src/llvm-project", None);
2856 }
2857
2858 let mut tarball = Tarball::new(builder, "rust-dev", &target.triple);
2859 tarball.set_overlay(OverlayKind::Llvm);
2860 tarball.permit_symlinks(true);
2862
2863 builder.ensure(crate::core::build_steps::llvm::Llvm { target });
2864
2865 let src_bindir = builder.llvm_out(target).join("bin");
2866 if src_bindir.exists() {
2872 for entry in walkdir::WalkDir::new(&src_bindir) {
2873 let entry = t!(entry);
2874 if entry.file_type().is_file() && !entry.path_is_symlink() {
2875 let name = entry.file_name().to_str().unwrap();
2876 tarball.add_file(src_bindir.join(name), "bin", FileType::Executable);
2877 }
2878 }
2879 }
2880
2881 if builder.config.lld_enabled {
2882 let lld_out = builder.ensure(crate::core::build_steps::llvm::Lld { target });
2884
2885 let lld_path = lld_out.join("bin").join(exe("lld", target));
2887 if lld_path.exists() {
2888 tarball.add_file(&lld_path, "bin", FileType::Executable);
2889 }
2890 }
2891
2892 tarball.add_file(builder.llvm_filecheck(target), "bin", FileType::Executable);
2893
2894 tarball.add_dir(builder.llvm_out(target).join("include"), "include");
2898
2899 let dst_libdir = tarball.image_dir().join("lib");
2904 maybe_install_llvm(builder, target, &dst_libdir, true);
2905 let link_type = if builder.llvm_link_shared() { "dynamic" } else { "static" };
2906 t!(std::fs::write(tarball.image_dir().join("link-type.txt"), link_type), dst_libdir);
2907
2908 copy_src_dirs(
2912 builder,
2913 &builder.src.join("src").join("llvm-project"),
2914 &["compiler-rt"],
2915 &["compiler-rt/test"],
2918 tarball.image_dir(),
2919 );
2920
2921 Some(tarball.generate())
2922 }
2923}
2924
2925#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2931pub struct Bootstrap {
2932 target: TargetSelection,
2933}
2934
2935impl Step for Bootstrap {
2936 type Output = Option<GeneratedTarball>;
2937
2938 const IS_HOST: bool = true;
2939
2940 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2941 run.alias("bootstrap")
2942 }
2943
2944 fn make_run(run: RunConfig<'_>) {
2945 run.builder.ensure(Bootstrap { target: run.target });
2946 }
2947
2948 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2949 let target = self.target;
2950
2951 let tarball = Tarball::new(builder, "bootstrap", &target.triple);
2952
2953 let bootstrap_outdir = &builder.bootstrap_out;
2954 for file in &["bootstrap", "rustc", "rustdoc"] {
2955 tarball.add_file(
2956 bootstrap_outdir.join(exe(file, target)),
2957 "bootstrap/bin",
2958 FileType::Executable,
2959 );
2960 }
2961
2962 Some(tarball.generate())
2963 }
2964
2965 fn metadata(&self) -> Option<StepMetadata> {
2966 Some(StepMetadata::dist("bootstrap", self.target))
2967 }
2968}
2969
2970#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2975pub struct BuildManifest {
2976 target: TargetSelection,
2977}
2978
2979impl Step for BuildManifest {
2980 type Output = GeneratedTarball;
2981
2982 const IS_HOST: bool = true;
2983
2984 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2985 run.alias("build-manifest")
2986 }
2987
2988 fn make_run(run: RunConfig<'_>) {
2989 run.builder.ensure(BuildManifest { target: run.target });
2990 }
2991
2992 fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
2993 let build_manifest =
2997 builder.ensure(tool::BuildManifest::new(builder, builder.config.host_target));
2998
2999 let tarball = Tarball::new(builder, "build-manifest", &self.target.triple);
3000 tarball.add_file(&build_manifest.tool_path, "bin", FileType::Executable);
3001 tarball.generate()
3002 }
3003
3004 fn metadata(&self) -> Option<StepMetadata> {
3005 Some(StepMetadata::dist("build-manifest", self.target))
3006 }
3007}
3008
3009#[derive(Clone, Debug, Eq, Hash, PartialEq)]
3015pub struct ReproducibleArtifacts {
3016 target: TargetSelection,
3017}
3018
3019impl Step for ReproducibleArtifacts {
3020 type Output = Option<GeneratedTarball>;
3021 const IS_HOST: bool = true;
3022
3023 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3024 run.alias("reproducible-artifacts")
3025 }
3026
3027 fn is_default_step(_builder: &Builder<'_>) -> bool {
3028 true
3029 }
3030
3031 fn make_run(run: RunConfig<'_>) {
3032 run.builder.ensure(ReproducibleArtifacts { target: run.target });
3033 }
3034
3035 fn run(self, builder: &Builder<'_>) -> Self::Output {
3036 let mut added_anything = false;
3037 let tarball = Tarball::new(builder, "reproducible-artifacts", &self.target.triple);
3038 if let Some(path) = builder.config.rust_profile_use.as_ref() {
3039 tarball.add_file(path, ".", FileType::Regular);
3040 added_anything = true;
3041 }
3042 if let Some(path) = builder.config.llvm_profile_use.as_ref() {
3043 tarball.add_file(path, ".", FileType::Regular);
3044 added_anything = true;
3045 }
3046 for profile in &builder.config.reproducible_artifacts {
3047 tarball.add_file(profile, ".", FileType::Regular);
3048 added_anything = true;
3049 }
3050 if added_anything { Some(tarball.generate()) } else { None }
3051 }
3052
3053 fn metadata(&self) -> Option<StepMetadata> {
3054 Some(StepMetadata::dist("reproducible-artifacts", self.target))
3055 }
3056}
3057
3058#[derive(Clone, Debug, Eq, Hash, PartialEq)]
3064pub struct GccDev {
3065 target: TargetSelection,
3066}
3067
3068impl Step for GccDev {
3069 type Output = GeneratedTarball;
3070
3071 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3072 run.alias("gcc-dev")
3073 }
3074
3075 fn make_run(run: RunConfig<'_>) {
3076 run.builder.ensure(GccDev { target: run.target });
3077 }
3078
3079 fn run(self, builder: &Builder<'_>) -> Self::Output {
3080 let tarball = Tarball::new(builder, "gcc-dev", &self.target.triple);
3081 let output = builder
3082 .ensure(super::gcc::Gcc { target_pair: GccTargetPair::for_native_build(self.target) });
3083 tarball.add_file(output.libgccjit(), "lib", FileType::NativeLibrary);
3084 tarball.generate()
3085 }
3086
3087 fn metadata(&self) -> Option<StepMetadata> {
3088 Some(StepMetadata::dist("gcc-dev", self.target))
3089 }
3090}
3091
3092#[derive(Clone, Debug, Eq, Hash, PartialEq)]
3098pub struct Gcc {
3099 host: TargetSelection,
3100 target: TargetSelection,
3101}
3102
3103impl Step for Gcc {
3104 type Output = Option<GeneratedTarball>;
3105
3106 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3107 run.alias("gcc")
3108 }
3109
3110 fn make_run(run: RunConfig<'_>) {
3111 run.builder.ensure(Gcc { host: run.builder.host_target, target: run.target });
3115 }
3116
3117 fn run(self, builder: &Builder<'_>) -> Self::Output {
3118 if !builder.build.unstable_features() {
3122 return None;
3123 }
3124
3125 let host = self.host;
3126 let target = self.target;
3127 if host != "x86_64-unknown-linux-gnu" {
3128 builder.info(&format!("host target `{host}` not supported by gcc. skipping"));
3129 return None;
3130 }
3131
3132 if builder.config.is_running_on_ci() {
3133 assert_eq!(
3134 builder.config.gcc_ci_mode,
3135 GccCiMode::BuildLocally,
3136 "Cannot use gcc.download-ci-gcc when distributing GCC on CI"
3137 );
3138 }
3139
3140 builder.require_submodule(
3143 "src/gcc",
3144 Some("The src/gcc submodule is required for disting libgccjit"),
3145 );
3146
3147 let target_pair = GccTargetPair::for_target_pair(host, target);
3148 let libgccjit = builder.ensure(super::gcc::Gcc { target_pair });
3149
3150 let mut tarball = Tarball::new(builder, &format!("gcc-{target}"), &host.triple);
3154 tarball.set_overlay(OverlayKind::Gcc);
3155 tarball.is_preview(true);
3156 tarball.add_legal_and_readme_to("share/doc/gcc");
3157
3158 let cg_dir = PathBuf::from(format!("lib/rustlib/{host}/codegen-backends"));
3163
3164 let rel_libgccjit_path = libgccjit_path_relative_to_cg_dir(&target_pair, &libgccjit);
3166 let path = cg_dir.join(rel_libgccjit_path.parent().unwrap());
3167
3168 tarball.add_file(libgccjit.libgccjit(), path, FileType::NativeLibrary);
3169 Some(tarball.generate())
3170 }
3171
3172 fn metadata(&self) -> Option<StepMetadata> {
3173 Some(StepMetadata::dist(
3174 "gcc",
3175 TargetSelection::from_user(&format!("({}, {})", self.host, self.target)),
3176 ))
3177 }
3178}