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