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