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