1use std::collections::HashSet;
12use std::ffi::OsStr;
13use std::io::Write;
14use std::path::{Path, PathBuf};
15use std::{env, fs};
16
17use object::BinaryFormat;
18use object::read::archive::ArchiveFile;
19#[cfg(feature = "tracing")]
20use tracing::instrument;
21
22use crate::core::build_steps::compile::{get_codegen_backend_file, normalize_codegen_backend_name};
23use crate::core::build_steps::doc::DocumentationFormat;
24use crate::core::build_steps::tool::{
25 self, RustcPrivateCompilers, ToolTargetBuildMode, get_tool_target_compiler,
26};
27use crate::core::build_steps::vendor::{VENDOR_DIR, Vendor};
28use crate::core::build_steps::{compile, llvm};
29use crate::core::builder::{Builder, Kind, RunConfig, ShouldRun, Step, StepMetadata};
30use crate::core::config::TargetSelection;
31use crate::utils::build_stamp::{self, BuildStamp};
32use crate::utils::channel::{self, Info};
33use crate::utils::exec::{BootstrapCommand, command};
34use crate::utils::helpers::{
35 exe, is_dylib, move_file, t, target_supports_cranelift_backend, timeit,
36};
37use crate::utils::tarball::{GeneratedTarball, OverlayKind, Tarball};
38use crate::{CodegenBackendKind, Compiler, DependencyType, FileType, LLVM_TOOLS, Mode, trace};
39
40pub fn pkgname(builder: &Builder<'_>, component: &str) -> String {
41 format!("{}-{}", component, builder.rust_package_vers())
42}
43
44pub(crate) fn distdir(builder: &Builder<'_>) -> PathBuf {
45 builder.out.join("dist")
46}
47
48pub fn tmpdir(builder: &Builder<'_>) -> PathBuf {
49 builder.out.join("tmp/dist")
50}
51
52fn should_build_extended_tool(builder: &Builder<'_>, tool: &str) -> bool {
53 if !builder.config.extended {
54 return false;
55 }
56 builder.config.tools.as_ref().is_none_or(|tools| tools.contains(tool))
57}
58
59#[derive(Debug, Clone, Hash, PartialEq, Eq)]
60pub struct Docs {
61 pub host: TargetSelection,
62}
63
64impl Step for Docs {
65 type Output = Option<GeneratedTarball>;
66
67 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
68 run.alias("rust-docs")
69 }
70
71 fn is_default_step(builder: &Builder<'_>) -> bool {
72 builder.config.docs
73 }
74
75 fn make_run(run: RunConfig<'_>) {
76 run.builder.ensure(Docs { host: run.target });
77 }
78
79 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
81 let host = self.host;
82 builder.run_default_doc_steps();
86
87 let dest = "share/doc/rust/html";
88
89 let mut tarball = Tarball::new(builder, "rust-docs", &host.triple);
90 tarball.set_product_name("Rust Documentation");
91 tarball.add_bulk_dir(builder.doc_out(host), dest);
92 tarball.add_file(builder.src.join("src/doc/robots.txt"), dest, FileType::Regular);
93 tarball.add_file(builder.src.join("src/doc/sitemap.txt"), dest, FileType::Regular);
94 Some(tarball.generate())
95 }
96
97 fn metadata(&self) -> Option<StepMetadata> {
98 Some(StepMetadata::dist("docs", self.host))
99 }
100}
101
102#[derive(Debug, Clone, Hash, PartialEq, Eq)]
105pub struct JsonDocs {
106 build_compiler: Compiler,
107 target: TargetSelection,
108}
109
110impl Step for JsonDocs {
111 type Output = Option<GeneratedTarball>;
112
113 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
114 run.alias("rust-docs-json")
115 }
116
117 fn is_default_step(builder: &Builder<'_>) -> bool {
118 builder.config.docs
119 }
120
121 fn make_run(run: RunConfig<'_>) {
122 run.builder.ensure(JsonDocs {
123 build_compiler: run.builder.compiler_for_std(run.builder.top_stage),
124 target: run.target,
125 });
126 }
127
128 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
129 let target = self.target;
130 let directory = builder.ensure(crate::core::build_steps::doc::Std::from_build_compiler(
131 self.build_compiler,
132 target,
133 DocumentationFormat::Json,
134 ));
135
136 let dest = "share/doc/rust/json";
137
138 let mut tarball = Tarball::new(builder, "rust-docs-json", &target.triple);
139 tarball.set_product_name("Rust Documentation In JSON Format");
140 tarball.is_preview(true);
141 tarball.add_bulk_dir(directory, dest);
142 Some(tarball.generate())
143 }
144
145 fn metadata(&self) -> Option<StepMetadata> {
146 Some(StepMetadata::dist("json-docs", self.target).built_by(self.build_compiler))
147 }
148}
149
150#[derive(Debug, Clone, Hash, PartialEq, Eq)]
157pub struct RustcDocs {
158 target: TargetSelection,
159}
160
161impl Step for RustcDocs {
162 type Output = GeneratedTarball;
163 const IS_HOST: bool = true;
164
165 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
166 run.alias("rustc-docs")
167 }
168
169 fn is_default_step(builder: &Builder<'_>) -> bool {
170 builder.config.compiler_docs
171 }
172
173 fn make_run(run: RunConfig<'_>) {
174 run.builder.ensure(RustcDocs { target: run.target });
175 }
176
177 fn run(self, builder: &Builder<'_>) -> Self::Output {
178 let target = self.target;
179 builder.run_default_doc_steps();
180
181 let mut tarball = Tarball::new(builder, "rustc-docs", &target.triple);
182 tarball.set_product_name("Rustc Documentation");
183 tarball.add_bulk_dir(builder.compiler_doc_out(target), "share/doc/rust/html/rustc");
184 tarball.generate()
185 }
186}
187
188fn find_files(files: &[&str], path: &[PathBuf]) -> Vec<PathBuf> {
189 let mut found = Vec::with_capacity(files.len());
190
191 for file in files {
192 let file_path = path.iter().map(|dir| dir.join(file)).find(|p| p.exists());
193
194 if let Some(file_path) = file_path {
195 found.push(file_path);
196 } else {
197 panic!("Could not find '{file}' in {path:?}");
198 }
199 }
200
201 found
202}
203
204fn make_win_dist(plat_root: &Path, target: TargetSelection, builder: &Builder<'_>) {
205 if builder.config.dry_run() {
206 return;
207 }
208
209 let (bin_path, lib_path) = get_cc_search_dirs(target, builder);
210
211 let compiler = if target == "i686-pc-windows-gnu" {
212 "i686-w64-mingw32-gcc.exe"
213 } else if target == "x86_64-pc-windows-gnu" {
214 "x86_64-w64-mingw32-gcc.exe"
215 } else {
216 "gcc.exe"
217 };
218 let target_tools = [compiler, "ld.exe", "dlltool.exe", "libwinpthread-1.dll"];
219
220 let target_libs = [
223 "libgcc.a",
225 "libgcc_eh.a",
226 "libgcc_s.a",
227 "libm.a",
228 "libmingw32.a",
229 "libmingwex.a",
230 "libstdc++.a",
231 "libiconv.a",
232 "libmoldname.a",
233 "libpthread.a",
234 "libadvapi32.a",
239 "libbcrypt.a",
240 "libcomctl32.a",
241 "libcomdlg32.a",
242 "libcredui.a",
243 "libcrypt32.a",
244 "libdbghelp.a",
245 "libgdi32.a",
246 "libimagehlp.a",
247 "libiphlpapi.a",
248 "libkernel32.a",
249 "libmsimg32.a",
250 "libmsvcrt.a",
251 "libntdll.a",
252 "libodbc32.a",
253 "libole32.a",
254 "liboleaut32.a",
255 "libopengl32.a",
256 "libpsapi.a",
257 "librpcrt4.a",
258 "libsecur32.a",
259 "libsetupapi.a",
260 "libshell32.a",
261 "libsynchronization.a",
262 "libuser32.a",
263 "libuserenv.a",
264 "libuuid.a",
265 "libwinhttp.a",
266 "libwinmm.a",
267 "libwinspool.a",
268 "libws2_32.a",
269 "libwsock32.a",
270 ];
271
272 let target_tools = find_files(&target_tools, &bin_path);
274 let target_libs = find_files(&target_libs, &lib_path);
275
276 let plat_target_bin_self_contained_dir =
278 plat_root.join("lib/rustlib").join(target).join("bin/self-contained");
279 fs::create_dir_all(&plat_target_bin_self_contained_dir)
280 .expect("creating plat_target_bin_self_contained_dir failed");
281 for src in target_tools {
282 builder.copy_link_to_folder(&src, &plat_target_bin_self_contained_dir);
283 }
284
285 builder.create(
287 &plat_target_bin_self_contained_dir.join("GCC-WARNING.txt"),
288 "gcc.exe contained in this folder cannot be used for compiling C files - it is only \
289 used as a linker. In order to be able to compile projects containing C code use \
290 the GCC provided by MinGW or Cygwin.",
291 );
292
293 let plat_target_lib_self_contained_dir =
295 plat_root.join("lib/rustlib").join(target).join("lib/self-contained");
296 fs::create_dir_all(&plat_target_lib_self_contained_dir)
297 .expect("creating plat_target_lib_self_contained_dir failed");
298 for src in target_libs {
299 builder.copy_link_to_folder(&src, &plat_target_lib_self_contained_dir);
300 }
301}
302
303fn make_win_llvm_dist(plat_root: &Path, target: TargetSelection, builder: &Builder<'_>) {
304 if builder.config.dry_run() {
305 return;
306 }
307
308 let (_, lib_path) = get_cc_search_dirs(target, builder);
309
310 let target_libs = [
313 "libunwind.a",
315 "libunwind.dll.a",
316 "libmingw32.a",
317 "libmingwex.a",
318 "libmsvcrt.a",
319 "libkernel32.a",
321 "libuser32.a",
322 "libntdll.a",
323 "libuserenv.a",
324 "libws2_32.a",
325 "libdbghelp.a",
326 ];
327
328 let target_libs = find_files(&target_libs, &lib_path);
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 runtime_dll_dist(rust_root: &Path, target: TargetSelection, builder: &Builder<'_>) {
342 if builder.config.dry_run() {
343 return;
344 }
345
346 let (bin_path, _) = get_cc_search_dirs(target, builder);
347
348 let mut rustc_dlls = vec![];
349 if target.is_windows_gnu() {
351 rustc_dlls.push("libwinpthread-1.dll");
352 if target.starts_with("i686-") {
353 rustc_dlls.push("libgcc_s_dw2-1.dll");
354 } else {
355 rustc_dlls.push("libgcc_s_seh-1.dll");
356 }
357 } else if target.is_windows_gnullvm() {
358 rustc_dlls.push("libunwind.dll");
359 } else {
360 panic!("Vendoring of runtime DLLs for `{target}` is not supported`");
361 }
362 let rustc_dlls = find_files(&rustc_dlls, &bin_path);
363
364 let rust_bin_dir = rust_root.join("bin/");
366 fs::create_dir_all(&rust_bin_dir).expect("creating rust_bin_dir failed");
367 for src in &rustc_dlls {
368 builder.copy_link_to_folder(src, &rust_bin_dir);
369 }
370
371 if builder.config.lld_enabled {
372 let rust_target_bin_dir = rust_root.join("lib/rustlib").join(target).join("bin");
374 fs::create_dir_all(&rust_target_bin_dir).expect("creating rust_target_bin_dir failed");
375 for src in &rustc_dlls {
376 builder.copy_link_to_folder(src, &rust_target_bin_dir);
377 }
378 }
379}
380
381fn get_cc_search_dirs(
382 target: TargetSelection,
383 builder: &Builder<'_>,
384) -> (Vec<PathBuf>, Vec<PathBuf>) {
385 let mut cmd = command(builder.cc(target));
387 cmd.arg("-print-search-dirs");
388 let gcc_out = cmd.run_capture_stdout(builder).stdout();
389
390 let mut bin_path: Vec<_> = env::split_paths(&env::var_os("PATH").unwrap_or_default()).collect();
391 let mut lib_path = Vec::new();
392
393 for line in gcc_out.lines() {
394 let idx = line.find(':').unwrap();
395 let key = &line[..idx];
396 let trim_chars: &[_] = &[' ', '='];
397 let value = env::split_paths(line[(idx + 1)..].trim_start_matches(trim_chars));
398
399 if key == "programs" {
400 bin_path.extend(value);
401 } else if key == "libraries" {
402 lib_path.extend(value);
403 }
404 }
405 (bin_path, lib_path)
406}
407
408#[derive(Debug, Clone, Hash, PartialEq, Eq)]
413pub struct Mingw {
414 target: TargetSelection,
415}
416
417impl Step for Mingw {
418 type Output = Option<GeneratedTarball>;
419
420 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
421 run.alias("rust-mingw")
422 }
423
424 fn is_default_step(_builder: &Builder<'_>) -> bool {
425 true
426 }
427
428 fn make_run(run: RunConfig<'_>) {
429 run.builder.ensure(Mingw { target: run.target });
430 }
431
432 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
433 let target = self.target;
434 if !target.contains("pc-windows-gnu") || !builder.config.dist_include_mingw_linker {
435 return None;
436 }
437
438 let mut tarball = Tarball::new(builder, "rust-mingw", &target.triple);
439 tarball.set_product_name("Rust MinGW");
440
441 if target.ends_with("pc-windows-gnu") {
442 make_win_dist(tarball.image_dir(), target, builder);
443 } else if target.ends_with("pc-windows-gnullvm") {
444 make_win_llvm_dist(tarball.image_dir(), target, builder);
445 } else {
446 unreachable!();
447 }
448
449 Some(tarball.generate())
450 }
451
452 fn metadata(&self) -> Option<StepMetadata> {
453 Some(StepMetadata::dist("mingw", self.target))
454 }
455}
456
457#[derive(Debug, Clone, Hash, PartialEq, Eq)]
467pub struct Rustc {
468 pub target_compiler: Compiler,
470}
471
472impl Step for Rustc {
473 type Output = GeneratedTarball;
474 const IS_HOST: bool = true;
475
476 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
477 run.alias("rustc")
478 }
479
480 fn is_default_step(_builder: &Builder<'_>) -> bool {
481 true
482 }
483
484 fn make_run(run: RunConfig<'_>) {
485 run.builder.ensure(Rustc {
486 target_compiler: run.builder.compiler(run.builder.top_stage, run.target),
487 });
488 }
489
490 fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
491 let target_compiler = self.target_compiler;
492 let target = self.target_compiler.host;
493
494 let tarball = Tarball::new(builder, "rustc", &target.triple);
495
496 prepare_image(builder, target_compiler, tarball.image_dir());
498
499 if target.contains("pc-windows-gnu") && builder.config.dist_include_mingw_linker {
507 runtime_dll_dist(tarball.image_dir(), target, builder);
508 tarball.add_dir(builder.src.join("src/etc/third-party"), "share/doc");
509 }
510
511 return tarball.generate();
512
513 fn prepare_image(builder: &Builder<'_>, target_compiler: Compiler, image: &Path) {
514 let target = target_compiler.host;
515 let src = builder.sysroot(target_compiler);
516
517 t!(fs::create_dir_all(image.join("bin")));
519 builder.cp_link_r(&src.join("bin"), &image.join("bin"));
520
521 if builder
523 .config
524 .tools
525 .as_ref()
526 .is_none_or(|tools| tools.iter().any(|tool| tool == "rustdoc"))
527 {
528 let rustdoc = builder.rustdoc_for_compiler(target_compiler);
529 builder.install(&rustdoc, &image.join("bin"), FileType::Executable);
530 }
531
532 let compilers = RustcPrivateCompilers::from_target_compiler(builder, target_compiler);
533
534 if let Some(ra_proc_macro_srv) = builder.ensure_if_default(
535 tool::RustAnalyzerProcMacroSrv::from_compilers(compilers),
536 builder.kind,
537 ) {
538 let dst = image.join("libexec");
539 builder.install(&ra_proc_macro_srv.tool_path, &dst, FileType::Executable);
540 }
541
542 let libdir_relative = builder.libdir_relative(target_compiler);
543
544 if libdir_relative.to_str() != Some("bin") {
546 let libdir = builder.rustc_libdir(target_compiler);
547 for entry in builder.read_dir(&libdir) {
548 if is_dylib(&entry.path())
554 && !entry
555 .path()
556 .file_name()
557 .and_then(|n| n.to_str())
558 .map(|n| n.contains("libgccjit"))
559 .unwrap_or(false)
560 {
561 builder.install(&entry.path(), &image.join("lib"), FileType::NativeLibrary);
564 }
565 }
566 }
567
568 maybe_install_llvm_runtime(builder, target, image);
574
575 let dst_dir = image.join("lib/rustlib").join(target).join("bin");
576 t!(fs::create_dir_all(&dst_dir));
577
578 if builder.config.lld_enabled {
580 let src_dir = builder.sysroot_target_bindir(target_compiler, target);
581 let rust_lld = exe("rust-lld", target_compiler.host);
582 builder.copy_link(
583 &src_dir.join(&rust_lld),
584 &dst_dir.join(&rust_lld),
585 FileType::Executable,
586 );
587 let self_contained_lld_src_dir = src_dir.join("gcc-ld");
588 let self_contained_lld_dst_dir = dst_dir.join("gcc-ld");
589 t!(fs::create_dir(&self_contained_lld_dst_dir));
590 for name in crate::LLD_FILE_NAMES {
591 let exe_name = exe(name, target_compiler.host);
592 builder.copy_link(
593 &self_contained_lld_src_dir.join(&exe_name),
594 &self_contained_lld_dst_dir.join(&exe_name),
595 FileType::Executable,
596 );
597 }
598 }
599
600 if builder.config.llvm_enabled(target_compiler.host)
601 && builder.config.llvm_tools_enabled
602 {
603 let src_dir = builder.sysroot_target_bindir(target_compiler, target);
604 let llvm_objcopy = exe("llvm-objcopy", target_compiler.host);
605 let rust_objcopy = exe("rust-objcopy", target_compiler.host);
606 builder.copy_link(
607 &src_dir.join(&llvm_objcopy),
608 &dst_dir.join(&rust_objcopy),
609 FileType::Executable,
610 );
611 }
612
613 if builder.tool_enabled("wasm-component-ld") {
614 let src_dir = builder.sysroot_target_bindir(target_compiler, target);
615 let ld = exe("wasm-component-ld", target_compiler.host);
616 builder.copy_link(&src_dir.join(&ld), &dst_dir.join(&ld), FileType::Executable);
617 }
618
619 t!(fs::create_dir_all(image.join("share/man/man1")));
621 let man_src = builder.src.join("src/doc/man");
622 let man_dst = image.join("share/man/man1");
623
624 for file_entry in builder.read_dir(&man_src) {
627 let page_src = file_entry.path();
628 let page_dst = man_dst.join(file_entry.file_name());
629 let src_text = t!(std::fs::read_to_string(&page_src));
630 let new_text = src_text.replace("<INSERT VERSION HERE>", &builder.version);
631 t!(std::fs::write(&page_dst, &new_text));
632 t!(fs::copy(&page_src, &page_dst));
633 }
634
635 builder.ensure(DebuggerScripts { sysroot: image.to_owned(), target });
637
638 generate_target_spec_json_schema(builder, image);
639
640 let file_list = builder.ensure(super::run::GenerateCopyright);
642 for file in file_list {
643 builder.install(&file, &image.join("share/doc/rust"), FileType::Regular);
644 }
645
646 builder.install(
648 &builder.src.join("README.md"),
649 &image.join("share/doc/rust"),
650 FileType::Regular,
651 );
652
653 let license = |path: &Path| {
655 builder.install(path, &image.join("share/doc/rust/licenses"), FileType::Regular);
656 };
657 for entry in t!(std::fs::read_dir(builder.src.join("LICENSES"))).flatten() {
658 license(&entry.path());
659 }
660 }
661 }
662
663 fn metadata(&self) -> Option<StepMetadata> {
664 Some(StepMetadata::dist("rustc", self.target_compiler.host))
665 }
666}
667
668fn generate_target_spec_json_schema(builder: &Builder<'_>, sysroot: &Path) {
669 let stage1_host = builder.compiler(1, builder.host_target);
673 let mut rustc = builder.rustc_cmd(stage1_host).fail_fast();
674 rustc
675 .env("RUSTC_BOOTSTRAP", "1")
676 .args(["--print=target-spec-json-schema", "-Zunstable-options"]);
677 let schema = rustc.run_capture(builder).stdout();
678
679 let schema_dir = tmpdir(builder);
680 t!(fs::create_dir_all(&schema_dir));
681 let schema_file = schema_dir.join("target-spec-json-schema.json");
682 t!(std::fs::write(&schema_file, schema));
683
684 let dst = sysroot.join("etc");
685 t!(fs::create_dir_all(&dst));
686
687 builder.install(&schema_file, &dst, FileType::Regular);
688}
689
690#[derive(Debug, Clone, Hash, PartialEq, Eq)]
692pub struct DebuggerScripts {
693 pub sysroot: PathBuf,
695 pub target: TargetSelection,
696}
697
698impl Step for DebuggerScripts {
699 type Output = ();
700
701 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
702 run.never()
703 }
704
705 fn run(self, builder: &Builder<'_>) {
706 let target = self.target;
707 let sysroot = self.sysroot;
708 let dst = sysroot.join("lib/rustlib/etc");
709 t!(fs::create_dir_all(&dst));
710 let cp_debugger_script = |file: &str| {
711 builder.install(&builder.src.join("src/etc/").join(file), &dst, FileType::Regular);
712 };
713 if target.contains("windows-msvc") {
714 builder.install(
716 &builder.src.join("src/etc/rust-windbg.cmd"),
717 &sysroot.join("bin"),
718 FileType::Script,
719 );
720
721 cp_debugger_script("natvis/intrinsic.natvis");
722 cp_debugger_script("natvis/liballoc.natvis");
723 cp_debugger_script("natvis/libcore.natvis");
724 cp_debugger_script("natvis/libstd.natvis");
725 }
726
727 cp_debugger_script("rust_types.py");
728
729 builder.install(
731 &builder.src.join("src/etc/rust-gdb"),
732 &sysroot.join("bin"),
733 FileType::Script,
734 );
735 builder.install(
736 &builder.src.join("src/etc/rust-gdbgui"),
737 &sysroot.join("bin"),
738 FileType::Script,
739 );
740
741 cp_debugger_script("gdb_load_rust_pretty_printers.py");
742 cp_debugger_script("gdb_lookup.py");
743 cp_debugger_script("gdb_providers.py");
744
745 builder.install(
747 &builder.src.join("src/etc/rust-lldb"),
748 &sysroot.join("bin"),
749 FileType::Script,
750 );
751
752 cp_debugger_script("lldb_lookup.py");
753 cp_debugger_script("lldb_providers.py");
754 cp_debugger_script("lldb_commands")
755 }
756}
757
758fn skip_host_target_lib(builder: &Builder<'_>, compiler: Compiler) -> bool {
759 if !builder.config.is_host_target(compiler.host) {
762 builder.info("\tskipping, not a build host");
763 true
764 } else {
765 false
766 }
767}
768
769fn verify_uefi_rlib_format(builder: &Builder<'_>, target: TargetSelection, stamp: &BuildStamp) {
773 if !target.ends_with("-uefi") {
774 return;
775 }
776
777 for (path, _) in builder.read_stamp_file(stamp) {
778 if path.extension() != Some(OsStr::new("rlib")) {
779 continue;
780 }
781
782 let data = t!(fs::read(&path));
783 let data = data.as_slice();
784 let archive = t!(ArchiveFile::parse(data));
785 for member in archive.members() {
786 let member = t!(member);
787 let member_data = t!(member.data(data));
788
789 let is_coff = match object::File::parse(member_data) {
790 Ok(member_file) => member_file.format() == BinaryFormat::Coff,
791 Err(_) => false,
792 };
793
794 if !is_coff {
795 let member_name = String::from_utf8_lossy(member.name());
796 panic!("member {} in {} is not COFF", member_name, path.display());
797 }
798 }
799 }
800}
801
802fn copy_target_libs(
804 builder: &Builder<'_>,
805 target: TargetSelection,
806 image: &Path,
807 stamp: &BuildStamp,
808) {
809 let dst = image.join("lib/rustlib").join(target).join("lib");
810 let self_contained_dst = dst.join("self-contained");
811 t!(fs::create_dir_all(&dst));
812 t!(fs::create_dir_all(&self_contained_dst));
813 for (path, dependency_type) in builder.read_stamp_file(stamp) {
814 if dependency_type == DependencyType::TargetSelfContained {
815 builder.copy_link(
816 &path,
817 &self_contained_dst.join(path.file_name().unwrap()),
818 FileType::NativeLibrary,
819 );
820 } else if dependency_type == DependencyType::Target || builder.config.is_host_target(target)
821 {
822 builder.copy_link(&path, &dst.join(path.file_name().unwrap()), FileType::NativeLibrary);
823 }
824 }
825}
826
827#[derive(Debug, Clone, Hash, PartialEq, Eq)]
834pub struct Std {
835 pub build_compiler: Compiler,
837 pub target: TargetSelection,
838}
839
840impl Std {
841 pub fn new(builder: &Builder<'_>, target: TargetSelection) -> Self {
842 Std { build_compiler: builder.compiler_for_std(builder.top_stage), target }
843 }
844}
845
846impl Step for Std {
847 type Output = Option<GeneratedTarball>;
848
849 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
850 run.alias("rust-std")
851 }
852
853 fn is_default_step(_builder: &Builder<'_>) -> bool {
854 true
855 }
856
857 fn make_run(run: RunConfig<'_>) {
858 run.builder.ensure(Std::new(run.builder, run.target));
859 }
860
861 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
862 let build_compiler = self.build_compiler;
863 let target = self.target;
864
865 if skip_host_target_lib(builder, build_compiler) {
866 return None;
867 }
868
869 let stamp =
872 builder.std(build_compiler, target).expect("Standard library has to be built for dist");
873
874 let mut tarball = Tarball::new(builder, "rust-std", &target.triple);
875 tarball.include_target_in_component_name(true);
876
877 verify_uefi_rlib_format(builder, target, &stamp);
878 copy_target_libs(builder, target, tarball.image_dir(), &stamp);
879
880 Some(tarball.generate())
881 }
882
883 fn metadata(&self) -> Option<StepMetadata> {
884 Some(StepMetadata::dist("std", self.target).built_by(self.build_compiler))
885 }
886}
887
888#[derive(Debug, Clone, Hash, PartialEq, Eq)]
893pub struct RustcDev {
894 pub build_compiler: Compiler,
896 pub target: TargetSelection,
897}
898
899impl RustcDev {
900 pub fn new(builder: &Builder<'_>, target: TargetSelection) -> Self {
901 Self {
902 build_compiler: builder.compiler(1, builder.config.host_target),
906 target,
907 }
908 }
909}
910
911impl Step for RustcDev {
912 type Output = Option<GeneratedTarball>;
913 const IS_HOST: bool = true;
914
915 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
916 run.alias("rustc-dev")
917 }
918
919 fn is_default_step(_builder: &Builder<'_>) -> bool {
920 true
921 }
922
923 fn make_run(run: RunConfig<'_>) {
924 run.builder.ensure(RustcDev::new(run.builder, run.target));
925 }
926
927 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
928 let build_compiler = self.build_compiler;
929 let target = self.target;
930 if skip_host_target_lib(builder, build_compiler) {
931 return None;
932 }
933
934 builder.ensure(compile::Rustc::new(build_compiler, target));
936
937 let tarball = Tarball::new(builder, "rustc-dev", &target.triple);
938
939 let stamp = build_stamp::librustc_stamp(builder, build_compiler, target);
940 copy_target_libs(builder, target, tarball.image_dir(), &stamp);
941
942 let src_files = &["Cargo.lock"];
943 copy_src_dirs(
946 builder,
947 &builder.src,
948 &["compiler", "library/proc_macro"],
950 &[],
951 &tarball.image_dir().join("lib/rustlib/rustc-src/rust"),
952 );
953 for file in src_files {
954 tarball.add_file(
955 builder.src.join(file),
956 "lib/rustlib/rustc-src/rust",
957 FileType::Regular,
958 );
959 }
960
961 Some(tarball.generate())
962 }
963
964 fn metadata(&self) -> Option<StepMetadata> {
965 Some(StepMetadata::dist("rustc-dev", self.target).built_by(self.build_compiler))
966 }
967}
968
969#[derive(Debug, Clone, Hash, PartialEq, Eq)]
974pub struct Analysis {
975 build_compiler: Compiler,
976 target: TargetSelection,
977}
978
979impl Step for Analysis {
980 type Output = Option<GeneratedTarball>;
981
982 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
983 run.alias("rust-analysis")
984 }
985
986 fn is_default_step(builder: &Builder<'_>) -> bool {
987 should_build_extended_tool(builder, "analysis")
988 }
989
990 fn make_run(run: RunConfig<'_>) {
991 run.builder.ensure(Analysis {
993 build_compiler: run.builder.compiler(1, run.builder.config.host_target),
994 target: run.target,
995 });
996 }
997
998 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
999 let compiler = self.build_compiler;
1000 let target = self.target;
1001 if skip_host_target_lib(builder, compiler) {
1002 return None;
1003 }
1004
1005 let src = builder
1006 .stage_out(compiler, Mode::Std)
1007 .join(target)
1008 .join(builder.cargo_dir())
1009 .join("deps")
1010 .join("save-analysis");
1011
1012 t!(std::fs::create_dir_all(&src));
1014 let mut removed = src.clone();
1015 removed.push("removed.json");
1016 let mut f = t!(std::fs::File::create(removed));
1017 t!(write!(f, r#"{{ "warning": "The `rust-analysis` component has been removed." }}"#));
1018
1019 let mut tarball = Tarball::new(builder, "rust-analysis", &target.triple);
1020 tarball.include_target_in_component_name(true);
1021 tarball.add_dir(src, format!("lib/rustlib/{}/analysis", target.triple));
1022 Some(tarball.generate())
1023 }
1024
1025 fn metadata(&self) -> Option<StepMetadata> {
1026 Some(StepMetadata::dist("analysis", self.target).built_by(self.build_compiler))
1027 }
1028}
1029
1030fn copy_src_dirs(
1033 builder: &Builder<'_>,
1034 base: &Path,
1035 src_dirs: &[&str],
1036 exclude_dirs: &[&str],
1037 dst_dir: &Path,
1038) {
1039 for src_dir in src_dirs {
1042 assert!(Path::new(src_dir).is_relative());
1043 }
1044
1045 if builder.config.dry_run() {
1048 return;
1049 }
1050
1051 fn filter_fn(exclude_dirs: &[&str], dir: &str, path: &Path) -> bool {
1052 let spath = match path.to_str() {
1054 Some(path) => path,
1055 None => return false,
1056 };
1057 if spath.ends_with('~') || spath.ends_with(".pyc") {
1058 return false;
1059 }
1060 let spath = spath.replace("\\", "/");
1062
1063 static LLVM_PROJECTS: &[&str] = &[
1064 "llvm-project/clang",
1065 "llvm-project/libunwind",
1066 "llvm-project/lld",
1067 "llvm-project/lldb",
1068 "llvm-project/llvm",
1069 "llvm-project/compiler-rt",
1070 "llvm-project/cmake",
1071 "llvm-project/runtimes",
1072 "llvm-project/third-party",
1073 ];
1074 if spath.starts_with("llvm-project") && spath != "llvm-project" {
1075 if !LLVM_PROJECTS.iter().any(|path| spath.starts_with(path)) {
1076 return false;
1077 }
1078
1079 if spath.starts_with("llvm-project/third-party")
1081 && spath != "llvm-project/third-party"
1082 && !spath.starts_with("llvm-project/third-party/siphash")
1083 {
1084 return false;
1085 }
1086
1087 if spath.starts_with("llvm-project/llvm/test")
1088 && (spath.ends_with(".ll") || spath.ends_with(".td") || spath.ends_with(".s"))
1089 {
1090 return false;
1091 }
1092 }
1093
1094 if spath.starts_with("tools/cargo/tests") {
1096 return true;
1097 }
1098
1099 if !exclude_dirs.is_empty() {
1100 let full_path = Path::new(dir).join(path);
1101 if exclude_dirs.iter().any(|excl| full_path == Path::new(excl)) {
1102 return false;
1103 }
1104 }
1105
1106 static EXCLUDES: &[&str] = &[
1107 "CVS",
1108 "RCS",
1109 "SCCS",
1110 ".git",
1111 ".gitignore",
1112 ".gitmodules",
1113 ".gitattributes",
1114 ".cvsignore",
1115 ".svn",
1116 ".arch-ids",
1117 "{arch}",
1118 "=RELEASE-ID",
1119 "=meta-update",
1120 "=update",
1121 ".bzr",
1122 ".bzrignore",
1123 ".bzrtags",
1124 ".hg",
1125 ".hgignore",
1126 ".hgrags",
1127 "_darcs",
1128 ];
1129
1130 let last_component = path.iter().next_back().map(|s| s.to_str().unwrap()).unwrap();
1137 !EXCLUDES.contains(&last_component)
1138 }
1139
1140 for item in src_dirs {
1142 let dst = &dst_dir.join(item);
1143 t!(fs::create_dir_all(dst));
1144 builder
1145 .cp_link_filtered(&base.join(item), dst, &|path| filter_fn(exclude_dirs, item, path));
1146 }
1147}
1148
1149#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1150pub struct Src;
1151
1152impl Step for Src {
1153 type Output = GeneratedTarball;
1155 const IS_HOST: bool = true;
1156
1157 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1158 run.alias("rust-src")
1159 }
1160
1161 fn is_default_step(_builder: &Builder<'_>) -> bool {
1162 true
1163 }
1164
1165 fn make_run(run: RunConfig<'_>) {
1166 run.builder.ensure(Src);
1167 }
1168
1169 fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
1171 if !builder.config.dry_run() {
1172 builder.require_submodule("src/llvm-project", None);
1173 }
1174
1175 let tarball = Tarball::new_targetless(builder, "rust-src");
1176
1177 let dst_src = tarball.image_dir().join("lib/rustlib/src/rust");
1185
1186 copy_src_dirs(
1189 builder,
1190 &builder.src,
1191 &["library", "src/llvm-project/libunwind"],
1192 &[
1193 "library/backtrace/crates",
1196 "library/stdarch/Cargo.toml",
1199 "library/stdarch/crates/stdarch-verify",
1200 "library/stdarch/crates/intrinsic-test",
1201 ],
1202 &dst_src,
1203 );
1204
1205 tarball.generate()
1206 }
1207
1208 fn metadata(&self) -> Option<StepMetadata> {
1209 Some(StepMetadata::dist("src", TargetSelection::default()))
1210 }
1211}
1212
1213#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1214pub struct PlainSourceTarball;
1215
1216impl Step for PlainSourceTarball {
1217 type Output = GeneratedTarball;
1219 const IS_HOST: bool = true;
1220
1221 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1222 run.alias("rustc-src")
1223 }
1224
1225 fn is_default_step(builder: &Builder<'_>) -> bool {
1226 builder.config.rust_dist_src
1227 }
1228
1229 fn make_run(run: RunConfig<'_>) {
1230 run.builder.ensure(PlainSourceTarball);
1231 }
1232
1233 fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
1235 let mut tarball = Tarball::new(builder, "rustc", "src");
1240 tarball.permit_symlinks(true);
1241 let plain_dst_src = tarball.image_dir();
1242
1243 let src_files = [
1245 ".gitmodules",
1247 "CONTRIBUTING.md",
1248 "COPYRIGHT",
1249 "Cargo.lock",
1250 "Cargo.toml",
1251 "LICENSE-APACHE",
1252 "LICENSE-MIT",
1253 "README.md",
1254 "RELEASES.md",
1255 "REUSE.toml",
1256 "bootstrap.example.toml",
1257 "configure",
1258 "license-metadata.json",
1259 "package.json",
1260 "x",
1261 "x.ps1",
1262 "x.py",
1263 "yarn.lock",
1264 ];
1266 let src_dirs = ["src", "compiler", "library", "tests", "LICENSES"];
1267
1268 copy_src_dirs(
1269 builder,
1270 &builder.src,
1271 &src_dirs,
1272 &[
1273 "src/gcc",
1277 ],
1278 plain_dst_src,
1279 );
1280 if !builder.config.dry_run() {
1285 builder.create_dir(&plain_dst_src.join("src/gcc"));
1286 t!(std::fs::write(
1287 plain_dst_src.join("src/gcc/notice.txt"),
1288 "The GCC source code is not included due to unclear licensing implications\n"
1289 ));
1290 }
1291
1292 for item in &src_files {
1294 builder.copy_link(
1295 &builder.src.join(item),
1296 &plain_dst_src.join(item),
1297 FileType::Regular,
1298 );
1299 }
1300
1301 builder.create(&plain_dst_src.join("version"), &builder.rust_version());
1303
1304 let write_git_info = |info: Option<&Info>, path: &Path| {
1306 if let Some(info) = info {
1307 t!(std::fs::create_dir_all(path));
1308 channel::write_commit_hash_file(path, &info.sha);
1309 channel::write_commit_info_file(path, info);
1310 }
1311 };
1312 write_git_info(builder.rust_info().info(), plain_dst_src);
1313 write_git_info(builder.cargo_info.info(), &plain_dst_src.join("./src/tools/cargo"));
1314
1315 if builder.config.dist_vendor {
1316 builder.require_and_update_all_submodules();
1317
1318 let pkgs_for_pgo_training = build_helper::LLVM_PGO_CRATES
1320 .iter()
1321 .chain(build_helper::RUSTC_PGO_CRATES)
1322 .map(|pkg| {
1323 let mut manifest_path =
1324 builder.src.join("./src/tools/rustc-perf/collector/compile-benchmarks");
1325 manifest_path.push(pkg);
1326 manifest_path.push("Cargo.toml");
1327 manifest_path
1328 });
1329
1330 let vendor = builder.ensure(Vendor {
1332 sync_args: pkgs_for_pgo_training.collect(),
1333 versioned_dirs: true,
1334 root_dir: plain_dst_src.into(),
1335 output_dir: VENDOR_DIR.into(),
1336 });
1337
1338 let cargo_config_dir = plain_dst_src.join(".cargo");
1339 builder.create_dir(&cargo_config_dir);
1340 builder.create(&cargo_config_dir.join("config.toml"), &vendor.config);
1341 }
1342
1343 for entry in walkdir::WalkDir::new(tarball.image_dir())
1347 .follow_links(true)
1348 .into_iter()
1349 .filter_map(|e| e.ok())
1350 {
1351 if entry.path().is_dir() && entry.path().file_name() == Some(OsStr::new("__pycache__"))
1352 {
1353 t!(fs::remove_dir_all(entry.path()));
1354 }
1355 }
1356
1357 tarball.bare()
1358 }
1359}
1360
1361#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1362pub struct Cargo {
1363 pub build_compiler: Compiler,
1364 pub target: TargetSelection,
1365}
1366
1367impl Step for Cargo {
1368 type Output = Option<GeneratedTarball>;
1369 const IS_HOST: bool = true;
1370
1371 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1372 run.alias("cargo")
1373 }
1374
1375 fn is_default_step(builder: &Builder<'_>) -> bool {
1376 should_build_extended_tool(builder, "cargo")
1377 }
1378
1379 fn make_run(run: RunConfig<'_>) {
1380 run.builder.ensure(Cargo {
1381 build_compiler: get_tool_target_compiler(
1382 run.builder,
1383 ToolTargetBuildMode::Build(run.target),
1384 ),
1385 target: run.target,
1386 });
1387 }
1388
1389 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1390 let build_compiler = self.build_compiler;
1391 let target = self.target;
1392
1393 let cargo = builder.ensure(tool::Cargo::from_build_compiler(build_compiler, target));
1394 let src = builder.src.join("src/tools/cargo");
1395 let etc = src.join("src/etc");
1396
1397 let mut tarball = Tarball::new(builder, "cargo", &target.triple);
1399 tarball.set_overlay(OverlayKind::Cargo);
1400
1401 tarball.add_file(&cargo.tool_path, "bin", FileType::Executable);
1402 tarball.add_file(etc.join("_cargo"), "share/zsh/site-functions", FileType::Regular);
1403 tarball.add_renamed_file(
1404 etc.join("cargo.bashcomp.sh"),
1405 "etc/bash_completion.d",
1406 "cargo",
1407 FileType::Regular,
1408 );
1409 tarball.add_dir(etc.join("man"), "share/man/man1");
1410 tarball.add_legal_and_readme_to("share/doc/cargo");
1411
1412 Some(tarball.generate())
1413 }
1414
1415 fn metadata(&self) -> Option<StepMetadata> {
1416 Some(StepMetadata::dist("cargo", self.target).built_by(self.build_compiler))
1417 }
1418}
1419
1420#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1422pub struct RustAnalyzer {
1423 pub compilers: RustcPrivateCompilers,
1424 pub target: TargetSelection,
1425}
1426
1427impl Step for RustAnalyzer {
1428 type Output = Option<GeneratedTarball>;
1429 const IS_HOST: bool = true;
1430
1431 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1432 run.alias("rust-analyzer")
1433 }
1434
1435 fn is_default_step(builder: &Builder<'_>) -> bool {
1436 should_build_extended_tool(builder, "rust-analyzer")
1437 }
1438
1439 fn make_run(run: RunConfig<'_>) {
1440 run.builder.ensure(RustAnalyzer {
1441 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1442 target: run.target,
1443 });
1444 }
1445
1446 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1447 let target = self.target;
1448 let rust_analyzer = builder.ensure(tool::RustAnalyzer::from_compilers(self.compilers));
1449
1450 let mut tarball = Tarball::new(builder, "rust-analyzer", &target.triple);
1451 tarball.set_overlay(OverlayKind::RustAnalyzer);
1452 tarball.is_preview(true);
1453 tarball.add_file(&rust_analyzer.tool_path, "bin", FileType::Executable);
1454 tarball.add_legal_and_readme_to("share/doc/rust-analyzer");
1455 Some(tarball.generate())
1456 }
1457
1458 fn metadata(&self) -> Option<StepMetadata> {
1459 Some(
1460 StepMetadata::dist("rust-analyzer", self.target)
1461 .built_by(self.compilers.build_compiler()),
1462 )
1463 }
1464}
1465
1466#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1467pub struct Clippy {
1468 pub compilers: RustcPrivateCompilers,
1469 pub target: TargetSelection,
1470}
1471
1472impl Step for Clippy {
1473 type Output = Option<GeneratedTarball>;
1474 const IS_HOST: bool = true;
1475
1476 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1477 run.alias("clippy")
1478 }
1479
1480 fn is_default_step(builder: &Builder<'_>) -> bool {
1481 should_build_extended_tool(builder, "clippy")
1482 }
1483
1484 fn make_run(run: RunConfig<'_>) {
1485 run.builder.ensure(Clippy {
1486 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1487 target: run.target,
1488 });
1489 }
1490
1491 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1492 let target = self.target;
1493
1494 let clippy = builder.ensure(tool::Clippy::from_compilers(self.compilers));
1498 let cargoclippy = builder.ensure(tool::CargoClippy::from_compilers(self.compilers));
1499
1500 let mut tarball = Tarball::new(builder, "clippy", &target.triple);
1501 tarball.set_overlay(OverlayKind::Clippy);
1502 tarball.is_preview(true);
1503 tarball.add_file(&clippy.tool_path, "bin", FileType::Executable);
1504 tarball.add_file(&cargoclippy.tool_path, "bin", FileType::Executable);
1505 tarball.add_legal_and_readme_to("share/doc/clippy");
1506 Some(tarball.generate())
1507 }
1508
1509 fn metadata(&self) -> Option<StepMetadata> {
1510 Some(StepMetadata::dist("clippy", self.target).built_by(self.compilers.build_compiler()))
1511 }
1512}
1513
1514#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1515pub struct Miri {
1516 pub compilers: RustcPrivateCompilers,
1517 pub target: TargetSelection,
1518}
1519
1520impl Step for Miri {
1521 type Output = Option<GeneratedTarball>;
1522 const IS_HOST: bool = true;
1523
1524 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1525 run.alias("miri")
1526 }
1527
1528 fn is_default_step(builder: &Builder<'_>) -> bool {
1529 should_build_extended_tool(builder, "miri")
1530 }
1531
1532 fn make_run(run: RunConfig<'_>) {
1533 run.builder.ensure(Miri {
1534 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1535 target: run.target,
1536 });
1537 }
1538
1539 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1540 if !builder.build.unstable_features() {
1544 return None;
1545 }
1546
1547 let miri = builder.ensure(tool::Miri::from_compilers(self.compilers));
1548 let cargomiri = builder.ensure(tool::CargoMiri::from_compilers(self.compilers));
1549
1550 let mut tarball = Tarball::new(builder, "miri", &self.target.triple);
1551 tarball.set_overlay(OverlayKind::Miri);
1552 tarball.is_preview(true);
1553 tarball.add_file(&miri.tool_path, "bin", FileType::Executable);
1554 tarball.add_file(&cargomiri.tool_path, "bin", FileType::Executable);
1555 tarball.add_legal_and_readme_to("share/doc/miri");
1556 Some(tarball.generate())
1557 }
1558
1559 fn metadata(&self) -> Option<StepMetadata> {
1560 Some(StepMetadata::dist("miri", self.target).built_by(self.compilers.build_compiler()))
1561 }
1562}
1563
1564#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1565pub struct CraneliftCodegenBackend {
1566 pub compilers: RustcPrivateCompilers,
1567 pub target: TargetSelection,
1568}
1569
1570impl Step for CraneliftCodegenBackend {
1571 type Output = Option<GeneratedTarball>;
1572 const IS_HOST: bool = true;
1573
1574 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1575 run.alias("rustc_codegen_cranelift")
1576 }
1577
1578 fn is_default_step(builder: &Builder<'_>) -> bool {
1579 builder
1584 .config
1585 .enabled_codegen_backends(builder.host_target)
1586 .contains(&CodegenBackendKind::Cranelift)
1587 }
1588
1589 fn make_run(run: RunConfig<'_>) {
1590 run.builder.ensure(CraneliftCodegenBackend {
1591 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1592 target: run.target,
1593 });
1594 }
1595
1596 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1597 if !builder.build.unstable_features() {
1601 return None;
1602 }
1603
1604 let target = self.target;
1605 if !target_supports_cranelift_backend(target) {
1606 builder.info("target not supported by rustc_codegen_cranelift. skipping");
1607 return None;
1608 }
1609
1610 let mut tarball = Tarball::new(builder, "rustc-codegen-cranelift", &target.triple);
1611 tarball.set_overlay(OverlayKind::RustcCodegenCranelift);
1612 tarball.is_preview(true);
1613 tarball.add_legal_and_readme_to("share/doc/rustc_codegen_cranelift");
1614
1615 let compilers = self.compilers;
1616 let stamp = builder.ensure(compile::CraneliftCodegenBackend { compilers });
1617
1618 if builder.config.dry_run() {
1619 return None;
1620 }
1621
1622 let backends_dst = builder.sysroot_codegen_backends(compilers.target_compiler());
1624 let backends_rel = backends_dst
1625 .strip_prefix(builder.sysroot(compilers.target_compiler()))
1626 .unwrap()
1627 .strip_prefix(builder.sysroot_libdir_relative(compilers.target_compiler()))
1628 .unwrap();
1629 let backends_dst = PathBuf::from("lib").join(backends_rel);
1631
1632 let codegen_backend_dylib = get_codegen_backend_file(&stamp);
1633 tarball.add_renamed_file(
1634 &codegen_backend_dylib,
1635 &backends_dst,
1636 &normalize_codegen_backend_name(builder, &codegen_backend_dylib),
1637 FileType::NativeLibrary,
1638 );
1639
1640 Some(tarball.generate())
1641 }
1642
1643 fn metadata(&self) -> Option<StepMetadata> {
1644 Some(
1645 StepMetadata::dist("rustc_codegen_cranelift", self.target)
1646 .built_by(self.compilers.build_compiler()),
1647 )
1648 }
1649}
1650
1651#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1652pub struct Rustfmt {
1653 pub compilers: RustcPrivateCompilers,
1654 pub target: TargetSelection,
1655}
1656
1657impl Step for Rustfmt {
1658 type Output = Option<GeneratedTarball>;
1659 const IS_HOST: bool = true;
1660
1661 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1662 run.alias("rustfmt")
1663 }
1664
1665 fn is_default_step(builder: &Builder<'_>) -> bool {
1666 should_build_extended_tool(builder, "rustfmt")
1667 }
1668
1669 fn make_run(run: RunConfig<'_>) {
1670 run.builder.ensure(Rustfmt {
1671 compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
1672 target: run.target,
1673 });
1674 }
1675
1676 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1677 let rustfmt = builder.ensure(tool::Rustfmt::from_compilers(self.compilers));
1678 let cargofmt = builder.ensure(tool::Cargofmt::from_compilers(self.compilers));
1679
1680 let mut tarball = Tarball::new(builder, "rustfmt", &self.target.triple);
1681 tarball.set_overlay(OverlayKind::Rustfmt);
1682 tarball.is_preview(true);
1683 tarball.add_file(&rustfmt.tool_path, "bin", FileType::Executable);
1684 tarball.add_file(&cargofmt.tool_path, "bin", FileType::Executable);
1685 tarball.add_legal_and_readme_to("share/doc/rustfmt");
1686 Some(tarball.generate())
1687 }
1688
1689 fn metadata(&self) -> Option<StepMetadata> {
1690 Some(StepMetadata::dist("rustfmt", self.target).built_by(self.compilers.build_compiler()))
1691 }
1692}
1693
1694#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1696pub struct Extended {
1697 build_compiler: Compiler,
1698 target: TargetSelection,
1699}
1700
1701impl Step for Extended {
1702 type Output = ();
1703 const IS_HOST: bool = true;
1704
1705 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1706 run.alias("extended")
1707 }
1708
1709 fn is_default_step(builder: &Builder<'_>) -> bool {
1710 builder.config.extended
1711 }
1712
1713 fn make_run(run: RunConfig<'_>) {
1714 run.builder.ensure(Extended {
1715 build_compiler: run
1716 .builder
1717 .compiler(run.builder.top_stage - 1, run.builder.host_target),
1718 target: run.target,
1719 });
1720 }
1721
1722 fn run(self, builder: &Builder<'_>) {
1724 let target = self.target;
1725 builder.info(&format!("Dist extended stage{} ({target})", builder.top_stage));
1726
1727 let mut tarballs = Vec::new();
1728 let mut built_tools = HashSet::new();
1729 macro_rules! add_component {
1730 ($name:expr => $step:expr) => {
1731 if let Some(Some(tarball)) = builder.ensure_if_default($step, Kind::Dist) {
1732 tarballs.push(tarball);
1733 built_tools.insert($name);
1734 }
1735 };
1736 }
1737
1738 let rustc_private_compilers =
1739 RustcPrivateCompilers::from_build_compiler(builder, self.build_compiler, target);
1740 let build_compiler = rustc_private_compilers.build_compiler();
1741 let target_compiler = rustc_private_compilers.target_compiler();
1742
1743 tarballs.push(builder.ensure(Rustc { target_compiler }));
1748 tarballs.push(builder.ensure(Std { build_compiler, target }).expect("missing std"));
1749
1750 if target.is_windows_gnu() || target.is_windows_gnullvm() {
1751 tarballs.push(builder.ensure(Mingw { target }).expect("missing mingw"));
1752 }
1753
1754 add_component!("rust-docs" => Docs { host: target });
1755 add_component!("rust-json-docs" => JsonDocs { build_compiler: target_compiler, target });
1757 add_component!("cargo" => Cargo { build_compiler, target });
1758 add_component!("rustfmt" => Rustfmt { compilers: rustc_private_compilers, target });
1759 add_component!("rust-analyzer" => RustAnalyzer { compilers: rustc_private_compilers, target });
1760 add_component!("llvm-components" => LlvmTools { target });
1761 add_component!("clippy" => Clippy { compilers: rustc_private_compilers, target });
1762 add_component!("miri" => Miri { compilers: rustc_private_compilers, target });
1763 add_component!("analysis" => Analysis { build_compiler, target });
1764 add_component!("rustc-codegen-cranelift" => CraneliftCodegenBackend {
1765 compilers: rustc_private_compilers,
1766 target
1767 });
1768 add_component!("llvm-bitcode-linker" => LlvmBitcodeLinker {
1769 build_compiler,
1770 target
1771 });
1772
1773 let etc = builder.src.join("src/etc/installer");
1774
1775 if builder.config.dry_run() {
1777 return;
1778 }
1779
1780 let tarball = Tarball::new(builder, "rust", &target.triple);
1781 let generated = tarball.combine(&tarballs);
1782
1783 let tmp = tmpdir(builder).join("combined-tarball");
1784 let work = generated.work_dir();
1785
1786 let mut license = String::new();
1787 license += &builder.read(&builder.src.join("COPYRIGHT"));
1788 license += &builder.read(&builder.src.join("LICENSE-APACHE"));
1789 license += &builder.read(&builder.src.join("LICENSE-MIT"));
1790 license.push('\n');
1791 license.push('\n');
1792
1793 let rtf = r"{\rtf1\ansi\deff0{\fonttbl{\f0\fnil\fcharset0 Arial;}}\nowwrap\fs18";
1794 let mut rtf = rtf.to_string();
1795 rtf.push('\n');
1796 for line in license.lines() {
1797 rtf.push_str(line);
1798 rtf.push_str("\\line ");
1799 }
1800 rtf.push('}');
1801
1802 fn filter(contents: &str, marker: &str) -> String {
1803 let start = format!("tool-{marker}-start");
1804 let end = format!("tool-{marker}-end");
1805 let mut lines = Vec::new();
1806 let mut omitted = false;
1807 for line in contents.lines() {
1808 if line.contains(&start) {
1809 omitted = true;
1810 } else if line.contains(&end) {
1811 omitted = false;
1812 } else if !omitted {
1813 lines.push(line);
1814 }
1815 }
1816
1817 lines.join("\n")
1818 }
1819
1820 let xform = |p: &Path| {
1821 let mut contents = t!(fs::read_to_string(p));
1822 for tool in &["miri", "rust-docs"] {
1823 if !built_tools.contains(tool) {
1824 contents = filter(&contents, tool);
1825 }
1826 }
1827 let ret = tmp.join(p.file_name().unwrap());
1828 t!(fs::write(&ret, &contents));
1829 ret
1830 };
1831
1832 if target.contains("apple-darwin") {
1833 builder.info("building pkg installer");
1834 let pkg = tmp.join("pkg");
1835 let _ = fs::remove_dir_all(&pkg);
1836
1837 let pkgbuild = |component: &str| {
1838 let mut cmd = command("pkgbuild");
1839 cmd.arg("--identifier")
1840 .arg(format!("org.rust-lang.{component}"))
1841 .arg("--scripts")
1842 .arg(pkg.join(component))
1843 .arg("--nopayload")
1844 .arg(pkg.join(component).with_extension("pkg"));
1845 cmd.run(builder);
1846 };
1847
1848 let prepare = |name: &str| {
1849 builder.create_dir(&pkg.join(name));
1850 builder.cp_link_r(
1851 &work.join(format!("{}-{}", pkgname(builder, name), target.triple)),
1852 &pkg.join(name),
1853 );
1854 builder.install(&etc.join("pkg/postinstall"), &pkg.join(name), FileType::Script);
1855 pkgbuild(name);
1856 };
1857 prepare("rustc");
1858 prepare("cargo");
1859 prepare("rust-std");
1860 prepare("rust-analysis");
1861
1862 for tool in &[
1863 "clippy",
1864 "rustfmt",
1865 "rust-analyzer",
1866 "rust-docs",
1867 "miri",
1868 "rustc-codegen-cranelift",
1869 ] {
1870 if built_tools.contains(tool) {
1871 prepare(tool);
1872 }
1873 }
1874 builder.install(&etc.join("pkg/postinstall"), &pkg.join("uninstall"), FileType::Script);
1876 pkgbuild("uninstall");
1877
1878 builder.create_dir(&pkg.join("res"));
1879 builder.create(&pkg.join("res/LICENSE.txt"), &license);
1880 builder.install(&etc.join("gfx/rust-logo.png"), &pkg.join("res"), FileType::Regular);
1881 let mut cmd = command("productbuild");
1882 cmd.arg("--distribution")
1883 .arg(xform(&etc.join("pkg/Distribution.xml")))
1884 .arg("--resources")
1885 .arg(pkg.join("res"))
1886 .arg(distdir(builder).join(format!(
1887 "{}-{}.pkg",
1888 pkgname(builder, "rust"),
1889 target.triple
1890 )))
1891 .arg("--package-path")
1892 .arg(&pkg);
1893 let _time = timeit(builder);
1894 cmd.run(builder);
1895 }
1896
1897 if target.is_windows() {
1898 let exe = tmp.join("exe");
1899 let _ = fs::remove_dir_all(&exe);
1900
1901 let prepare = |name: &str| {
1902 builder.create_dir(&exe.join(name));
1903 let dir = if name == "rust-std" || name == "rust-analysis" {
1904 format!("{}-{}", name, target.triple)
1905 } else if name == "rust-analyzer" {
1906 "rust-analyzer-preview".to_string()
1907 } else if name == "clippy" {
1908 "clippy-preview".to_string()
1909 } else if name == "rustfmt" {
1910 "rustfmt-preview".to_string()
1911 } else if name == "miri" {
1912 "miri-preview".to_string()
1913 } else if name == "rustc-codegen-cranelift" {
1914 unreachable!("cg_clif shouldn't be built for windows");
1917 } else {
1918 name.to_string()
1919 };
1920 builder.cp_link_r(
1921 &work.join(format!("{}-{}", pkgname(builder, name), target.triple)).join(dir),
1922 &exe.join(name),
1923 );
1924 builder.remove(&exe.join(name).join("manifest.in"));
1925 };
1926 prepare("rustc");
1927 prepare("cargo");
1928 prepare("rust-analysis");
1929 prepare("rust-std");
1930 for tool in &["clippy", "rustfmt", "rust-analyzer", "rust-docs", "miri"] {
1931 if built_tools.contains(tool) {
1932 prepare(tool);
1933 }
1934 }
1935 if target.is_windows_gnu() || target.is_windows_gnullvm() {
1936 prepare("rust-mingw");
1937 }
1938
1939 builder.install(&etc.join("gfx/rust-logo.ico"), &exe, FileType::Regular);
1940
1941 let wix_path = env::var_os("WIX")
1943 .expect("`WIX` environment variable must be set for generating MSI installer(s).");
1944 let wix = PathBuf::from(wix_path);
1945 let heat = wix.join("bin/heat.exe");
1946 let candle = wix.join("bin/candle.exe");
1947 let light = wix.join("bin/light.exe");
1948
1949 let heat_flags = ["-nologo", "-gg", "-sfrag", "-srd", "-sreg"];
1950 command(&heat)
1951 .current_dir(&exe)
1952 .arg("dir")
1953 .arg("rustc")
1954 .args(heat_flags)
1955 .arg("-cg")
1956 .arg("RustcGroup")
1957 .arg("-dr")
1958 .arg("Rustc")
1959 .arg("-var")
1960 .arg("var.RustcDir")
1961 .arg("-out")
1962 .arg(exe.join("RustcGroup.wxs"))
1963 .run(builder);
1964 if built_tools.contains("rust-docs") {
1965 command(&heat)
1966 .current_dir(&exe)
1967 .arg("dir")
1968 .arg("rust-docs")
1969 .args(heat_flags)
1970 .arg("-cg")
1971 .arg("DocsGroup")
1972 .arg("-dr")
1973 .arg("Docs")
1974 .arg("-var")
1975 .arg("var.DocsDir")
1976 .arg("-out")
1977 .arg(exe.join("DocsGroup.wxs"))
1978 .arg("-t")
1979 .arg(etc.join("msi/squash-components.xsl"))
1980 .run(builder);
1981 }
1982 command(&heat)
1983 .current_dir(&exe)
1984 .arg("dir")
1985 .arg("cargo")
1986 .args(heat_flags)
1987 .arg("-cg")
1988 .arg("CargoGroup")
1989 .arg("-dr")
1990 .arg("Cargo")
1991 .arg("-var")
1992 .arg("var.CargoDir")
1993 .arg("-out")
1994 .arg(exe.join("CargoGroup.wxs"))
1995 .arg("-t")
1996 .arg(etc.join("msi/remove-duplicates.xsl"))
1997 .run(builder);
1998 command(&heat)
1999 .current_dir(&exe)
2000 .arg("dir")
2001 .arg("rust-std")
2002 .args(heat_flags)
2003 .arg("-cg")
2004 .arg("StdGroup")
2005 .arg("-dr")
2006 .arg("Std")
2007 .arg("-var")
2008 .arg("var.StdDir")
2009 .arg("-out")
2010 .arg(exe.join("StdGroup.wxs"))
2011 .run(builder);
2012 if built_tools.contains("rust-analyzer") {
2013 command(&heat)
2014 .current_dir(&exe)
2015 .arg("dir")
2016 .arg("rust-analyzer")
2017 .args(heat_flags)
2018 .arg("-cg")
2019 .arg("RustAnalyzerGroup")
2020 .arg("-dr")
2021 .arg("RustAnalyzer")
2022 .arg("-var")
2023 .arg("var.RustAnalyzerDir")
2024 .arg("-out")
2025 .arg(exe.join("RustAnalyzerGroup.wxs"))
2026 .arg("-t")
2027 .arg(etc.join("msi/remove-duplicates.xsl"))
2028 .run(builder);
2029 }
2030 if built_tools.contains("clippy") {
2031 command(&heat)
2032 .current_dir(&exe)
2033 .arg("dir")
2034 .arg("clippy")
2035 .args(heat_flags)
2036 .arg("-cg")
2037 .arg("ClippyGroup")
2038 .arg("-dr")
2039 .arg("Clippy")
2040 .arg("-var")
2041 .arg("var.ClippyDir")
2042 .arg("-out")
2043 .arg(exe.join("ClippyGroup.wxs"))
2044 .arg("-t")
2045 .arg(etc.join("msi/remove-duplicates.xsl"))
2046 .run(builder);
2047 }
2048 if built_tools.contains("rustfmt") {
2049 command(&heat)
2050 .current_dir(&exe)
2051 .arg("dir")
2052 .arg("rustfmt")
2053 .args(heat_flags)
2054 .arg("-cg")
2055 .arg("RustFmtGroup")
2056 .arg("-dr")
2057 .arg("RustFmt")
2058 .arg("-var")
2059 .arg("var.RustFmtDir")
2060 .arg("-out")
2061 .arg(exe.join("RustFmtGroup.wxs"))
2062 .arg("-t")
2063 .arg(etc.join("msi/remove-duplicates.xsl"))
2064 .run(builder);
2065 }
2066 if built_tools.contains("miri") {
2067 command(&heat)
2068 .current_dir(&exe)
2069 .arg("dir")
2070 .arg("miri")
2071 .args(heat_flags)
2072 .arg("-cg")
2073 .arg("MiriGroup")
2074 .arg("-dr")
2075 .arg("Miri")
2076 .arg("-var")
2077 .arg("var.MiriDir")
2078 .arg("-out")
2079 .arg(exe.join("MiriGroup.wxs"))
2080 .arg("-t")
2081 .arg(etc.join("msi/remove-duplicates.xsl"))
2082 .run(builder);
2083 }
2084 command(&heat)
2085 .current_dir(&exe)
2086 .arg("dir")
2087 .arg("rust-analysis")
2088 .args(heat_flags)
2089 .arg("-cg")
2090 .arg("AnalysisGroup")
2091 .arg("-dr")
2092 .arg("Analysis")
2093 .arg("-var")
2094 .arg("var.AnalysisDir")
2095 .arg("-out")
2096 .arg(exe.join("AnalysisGroup.wxs"))
2097 .arg("-t")
2098 .arg(etc.join("msi/remove-duplicates.xsl"))
2099 .run(builder);
2100 if target.is_windows_gnu() || target.is_windows_gnullvm() {
2101 command(&heat)
2102 .current_dir(&exe)
2103 .arg("dir")
2104 .arg("rust-mingw")
2105 .args(heat_flags)
2106 .arg("-cg")
2107 .arg("GccGroup")
2108 .arg("-dr")
2109 .arg("Gcc")
2110 .arg("-var")
2111 .arg("var.GccDir")
2112 .arg("-out")
2113 .arg(exe.join("GccGroup.wxs"))
2114 .run(builder);
2115 }
2116
2117 let candle = |input: &Path| {
2118 let output = exe.join(input.file_stem().unwrap()).with_extension("wixobj");
2119 let arch = if target.contains("x86_64") { "x64" } else { "x86" };
2120 let mut cmd = command(&candle);
2121 cmd.current_dir(&exe)
2122 .arg("-nologo")
2123 .arg("-dRustcDir=rustc")
2124 .arg("-dCargoDir=cargo")
2125 .arg("-dStdDir=rust-std")
2126 .arg("-dAnalysisDir=rust-analysis")
2127 .arg("-arch")
2128 .arg(arch)
2129 .arg("-out")
2130 .arg(&output)
2131 .arg(input);
2132 add_env(builder, &mut cmd, target, &built_tools);
2133
2134 if built_tools.contains("clippy") {
2135 cmd.arg("-dClippyDir=clippy");
2136 }
2137 if built_tools.contains("rustfmt") {
2138 cmd.arg("-dRustFmtDir=rustfmt");
2139 }
2140 if built_tools.contains("rust-docs") {
2141 cmd.arg("-dDocsDir=rust-docs");
2142 }
2143 if built_tools.contains("rust-analyzer") {
2144 cmd.arg("-dRustAnalyzerDir=rust-analyzer");
2145 }
2146 if built_tools.contains("miri") {
2147 cmd.arg("-dMiriDir=miri");
2148 }
2149 if target.is_windows_gnu() || target.is_windows_gnullvm() {
2150 cmd.arg("-dGccDir=rust-mingw");
2151 }
2152 cmd.run(builder);
2153 };
2154 candle(&xform(&etc.join("msi/rust.wxs")));
2155 candle(&etc.join("msi/ui.wxs"));
2156 candle(&etc.join("msi/rustwelcomedlg.wxs"));
2157 candle("RustcGroup.wxs".as_ref());
2158 if built_tools.contains("rust-docs") {
2159 candle("DocsGroup.wxs".as_ref());
2160 }
2161 candle("CargoGroup.wxs".as_ref());
2162 candle("StdGroup.wxs".as_ref());
2163 if built_tools.contains("clippy") {
2164 candle("ClippyGroup.wxs".as_ref());
2165 }
2166 if built_tools.contains("rustfmt") {
2167 candle("RustFmtGroup.wxs".as_ref());
2168 }
2169 if built_tools.contains("miri") {
2170 candle("MiriGroup.wxs".as_ref());
2171 }
2172 if built_tools.contains("rust-analyzer") {
2173 candle("RustAnalyzerGroup.wxs".as_ref());
2174 }
2175 candle("AnalysisGroup.wxs".as_ref());
2176
2177 if target.is_windows_gnu() || target.is_windows_gnullvm() {
2178 candle("GccGroup.wxs".as_ref());
2179 }
2180
2181 builder.create(&exe.join("LICENSE.rtf"), &rtf);
2182 builder.install(&etc.join("gfx/banner.bmp"), &exe, FileType::Regular);
2183 builder.install(&etc.join("gfx/dialogbg.bmp"), &exe, FileType::Regular);
2184
2185 builder.info(&format!("building `msi` installer with {light:?}"));
2186 let filename = format!("{}-{}.msi", pkgname(builder, "rust"), target.triple);
2187 let mut cmd = command(&light);
2188 cmd.arg("-nologo")
2189 .arg("-ext")
2190 .arg("WixUIExtension")
2191 .arg("-ext")
2192 .arg("WixUtilExtension")
2193 .arg("-out")
2194 .arg(exe.join(&filename))
2195 .arg("rust.wixobj")
2196 .arg("ui.wixobj")
2197 .arg("rustwelcomedlg.wixobj")
2198 .arg("RustcGroup.wixobj")
2199 .arg("CargoGroup.wixobj")
2200 .arg("StdGroup.wixobj")
2201 .arg("AnalysisGroup.wixobj")
2202 .current_dir(&exe);
2203
2204 if built_tools.contains("clippy") {
2205 cmd.arg("ClippyGroup.wixobj");
2206 }
2207 if built_tools.contains("rustfmt") {
2208 cmd.arg("RustFmtGroup.wixobj");
2209 }
2210 if built_tools.contains("miri") {
2211 cmd.arg("MiriGroup.wixobj");
2212 }
2213 if built_tools.contains("rust-analyzer") {
2214 cmd.arg("RustAnalyzerGroup.wixobj");
2215 }
2216 if built_tools.contains("rust-docs") {
2217 cmd.arg("DocsGroup.wixobj");
2218 }
2219
2220 if target.is_windows_gnu() || target.is_windows_gnullvm() {
2221 cmd.arg("GccGroup.wixobj");
2222 }
2223 cmd.arg("-sice:ICE57");
2225
2226 let _time = timeit(builder);
2227 cmd.run(builder);
2228
2229 if !builder.config.dry_run() {
2230 t!(move_file(exe.join(&filename), distdir(builder).join(&filename)));
2231 }
2232 }
2233 }
2234
2235 fn metadata(&self) -> Option<StepMetadata> {
2236 Some(StepMetadata::dist("extended", self.target).built_by(self.build_compiler))
2237 }
2238}
2239
2240fn add_env(
2241 builder: &Builder<'_>,
2242 cmd: &mut BootstrapCommand,
2243 target: TargetSelection,
2244 built_tools: &HashSet<&'static str>,
2245) {
2246 let mut parts = builder.version.split('.');
2247 cmd.env("CFG_RELEASE_INFO", builder.rust_version())
2248 .env("CFG_RELEASE_NUM", &builder.version)
2249 .env("CFG_RELEASE", builder.rust_release())
2250 .env("CFG_VER_MAJOR", parts.next().unwrap())
2251 .env("CFG_VER_MINOR", parts.next().unwrap())
2252 .env("CFG_VER_PATCH", parts.next().unwrap())
2253 .env("CFG_VER_BUILD", "0") .env("CFG_PACKAGE_VERS", builder.rust_package_vers())
2255 .env("CFG_PACKAGE_NAME", pkgname(builder, "rust"))
2256 .env("CFG_BUILD", target.triple)
2257 .env("CFG_CHANNEL", &builder.config.channel);
2258
2259 if target.is_windows_gnullvm() {
2260 cmd.env("CFG_MINGW", "1").env("CFG_ABI", "LLVM");
2261 } else if target.is_windows_gnu() {
2262 cmd.env("CFG_MINGW", "1").env("CFG_ABI", "GNU");
2263 } else {
2264 cmd.env("CFG_MINGW", "0").env("CFG_ABI", "MSVC");
2265 }
2266
2267 let mut define_optional_tool = |tool_name: &str, env_name: &str| {
2269 cmd.env(env_name, if built_tools.contains(tool_name) { "1" } else { "0" });
2270 };
2271 define_optional_tool("rustfmt", "CFG_RUSTFMT");
2272 define_optional_tool("clippy", "CFG_CLIPPY");
2273 define_optional_tool("miri", "CFG_MIRI");
2274 define_optional_tool("rust-analyzer", "CFG_RA");
2275}
2276
2277fn install_llvm_file(
2278 builder: &Builder<'_>,
2279 source: &Path,
2280 destination: &Path,
2281 install_symlink: bool,
2282) {
2283 if builder.config.dry_run() {
2284 return;
2285 }
2286
2287 if source.is_symlink() {
2288 builder.install(&t!(fs::canonicalize(source)), destination, FileType::NativeLibrary);
2291
2292 let full_dest = destination.join(source.file_name().unwrap());
2293 if install_symlink {
2294 builder.copy_link(source, &full_dest, FileType::NativeLibrary);
2297 } else {
2298 let link = t!(fs::read_link(source));
2302 let mut linker_script = t!(fs::File::create(full_dest));
2303 t!(write!(linker_script, "INPUT({})\n", link.display()));
2304
2305 let meta = t!(fs::metadata(source));
2308 if let Ok(mtime) = meta.modified() {
2309 t!(linker_script.set_modified(mtime));
2310 }
2311 }
2312 } else {
2313 builder.install(source, destination, FileType::NativeLibrary);
2314 }
2315}
2316
2317#[cfg_attr(
2321 feature = "tracing",
2322 instrument(
2323 level = "trace",
2324 name = "maybe_install_llvm",
2325 skip_all,
2326 fields(target = ?target, dst_libdir = ?dst_libdir, install_symlink = install_symlink),
2327 ),
2328)]
2329fn maybe_install_llvm(
2330 builder: &Builder<'_>,
2331 target: TargetSelection,
2332 dst_libdir: &Path,
2333 install_symlink: bool,
2334) -> bool {
2335 if builder.config.is_system_llvm(target) {
2352 trace!("system LLVM requested, no install");
2353 return false;
2354 }
2355
2356 if target.contains("apple-darwin") && builder.llvm_link_shared() {
2362 let src_libdir = builder.llvm_out(target).join("lib");
2363 let llvm_dylib_path = src_libdir.join("libLLVM.dylib");
2364 if llvm_dylib_path.exists() {
2365 builder.install(&llvm_dylib_path, dst_libdir, FileType::NativeLibrary);
2366 }
2367 !builder.config.dry_run()
2368 } else if let llvm::LlvmBuildStatus::AlreadyBuilt(llvm::LlvmResult {
2369 host_llvm_config, ..
2370 }) = llvm::prebuilt_llvm_config(builder, target, true)
2371 {
2372 trace!("LLVM already built, installing LLVM files");
2373 let mut cmd = command(host_llvm_config);
2374 cmd.cached();
2375 cmd.arg("--libfiles");
2376 builder.do_if_verbose(|| println!("running {cmd:?}"));
2377 let files = cmd.run_capture_stdout(builder).stdout();
2378 let build_llvm_out = &builder.llvm_out(builder.config.host_target);
2379 let target_llvm_out = &builder.llvm_out(target);
2380 for file in files.trim_end().split(' ') {
2381 let file = if let Ok(relative_path) = Path::new(file).strip_prefix(build_llvm_out) {
2383 target_llvm_out.join(relative_path)
2384 } else {
2385 PathBuf::from(file)
2386 };
2387 install_llvm_file(builder, &file, dst_libdir, install_symlink);
2388 }
2389 !builder.config.dry_run()
2390 } else {
2391 false
2392 }
2393}
2394
2395#[cfg_attr(
2397 feature = "tracing",
2398 instrument(
2399 level = "trace",
2400 name = "maybe_install_llvm_target",
2401 skip_all,
2402 fields(
2403 llvm_link_shared = ?builder.llvm_link_shared(),
2404 target = ?target,
2405 sysroot = ?sysroot,
2406 ),
2407 ),
2408)]
2409pub fn maybe_install_llvm_target(builder: &Builder<'_>, target: TargetSelection, sysroot: &Path) {
2410 let dst_libdir = sysroot.join("lib/rustlib").join(target).join("lib");
2411 if builder.llvm_link_shared() {
2415 maybe_install_llvm(builder, target, &dst_libdir, false);
2416 }
2417}
2418
2419#[cfg_attr(
2421 feature = "tracing",
2422 instrument(
2423 level = "trace",
2424 name = "maybe_install_llvm_runtime",
2425 skip_all,
2426 fields(
2427 llvm_link_shared = ?builder.llvm_link_shared(),
2428 target = ?target,
2429 sysroot = ?sysroot,
2430 ),
2431 ),
2432)]
2433pub fn maybe_install_llvm_runtime(builder: &Builder<'_>, target: TargetSelection, sysroot: &Path) {
2434 let dst_libdir = sysroot.join(builder.sysroot_libdir_relative(Compiler::new(1, target)));
2435 if builder.llvm_link_shared() {
2439 maybe_install_llvm(builder, target, &dst_libdir, false);
2440 }
2441}
2442
2443#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2444pub struct LlvmTools {
2445 pub target: TargetSelection,
2446}
2447
2448impl Step for LlvmTools {
2449 type Output = Option<GeneratedTarball>;
2450 const IS_HOST: bool = true;
2451
2452 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2453 let mut run = run.alias("llvm-tools");
2454 for tool in LLVM_TOOLS {
2455 run = run.alias(tool);
2456 }
2457
2458 run
2459 }
2460
2461 fn is_default_step(builder: &Builder<'_>) -> bool {
2462 should_build_extended_tool(builder, "llvm-tools")
2463 }
2464
2465 fn make_run(run: RunConfig<'_>) {
2466 run.builder.ensure(LlvmTools { target: run.target });
2467 }
2468
2469 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2470 fn tools_to_install(paths: &[PathBuf]) -> Vec<&'static str> {
2471 let mut tools = vec![];
2472
2473 for path in paths {
2474 let path = path.to_str().unwrap();
2475
2476 if path == "llvm-tools" {
2478 return LLVM_TOOLS.to_owned();
2479 }
2480
2481 for tool in LLVM_TOOLS {
2482 if path == *tool {
2483 tools.push(*tool);
2484 }
2485 }
2486 }
2487
2488 if tools.is_empty() {
2490 tools = LLVM_TOOLS.to_owned();
2491 }
2492
2493 tools
2494 }
2495
2496 let target = self.target;
2497
2498 if let Some(config) = builder.config.target_config.get(&target)
2500 && !builder.config.llvm_from_ci
2501 && config.llvm_config.is_some()
2502 {
2503 builder.info(&format!("Skipping LlvmTools ({target}): external LLVM"));
2504 return None;
2505 }
2506
2507 if !builder.config.dry_run() {
2508 builder.require_submodule("src/llvm-project", None);
2509 }
2510
2511 builder.ensure(crate::core::build_steps::llvm::Llvm { target });
2512
2513 let mut tarball = Tarball::new(builder, "llvm-tools", &target.triple);
2514 tarball.set_overlay(OverlayKind::Llvm);
2515 tarball.is_preview(true);
2516
2517 if builder.config.llvm_tools_enabled {
2518 let src_bindir = builder.llvm_out(target).join("bin");
2520 let dst_bindir = format!("lib/rustlib/{}/bin", target.triple);
2521 for tool in tools_to_install(&builder.paths) {
2522 let exe = src_bindir.join(exe(tool, target));
2523 if !exe.exists() && builder.config.llvm_from_ci {
2525 eprintln!("{} does not exist; skipping copy", exe.display());
2526 continue;
2527 }
2528
2529 tarball.add_file(&exe, &dst_bindir, FileType::Executable);
2530 }
2531 }
2532
2533 maybe_install_llvm_target(builder, target, tarball.image_dir());
2538
2539 Some(tarball.generate())
2540 }
2541}
2542
2543#[derive(Debug, Clone, Hash, PartialEq, Eq)]
2546pub struct LlvmBitcodeLinker {
2547 pub build_compiler: Compiler,
2549 pub target: TargetSelection,
2551}
2552
2553impl Step for LlvmBitcodeLinker {
2554 type Output = Option<GeneratedTarball>;
2555 const IS_HOST: bool = true;
2556
2557 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2558 run.alias("llvm-bitcode-linker")
2559 }
2560
2561 fn is_default_step(builder: &Builder<'_>) -> bool {
2562 should_build_extended_tool(builder, "llvm-bitcode-linker")
2563 }
2564
2565 fn make_run(run: RunConfig<'_>) {
2566 run.builder.ensure(LlvmBitcodeLinker {
2567 build_compiler: tool::LlvmBitcodeLinker::get_build_compiler_for_target(
2568 run.builder,
2569 run.target,
2570 ),
2571 target: run.target,
2572 });
2573 }
2574
2575 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2576 let target = self.target;
2577
2578 let llbc_linker = builder
2579 .ensure(tool::LlvmBitcodeLinker::from_build_compiler(self.build_compiler, target));
2580
2581 let self_contained_bin_dir = format!("lib/rustlib/{}/bin/self-contained", target.triple);
2582
2583 let mut tarball = Tarball::new(builder, "llvm-bitcode-linker", &target.triple);
2585 tarball.set_overlay(OverlayKind::LlvmBitcodeLinker);
2586 tarball.is_preview(true);
2587
2588 tarball.add_file(&llbc_linker.tool_path, self_contained_bin_dir, FileType::Executable);
2589
2590 Some(tarball.generate())
2591 }
2592}
2593
2594#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2603pub struct RustDev {
2604 pub target: TargetSelection,
2605}
2606
2607impl Step for RustDev {
2608 type Output = Option<GeneratedTarball>;
2609 const IS_HOST: bool = true;
2610
2611 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2612 run.alias("rust-dev")
2613 }
2614
2615 fn is_default_step(_builder: &Builder<'_>) -> bool {
2616 true
2617 }
2618
2619 fn make_run(run: RunConfig<'_>) {
2620 run.builder.ensure(RustDev { target: run.target });
2621 }
2622
2623 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2624 let target = self.target;
2625
2626 if let Some(config) = builder.config.target_config.get(&target)
2628 && let Some(ref _s) = config.llvm_config
2629 {
2630 builder.info(&format!("Skipping RustDev ({target}): external LLVM"));
2631 return None;
2632 }
2633
2634 if !builder.config.dry_run() {
2635 builder.require_submodule("src/llvm-project", None);
2636 }
2637
2638 let mut tarball = Tarball::new(builder, "rust-dev", &target.triple);
2639 tarball.set_overlay(OverlayKind::Llvm);
2640 tarball.permit_symlinks(true);
2642
2643 builder.ensure(crate::core::build_steps::llvm::Llvm { target });
2644
2645 let src_bindir = builder.llvm_out(target).join("bin");
2646 if src_bindir.exists() {
2652 for entry in walkdir::WalkDir::new(&src_bindir) {
2653 let entry = t!(entry);
2654 if entry.file_type().is_file() && !entry.path_is_symlink() {
2655 let name = entry.file_name().to_str().unwrap();
2656 tarball.add_file(src_bindir.join(name), "bin", FileType::Executable);
2657 }
2658 }
2659 }
2660
2661 if builder.config.lld_enabled {
2662 let lld_out = builder.ensure(crate::core::build_steps::llvm::Lld { target });
2664
2665 let lld_path = lld_out.join("bin").join(exe("lld", target));
2667 if lld_path.exists() {
2668 tarball.add_file(&lld_path, "bin", FileType::Executable);
2669 }
2670 }
2671
2672 tarball.add_file(builder.llvm_filecheck(target), "bin", FileType::Executable);
2673
2674 tarball.add_dir(builder.llvm_out(target).join("include"), "include");
2678
2679 let dst_libdir = tarball.image_dir().join("lib");
2684 maybe_install_llvm(builder, target, &dst_libdir, true);
2685 let link_type = if builder.llvm_link_shared() { "dynamic" } else { "static" };
2686 t!(std::fs::write(tarball.image_dir().join("link-type.txt"), link_type), dst_libdir);
2687
2688 copy_src_dirs(
2692 builder,
2693 &builder.src.join("src").join("llvm-project"),
2694 &["compiler-rt"],
2695 &["compiler-rt/test"],
2698 tarball.image_dir(),
2699 );
2700
2701 Some(tarball.generate())
2702 }
2703}
2704
2705#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2711pub struct Bootstrap {
2712 target: TargetSelection,
2713}
2714
2715impl Step for Bootstrap {
2716 type Output = Option<GeneratedTarball>;
2717
2718 const IS_HOST: bool = true;
2719
2720 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2721 run.alias("bootstrap")
2722 }
2723
2724 fn make_run(run: RunConfig<'_>) {
2725 run.builder.ensure(Bootstrap { target: run.target });
2726 }
2727
2728 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2729 let target = self.target;
2730
2731 let tarball = Tarball::new(builder, "bootstrap", &target.triple);
2732
2733 let bootstrap_outdir = &builder.bootstrap_out;
2734 for file in &["bootstrap", "rustc", "rustdoc"] {
2735 tarball.add_file(
2736 bootstrap_outdir.join(exe(file, target)),
2737 "bootstrap/bin",
2738 FileType::Executable,
2739 );
2740 }
2741
2742 Some(tarball.generate())
2743 }
2744
2745 fn metadata(&self) -> Option<StepMetadata> {
2746 Some(StepMetadata::dist("bootstrap", self.target))
2747 }
2748}
2749
2750#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2755pub struct BuildManifest {
2756 target: TargetSelection,
2757}
2758
2759impl Step for BuildManifest {
2760 type Output = GeneratedTarball;
2761
2762 const IS_HOST: bool = true;
2763
2764 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2765 run.alias("build-manifest")
2766 }
2767
2768 fn make_run(run: RunConfig<'_>) {
2769 run.builder.ensure(BuildManifest { target: run.target });
2770 }
2771
2772 fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
2773 let build_manifest =
2777 builder.ensure(tool::BuildManifest::new(builder, builder.config.host_target));
2778
2779 let tarball = Tarball::new(builder, "build-manifest", &self.target.triple);
2780 tarball.add_file(&build_manifest.tool_path, "bin", FileType::Executable);
2781 tarball.generate()
2782 }
2783
2784 fn metadata(&self) -> Option<StepMetadata> {
2785 Some(StepMetadata::dist("build-manifest", self.target))
2786 }
2787}
2788
2789#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2795pub struct ReproducibleArtifacts {
2796 target: TargetSelection,
2797}
2798
2799impl Step for ReproducibleArtifacts {
2800 type Output = Option<GeneratedTarball>;
2801 const IS_HOST: bool = true;
2802
2803 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2804 run.alias("reproducible-artifacts")
2805 }
2806
2807 fn is_default_step(_builder: &Builder<'_>) -> bool {
2808 true
2809 }
2810
2811 fn make_run(run: RunConfig<'_>) {
2812 run.builder.ensure(ReproducibleArtifacts { target: run.target });
2813 }
2814
2815 fn run(self, builder: &Builder<'_>) -> Self::Output {
2816 let mut added_anything = false;
2817 let tarball = Tarball::new(builder, "reproducible-artifacts", &self.target.triple);
2818 if let Some(path) = builder.config.rust_profile_use.as_ref() {
2819 tarball.add_file(path, ".", FileType::Regular);
2820 added_anything = true;
2821 }
2822 if let Some(path) = builder.config.llvm_profile_use.as_ref() {
2823 tarball.add_file(path, ".", FileType::Regular);
2824 added_anything = true;
2825 }
2826 for profile in &builder.config.reproducible_artifacts {
2827 tarball.add_file(profile, ".", FileType::Regular);
2828 added_anything = true;
2829 }
2830 if added_anything { Some(tarball.generate()) } else { None }
2831 }
2832
2833 fn metadata(&self) -> Option<StepMetadata> {
2834 Some(StepMetadata::dist("reproducible-artifacts", self.target))
2835 }
2836}
2837
2838#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2842pub struct Gcc {
2843 target: TargetSelection,
2844}
2845
2846impl Step for Gcc {
2847 type Output = GeneratedTarball;
2848
2849 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2850 run.alias("gcc")
2851 }
2852
2853 fn make_run(run: RunConfig<'_>) {
2854 run.builder.ensure(Gcc { target: run.target });
2855 }
2856
2857 fn run(self, builder: &Builder<'_>) -> Self::Output {
2858 let tarball = Tarball::new(builder, "gcc", &self.target.triple);
2859 let output = builder.ensure(super::gcc::Gcc { target: self.target });
2860 tarball.add_file(&output.libgccjit, "lib", FileType::NativeLibrary);
2861 tarball.generate()
2862 }
2863
2864 fn metadata(&self) -> Option<StepMetadata> {
2865 Some(StepMetadata::dist("gcc", self.target))
2866 }
2867}