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::backend::CodegenBackendKind;
23use crate::core::build_steps::compile::{
24 get_codegen_backend_file, libgccjit_path_relative_to_cg_dir, normalize_codegen_backend_name,
25};
26use crate::core::build_steps::doc::DocumentationFormat;
27use crate::core::build_steps::gcc::GccTargetPair;
28use crate::core::build_steps::llvm::{
29 LLVM_CI_LINK_TYPE_PATH, LlvmBuildStatus, LlvmKind, get_llvm_build_status,
30};
31use crate::core::build_steps::tool::{
32 self, RustcPrivateCompilers, ToolTargetBuildMode, get_tool_target_compiler,
33};
34use crate::core::build_steps::vendor::Vendor;
35use crate::core::build_steps::{compile, llvm};
36use crate::core::builder::{
37 Builder, CommandLineStep, Kind, RunConfig, ShouldRun, Step, StepMetadata,
38};
39use crate::core::compiler::Compiler;
40use crate::core::config::{GccCiMode, TargetSelection};
41use crate::core::session::{DependencyType, FileType, Mode};
42use crate::trace;
43use crate::utils::build_stamp::{self, BuildStamp};
44use crate::utils::channel::{self, Info};
45use crate::utils::exec::{BootstrapCommand, command};
46use crate::utils::helpers::{
47 exe, is_dylib, move_file, t, target_supports_cranelift_backend, timeit,
48};
49use crate::utils::tarball::{GeneratedTarball, OverlayKind, Tarball};
50
51pub(crate) const LLVM_TOOLS: &[&str] = &[
52 "llvm-cov", "llvm-nm", "llvm-objcopy", "llvm-objdump", "llvm-profdata", "llvm-readobj", "llvm-size", "llvm-strip", "llvm-ar", "llvm-as", "llvm-dis", "llvm-link", "llc", "opt", "llubi", ];
68
69pub(crate) const LLD_FILE_NAMES: &[&str] = &["ld.lld", "ld64.lld", "lld-link", "wasm-ld"];
71
72pub fn pkgname(builder: &Builder<'_>, component: &str) -> String {
73 format!("{}-{}", component, builder.rust_package_vers())
74}
75
76pub(crate) fn distdir(builder: &Builder<'_>) -> PathBuf {
77 builder.out.join("dist")
78}
79
80pub fn tmpdir(builder: &Builder<'_>) -> PathBuf {
81 builder.out.join("tmp/dist")
82}
83
84fn should_build_extended_tool(builder: &Builder<'_>, tool: &str) -> bool {
85 if !builder.config.extended {
86 return false;
87 }
88 builder.config.tools.as_ref().is_none_or(|tools| tools.contains(tool))
89}
90
91#[derive(Debug, Clone, Hash, PartialEq, Eq)]
92pub struct Docs {
93 pub host: TargetSelection,
94}
95
96impl CommandLineStep for Docs {
97 type Output = Option<GeneratedTarball>;
98
99 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
100 run.alias("rust-docs")
101 }
102
103 fn is_default_step(builder: &Builder<'_>) -> bool {
104 builder.config.docs
105 }
106
107 fn make_run(run: RunConfig<'_>) {
108 run.builder.ensure(Docs { host: run.target });
109 }
110
111 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
113 let host = self.host;
114 builder.run_default_doc_steps();
118
119 if !builder.config.dry_run() {
122 t!(fs::create_dir_all(builder.doc_out(host)));
123 }
124
125 let dest = "share/doc/rust/html";
126
127 let mut tarball = Tarball::new(builder, "rust-docs", &host.triple);
128 tarball.set_product_name("Rust Documentation");
129 tarball.add_bulk_dir(builder.doc_out(host), dest);
130 tarball.add_file(builder.src.join("src/doc/robots.txt"), dest, FileType::Regular);
131 tarball.add_file(builder.src.join("src/doc/sitemap.txt"), dest, FileType::Regular);
132 Some(tarball.generate())
133 }
134
135 fn metadata(&self) -> Option<StepMetadata> {
136 Some(StepMetadata::dist("docs", self.host))
137 }
138}
139
140#[derive(Debug, Clone, Hash, PartialEq, Eq)]
143pub struct JsonDocs {
144 build_compiler: Compiler,
145 target: TargetSelection,
146}
147
148impl CommandLineStep for JsonDocs {
149 type Output = Option<GeneratedTarball>;
150
151 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
152 run.alias("rust-docs-json")
153 }
154
155 fn is_default_step(builder: &Builder<'_>) -> bool {
156 builder.config.docs
157 }
158
159 fn make_run(run: RunConfig<'_>) {
160 run.builder.ensure(JsonDocs {
161 build_compiler: run.builder.compiler_for_std(run.builder.top_stage),
162 target: run.target,
163 });
164 }
165
166 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
167 let target = self.target;
168 let directory = builder.ensure(crate::core::build_steps::doc::Std::from_build_compiler(
169 self.build_compiler,
170 target,
171 DocumentationFormat::Json,
172 ));
173
174 let dest = "share/doc/rust/json";
175
176 let mut tarball = Tarball::new(builder, "rust-docs-json", &target.triple);
177 tarball.set_product_name("Rust Documentation In JSON Format");
178 tarball.is_preview(true);
179 tarball.add_bulk_dir(directory, dest);
180 Some(tarball.generate())
181 }
182
183 fn metadata(&self) -> Option<StepMetadata> {
184 Some(StepMetadata::dist("json-docs", self.target).built_by(self.build_compiler))
185 }
186}
187
188#[derive(Debug, Clone, Hash, PartialEq, Eq)]
195pub struct RustcDocs {
196 target: TargetSelection,
197}
198
199impl CommandLineStep for RustcDocs {
200 type Output = GeneratedTarball;
201 const IS_HOST: bool = true;
202
203 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
204 run.alias("rustc-docs")
205 }
206
207 fn is_default_step(builder: &Builder<'_>) -> bool {
208 builder.config.compiler_docs
209 }
210
211 fn make_run(run: RunConfig<'_>) {
212 run.builder.ensure(RustcDocs { target: run.target });
213 }
214
215 fn run(self, builder: &Builder<'_>) -> Self::Output {
216 let target = self.target;
217 builder.run_default_doc_steps();
218
219 let mut tarball = Tarball::new(builder, "rustc-docs", &target.triple);
220 tarball.set_product_name("Rustc Documentation");
221 tarball.add_bulk_dir(builder.compiler_doc_out(target), "share/doc/rust/html/rustc-docs");
222 tarball.generate()
223 }
224}
225
226fn find_files(files: &[&str], path: &[PathBuf]) -> Vec<PathBuf> {
227 let mut found = Vec::with_capacity(files.len());
228
229 for file in files {
230 let file_path = path.iter().map(|dir| dir.join(file)).find(|p| p.exists());
231
232 if let Some(file_path) = file_path {
233 found.push(file_path);
234 } else {
235 panic!("Could not find '{file}' in {path:?}");
236 }
237 }
238
239 found
240}
241
242fn make_win_dist(plat_root: &Path, target: TargetSelection, builder: &Builder<'_>) {
243 if builder.config.dry_run() {
244 return;
245 }
246
247 let (bin_path, lib_path) = get_cc_search_dirs(target, builder);
248
249 let compiler = if target == "i686-pc-windows-gnu" {
250 "i686-w64-mingw32-gcc.exe"
251 } else if target == "x86_64-pc-windows-gnu" {
252 "x86_64-w64-mingw32-gcc.exe"
253 } else {
254 "gcc.exe"
255 };
256 let target_tools = [compiler, "ld.exe", "dlltool.exe", "libwinpthread-1.dll"];
257
258 let target_libs = [
261 "libgcc.a",
263 "libgcc_eh.a",
264 "libgcc_s.a",
265 "libm.a",
266 "libmingw32.a",
267 "libmingwex.a",
268 "libstdc++.a",
269 "libiconv.a",
270 "libmoldname.a",
271 "libpthread.a",
272 "libadvapi32.a",
277 "libbcrypt.a",
278 "libcomctl32.a",
279 "libcomdlg32.a",
280 "libcredui.a",
281 "libcrypt32.a",
282 "libdbghelp.a",
283 "libgdi32.a",
284 "libimagehlp.a",
285 "libiphlpapi.a",
286 "libkernel32.a",
287 "libmsimg32.a",
288 "libmsvcrt.a",
289 "libntdll.a",
290 "libodbc32.a",
291 "libole32.a",
292 "liboleaut32.a",
293 "libopengl32.a",
294 "libpsapi.a",
295 "librpcrt4.a",
296 "libsecur32.a",
297 "libsetupapi.a",
298 "libshell32.a",
299 "libsynchronization.a",
300 "libuser32.a",
301 "libuserenv.a",
302 "libuuid.a",
303 "libwinhttp.a",
304 "libwinmm.a",
305 "libwinspool.a",
306 "libws2_32.a",
307 "libwsock32.a",
308 ];
309
310 let target_tools = find_files(&target_tools, &bin_path);
312 let target_libs = find_files(&target_libs, &lib_path);
313
314 let plat_target_bin_self_contained_dir =
316 plat_root.join("lib/rustlib").join(target).join("bin/self-contained");
317 fs::create_dir_all(&plat_target_bin_self_contained_dir)
318 .expect("creating plat_target_bin_self_contained_dir failed");
319 for src in target_tools {
320 builder.copy_link_to_folder(&src, &plat_target_bin_self_contained_dir);
321 }
322
323 builder.create(
325 &plat_target_bin_self_contained_dir.join("GCC-WARNING.txt"),
326 "gcc.exe contained in this folder cannot be used for compiling C files - it is only \
327 used as a linker. In order to be able to compile projects containing C code use \
328 the GCC provided by MinGW or Cygwin.",
329 );
330
331 let plat_target_lib_self_contained_dir =
333 plat_root.join("lib/rustlib").join(target).join("lib/self-contained");
334 fs::create_dir_all(&plat_target_lib_self_contained_dir)
335 .expect("creating plat_target_lib_self_contained_dir failed");
336 for src in target_libs {
337 builder.copy_link_to_folder(&src, &plat_target_lib_self_contained_dir);
338 }
339}
340
341fn make_win_llvm_dist(plat_root: &Path, target: TargetSelection, builder: &Builder<'_>) {
342 if builder.config.dry_run() {
343 return;
344 }
345
346 let (_, lib_path) = get_cc_search_dirs(target, builder);
347
348 let target_libs = [
351 "libunwind.a",
353 "libmingw32.a",
354 "libmingwex.a",
355 "libmsvcrt.a",
356 "libdbghelp.a",
358 "libkernel32.a",
359 "libntdll.a",
360 "libsynchronization.a",
361 "libuser32.a",
362 "libuserenv.a",
363 "libws2_32.a",
364 ];
365
366 let target_libs = find_files(&target_libs, &lib_path);
368
369 let plat_target_lib_self_contained_dir =
371 plat_root.join("lib/rustlib").join(target).join("lib/self-contained");
372 fs::create_dir_all(&plat_target_lib_self_contained_dir)
373 .expect("creating plat_target_lib_self_contained_dir failed");
374 for src in target_libs {
375 builder.copy_link_to_folder(&src, &plat_target_lib_self_contained_dir);
376 }
377}
378
379fn runtime_dll_dist(rust_root: &Path, target: TargetSelection, builder: &Builder<'_>) {
380 if builder.config.dry_run() {
381 return;
382 }
383
384 let (bin_path, _) = get_cc_search_dirs(target, builder);
385
386 let mut rustc_dlls = vec![];
387 if target.is_windows_gnu() {
389 rustc_dlls.push("libwinpthread-1.dll");
390 if target.starts_with("i686-") {
391 rustc_dlls.push("libgcc_s_dw2-1.dll");
392 } else {
393 rustc_dlls.push("libgcc_s_seh-1.dll");
394 }
395 } else if target.is_windows_gnullvm() {
396 rustc_dlls.push("libunwind.dll");
397 } else {
398 panic!("Vendoring of runtime DLLs for `{target}` is not supported`");
399 }
400 let rustc_dlls = find_files(&rustc_dlls, &bin_path);
401
402 let rust_bin_dir = rust_root.join("bin/");
404 fs::create_dir_all(&rust_bin_dir).expect("creating rust_bin_dir failed");
405 for src in &rustc_dlls {
406 builder.copy_link_to_folder(src, &rust_bin_dir);
407 }
408
409 if builder.config.lld_enabled {
410 let rust_target_bin_dir = rust_root.join("lib/rustlib").join(target).join("bin");
412 fs::create_dir_all(&rust_target_bin_dir).expect("creating rust_target_bin_dir failed");
413 for src in &rustc_dlls {
414 builder.copy_link_to_folder(src, &rust_target_bin_dir);
415 }
416 }
417}
418
419fn get_cc_search_dirs(
420 target: TargetSelection,
421 builder: &Builder<'_>,
422) -> (Vec<PathBuf>, Vec<PathBuf>) {
423 let mut cmd = command(builder.cc(target));
425 cmd.arg("-print-search-dirs");
426 let gcc_out = cmd.run_capture_stdout(builder).stdout();
427
428 let mut bin_path: Vec<_> = env::split_paths(&env::var_os("PATH").unwrap_or_default()).collect();
429 let mut lib_path = Vec::new();
430
431 for line in gcc_out.lines() {
432 let idx = line.find(':').unwrap();
433 let key = &line[..idx];
434 let trim_chars: &[_] = &[' ', '='];
435 let value = env::split_paths(line[(idx + 1)..].trim_start_matches(trim_chars));
436
437 if key == "programs" {
438 bin_path.extend(value);
439 } else if key == "libraries" {
440 lib_path.extend(value);
441 }
442 }
443 (bin_path, lib_path)
444}
445
446#[derive(Debug, Clone, Hash, PartialEq, Eq)]
451pub struct Mingw {
452 target: TargetSelection,
453}
454
455impl CommandLineStep for Mingw {
456 type Output = Option<GeneratedTarball>;
457
458 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
459 run.alias("rust-mingw")
460 }
461
462 fn is_default_step(_builder: &Builder<'_>) -> bool {
463 true
464 }
465
466 fn make_run(run: RunConfig<'_>) {
467 run.builder.ensure(Mingw { target: run.target });
468 }
469
470 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
471 let target = self.target;
472 if !target.contains("pc-windows-gnu") || !builder.config.dist_include_mingw_linker {
473 return None;
474 }
475
476 let mut tarball = Tarball::new(builder, "rust-mingw", &target.triple);
477 tarball.set_product_name("Rust MinGW");
478
479 if target.ends_with("pc-windows-gnu") {
480 make_win_dist(tarball.image_dir(), target, builder);
481 } else if target.ends_with("pc-windows-gnullvm") {
482 make_win_llvm_dist(tarball.image_dir(), target, builder);
483 } else {
484 unreachable!();
485 }
486
487 Some(tarball.generate())
488 }
489
490 fn metadata(&self) -> Option<StepMetadata> {
491 Some(StepMetadata::dist("mingw", self.target))
492 }
493}
494
495#[derive(Debug, Clone, Hash, PartialEq, Eq)]
505pub struct Rustc {
506 pub target_compiler: Compiler,
508}
509
510impl CommandLineStep for Rustc {
511 type Output = GeneratedTarball;
512 const IS_HOST: bool = true;
513
514 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
515 run.alias("rustc")
516 }
517
518 fn is_default_step(_builder: &Builder<'_>) -> bool {
519 true
520 }
521
522 fn make_run(run: RunConfig<'_>) {
523 run.builder.ensure(Rustc {
524 target_compiler: run.builder.compiler(run.builder.top_stage, run.target),
525 });
526 }
527
528 fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
529 let target_compiler = self.target_compiler;
530 let target = self.target_compiler.host;
531
532 let tarball = Tarball::new(builder, "rustc", &target.triple);
533
534 prepare_image(builder, target_compiler, tarball.image_dir());
536
537 if target.contains("pc-windows-gnu") && builder.config.dist_include_mingw_linker {
545 runtime_dll_dist(tarball.image_dir(), target, builder);
546 tarball.add_dir(builder.src.join("src/etc/third-party"), "share/doc");
547 }
548
549 return tarball.generate();
550
551 fn prepare_image(builder: &Builder<'_>, target_compiler: Compiler, image: &Path) {
552 let target = target_compiler.host;
553 let src = builder.sysroot(target_compiler);
554
555 t!(fs::create_dir_all(image.join("bin")));
557 builder.cp_link_r(&src.join("bin"), &image.join("bin"));
558
559 if builder
561 .config
562 .tools
563 .as_ref()
564 .is_none_or(|tools| tools.iter().any(|tool| tool == "rustdoc"))
565 {
566 let rustdoc = builder.rustdoc_for_compiler(target_compiler);
567 builder.install(&rustdoc, &image.join("bin"), FileType::Executable);
568 }
569
570 let compilers = RustcPrivateCompilers::from_target_compiler(builder, target_compiler);
571
572 if let Some(ra_proc_macro_srv) = builder.ensure_if_default(
573 tool::RustAnalyzerProcMacroSrv::from_compilers(compilers),
574 builder.kind,
575 ) {
576 let dst = image.join("libexec");
577 builder.install(&ra_proc_macro_srv.tool_path, &dst, FileType::Executable);
578 }
579
580 let libdir_relative = builder.libdir_relative(target_compiler);
581
582 if libdir_relative.to_str() != Some("bin") {
584 let libdir = builder.rustc_libdir(target_compiler);
585 for entry in builder.read_dir(&libdir) {
586 if is_dylib(&entry.path())
592 && !entry
593 .path()
594 .file_name()
595 .and_then(|n| n.to_str())
596 .map(|n| n.contains("libgccjit"))
597 .unwrap_or(false)
598 {
599 builder.install(&entry.path(), &image.join("lib"), FileType::NativeLibrary);
602 }
603 }
604 }
605
606 maybe_install_llvm_runtime(builder, target, image);
612
613 let dst_dir = image.join("lib/rustlib").join(target).join("bin");
614 t!(fs::create_dir_all(&dst_dir));
615
616 if builder.config.lld_enabled {
618 let src_dir = builder.sysroot_target_bindir(target_compiler, target);
619 let rust_lld = exe("rust-lld", target_compiler.host);
620 builder.copy_link(
621 &src_dir.join(&rust_lld),
622 &dst_dir.join(&rust_lld),
623 FileType::Executable,
624 );
625 let self_contained_lld_src_dir = src_dir.join("gcc-ld");
626 let self_contained_lld_dst_dir = dst_dir.join("gcc-ld");
627 t!(fs::create_dir(&self_contained_lld_dst_dir));
628 for name in LLD_FILE_NAMES {
629 let exe_name = exe(name, target_compiler.host);
630 builder.copy_link(
631 &self_contained_lld_src_dir.join(&exe_name),
632 &self_contained_lld_dst_dir.join(&exe_name),
633 FileType::Executable,
634 );
635 }
636 }
637
638 if builder.config.llvm_enabled(target_compiler.host)
639 && builder.config.llvm_tools_enabled
640 {
641 let src_dir = builder.sysroot_target_bindir(target_compiler, target);
642 let llvm_objcopy = exe("llvm-objcopy", target_compiler.host);
643 let rust_objcopy = exe("rust-objcopy", target_compiler.host);
644 builder.copy_link(
645 &src_dir.join(&llvm_objcopy),
646 &dst_dir.join(&rust_objcopy),
647 FileType::Executable,
648 );
649 }
650
651 if builder.tool_enabled("wasm-component-ld") {
652 let src_dir = builder.sysroot_target_bindir(target_compiler, target);
653 let ld = exe("wasm-component-ld", target_compiler.host);
654 builder.copy_link(&src_dir.join(&ld), &dst_dir.join(&ld), FileType::Executable);
655 }
656
657 t!(fs::create_dir_all(image.join("share/man/man1")));
659 let man_src = builder.src.join("src/doc/man");
660 let man_dst = image.join("share/man/man1");
661
662 for file_entry in builder.read_dir(&man_src) {
665 let page_src = file_entry.path();
666 let page_dst = man_dst.join(file_entry.file_name());
667 let src_text = t!(std::fs::read_to_string(&page_src));
668 let version = builder.rust_info().version(builder.sess, &builder.version);
669 let new_text = src_text.replace("<INSERT VERSION HERE>", &version);
670 t!(std::fs::write(&page_dst, &new_text));
671 }
672
673 builder.ensure(DebuggerScripts { sysroot: image.to_owned(), target });
675
676 generate_target_spec_json_schema(builder, image);
677
678 let file_list = builder.ensure(super::run::GenerateCopyright);
680 for file in file_list {
681 builder.install(&file, &image.join("share/doc/rust"), FileType::Regular);
682 }
683
684 builder.install(
686 &builder.src.join("README.md"),
687 &image.join("share/doc/rust"),
688 FileType::Regular,
689 );
690
691 let license = |path: &Path| {
693 builder.install(path, &image.join("share/doc/rust/licenses"), FileType::Regular);
694 };
695 for entry in t!(std::fs::read_dir(builder.src.join("LICENSES"))).flatten() {
696 license(&entry.path());
697 }
698 }
699 }
700
701 fn metadata(&self) -> Option<StepMetadata> {
702 Some(StepMetadata::dist("rustc", self.target_compiler.host))
703 }
704}
705
706fn generate_target_spec_json_schema(builder: &Builder<'_>, sysroot: &Path) {
707 let stage1_host = builder.compiler(1, builder.host_target);
711 let mut rustc = builder.rustc_cmd(stage1_host).fail_fast();
712 rustc
713 .env("RUSTC_BOOTSTRAP", "1")
714 .args(["--print=target-spec-json-schema", "-Zunstable-options"]);
715 let schema = rustc.run_capture(builder).stdout();
716
717 let schema_dir = tmpdir(builder);
718 t!(fs::create_dir_all(&schema_dir));
719 let schema_file = schema_dir.join("target-spec-json-schema.json");
720 t!(std::fs::write(&schema_file, schema));
721
722 let dst = sysroot.join("etc");
723 t!(fs::create_dir_all(&dst));
724
725 builder.install(&schema_file, &dst, FileType::Regular);
726}
727
728#[derive(Debug, Clone, Hash, PartialEq, Eq)]
730pub struct DebuggerScripts {
731 pub sysroot: PathBuf,
733 pub target: TargetSelection,
734}
735
736impl Step for DebuggerScripts {
737 type Output = ();
738
739 fn run(self, builder: &Builder<'_>) {
740 let target = self.target;
741 let sysroot = self.sysroot;
742 let dst = sysroot.join("lib/rustlib/etc");
743 t!(fs::create_dir_all(&dst));
744 let cp_debugger_script = |file: &str| {
745 builder.install(&builder.src.join("src/etc/").join(file), &dst, FileType::Regular);
746 };
747 if target.contains("windows-msvc") {
748 builder.install(
750 &builder.src.join("src/etc/rust-windbg.cmd"),
751 &sysroot.join("bin"),
752 FileType::Script,
753 );
754
755 cp_debugger_script("natvis/intrinsic.natvis");
756 cp_debugger_script("natvis/liballoc.natvis");
757 cp_debugger_script("natvis/libcore.natvis");
758 cp_debugger_script("natvis/libstd.natvis");
759 }
760
761 cp_debugger_script("rust_types.py");
762
763 builder.install(
765 &builder.src.join("src/etc/rust-gdb"),
766 &sysroot.join("bin"),
767 FileType::Script,
768 );
769 builder.install(
770 &builder.src.join("src/etc/rust-gdbgui"),
771 &sysroot.join("bin"),
772 FileType::Script,
773 );
774
775 cp_debugger_script("gdb_load_rust_pretty_printers.py");
776 cp_debugger_script("gdb_lookup.py");
777 cp_debugger_script("gdb_providers.py");
778 if builder.sess.unstable_features() {
779 cp_debugger_script("gdb_trim_paths.py");
780 }
781
782 builder.install(
784 &builder.src.join("src/etc/rust-lldb"),
785 &sysroot.join("bin"),
786 FileType::Script,
787 );
788
789 cp_debugger_script("lldb_lookup.py");
790 cp_debugger_script("lldb_providers.py");
791 if builder.sess.unstable_features() {
792 cp_debugger_script("lldb_trim_paths.py");
793 }
794 }
795}
796
797fn skip_host_target_lib(builder: &Builder<'_>, compiler: Compiler) -> bool {
798 if !builder.config.is_host_target(compiler.host) {
801 builder.info("\tskipping, not a build host");
802 true
803 } else {
804 false
805 }
806}
807
808fn verify_uefi_rlib_format(builder: &Builder<'_>, target: TargetSelection, stamp: &BuildStamp) {
812 if !target.ends_with("-uefi") {
813 return;
814 }
815
816 for (path, _) in builder.read_stamp_file(stamp) {
817 if path.extension() != Some(OsStr::new("rlib")) {
818 continue;
819 }
820
821 let data = t!(fs::read(&path));
822 let data = data.as_slice();
823 let archive = t!(ArchiveFile::parse(data));
824 for member in archive.members() {
825 let member = t!(member);
826 let member_data = t!(member.data(data));
827
828 let is_coff = match object::File::parse(member_data) {
829 Ok(member_file) => member_file.format() == BinaryFormat::Coff,
830 Err(_) => false,
831 };
832
833 if !is_coff {
834 let member_name = String::from_utf8_lossy(member.name());
835 panic!("member {} in {} is not COFF", member_name, path.display());
836 }
837 }
838 }
839}
840
841fn copy_target_libs(
843 builder: &Builder<'_>,
844 target: TargetSelection,
845 image: &Path,
846 stamp: &BuildStamp,
847) {
848 let dst = image.join("lib/rustlib").join(target).join("lib");
849 let self_contained_dst = dst.join("self-contained");
850 t!(fs::create_dir_all(&dst));
851 t!(fs::create_dir_all(&self_contained_dst));
852 for (path, dependency_type) in builder.read_stamp_file(stamp) {
853 if dependency_type == DependencyType::TargetSelfContained {
854 builder.copy_link(
855 &path,
856 &self_contained_dst.join(path.file_name().unwrap()),
857 FileType::NativeLibrary,
858 );
859 } else if dependency_type == DependencyType::Target || builder.config.is_host_target(target)
860 {
861 builder.copy_link(&path, &dst.join(path.file_name().unwrap()), FileType::NativeLibrary);
862 }
863 }
864}
865
866#[derive(Debug, Clone, Hash, PartialEq, Eq)]
873pub struct Std {
874 pub build_compiler: Compiler,
876 pub target: TargetSelection,
877}
878
879impl Std {
880 pub fn new(builder: &Builder<'_>, target: TargetSelection) -> Self {
881 Std { build_compiler: builder.compiler_for_std(builder.top_stage), target }
882 }
883}
884
885impl CommandLineStep for Std {
886 type Output = Option<GeneratedTarball>;
887
888 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
889 run.alias("rust-std")
890 }
891
892 fn is_default_step(_builder: &Builder<'_>) -> bool {
893 true
894 }
895
896 fn make_run(run: RunConfig<'_>) {
897 run.builder.ensure(Std::new(run.builder, run.target));
898 }
899
900 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
901 let build_compiler = self.build_compiler;
902 let target = self.target;
903
904 if skip_host_target_lib(builder, build_compiler) {
905 return None;
906 }
907
908 let stamp =
911 builder.std(build_compiler, target).expect("Standard library has to be built for dist");
912
913 let mut tarball = Tarball::new(builder, "rust-std", &target.triple);
914 tarball.include_target_in_component_name(true);
915
916 verify_uefi_rlib_format(builder, target, &stamp);
917 copy_target_libs(builder, target, tarball.image_dir(), &stamp);
918
919 Some(tarball.generate())
920 }
921
922 fn metadata(&self) -> Option<StepMetadata> {
923 Some(StepMetadata::dist("std", self.target).built_by(self.build_compiler))
924 }
925}
926
927#[derive(Debug, Clone, Hash, PartialEq, Eq)]
932pub struct RustcDev {
933 pub build_compiler: Compiler,
935 pub target: TargetSelection,
936}
937
938impl RustcDev {
939 pub fn new(builder: &Builder<'_>, target: TargetSelection) -> Self {
940 Self {
941 build_compiler: builder.compiler(1, builder.config.host_target),
945 target,
946 }
947 }
948}
949
950impl CommandLineStep for RustcDev {
951 type Output = Option<GeneratedTarball>;
952 const IS_HOST: bool = true;
953
954 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
955 run.alias("rustc-dev")
956 }
957
958 fn is_default_step(_builder: &Builder<'_>) -> bool {
959 true
960 }
961
962 fn make_run(run: RunConfig<'_>) {
963 run.builder.ensure(RustcDev::new(run.builder, run.target));
964 }
965
966 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
967 let build_compiler = self.build_compiler;
968 let target = self.target;
969 if skip_host_target_lib(builder, build_compiler) {
970 return None;
971 }
972
973 builder.ensure(compile::Rustc::new(build_compiler, target));
975
976 let tarball = Tarball::new(builder, "rustc-dev", &target.triple);
977
978 let stamp = build_stamp::librustc_stamp(builder, build_compiler, target);
979 copy_target_libs(builder, target, tarball.image_dir(), &stamp);
980
981 let src_files = &["Cargo.lock"];
982 copy_src_dirs(
985 builder,
986 &builder.src,
987 &["compiler", "library/proc_macro"],
989 &[],
990 &tarball.image_dir().join("lib/rustlib/rustc-src/rust"),
991 );
992 for file in src_files {
993 tarball.add_file(
994 builder.src.join(file),
995 "lib/rustlib/rustc-src/rust",
996 FileType::Regular,
997 );
998 }
999
1000 Some(tarball.generate())
1001 }
1002
1003 fn metadata(&self) -> Option<StepMetadata> {
1004 Some(StepMetadata::dist("rustc-dev", self.target).built_by(self.build_compiler))
1005 }
1006}
1007
1008#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1013pub struct Analysis {
1014 build_compiler: Compiler,
1015 target: TargetSelection,
1016}
1017
1018impl CommandLineStep for Analysis {
1019 type Output = Option<GeneratedTarball>;
1020
1021 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1022 run.alias("rust-analysis")
1023 }
1024
1025 fn is_default_step(builder: &Builder<'_>) -> bool {
1026 should_build_extended_tool(builder, "analysis")
1027 }
1028
1029 fn make_run(run: RunConfig<'_>) {
1030 run.builder.ensure(Analysis {
1032 build_compiler: run.builder.compiler(1, run.builder.config.host_target),
1033 target: run.target,
1034 });
1035 }
1036
1037 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1038 let compiler = self.build_compiler;
1039 let target = self.target;
1040 if skip_host_target_lib(builder, compiler) {
1041 return None;
1042 }
1043
1044 let src = builder
1045 .stage_out(compiler, Mode::Std)
1046 .join(target)
1047 .join(builder.cargo_dir(Mode::Std))
1048 .join("deps")
1049 .join("save-analysis");
1050
1051 t!(std::fs::create_dir_all(&src));
1053 let mut removed = src.clone();
1054 removed.push("removed.json");
1055 let mut f = t!(std::fs::File::create(removed));
1056 t!(write!(f, r#"{{ "warning": "The `rust-analysis` component has been removed." }}"#));
1057
1058 let mut tarball = Tarball::new(builder, "rust-analysis", &target.triple);
1059 tarball.include_target_in_component_name(true);
1060 tarball.add_dir(src, format!("lib/rustlib/{}/analysis", target.triple));
1061 Some(tarball.generate())
1062 }
1063
1064 fn metadata(&self) -> Option<StepMetadata> {
1065 Some(StepMetadata::dist("analysis", self.target).built_by(self.build_compiler))
1066 }
1067}
1068
1069fn copy_src_dirs(
1072 builder: &Builder<'_>,
1073 base: &Path,
1074 src_dirs: &[&str],
1075 exclude_dirs: &[&str],
1076 dst_dir: &Path,
1077) {
1078 for src_dir in src_dirs {
1081 assert!(Path::new(src_dir).is_relative());
1082 }
1083
1084 if builder.config.dry_run() {
1087 return;
1088 }
1089
1090 fn filter_fn(exclude_dirs: &[&str], dir: &str, path: &Path) -> bool {
1091 let spath = match path.to_str() {
1093 Some(path) => path,
1094 None => return false,
1095 };
1096 if spath.ends_with('~') || spath.ends_with(".pyc") {
1097 return false;
1098 }
1099 let spath = spath.replace("\\", "/");
1101
1102 static LLVM_PROJECTS: &[&str] = &[
1103 "llvm-project/clang",
1104 "llvm-project/libc",
1105 "llvm-project/libunwind",
1106 "llvm-project/lld",
1107 "llvm-project/lldb",
1108 "llvm-project/llvm",
1109 "llvm-project/compiler-rt",
1110 "llvm-project/cmake",
1111 "llvm-project/runtimes",
1112 "llvm-project/third-party",
1113 ];
1114 if spath.starts_with("llvm-project") && spath != "llvm-project" {
1115 if !LLVM_PROJECTS.iter().any(|path| spath.starts_with(path)) {
1116 return false;
1117 }
1118
1119 if spath.starts_with("llvm-project/third-party")
1121 && spath != "llvm-project/third-party"
1122 && !spath.starts_with("llvm-project/third-party/siphash")
1123 {
1124 return false;
1125 }
1126
1127 if spath.starts_with("llvm-project/llvm/test")
1128 && (spath.ends_with(".ll") || spath.ends_with(".td") || spath.ends_with(".s"))
1129 {
1130 return false;
1131 }
1132 }
1133
1134 if spath.starts_with("tools/cargo/tests") {
1136 return true;
1137 }
1138
1139 if !exclude_dirs.is_empty() {
1140 let full_path = Path::new(dir).join(path);
1141 if exclude_dirs.iter().any(|excl| full_path == Path::new(excl)) {
1142 return false;
1143 }
1144 }
1145
1146 static EXCLUDES: &[&str] = &[
1147 "CVS",
1148 "RCS",
1149 "SCCS",
1150 ".git",
1151 ".gitignore",
1152 ".gitmodules",
1153 ".gitattributes",
1154 ".cvsignore",
1155 ".svn",
1156 ".arch-ids",
1157 "{arch}",
1158 "=RELEASE-ID",
1159 "=meta-update",
1160 "=update",
1161 ".bzr",
1162 ".bzrignore",
1163 ".bzrtags",
1164 ".hg",
1165 ".hgignore",
1166 ".hgrags",
1167 "_darcs",
1168 ];
1169
1170 let last_component = path.iter().next_back().map(|s| s.to_str().unwrap()).unwrap();
1177 !EXCLUDES.contains(&last_component)
1178 }
1179
1180 for item in src_dirs {
1182 let dst = &dst_dir.join(item);
1183 t!(fs::create_dir_all(dst));
1184 builder
1185 .cp_link_filtered(&base.join(item), dst, &|path| filter_fn(exclude_dirs, item, path));
1186 }
1187}
1188
1189#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1190pub struct Src;
1191
1192impl CommandLineStep for Src {
1193 type Output = GeneratedTarball;
1195 const IS_HOST: bool = true;
1196
1197 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1198 run.alias("rust-src")
1199 }
1200
1201 fn is_default_step(_builder: &Builder<'_>) -> bool {
1202 true
1203 }
1204
1205 fn make_run(run: RunConfig<'_>) {
1206 run.builder.ensure(Src);
1207 }
1208
1209 fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
1211 if !builder.config.dry_run() {
1212 builder.require_submodule("src/llvm-project", None);
1213 }
1214
1215 let tarball = Tarball::new_targetless(builder, "rust-src");
1216
1217 let dst_src = tarball.image_dir().join("lib/rustlib/src/rust");
1225
1226 copy_src_dirs(
1229 builder,
1230 &builder.src,
1231 &["library", "src/llvm-project/libunwind"],
1232 &[
1233 "library/backtrace/crates",
1236 ],
1237 &dst_src,
1238 );
1239
1240 let vendor = builder.ensure(Vendor {
1242 sync_args: vec![],
1243 versioned_dirs: true,
1244 root_dir: dst_src.clone(),
1245 output_dir: None,
1246 only_library_workspace: true,
1247 });
1248
1249 let library_cargo_config_dir = dst_src.join("library").join(".cargo");
1250 builder.create_dir(&library_cargo_config_dir);
1251 builder.create(&library_cargo_config_dir.join("config.toml"), &vendor.config_library);
1252
1253 tarball.generate()
1254 }
1255
1256 fn metadata(&self) -> Option<StepMetadata> {
1257 Some(StepMetadata::dist("src", TargetSelection::default()))
1258 }
1259}
1260
1261#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1265pub struct PlainSourceTarball;
1266
1267impl CommandLineStep for PlainSourceTarball {
1268 type Output = GeneratedTarball;
1270 const IS_HOST: bool = true;
1271
1272 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1273 run.alias("rustc-src")
1274 }
1275
1276 fn is_default_step(builder: &Builder<'_>) -> bool {
1277 builder.config.rust_dist_src
1278 }
1279
1280 fn make_run(run: RunConfig<'_>) {
1281 run.builder.ensure(PlainSourceTarball);
1282 }
1283
1284 fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
1286 let tarball = prepare_source_tarball(
1287 builder,
1288 "src",
1289 &[
1290 "src/gcc",
1294 ],
1295 );
1296
1297 let plain_dst_src = tarball.image_dir();
1298 if !builder.config.dry_run() {
1303 builder.create_dir(&plain_dst_src.join("src/gcc"));
1304 t!(std::fs::write(
1305 plain_dst_src.join("src/gcc/notice.txt"),
1306 "The GCC source code is not included due to unclear licensing implications\n"
1307 ));
1308 }
1309 tarball.bare()
1310 }
1311}
1312
1313#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1315pub struct PlainSourceTarballGpl;
1316
1317impl CommandLineStep for PlainSourceTarballGpl {
1318 type Output = GeneratedTarball;
1320 const IS_HOST: bool = true;
1321
1322 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1323 run.alias("rustc-src-gpl")
1324 }
1325
1326 fn is_default_step(builder: &Builder<'_>) -> bool {
1327 builder.config.rust_dist_src
1328 }
1329
1330 fn make_run(run: RunConfig<'_>) {
1331 run.builder.ensure(PlainSourceTarballGpl);
1332 }
1333
1334 fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
1336 let tarball = prepare_source_tarball(builder, "src-gpl", &[]);
1337 tarball.bare()
1338 }
1339}
1340
1341fn prepare_source_tarball<'a>(
1342 builder: &'a Builder<'a>,
1343 name: &str,
1344 exclude_dirs: &[&str],
1345) -> Tarball<'a> {
1346 let mut tarball = Tarball::new(builder, "rustc", name);
1351 tarball.permit_symlinks(true);
1352 let plain_dst_src = tarball.image_dir();
1353
1354 let src_files = [
1356 ".gitmodules",
1358 "CONTRIBUTING.md",
1359 "COPYRIGHT",
1360 "Cargo.lock",
1361 "Cargo.toml",
1362 "LICENSE-APACHE",
1363 "LICENSE-MIT",
1364 "README.md",
1365 "RELEASES.md",
1366 "REUSE.toml",
1367 "bootstrap.example.toml",
1368 "configure",
1369 "license-metadata.json",
1370 "package.json",
1371 "x",
1372 "x.ps1",
1373 "x.py",
1374 "yarn.lock",
1375 ];
1377 let src_dirs = ["src", "compiler", "library", "tests", "LICENSES"];
1378
1379 copy_src_dirs(builder, &builder.src, &src_dirs, exclude_dirs, plain_dst_src);
1380
1381 for item in &src_files {
1383 builder.copy_link(&builder.src.join(item), &plain_dst_src.join(item), FileType::Regular);
1384 }
1385
1386 builder.create(&plain_dst_src.join("version"), &builder.rust_version());
1388
1389 let write_git_info = |info: Option<&Info>, path: &Path| {
1391 if let Some(info) = info {
1392 t!(std::fs::create_dir_all(path));
1393 channel::write_commit_hash_file(path, &info.sha);
1394 channel::write_commit_info_file(path, info);
1395 }
1396 };
1397 write_git_info(builder.rust_info().info(), plain_dst_src);
1398 write_git_info(builder.cargo_info.info(), &plain_dst_src.join("./src/tools/cargo"));
1399
1400 if builder.config.dist_vendor {
1401 builder.require_and_update_all_submodules();
1402
1403 let pkgs_for_pgo_training =
1405 build_helper::LLVM_PGO_CRATES.iter().chain(build_helper::RUSTC_PGO_CRATES).map(|pkg| {
1406 let mut manifest_path =
1407 builder.src.join("./src/tools/rustc-perf/collector/compile-benchmarks");
1408 manifest_path.push(pkg);
1409 manifest_path.push("Cargo.toml");
1410 manifest_path
1411 });
1412
1413 let vendor = builder.ensure(Vendor {
1415 sync_args: pkgs_for_pgo_training.collect(),
1416 versioned_dirs: true,
1417 root_dir: plain_dst_src.into(),
1418 output_dir: None,
1419 only_library_workspace: false,
1420 });
1421
1422 let cargo_config_dir = plain_dst_src.join(".cargo");
1423 builder.create_dir(&cargo_config_dir);
1424 builder.create(&cargo_config_dir.join("config.toml"), &vendor.config);
1425
1426 let library_cargo_config_dir = plain_dst_src.join("library").join(".cargo");
1427 builder.create_dir(&library_cargo_config_dir);
1428 builder.create(&library_cargo_config_dir.join("config.toml"), &vendor.config_library);
1429 }
1430
1431 for entry in walkdir::WalkDir::new(tarball.image_dir())
1435 .follow_links(true)
1436 .into_iter()
1437 .filter_map(|e| e.ok())
1438 {
1439 if entry.path().is_dir() && entry.path().file_name() == Some(OsStr::new("__pycache__")) {
1440 t!(fs::remove_dir_all(entry.path()));
1441 }
1442 }
1443 tarball
1444}
1445
1446#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1447pub struct Cargo {
1448 pub build_compiler: Compiler,
1449 pub target: TargetSelection,
1450}
1451
1452impl CommandLineStep for Cargo {
1453 type Output = Option<GeneratedTarball>;
1454 const IS_HOST: bool = true;
1455
1456 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1457 run.alias("cargo")
1458 }
1459
1460 fn is_default_step(builder: &Builder<'_>) -> bool {
1461 should_build_extended_tool(builder, "cargo")
1462 }
1463
1464 fn make_run(run: RunConfig<'_>) {
1465 run.builder.ensure(Cargo {
1466 build_compiler: get_tool_target_compiler(
1467 run.builder,
1468 ToolTargetBuildMode::Build(run.target),
1469 ),
1470 target: run.target,
1471 });
1472 }
1473
1474 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1475 let build_compiler = self.build_compiler;
1476 let target = self.target;
1477
1478 let cargo = builder.ensure(tool::Cargo::from_build_compiler(build_compiler, target));
1479 let src = builder.src.join("src/tools/cargo");
1480 let etc = src.join("etc");
1481
1482 let mut tarball = Tarball::new(builder, "cargo", &target.triple);
1484 tarball.set_overlay(OverlayKind::Cargo);
1485
1486 tarball.add_file(&cargo.tool_path, "bin", FileType::Executable);
1487 tarball.add_file(etc.join("_cargo"), "share/zsh/site-functions", FileType::Regular);
1488 tarball.add_renamed_file(
1489 etc.join("cargo.bashcomp.sh"),
1490 "etc/bash_completion.d",
1491 "cargo",
1492 FileType::Regular,
1493 );
1494 tarball.add_dir(etc.join("man"), "share/man/man1");
1495 tarball.add_legal_and_readme_to("share/doc/cargo");
1496
1497 Some(tarball.generate())
1498 }
1499
1500 fn metadata(&self) -> Option<StepMetadata> {
1501 Some(StepMetadata::dist("cargo", self.target).built_by(self.build_compiler))
1502 }
1503}
1504
1505#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1507pub struct RustAnalyzer {
1508 pub compilers: RustcPrivateCompilers,
1509 pub target: TargetSelection,
1510}
1511
1512impl CommandLineStep for RustAnalyzer {
1513 type Output = Option<GeneratedTarball>;
1514 const IS_HOST: bool = true;
1515
1516 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1517 run.alias("rust-analyzer")
1518 }
1519
1520 fn is_default_step(builder: &Builder<'_>) -> bool {
1521 should_build_extended_tool(builder, "rust-analyzer")
1522 }
1523
1524 fn make_run(run: RunConfig<'_>) {
1525 run.builder.ensure(RustAnalyzer {
1526 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1527 target: run.target,
1528 });
1529 }
1530
1531 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1532 let target = self.target;
1533 let rust_analyzer = builder.ensure(tool::RustAnalyzer::from_compilers(self.compilers));
1534
1535 let mut tarball = Tarball::new(builder, "rust-analyzer", &target.triple);
1536 tarball.set_overlay(OverlayKind::RustAnalyzer);
1537 tarball.is_preview(true);
1538 tarball.add_file(&rust_analyzer.tool_path, "bin", FileType::Executable);
1539 tarball.add_legal_and_readme_to("share/doc/rust-analyzer");
1540 Some(tarball.generate())
1541 }
1542
1543 fn metadata(&self) -> Option<StepMetadata> {
1544 Some(
1545 StepMetadata::dist("rust-analyzer", self.target)
1546 .built_by(self.compilers.build_compiler()),
1547 )
1548 }
1549}
1550
1551#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1552pub struct Clippy {
1553 pub compilers: RustcPrivateCompilers,
1554 pub target: TargetSelection,
1555}
1556
1557impl CommandLineStep for Clippy {
1558 type Output = Option<GeneratedTarball>;
1559 const IS_HOST: bool = true;
1560
1561 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1562 run.alias("clippy")
1563 }
1564
1565 fn is_default_step(builder: &Builder<'_>) -> bool {
1566 should_build_extended_tool(builder, "clippy")
1567 }
1568
1569 fn make_run(run: RunConfig<'_>) {
1570 run.builder.ensure(Clippy {
1571 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1572 target: run.target,
1573 });
1574 }
1575
1576 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1577 let target = self.target;
1578
1579 let clippy = builder.ensure(tool::Clippy::from_compilers(self.compilers));
1583 let cargoclippy = builder.ensure(tool::CargoClippy::from_compilers(self.compilers));
1584
1585 let mut tarball = Tarball::new(builder, "clippy", &target.triple);
1586 tarball.set_overlay(OverlayKind::Clippy);
1587 tarball.is_preview(true);
1588 tarball.add_file(&clippy.tool_path, "bin", FileType::Executable);
1589 tarball.add_file(&cargoclippy.tool_path, "bin", FileType::Executable);
1590 tarball.add_legal_and_readme_to("share/doc/clippy");
1591 Some(tarball.generate())
1592 }
1593
1594 fn metadata(&self) -> Option<StepMetadata> {
1595 Some(StepMetadata::dist("clippy", self.target).built_by(self.compilers.build_compiler()))
1596 }
1597}
1598
1599#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1600pub struct Miri {
1601 pub compilers: RustcPrivateCompilers,
1602 pub target: TargetSelection,
1603}
1604
1605impl CommandLineStep for Miri {
1606 type Output = Option<GeneratedTarball>;
1607 const IS_HOST: bool = true;
1608
1609 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1610 run.alias("miri")
1611 }
1612
1613 fn is_default_step(builder: &Builder<'_>) -> bool {
1614 should_build_extended_tool(builder, "miri")
1615 }
1616
1617 fn make_run(run: RunConfig<'_>) {
1618 run.builder.ensure(Miri {
1619 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1620 target: run.target,
1621 });
1622 }
1623
1624 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1625 if !builder.sess.unstable_features() {
1629 return None;
1630 }
1631
1632 let miri = builder.ensure(tool::Miri::from_compilers(self.compilers));
1633 let cargomiri = builder.ensure(tool::CargoMiri::from_compilers(self.compilers));
1634
1635 let mut tarball = Tarball::new(builder, "miri", &self.target.triple);
1636 tarball.set_overlay(OverlayKind::Miri);
1637 tarball.is_preview(true);
1638 tarball.add_file(&miri.tool_path, "bin", FileType::Executable);
1639 tarball.add_file(&cargomiri.tool_path, "bin", FileType::Executable);
1640 tarball.add_legal_and_readme_to("share/doc/miri");
1641 Some(tarball.generate())
1642 }
1643
1644 fn metadata(&self) -> Option<StepMetadata> {
1645 Some(StepMetadata::dist("miri", self.target).built_by(self.compilers.build_compiler()))
1646 }
1647}
1648
1649#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1650pub struct CraneliftCodegenBackend {
1651 pub compilers: RustcPrivateCompilers,
1652 pub target: TargetSelection,
1653}
1654
1655impl CommandLineStep for CraneliftCodegenBackend {
1656 type Output = Option<GeneratedTarball>;
1657 const IS_HOST: bool = true;
1658
1659 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1660 run.alias("rustc_codegen_cranelift")
1661 }
1662
1663 fn is_default_step(builder: &Builder<'_>) -> bool {
1664 builder
1669 .config
1670 .enabled_codegen_backends(builder.host_target)
1671 .contains(&CodegenBackendKind::Cranelift)
1672 }
1673
1674 fn make_run(run: RunConfig<'_>) {
1675 run.builder.ensure(CraneliftCodegenBackend {
1676 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1677 target: run.target,
1678 });
1679 }
1680
1681 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1682 if !builder.sess.unstable_features() {
1686 return None;
1687 }
1688
1689 let target = self.target;
1690 if !target_supports_cranelift_backend(target) {
1691 builder.info("target not supported by rustc_codegen_cranelift. skipping");
1692 return None;
1693 }
1694
1695 let mut tarball = Tarball::new(builder, "rustc-codegen-cranelift", &target.triple);
1696 tarball.set_overlay(OverlayKind::RustcCodegenCranelift);
1697 tarball.is_preview(true);
1698 tarball.add_legal_and_readme_to("share/doc/rustc_codegen_cranelift");
1699
1700 let compilers = self.compilers;
1701 let stamp = builder.ensure(compile::CraneliftCodegenBackend { compilers });
1702
1703 if builder.config.dry_run() {
1704 return None;
1705 }
1706
1707 add_codegen_backend_to_tarball(builder, &tarball, compilers.target_compiler(), &stamp);
1708
1709 Some(tarball.generate())
1710 }
1711
1712 fn metadata(&self) -> Option<StepMetadata> {
1713 Some(
1714 StepMetadata::dist("rustc_codegen_cranelift", self.target)
1715 .built_by(self.compilers.build_compiler()),
1716 )
1717 }
1718}
1719
1720#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1724pub struct GccCodegenBackend {
1725 pub compilers: RustcPrivateCompilers,
1726 pub target: TargetSelection,
1727}
1728
1729impl CommandLineStep for GccCodegenBackend {
1730 type Output = Option<GeneratedTarball>;
1731 const IS_HOST: bool = true;
1732
1733 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1734 run.alias("rustc_codegen_gcc")
1735 }
1736
1737 fn is_default_step(builder: &Builder<'_>) -> bool {
1738 builder
1743 .config
1744 .enabled_codegen_backends(builder.host_target)
1745 .contains(&CodegenBackendKind::Gcc)
1746 }
1747
1748 fn make_run(run: RunConfig<'_>) {
1749 run.builder.ensure(GccCodegenBackend {
1750 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1751 target: run.target,
1752 });
1753 }
1754
1755 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1756 if !builder.sess.unstable_features() {
1760 return None;
1761 }
1762
1763 let target = self.target;
1764 if target != "x86_64-unknown-linux-gnu" {
1765 builder
1766 .info(&format!("target `{target}` not supported by rustc_codegen_gcc. skipping"));
1767 return None;
1768 }
1769
1770 let mut tarball = Tarball::new(builder, "rustc-codegen-gcc", &target.triple);
1771 tarball.set_overlay(OverlayKind::RustcCodegenGcc);
1772 tarball.is_preview(true);
1773 tarball.add_legal_and_readme_to("share/doc/rustc_codegen_gcc");
1774
1775 let compilers = self.compilers;
1776 let backend = builder.ensure(compile::GccCodegenBackend::for_target(compilers, target));
1777
1778 if builder.config.dry_run() {
1779 return None;
1780 }
1781
1782 add_codegen_backend_to_tarball(
1783 builder,
1784 &tarball,
1785 compilers.target_compiler(),
1786 backend.stamp(),
1787 );
1788
1789 Some(tarball.generate())
1790 }
1791
1792 fn metadata(&self) -> Option<StepMetadata> {
1793 Some(
1794 StepMetadata::dist("rustc_codegen_gcc", self.target)
1795 .built_by(self.compilers.build_compiler()),
1796 )
1797 }
1798}
1799
1800fn add_codegen_backend_to_tarball(
1803 builder: &Builder<'_>,
1804 tarball: &Tarball<'_>,
1805 compiler: Compiler,
1806 stamp: &BuildStamp,
1807) {
1808 let backends_dst = builder.sysroot_codegen_backends(compiler);
1810 let backends_rel = backends_dst
1811 .strip_prefix(builder.sysroot(compiler))
1812 .unwrap()
1813 .strip_prefix(builder.sysroot_libdir_relative(compiler))
1814 .unwrap();
1815 let backends_dst = PathBuf::from("lib").join(backends_rel);
1817
1818 let codegen_backend_dylib = get_codegen_backend_file(stamp);
1819 tarball.add_renamed_file(
1820 &codegen_backend_dylib,
1821 &backends_dst,
1822 &normalize_codegen_backend_name(builder, &codegen_backend_dylib),
1823 FileType::NativeLibrary,
1824 );
1825}
1826
1827#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1828pub struct Rustfmt {
1829 pub compilers: RustcPrivateCompilers,
1830 pub target: TargetSelection,
1831}
1832
1833impl CommandLineStep for Rustfmt {
1834 type Output = Option<GeneratedTarball>;
1835 const IS_HOST: bool = true;
1836
1837 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1838 run.alias("rustfmt")
1839 }
1840
1841 fn is_default_step(builder: &Builder<'_>) -> bool {
1842 should_build_extended_tool(builder, "rustfmt")
1843 }
1844
1845 fn make_run(run: RunConfig<'_>) {
1846 run.builder.ensure(Rustfmt {
1847 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1848 target: run.target,
1849 });
1850 }
1851
1852 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1853 let rustfmt = builder.ensure(tool::Rustfmt::from_compilers(self.compilers));
1854 let cargofmt = builder.ensure(tool::Cargofmt::from_compilers(self.compilers));
1855
1856 let mut tarball = Tarball::new(builder, "rustfmt", &self.target.triple);
1857 tarball.set_overlay(OverlayKind::Rustfmt);
1858 tarball.is_preview(true);
1859 tarball.add_file(&rustfmt.tool_path, "bin", FileType::Executable);
1860 tarball.add_file(&cargofmt.tool_path, "bin", FileType::Executable);
1861 tarball.add_legal_and_readme_to("share/doc/rustfmt");
1862 Some(tarball.generate())
1863 }
1864
1865 fn metadata(&self) -> Option<StepMetadata> {
1866 Some(StepMetadata::dist("rustfmt", self.target).built_by(self.compilers.build_compiler()))
1867 }
1868}
1869
1870#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1872pub struct Extended {
1873 build_compiler: Compiler,
1874 target: TargetSelection,
1875}
1876
1877impl CommandLineStep for Extended {
1878 type Output = ();
1879 const IS_HOST: bool = true;
1880
1881 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1882 run.alias("extended")
1883 }
1884
1885 fn is_default_step(builder: &Builder<'_>) -> bool {
1886 builder.config.extended
1887 }
1888
1889 fn make_run(run: RunConfig<'_>) {
1890 run.builder.ensure(Extended {
1891 build_compiler: run
1892 .builder
1893 .compiler(run.builder.top_stage - 1, run.builder.host_target),
1894 target: run.target,
1895 });
1896 }
1897
1898 fn run(self, builder: &Builder<'_>) {
1900 let target = self.target;
1901 builder.info(&format!("Dist extended stage{} ({target})", builder.top_stage));
1902
1903 let mut tarballs = Vec::new();
1904 let mut built_tools = HashSet::new();
1905 macro_rules! add_component {
1906 ($name:expr => $step:expr) => {
1907 if let Some(Some(tarball)) = builder.ensure_if_default($step, Kind::Dist) {
1908 tarballs.push(tarball);
1909 built_tools.insert($name);
1910 }
1911 };
1912 }
1913
1914 let rustc_private_compilers =
1915 RustcPrivateCompilers::from_build_compiler(builder, self.build_compiler, target);
1916 let build_compiler = rustc_private_compilers.build_compiler();
1917 let target_compiler = rustc_private_compilers.target_compiler();
1918
1919 tarballs.push(builder.ensure(Rustc { target_compiler }));
1924 tarballs.push(builder.ensure(Std { build_compiler, target }).expect("missing std"));
1925
1926 if target.is_windows_gnu() || target.is_windows_gnullvm() {
1927 tarballs.push(builder.ensure(Mingw { target }).expect("missing mingw"));
1928 }
1929
1930 add_component!("rust-docs" => Docs { host: target });
1931 add_component!("rust-json-docs" => JsonDocs { build_compiler: target_compiler, target });
1933 add_component!("cargo" => Cargo { build_compiler, target });
1934 add_component!("rustfmt" => Rustfmt { compilers: rustc_private_compilers, target });
1935 add_component!("rust-analyzer" => RustAnalyzer { compilers: rustc_private_compilers, target });
1936 add_component!("llvm-components" => LlvmTools { target });
1937 add_component!("clippy" => Clippy { compilers: rustc_private_compilers, target });
1938 add_component!("miri" => Miri { compilers: rustc_private_compilers, target });
1939 add_component!("analysis" => Analysis { build_compiler, target });
1940 add_component!("rustc-codegen-cranelift" => CraneliftCodegenBackend {
1941 compilers: rustc_private_compilers,
1942 target
1943 });
1944 add_component!("llvm-bitcode-linker" => LlvmBitcodeLinker {
1945 build_compiler,
1946 target
1947 });
1948
1949 let etc = builder.src.join("src/etc/installer");
1950
1951 if builder.config.dry_run() {
1953 return;
1954 }
1955
1956 let tarball = Tarball::new(builder, "rust", &target.triple);
1957 let generated = tarball.combine(&tarballs);
1958
1959 let tmp = tmpdir(builder).join("combined-tarball");
1960 let work = generated.work_dir();
1961
1962 let mut license = String::new();
1963 license += &builder.read(&builder.src.join("COPYRIGHT"));
1964 license += &builder.read(&builder.src.join("LICENSE-APACHE"));
1965 license += &builder.read(&builder.src.join("LICENSE-MIT"));
1966 license.push('\n');
1967 license.push('\n');
1968
1969 let rtf = r"{\rtf1\ansi\deff0{\fonttbl{\f0\fnil\fcharset0 Arial;}}\nowwrap\fs18";
1970 let mut rtf = rtf.to_string();
1971 rtf.push('\n');
1972 for line in license.lines() {
1973 rtf.push_str(line);
1974 rtf.push_str("\\line ");
1975 }
1976 rtf.push('}');
1977
1978 fn filter(contents: &str, marker: &str) -> String {
1979 let start = format!("tool-{marker}-start");
1980 let end = format!("tool-{marker}-end");
1981 let mut lines = Vec::new();
1982 let mut omitted = false;
1983 for line in contents.lines() {
1984 if line.contains(&start) {
1985 omitted = true;
1986 } else if line.contains(&end) {
1987 omitted = false;
1988 } else if !omitted {
1989 lines.push(line);
1990 }
1991 }
1992
1993 lines.join("\n")
1994 }
1995
1996 let xform = |p: &Path| {
1997 let mut contents = t!(fs::read_to_string(p));
1998 for tool in &["miri", "rust-docs"] {
1999 if !built_tools.contains(tool) {
2000 contents = filter(&contents, tool);
2001 }
2002 }
2003 let ret = tmp.join(p.file_name().unwrap());
2004 t!(fs::write(&ret, &contents));
2005 ret
2006 };
2007
2008 if target.contains("apple-darwin") {
2009 builder.info("building pkg installer");
2010 let pkg = tmp.join("pkg");
2011 let _ = fs::remove_dir_all(&pkg);
2012
2013 let pkgbuild = |component: &str| {
2014 let mut cmd = command("pkgbuild");
2015 cmd.arg("--identifier")
2016 .arg(format!("org.rust-lang.{component}"))
2017 .arg("--scripts")
2018 .arg(pkg.join(component))
2019 .arg("--nopayload")
2020 .arg(pkg.join(component).with_extension("pkg"));
2021 cmd.run(builder);
2022 };
2023
2024 let prepare = |name: &str| {
2025 builder.create_dir(&pkg.join(name));
2026 builder.cp_link_r(
2027 &work.join(format!("{}-{}", pkgname(builder, name), target.triple)),
2028 &pkg.join(name),
2029 );
2030 builder.install(&etc.join("pkg/postinstall"), &pkg.join(name), FileType::Script);
2031 pkgbuild(name);
2032 };
2033 prepare("rustc");
2034 prepare("cargo");
2035 prepare("rust-std");
2036 prepare("rust-analysis");
2037
2038 for tool in &[
2039 "clippy",
2040 "rustfmt",
2041 "rust-analyzer",
2042 "rust-docs",
2043 "miri",
2044 "rustc-codegen-cranelift",
2045 ] {
2046 if built_tools.contains(tool) {
2047 prepare(tool);
2048 }
2049 }
2050 builder.install(&etc.join("pkg/postinstall"), &pkg.join("uninstall"), FileType::Script);
2052 pkgbuild("uninstall");
2053
2054 builder.create_dir(&pkg.join("res"));
2055 builder.create(&pkg.join("res/LICENSE.txt"), &license);
2056 builder.install(&etc.join("gfx/rust-logo.png"), &pkg.join("res"), FileType::Regular);
2057 let mut cmd = command("productbuild");
2058 cmd.arg("--distribution")
2059 .arg(xform(&etc.join("pkg/Distribution.xml")))
2060 .arg("--resources")
2061 .arg(pkg.join("res"))
2062 .arg(distdir(builder).join(format!(
2063 "{}-{}.pkg",
2064 pkgname(builder, "rust"),
2065 target.triple
2066 )))
2067 .arg("--package-path")
2068 .arg(&pkg);
2069 let _time = timeit(builder);
2070 cmd.run(builder);
2071 }
2072
2073 if target.is_windows() {
2074 let exe = tmp.join("exe");
2075 let _ = fs::remove_dir_all(&exe);
2076
2077 let prepare = |name: &str| {
2078 builder.create_dir(&exe.join(name));
2079 let dir = if name == "rust-std" || name == "rust-analysis" {
2080 format!("{}-{}", name, target.triple)
2081 } else if name == "rust-analyzer" {
2082 "rust-analyzer-preview".to_string()
2083 } else if name == "clippy" {
2084 "clippy-preview".to_string()
2085 } else if name == "rustfmt" {
2086 "rustfmt-preview".to_string()
2087 } else if name == "miri" {
2088 "miri-preview".to_string()
2089 } else if name == "rustc-codegen-cranelift" {
2090 unreachable!("cg_clif shouldn't be built for windows");
2093 } else {
2094 name.to_string()
2095 };
2096 builder.cp_link_r(
2097 &work.join(format!("{}-{}", pkgname(builder, name), target.triple)).join(dir),
2098 &exe.join(name),
2099 );
2100 builder.remove(&exe.join(name).join("manifest.in"));
2101 };
2102 prepare("rustc");
2103 prepare("cargo");
2104 prepare("rust-analysis");
2105 prepare("rust-std");
2106 for tool in &["clippy", "rustfmt", "rust-analyzer", "rust-docs", "miri"] {
2107 if built_tools.contains(tool) {
2108 prepare(tool);
2109 }
2110 }
2111 if target.is_windows_gnu() || target.is_windows_gnullvm() {
2112 prepare("rust-mingw");
2113 }
2114
2115 builder.install(&etc.join("gfx/rust-logo.ico"), &exe, FileType::Regular);
2116
2117 let wix_path = env::var_os("WIX")
2119 .expect("`WIX` environment variable must be set for generating MSI installer(s).");
2120 let wix = PathBuf::from(wix_path);
2121 let heat = wix.join("bin/heat.exe");
2122 let candle = wix.join("bin/candle.exe");
2123 let light = wix.join("bin/light.exe");
2124
2125 let heat_flags = ["-nologo", "-gg", "-sfrag", "-srd", "-sreg"];
2126 command(&heat)
2127 .current_dir(&exe)
2128 .arg("dir")
2129 .arg("rustc")
2130 .args(heat_flags)
2131 .arg("-cg")
2132 .arg("RustcGroup")
2133 .arg("-dr")
2134 .arg("Rustc")
2135 .arg("-var")
2136 .arg("var.RustcDir")
2137 .arg("-out")
2138 .arg(exe.join("RustcGroup.wxs"))
2139 .run(builder);
2140 if built_tools.contains("rust-docs") {
2141 command(&heat)
2142 .current_dir(&exe)
2143 .arg("dir")
2144 .arg("rust-docs")
2145 .args(heat_flags)
2146 .arg("-cg")
2147 .arg("DocsGroup")
2148 .arg("-dr")
2149 .arg("Docs")
2150 .arg("-var")
2151 .arg("var.DocsDir")
2152 .arg("-out")
2153 .arg(exe.join("DocsGroup.wxs"))
2154 .arg("-t")
2155 .arg(etc.join("msi/squash-components.xsl"))
2156 .run(builder);
2157 }
2158 command(&heat)
2159 .current_dir(&exe)
2160 .arg("dir")
2161 .arg("cargo")
2162 .args(heat_flags)
2163 .arg("-cg")
2164 .arg("CargoGroup")
2165 .arg("-dr")
2166 .arg("Cargo")
2167 .arg("-var")
2168 .arg("var.CargoDir")
2169 .arg("-out")
2170 .arg(exe.join("CargoGroup.wxs"))
2171 .arg("-t")
2172 .arg(etc.join("msi/remove-duplicates.xsl"))
2173 .run(builder);
2174 command(&heat)
2175 .current_dir(&exe)
2176 .arg("dir")
2177 .arg("rust-std")
2178 .args(heat_flags)
2179 .arg("-cg")
2180 .arg("StdGroup")
2181 .arg("-dr")
2182 .arg("Std")
2183 .arg("-var")
2184 .arg("var.StdDir")
2185 .arg("-out")
2186 .arg(exe.join("StdGroup.wxs"))
2187 .run(builder);
2188 if built_tools.contains("rust-analyzer") {
2189 command(&heat)
2190 .current_dir(&exe)
2191 .arg("dir")
2192 .arg("rust-analyzer")
2193 .args(heat_flags)
2194 .arg("-cg")
2195 .arg("RustAnalyzerGroup")
2196 .arg("-dr")
2197 .arg("RustAnalyzer")
2198 .arg("-var")
2199 .arg("var.RustAnalyzerDir")
2200 .arg("-out")
2201 .arg(exe.join("RustAnalyzerGroup.wxs"))
2202 .arg("-t")
2203 .arg(etc.join("msi/remove-duplicates.xsl"))
2204 .run(builder);
2205 }
2206 if built_tools.contains("clippy") {
2207 command(&heat)
2208 .current_dir(&exe)
2209 .arg("dir")
2210 .arg("clippy")
2211 .args(heat_flags)
2212 .arg("-cg")
2213 .arg("ClippyGroup")
2214 .arg("-dr")
2215 .arg("Clippy")
2216 .arg("-var")
2217 .arg("var.ClippyDir")
2218 .arg("-out")
2219 .arg(exe.join("ClippyGroup.wxs"))
2220 .arg("-t")
2221 .arg(etc.join("msi/remove-duplicates.xsl"))
2222 .run(builder);
2223 }
2224 if built_tools.contains("rustfmt") {
2225 command(&heat)
2226 .current_dir(&exe)
2227 .arg("dir")
2228 .arg("rustfmt")
2229 .args(heat_flags)
2230 .arg("-cg")
2231 .arg("RustFmtGroup")
2232 .arg("-dr")
2233 .arg("RustFmt")
2234 .arg("-var")
2235 .arg("var.RustFmtDir")
2236 .arg("-out")
2237 .arg(exe.join("RustFmtGroup.wxs"))
2238 .arg("-t")
2239 .arg(etc.join("msi/remove-duplicates.xsl"))
2240 .run(builder);
2241 }
2242 if built_tools.contains("miri") {
2243 command(&heat)
2244 .current_dir(&exe)
2245 .arg("dir")
2246 .arg("miri")
2247 .args(heat_flags)
2248 .arg("-cg")
2249 .arg("MiriGroup")
2250 .arg("-dr")
2251 .arg("Miri")
2252 .arg("-var")
2253 .arg("var.MiriDir")
2254 .arg("-out")
2255 .arg(exe.join("MiriGroup.wxs"))
2256 .arg("-t")
2257 .arg(etc.join("msi/remove-duplicates.xsl"))
2258 .run(builder);
2259 }
2260 command(&heat)
2261 .current_dir(&exe)
2262 .arg("dir")
2263 .arg("rust-analysis")
2264 .args(heat_flags)
2265 .arg("-cg")
2266 .arg("AnalysisGroup")
2267 .arg("-dr")
2268 .arg("Analysis")
2269 .arg("-var")
2270 .arg("var.AnalysisDir")
2271 .arg("-out")
2272 .arg(exe.join("AnalysisGroup.wxs"))
2273 .arg("-t")
2274 .arg(etc.join("msi/remove-duplicates.xsl"))
2275 .run(builder);
2276 if target.is_windows_gnu() || target.is_windows_gnullvm() {
2277 command(&heat)
2278 .current_dir(&exe)
2279 .arg("dir")
2280 .arg("rust-mingw")
2281 .args(heat_flags)
2282 .arg("-cg")
2283 .arg("GccGroup")
2284 .arg("-dr")
2285 .arg("Gcc")
2286 .arg("-var")
2287 .arg("var.GccDir")
2288 .arg("-out")
2289 .arg(exe.join("GccGroup.wxs"))
2290 .run(builder);
2291 }
2292
2293 let candle = |input: &Path| {
2294 let output = exe.join(input.file_stem().unwrap()).with_extension("wixobj");
2295 let arch = if target.contains("x86_64") { "x64" } else { "x86" };
2296 let mut cmd = command(&candle);
2297 cmd.current_dir(&exe)
2298 .arg("-nologo")
2299 .arg("-dRustcDir=rustc")
2300 .arg("-dCargoDir=cargo")
2301 .arg("-dStdDir=rust-std")
2302 .arg("-dAnalysisDir=rust-analysis")
2303 .arg("-arch")
2304 .arg(arch)
2305 .arg("-out")
2306 .arg(&output)
2307 .arg(input);
2308 add_env(builder, &mut cmd, target, &built_tools);
2309
2310 if built_tools.contains("clippy") {
2311 cmd.arg("-dClippyDir=clippy");
2312 }
2313 if built_tools.contains("rustfmt") {
2314 cmd.arg("-dRustFmtDir=rustfmt");
2315 }
2316 if built_tools.contains("rust-docs") {
2317 cmd.arg("-dDocsDir=rust-docs");
2318 }
2319 if built_tools.contains("rust-analyzer") {
2320 cmd.arg("-dRustAnalyzerDir=rust-analyzer");
2321 }
2322 if built_tools.contains("miri") {
2323 cmd.arg("-dMiriDir=miri");
2324 }
2325 if target.is_windows_gnu() || target.is_windows_gnullvm() {
2326 cmd.arg("-dGccDir=rust-mingw");
2327 }
2328 cmd.run(builder);
2329 };
2330 candle(&xform(&etc.join("msi/rust.wxs")));
2331 candle(&etc.join("msi/ui.wxs"));
2332 candle(&etc.join("msi/rustwelcomedlg.wxs"));
2333 candle("RustcGroup.wxs".as_ref());
2334 if built_tools.contains("rust-docs") {
2335 candle("DocsGroup.wxs".as_ref());
2336 }
2337 candle("CargoGroup.wxs".as_ref());
2338 candle("StdGroup.wxs".as_ref());
2339 if built_tools.contains("clippy") {
2340 candle("ClippyGroup.wxs".as_ref());
2341 }
2342 if built_tools.contains("rustfmt") {
2343 candle("RustFmtGroup.wxs".as_ref());
2344 }
2345 if built_tools.contains("miri") {
2346 candle("MiriGroup.wxs".as_ref());
2347 }
2348 if built_tools.contains("rust-analyzer") {
2349 candle("RustAnalyzerGroup.wxs".as_ref());
2350 }
2351 candle("AnalysisGroup.wxs".as_ref());
2352
2353 if target.is_windows_gnu() || target.is_windows_gnullvm() {
2354 candle("GccGroup.wxs".as_ref());
2355 }
2356
2357 builder.create(&exe.join("LICENSE.rtf"), &rtf);
2358 builder.install(&etc.join("gfx/banner.bmp"), &exe, FileType::Regular);
2359 builder.install(&etc.join("gfx/dialogbg.bmp"), &exe, FileType::Regular);
2360
2361 builder.info(&format!("building `msi` installer with {light:?}"));
2362 let filename = format!("{}-{}.msi", pkgname(builder, "rust"), target.triple);
2363 let mut cmd = command(&light);
2364 cmd.arg("-nologo")
2365 .arg("-ext")
2366 .arg("WixUIExtension")
2367 .arg("-ext")
2368 .arg("WixUtilExtension")
2369 .arg("-out")
2370 .arg(exe.join(&filename))
2371 .arg("rust.wixobj")
2372 .arg("ui.wixobj")
2373 .arg("rustwelcomedlg.wixobj")
2374 .arg("RustcGroup.wixobj")
2375 .arg("CargoGroup.wixobj")
2376 .arg("StdGroup.wixobj")
2377 .arg("AnalysisGroup.wixobj")
2378 .current_dir(&exe);
2379
2380 if built_tools.contains("clippy") {
2381 cmd.arg("ClippyGroup.wixobj");
2382 }
2383 if built_tools.contains("rustfmt") {
2384 cmd.arg("RustFmtGroup.wixobj");
2385 }
2386 if built_tools.contains("miri") {
2387 cmd.arg("MiriGroup.wixobj");
2388 }
2389 if built_tools.contains("rust-analyzer") {
2390 cmd.arg("RustAnalyzerGroup.wixobj");
2391 }
2392 if built_tools.contains("rust-docs") {
2393 cmd.arg("DocsGroup.wixobj");
2394 }
2395
2396 if target.is_windows_gnu() || target.is_windows_gnullvm() {
2397 cmd.arg("GccGroup.wixobj");
2398 }
2399 cmd.arg("-sice:ICE57");
2401
2402 let _time = timeit(builder);
2403 cmd.run(builder);
2404
2405 if !builder.config.dry_run() {
2406 t!(move_file(exe.join(&filename), distdir(builder).join(&filename)));
2407 }
2408 }
2409 }
2410
2411 fn metadata(&self) -> Option<StepMetadata> {
2412 Some(StepMetadata::dist("extended", self.target).built_by(self.build_compiler))
2413 }
2414}
2415
2416fn add_env(
2417 builder: &Builder<'_>,
2418 cmd: &mut BootstrapCommand,
2419 target: TargetSelection,
2420 built_tools: &HashSet<&'static str>,
2421) {
2422 let mut parts = builder.version.split('.');
2423 cmd.env("CFG_RELEASE_INFO", builder.rust_version())
2424 .env("CFG_RELEASE_NUM", &builder.version)
2425 .env("CFG_RELEASE", builder.rust_release())
2426 .env("CFG_VER_MAJOR", parts.next().unwrap())
2427 .env("CFG_VER_MINOR", parts.next().unwrap())
2428 .env("CFG_VER_PATCH", parts.next().unwrap())
2429 .env("CFG_VER_BUILD", "0") .env("CFG_PACKAGE_VERS", builder.rust_package_vers())
2431 .env("CFG_PACKAGE_NAME", pkgname(builder, "rust"))
2432 .env("CFG_BUILD", target.triple)
2433 .env("CFG_CHANNEL", &builder.config.channel);
2434
2435 if target.is_windows_gnullvm() {
2436 cmd.env("CFG_MINGW", "1").env("CFG_ABI", "LLVM");
2437 } else if target.is_windows_gnu() {
2438 cmd.env("CFG_MINGW", "1").env("CFG_ABI", "GNU");
2439 } else {
2440 cmd.env("CFG_MINGW", "0").env("CFG_ABI", "MSVC");
2441 }
2442
2443 let mut define_optional_tool = |tool_name: &str, env_name: &str| {
2445 cmd.env(env_name, if built_tools.contains(tool_name) { "1" } else { "0" });
2446 };
2447 define_optional_tool("rustfmt", "CFG_RUSTFMT");
2448 define_optional_tool("clippy", "CFG_CLIPPY");
2449 define_optional_tool("miri", "CFG_MIRI");
2450 define_optional_tool("rust-analyzer", "CFG_RA");
2451}
2452
2453fn install_llvm_file(
2454 builder: &Builder<'_>,
2455 source: &Path,
2456 destination: &Path,
2457 install_symlink: bool,
2458) {
2459 if builder.config.dry_run() {
2460 return;
2461 }
2462
2463 if source.is_symlink() {
2464 builder.install(&t!(fs::canonicalize(source)), destination, FileType::NativeLibrary);
2467
2468 let full_dest = destination.join(source.file_name().unwrap());
2469 if install_symlink {
2470 builder.copy_link(source, &full_dest, FileType::NativeLibrary);
2473 } else {
2474 let link = t!(fs::read_link(source));
2478 let mut linker_script = t!(fs::File::create(full_dest));
2479 t!(write!(linker_script, "INPUT({})\n", link.display()));
2480
2481 let meta = t!(fs::metadata(source));
2484 if let Ok(mtime) = meta.modified() {
2485 t!(linker_script.set_modified(mtime));
2486 }
2487 }
2488 } else {
2489 builder.install(source, destination, FileType::NativeLibrary);
2490 }
2491}
2492
2493#[cfg_attr(
2497 feature = "tracing",
2498 instrument(
2499 level = "trace",
2500 name = "maybe_install_llvm",
2501 skip_all,
2502 fields(target = ?target, dst_libdir = ?dst_libdir, install_symlink = install_symlink),
2503 ),
2504)]
2505fn maybe_install_llvm(
2506 builder: &Builder<'_>,
2507 llvm: &LlvmBuildStatus,
2508 target: TargetSelection,
2509 dst_libdir: &Path,
2510 install_symlink: bool,
2511) -> bool {
2512 let is_system_llvm = llvm.llvm_output().kind() == LlvmKind::External;
2530 if is_system_llvm {
2531 trace!("system LLVM requested, no install");
2532 return false;
2533 }
2534
2535 if target.contains("apple-darwin") && llvm.llvm_output().link_shared() {
2541 let src_libdir = llvm.llvm_output().root_dir().join("lib");
2542 let llvm_dylib_path = src_libdir.join("libLLVM.dylib");
2543 if llvm_dylib_path.exists() {
2544 builder.install(&llvm_dylib_path, dst_libdir, FileType::NativeLibrary);
2545
2546 if install_symlink {
2547 let major = llvm::get_llvm_version_major(builder, &builder.host_llvm_config());
2548 let versioned_name = match &builder.config.llvm_version_suffix {
2549 Some(version_suffix) => format!("libLLVM-{major}{version_suffix}.dylib"),
2550 None => {
2551 if builder.config.channel == "dev" {
2553 format!("libLLVM-{major}-rust-dev.dylib")
2554 } else {
2555 format!(
2556 "libLLVM-{major}-rust-{}-{}.dylib",
2557 builder.version, builder.config.channel
2558 )
2559 }
2560 }
2561 };
2562 t!(builder.symlink_file("libLLVM.dylib", dst_libdir.join(versioned_name)));
2563 }
2564 }
2565 !builder.config.dry_run()
2566 } else if let llvm::LlvmBuildStatus::AlreadyBuilt(llvm_output) = llvm {
2567 trace!("LLVM already built, installing LLVM files");
2568
2569 let host_llvm = builder.ensure(llvm::Llvm { target: builder.host_target });
2570 let mut cmd = command(host_llvm.llvm_config());
2571 cmd.cached();
2572 cmd.arg("--libfiles");
2573 builder.do_if_verbose(|| println!("running {cmd:?}"));
2574 let files = cmd.run_capture_stdout(builder).stdout();
2575 let build_llvm_out = host_llvm.root_dir();
2576 let target_llvm_out = llvm_output.root_dir();
2577 for file in files.trim_end().split(' ') {
2578 let file = if let Ok(relative_path) = Path::new(file).strip_prefix(build_llvm_out) {
2580 target_llvm_out.join(relative_path)
2581 } else {
2582 PathBuf::from(file)
2583 };
2584 install_llvm_file(builder, &file, dst_libdir, install_symlink);
2585 }
2586 !builder.config.dry_run()
2587 } else {
2588 false
2589 }
2590}
2591
2592#[cfg_attr(
2594 feature = "tracing",
2595 instrument(
2596 level = "trace",
2597 name = "maybe_install_llvm_target",
2598 skip_all,
2599 fields(
2600 target = ?target,
2601 sysroot = ?sysroot,
2602 ),
2603 ),
2604)]
2605pub fn maybe_install_llvm_target(builder: &Builder<'_>, target: TargetSelection, sysroot: &Path) {
2606 let dst_libdir = sysroot.join("lib/rustlib").join(target).join("lib");
2607
2608 let config = get_llvm_build_status(builder, target);
2611
2612 if config.llvm_output().link_shared() {
2616 maybe_install_llvm(builder, &config, target, &dst_libdir, false);
2617 }
2618}
2619
2620#[cfg_attr(
2622 feature = "tracing",
2623 instrument(
2624 level = "trace",
2625 name = "maybe_install_llvm_runtime",
2626 skip_all,
2627 fields(
2628 target = ?target,
2629 sysroot = ?sysroot,
2630 ),
2631 ),
2632)]
2633pub fn maybe_install_llvm_runtime(builder: &Builder<'_>, target: TargetSelection, sysroot: &Path) {
2634 let dst_libdir = sysroot.join(builder.libdir_relative(Compiler::new(1, target)));
2635
2636 let config = get_llvm_build_status(builder, target);
2639
2640 if config.llvm_output().link_shared() {
2644 maybe_install_llvm(builder, &config, target, &dst_libdir, false);
2645
2646 if target.triple.contains("windows") {
2650 let dst_libdir = sysroot.join("lib/rustlib").join(target).join("bin");
2651 maybe_install_llvm(builder, &config, target, &dst_libdir, false);
2652 }
2653 }
2654}
2655
2656#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2657pub struct LlvmTools {
2658 pub target: TargetSelection,
2659}
2660
2661impl CommandLineStep for LlvmTools {
2662 type Output = Option<GeneratedTarball>;
2663 const IS_HOST: bool = true;
2664
2665 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2666 let mut run = run.alias("llvm-tools");
2667 for tool in LLVM_TOOLS {
2668 run = run.alias(tool);
2669 }
2670
2671 run
2672 }
2673
2674 fn is_default_step(builder: &Builder<'_>) -> bool {
2675 should_build_extended_tool(builder, "llvm-tools")
2676 }
2677
2678 fn make_run(run: RunConfig<'_>) {
2679 run.builder.ensure(LlvmTools { target: run.target });
2680 }
2681
2682 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2683 fn tools_to_install(paths: &[PathBuf]) -> Vec<&'static str> {
2684 let mut tools = vec![];
2685
2686 for path in paths {
2687 let path = path.to_str().unwrap();
2688
2689 if path == "llvm-tools" {
2691 return LLVM_TOOLS.to_owned();
2692 }
2693
2694 for tool in LLVM_TOOLS {
2695 if path == *tool {
2696 tools.push(*tool);
2697 }
2698 }
2699 }
2700
2701 if tools.is_empty() {
2703 tools = LLVM_TOOLS.to_owned();
2704 }
2705
2706 tools
2707 }
2708
2709 let target = self.target;
2710
2711 let llvm_output = builder.ensure(crate::core::build_steps::llvm::Llvm { target });
2712
2713 if llvm_output.kind() == LlvmKind::External {
2715 builder.info(&format!("Skipping LlvmTools ({target}): external LLVM"));
2716 return None;
2717 }
2718
2719 if !builder.config.dry_run() {
2720 builder.require_submodule("src/llvm-project", None);
2721 }
2722
2723 let mut tarball = Tarball::new(builder, "llvm-tools", &target.triple);
2724 tarball.set_overlay(OverlayKind::Llvm);
2725 tarball.is_preview(true);
2726
2727 if builder.config.llvm_tools_enabled {
2728 let src_bindir = llvm_output.root_dir().join("bin");
2730 let dst_bindir = format!("lib/rustlib/{}/bin", target.triple);
2731 for tool in tools_to_install(&builder.paths) {
2732 let exe = src_bindir.join(exe(tool, target));
2733 if !exe.exists() && llvm_output.kind() == LlvmKind::DownloadedFromCi {
2735 eprintln!("{} does not exist; skipping copy", exe.display());
2736 continue;
2737 }
2738
2739 tarball.add_file(&exe, &dst_bindir, FileType::Executable);
2740 }
2741 }
2742
2743 maybe_install_llvm_target(builder, target, tarball.image_dir());
2748
2749 Some(tarball.generate())
2750 }
2751}
2752
2753#[derive(Debug, Clone, Hash, PartialEq, Eq)]
2756pub struct LlvmBitcodeLinker {
2757 pub build_compiler: Compiler,
2759 pub target: TargetSelection,
2761}
2762
2763impl CommandLineStep for LlvmBitcodeLinker {
2764 type Output = Option<GeneratedTarball>;
2765 const IS_HOST: bool = true;
2766
2767 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2768 run.alias("llvm-bitcode-linker")
2769 }
2770
2771 fn is_default_step(builder: &Builder<'_>) -> bool {
2772 should_build_extended_tool(builder, "llvm-bitcode-linker")
2773 }
2774
2775 fn make_run(run: RunConfig<'_>) {
2776 run.builder.ensure(LlvmBitcodeLinker {
2777 build_compiler: tool::LlvmBitcodeLinker::get_build_compiler_for_target(
2778 run.builder,
2779 run.target,
2780 ),
2781 target: run.target,
2782 });
2783 }
2784
2785 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2786 let target = self.target;
2787
2788 let llbc_linker = builder
2789 .ensure(tool::LlvmBitcodeLinker::from_build_compiler(self.build_compiler, target));
2790
2791 let self_contained_bin_dir = format!("lib/rustlib/{}/bin/self-contained", target.triple);
2792
2793 let mut tarball = Tarball::new(builder, "llvm-bitcode-linker", &target.triple);
2795 tarball.set_overlay(OverlayKind::LlvmBitcodeLinker);
2796 tarball.is_preview(true);
2797
2798 tarball.add_file(&llbc_linker.tool_path, self_contained_bin_dir, FileType::Executable);
2799
2800 Some(tarball.generate())
2801 }
2802}
2803
2804#[derive(Debug, Clone, Hash, PartialEq, Eq)]
2807pub struct Enzyme {
2808 pub target: TargetSelection,
2810}
2811
2812impl CommandLineStep for Enzyme {
2813 type Output = Option<GeneratedTarball>;
2814 const IS_HOST: bool = true;
2815
2816 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2817 run.alias("enzyme")
2818 }
2819
2820 fn is_default_step(builder: &Builder<'_>) -> bool {
2821 builder.config.llvm_enzyme
2822 }
2823
2824 fn make_run(run: RunConfig<'_>) {
2825 run.builder.ensure(Enzyme { target: run.target });
2826 }
2827
2828 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2829 if !builder.sess.unstable_features() {
2833 return None;
2834 }
2835
2836 let target = self.target;
2837
2838 let enzyme = builder.ensure(llvm::Enzyme { target });
2839
2840 let target_libdir = format!("lib/rustlib/{}/lib", target.triple);
2841
2842 let mut tarball = Tarball::new(builder, "enzyme", &target.triple);
2844 tarball.set_overlay(OverlayKind::Enzyme);
2845 tarball.is_preview(true);
2846
2847 tarball.add_file(enzyme.enzyme_path(), target_libdir, FileType::NativeLibrary);
2848
2849 Some(tarball.generate())
2850 }
2851}
2852
2853#[derive(Debug, Clone, Hash, PartialEq, Eq)]
2854pub struct Offload {
2855 pub target: TargetSelection,
2856}
2857
2858impl CommandLineStep for Offload {
2859 type Output = Option<GeneratedTarball>;
2860 const IS_HOST: bool = true;
2861
2862 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2863 run.alias("offload")
2864 }
2865
2866 fn is_default_step(builder: &Builder<'_>) -> bool {
2867 builder.config.llvm_offload
2868 }
2869
2870 fn make_run(run: RunConfig<'_>) {
2871 run.builder.ensure(Offload { target: run.target });
2872 }
2873
2874 fn run(self, builder: &Builder<'_>) -> Self::Output {
2875 if !builder.unstable_features() {
2876 return None;
2877 }
2878
2879 let target = self.target;
2880
2881 let omp_offload = builder.ensure(llvm::OmpOffload { target });
2882 let rust_offload = builder.ensure(llvm::RustOffload { target });
2883
2884 if builder.config.dry_run() {
2885 return None;
2886 }
2887
2888 let target_libdir = PathBuf::from(format!("lib/rustlib/{}/lib", target.triple));
2889
2890 let mut tarball = Tarball::new(builder, "offload", &target.triple);
2891 tarball.set_overlay(OverlayKind::Offload);
2892 tarball.is_preview(true);
2893
2894 let omp_offload_libdir = omp_offload.lib_dir();
2895
2896 for path in omp_offload.artifact_paths_with_symlink_targets() {
2897 let relative = t!(path.strip_prefix(omp_offload_libdir));
2898 let destdir = target_libdir.join(relative.parent().unwrap());
2899
2900 tarball.add_file(path, destdir, FileType::NativeLibrary);
2901 }
2902
2903 tarball.add_file(rust_offload.rust_offload_path(), target_libdir, FileType::NativeLibrary);
2904
2905 Some(tarball.generate())
2906 }
2907}
2908
2909#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2918pub struct RustDev {
2919 pub target: TargetSelection,
2920}
2921
2922impl CommandLineStep for RustDev {
2923 type Output = Option<GeneratedTarball>;
2924 const IS_HOST: bool = true;
2925
2926 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2927 run.alias("rust-dev")
2928 }
2929
2930 fn is_default_step(_builder: &Builder<'_>) -> bool {
2931 true
2932 }
2933
2934 fn make_run(run: RunConfig<'_>) {
2935 run.builder.ensure(RustDev { target: run.target });
2936 }
2937
2938 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2939 let target = self.target;
2940
2941 if let Some(config) = builder.config.target_config.get(&target)
2943 && let Some(ref _s) = config.llvm_config
2944 {
2945 builder.info(&format!("Skipping RustDev ({target}): external LLVM"));
2946 return None;
2947 }
2948
2949 if !builder.config.dry_run() {
2950 builder.require_submodule("src/llvm-project", None);
2951 }
2952
2953 let mut tarball = Tarball::new(builder, "rust-dev", &target.triple);
2954 tarball.set_overlay(OverlayKind::Llvm);
2955 tarball.permit_symlinks(true);
2957
2958 let llvm_output = builder.ensure(crate::core::build_steps::llvm::Llvm { target });
2959
2960 let src_bindir = llvm_output.root_dir().join("bin");
2961 if src_bindir.exists() {
2967 for entry in walkdir::WalkDir::new(&src_bindir) {
2968 let entry = t!(entry);
2969 if entry.file_type().is_file() && !entry.path_is_symlink() {
2970 let name = entry.file_name().to_str().unwrap();
2971 tarball.add_file(src_bindir.join(name), "bin", FileType::Executable);
2972 }
2973 }
2974 }
2975
2976 if builder.config.lld_enabled {
2977 let lld_out = builder.ensure(crate::core::build_steps::llvm::Lld { target });
2979
2980 let lld_path = lld_out.join("bin").join(exe("lld", target));
2982 if lld_path.exists() {
2983 tarball.add_file(&lld_path, "bin", FileType::Executable);
2984 }
2985 }
2986
2987 let filecheck = builder.ensure(llvm::FileCheck { target });
2988 tarball.add_file(filecheck, "bin", FileType::Executable);
2989
2990 tarball.add_dir(llvm_output.root_dir().join("include"), "include");
2994
2995 let dst_libdir = tarball.image_dir().join("lib");
3000
3001 let config = get_llvm_build_status(builder, target);
3002 maybe_install_llvm(builder, &config, target, &dst_libdir, true);
3003
3004 let link_type = if llvm_output.link_shared() { "dynamic" } else { "static" };
3006 t!(std::fs::write(tarball.image_dir().join(LLVM_CI_LINK_TYPE_PATH), link_type), dst_libdir);
3007
3008 copy_src_dirs(
3012 builder,
3013 &builder.src.join("src").join("llvm-project"),
3014 &["compiler-rt"],
3015 &["compiler-rt/test"],
3018 tarball.image_dir(),
3019 );
3020
3021 Some(tarball.generate())
3022 }
3023}
3024
3025#[derive(Clone, Debug, Eq, Hash, PartialEq)]
3031pub struct Bootstrap {
3032 target: TargetSelection,
3033}
3034
3035impl CommandLineStep for Bootstrap {
3036 type Output = Option<GeneratedTarball>;
3037
3038 const IS_HOST: bool = true;
3039
3040 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3041 run.alias("bootstrap")
3042 }
3043
3044 fn make_run(run: RunConfig<'_>) {
3045 run.builder.ensure(Bootstrap { target: run.target });
3046 }
3047
3048 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
3049 let target = self.target;
3050
3051 let tarball = Tarball::new(builder, "bootstrap", &target.triple);
3052
3053 let bootstrap_outdir = &builder.bootstrap_out;
3054 for file in &["bootstrap", "rustc", "rustdoc"] {
3055 tarball.add_file(
3056 bootstrap_outdir.join(exe(file, target)),
3057 "bootstrap/bin",
3058 FileType::Executable,
3059 );
3060 }
3061
3062 Some(tarball.generate())
3063 }
3064
3065 fn metadata(&self) -> Option<StepMetadata> {
3066 Some(StepMetadata::dist("bootstrap", self.target))
3067 }
3068}
3069
3070#[derive(Clone, Debug, Eq, Hash, PartialEq)]
3075pub struct BuildManifest {
3076 target: TargetSelection,
3077}
3078
3079impl CommandLineStep for BuildManifest {
3080 type Output = GeneratedTarball;
3081
3082 const IS_HOST: bool = true;
3083
3084 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3085 run.alias("build-manifest")
3086 }
3087
3088 fn make_run(run: RunConfig<'_>) {
3089 run.builder.ensure(BuildManifest { target: run.target });
3090 }
3091
3092 fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
3093 let build_manifest =
3097 builder.ensure(tool::BuildManifest::new(builder, builder.config.host_target));
3098
3099 let tarball = Tarball::new(builder, "build-manifest", &self.target.triple);
3100 tarball.add_file(&build_manifest.tool_path, "bin", FileType::Executable);
3101 tarball.generate()
3102 }
3103
3104 fn metadata(&self) -> Option<StepMetadata> {
3105 Some(StepMetadata::dist("build-manifest", self.target))
3106 }
3107}
3108
3109#[derive(Clone, Debug, Eq, Hash, PartialEq)]
3115pub struct ReproducibleArtifacts {
3116 target: TargetSelection,
3117}
3118
3119impl CommandLineStep for ReproducibleArtifacts {
3120 type Output = Option<GeneratedTarball>;
3121 const IS_HOST: bool = true;
3122
3123 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3124 run.alias("reproducible-artifacts")
3125 }
3126
3127 fn is_default_step(_builder: &Builder<'_>) -> bool {
3128 true
3129 }
3130
3131 fn make_run(run: RunConfig<'_>) {
3132 run.builder.ensure(ReproducibleArtifacts { target: run.target });
3133 }
3134
3135 fn run(self, builder: &Builder<'_>) -> Self::Output {
3136 let mut added_anything = false;
3137 let tarball = Tarball::new(builder, "reproducible-artifacts", &self.target.triple);
3138
3139 let pgo_profiles = [
3140 &builder.config.rust_pgo.use_profile,
3141 &builder.config.llvm_pgo.use_profile,
3142 &builder.config.rustdoc_pgo.use_profile,
3143 &builder.config.cargo_pgo.use_profile,
3144 &builder.config.clippy_pgo.use_profile,
3145 ];
3146 for profile in pgo_profiles {
3147 if let Some(path) = profile.as_ref() {
3148 tarball.add_file(path, ".", FileType::Regular);
3149 added_anything = true;
3150 }
3151 }
3152 for profile in &builder.config.reproducible_artifacts {
3153 tarball.add_file(profile, ".", FileType::Regular);
3154 added_anything = true;
3155 }
3156 if added_anything { Some(tarball.generate()) } else { None }
3157 }
3158
3159 fn metadata(&self) -> Option<StepMetadata> {
3160 Some(StepMetadata::dist("reproducible-artifacts", self.target))
3161 }
3162}
3163
3164#[derive(Clone, Debug, Eq, Hash, PartialEq)]
3170pub struct GccDev {
3171 target: TargetSelection,
3172}
3173
3174impl CommandLineStep for GccDev {
3175 type Output = GeneratedTarball;
3176
3177 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3178 run.alias("gcc-dev")
3179 }
3180
3181 fn make_run(run: RunConfig<'_>) {
3182 run.builder.ensure(GccDev { target: run.target });
3183 }
3184
3185 fn run(self, builder: &Builder<'_>) -> Self::Output {
3186 let tarball = Tarball::new(builder, "gcc-dev", &self.target.triple);
3187 let output = builder
3188 .ensure(super::gcc::Gcc { target_pair: GccTargetPair::for_native_build(self.target) });
3189 tarball.add_file(output.libgccjit(), "lib", FileType::NativeLibrary);
3190 tarball.generate()
3191 }
3192
3193 fn metadata(&self) -> Option<StepMetadata> {
3194 Some(StepMetadata::dist("gcc-dev", self.target))
3195 }
3196}
3197
3198#[derive(Clone, Debug, Eq, Hash, PartialEq)]
3204pub struct Gcc {
3205 host: TargetSelection,
3206 target: TargetSelection,
3207}
3208
3209impl CommandLineStep for Gcc {
3210 type Output = Option<GeneratedTarball>;
3211
3212 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
3213 run.alias("gcc")
3214 }
3215
3216 fn make_run(run: RunConfig<'_>) {
3217 run.builder.ensure(Gcc { host: run.builder.host_target, target: run.target });
3221 }
3222
3223 fn run(self, builder: &Builder<'_>) -> Self::Output {
3224 if !builder.sess.unstable_features() {
3228 return None;
3229 }
3230
3231 let host = self.host;
3232 let target = self.target;
3233 if host != "x86_64-unknown-linux-gnu" {
3234 builder.info(&format!("host target `{host}` not supported by gcc. skipping"));
3235 return None;
3236 }
3237
3238 if builder.config.is_running_on_ci() {
3239 assert_eq!(
3240 builder.config.gcc_ci_mode,
3241 GccCiMode::BuildLocally,
3242 "Cannot use gcc.download-ci-gcc when distributing GCC on CI"
3243 );
3244 }
3245
3246 builder.require_submodule(
3249 "src/gcc",
3250 Some("The src/gcc submodule is required for disting libgccjit"),
3251 );
3252
3253 let target_pair = GccTargetPair::for_target_pair(host, target);
3254 let libgccjit = builder.ensure(super::gcc::Gcc { target_pair });
3255
3256 let mut tarball = Tarball::new(builder, &format!("gcc-{target}"), &host.triple);
3260 tarball.set_overlay(OverlayKind::Gcc);
3261 tarball.is_preview(true);
3262 tarball.add_legal_and_readme_to("share/doc/gcc");
3263
3264 let cg_dir = PathBuf::from(format!("lib/rustlib/{host}/codegen-backends"));
3269
3270 let rel_libgccjit_path = libgccjit_path_relative_to_cg_dir(&target_pair, &libgccjit);
3272 let path = cg_dir.join(rel_libgccjit_path.parent().unwrap());
3273
3274 tarball.add_file(libgccjit.libgccjit(), path, FileType::NativeLibrary);
3275 Some(tarball.generate())
3276 }
3277
3278 fn metadata(&self) -> Option<StepMetadata> {
3279 Some(StepMetadata::dist(
3280 "gcc",
3281 TargetSelection::from_user(&format!("({}, {})", self.host, self.target)),
3282 ))
3283 }
3284}