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