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 for src_dir in src_dirs {
922 assert!(Path::new(src_dir).is_relative());
923 }
924
925 if builder.config.dry_run() {
928 return;
929 }
930
931 fn filter_fn(exclude_dirs: &[&str], dir: &str, path: &Path) -> bool {
932 let spath = match path.to_str() {
934 Some(path) => path,
935 None => return false,
936 };
937 if spath.ends_with('~') || spath.ends_with(".pyc") {
938 return false;
939 }
940 let spath = spath.replace("\\", "/");
942
943 static LLVM_PROJECTS: &[&str] = &[
944 "llvm-project/clang",
945 "llvm-project/libunwind",
946 "llvm-project/lld",
947 "llvm-project/lldb",
948 "llvm-project/llvm",
949 "llvm-project/compiler-rt",
950 "llvm-project/cmake",
951 "llvm-project/runtimes",
952 "llvm-project/third-party",
953 ];
954 if spath.starts_with("llvm-project") && spath != "llvm-project" {
955 if !LLVM_PROJECTS.iter().any(|path| spath.starts_with(path)) {
956 return false;
957 }
958
959 if spath.starts_with("llvm-project/third-party")
961 && spath != "llvm-project/third-party"
962 && !spath.starts_with("llvm-project/third-party/siphash")
963 {
964 return false;
965 }
966
967 if spath.starts_with("llvm-project/llvm/test")
968 && (spath.ends_with(".ll") || spath.ends_with(".td") || spath.ends_with(".s"))
969 {
970 return false;
971 }
972 }
973
974 if spath.starts_with("tools/cargo/tests") {
976 return true;
977 }
978
979 if !exclude_dirs.is_empty() {
980 let full_path = Path::new(dir).join(path);
981 if exclude_dirs.iter().any(|excl| full_path == Path::new(excl)) {
982 return false;
983 }
984 }
985
986 static EXCLUDES: &[&str] = &[
987 "CVS",
988 "RCS",
989 "SCCS",
990 ".git",
991 ".gitignore",
992 ".gitmodules",
993 ".gitattributes",
994 ".cvsignore",
995 ".svn",
996 ".arch-ids",
997 "{arch}",
998 "=RELEASE-ID",
999 "=meta-update",
1000 "=update",
1001 ".bzr",
1002 ".bzrignore",
1003 ".bzrtags",
1004 ".hg",
1005 ".hgignore",
1006 ".hgrags",
1007 "_darcs",
1008 ];
1009
1010 let last_component = path.iter().next_back().map(|s| s.to_str().unwrap()).unwrap();
1017 !EXCLUDES.contains(&last_component)
1018 }
1019
1020 for item in src_dirs {
1022 let dst = &dst_dir.join(item);
1023 t!(fs::create_dir_all(dst));
1024 builder
1025 .cp_link_filtered(&base.join(item), dst, &|path| filter_fn(exclude_dirs, item, path));
1026 }
1027}
1028
1029#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
1030pub struct Src;
1031
1032impl Step for Src {
1033 type Output = GeneratedTarball;
1035 const DEFAULT: bool = true;
1036 const IS_HOST: bool = true;
1037
1038 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1039 run.alias("rust-src")
1040 }
1041
1042 fn make_run(run: RunConfig<'_>) {
1043 run.builder.ensure(Src);
1044 }
1045
1046 fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
1048 if !builder.config.dry_run() {
1049 builder.require_submodule("src/llvm-project", None);
1050 }
1051
1052 let tarball = Tarball::new_targetless(builder, "rust-src");
1053
1054 let dst_src = tarball.image_dir().join("lib/rustlib/src/rust");
1062
1063 copy_src_dirs(
1066 builder,
1067 &builder.src,
1068 &["library", "src/llvm-project/libunwind"],
1069 &[
1070 "library/backtrace/crates",
1073 "library/stdarch/Cargo.toml",
1076 "library/stdarch/crates/stdarch-verify",
1077 "library/stdarch/crates/intrinsic-test",
1078 ],
1079 &dst_src,
1080 );
1081
1082 tarball.generate()
1083 }
1084
1085 fn metadata(&self) -> Option<StepMetadata> {
1086 Some(StepMetadata::dist("src", TargetSelection::default()))
1087 }
1088}
1089
1090#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
1091pub struct PlainSourceTarball;
1092
1093impl Step for PlainSourceTarball {
1094 type Output = GeneratedTarball;
1096 const DEFAULT: bool = true;
1097 const IS_HOST: bool = true;
1098
1099 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1100 let builder = run.builder;
1101 run.alias("rustc-src").default_condition(builder.config.rust_dist_src)
1102 }
1103
1104 fn make_run(run: RunConfig<'_>) {
1105 run.builder.ensure(PlainSourceTarball);
1106 }
1107
1108 fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
1110 let mut tarball = Tarball::new(builder, "rustc", "src");
1115 tarball.permit_symlinks(true);
1116 let plain_dst_src = tarball.image_dir();
1117
1118 let src_files = [
1120 ".gitmodules",
1122 "CONTRIBUTING.md",
1123 "COPYRIGHT",
1124 "Cargo.lock",
1125 "Cargo.toml",
1126 "LICENSE-APACHE",
1127 "LICENSE-MIT",
1128 "README.md",
1129 "RELEASES.md",
1130 "REUSE.toml",
1131 "bootstrap.example.toml",
1132 "configure",
1133 "license-metadata.json",
1134 "package-lock.json",
1135 "package.json",
1136 "x",
1137 "x.ps1",
1138 "x.py",
1139 ];
1141 let src_dirs = ["src", "compiler", "library", "tests", "LICENSES"];
1142
1143 copy_src_dirs(
1144 builder,
1145 &builder.src,
1146 &src_dirs,
1147 &[
1148 "src/gcc",
1152 ],
1153 plain_dst_src,
1154 );
1155 if !builder.config.dry_run() {
1160 builder.create_dir(&plain_dst_src.join("src/gcc"));
1161 t!(std::fs::write(
1162 plain_dst_src.join("src/gcc/notice.txt"),
1163 "The GCC source code is not included due to unclear licensing implications\n"
1164 ));
1165 }
1166
1167 for item in &src_files {
1169 builder.copy_link(
1170 &builder.src.join(item),
1171 &plain_dst_src.join(item),
1172 FileType::Regular,
1173 );
1174 }
1175
1176 builder.create(&plain_dst_src.join("version"), &builder.rust_version());
1178
1179 let write_git_info = |info: Option<&Info>, path: &Path| {
1181 if let Some(info) = info {
1182 t!(std::fs::create_dir_all(path));
1183 channel::write_commit_hash_file(path, &info.sha);
1184 channel::write_commit_info_file(path, info);
1185 }
1186 };
1187 write_git_info(builder.rust_info().info(), plain_dst_src);
1188 write_git_info(builder.cargo_info.info(), &plain_dst_src.join("./src/tools/cargo"));
1189
1190 if builder.config.dist_vendor {
1191 builder.require_and_update_all_submodules();
1192
1193 let pkgs_for_pgo_training = build_helper::LLVM_PGO_CRATES
1195 .iter()
1196 .chain(build_helper::RUSTC_PGO_CRATES)
1197 .map(|pkg| {
1198 let mut manifest_path =
1199 builder.src.join("./src/tools/rustc-perf/collector/compile-benchmarks");
1200 manifest_path.push(pkg);
1201 manifest_path.push("Cargo.toml");
1202 manifest_path
1203 });
1204
1205 let vendor = builder.ensure(Vendor {
1207 sync_args: pkgs_for_pgo_training.collect(),
1208 versioned_dirs: true,
1209 root_dir: plain_dst_src.into(),
1210 output_dir: VENDOR_DIR.into(),
1211 });
1212
1213 let cargo_config_dir = plain_dst_src.join(".cargo");
1214 builder.create_dir(&cargo_config_dir);
1215 builder.create(&cargo_config_dir.join("config.toml"), &vendor.config);
1216 }
1217
1218 for entry in walkdir::WalkDir::new(tarball.image_dir())
1222 .follow_links(true)
1223 .into_iter()
1224 .filter_map(|e| e.ok())
1225 {
1226 if entry.path().is_dir() && entry.path().file_name() == Some(OsStr::new("__pycache__"))
1227 {
1228 t!(fs::remove_dir_all(entry.path()));
1229 }
1230 }
1231
1232 tarball.bare()
1233 }
1234}
1235
1236#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
1237pub struct Cargo {
1238 pub build_compiler: Compiler,
1239 pub target: TargetSelection,
1240}
1241
1242impl Step for Cargo {
1243 type Output = Option<GeneratedTarball>;
1244 const DEFAULT: bool = true;
1245 const IS_HOST: bool = true;
1246
1247 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1248 let default = should_build_extended_tool(run.builder, "cargo");
1249 run.alias("cargo").default_condition(default)
1250 }
1251
1252 fn make_run(run: RunConfig<'_>) {
1253 run.builder.ensure(Cargo {
1254 build_compiler: run.builder.compiler_for(
1255 run.builder.top_stage,
1256 run.builder.config.host_target,
1257 run.target,
1258 ),
1259 target: run.target,
1260 });
1261 }
1262
1263 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1264 let build_compiler = self.build_compiler;
1265 let target = self.target;
1266
1267 let cargo = builder.ensure(tool::Cargo::from_build_compiler(build_compiler, target));
1268 let src = builder.src.join("src/tools/cargo");
1269 let etc = src.join("src/etc");
1270
1271 let mut tarball = Tarball::new(builder, "cargo", &target.triple);
1273 tarball.set_overlay(OverlayKind::Cargo);
1274
1275 tarball.add_file(&cargo.tool_path, "bin", FileType::Executable);
1276 tarball.add_file(etc.join("_cargo"), "share/zsh/site-functions", FileType::Regular);
1277 tarball.add_renamed_file(
1278 etc.join("cargo.bashcomp.sh"),
1279 "etc/bash_completion.d",
1280 "cargo",
1281 FileType::Regular,
1282 );
1283 tarball.add_dir(etc.join("man"), "share/man/man1");
1284 tarball.add_legal_and_readme_to("share/doc/cargo");
1285
1286 Some(tarball.generate())
1287 }
1288}
1289
1290#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
1291pub struct RustAnalyzer {
1292 pub build_compiler: Compiler,
1293 pub target: TargetSelection,
1294}
1295
1296impl Step for RustAnalyzer {
1297 type Output = Option<GeneratedTarball>;
1298 const DEFAULT: bool = true;
1299 const IS_HOST: bool = true;
1300
1301 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1302 let default = should_build_extended_tool(run.builder, "rust-analyzer");
1303 run.alias("rust-analyzer").default_condition(default)
1304 }
1305
1306 fn make_run(run: RunConfig<'_>) {
1307 run.builder.ensure(RustAnalyzer {
1308 build_compiler: run.builder.compiler_for(
1309 run.builder.top_stage,
1310 run.builder.config.host_target,
1311 run.target,
1312 ),
1313 target: run.target,
1314 });
1315 }
1316
1317 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1318 let target = self.target;
1319 let compilers =
1320 RustcPrivateCompilers::from_build_compiler(builder, self.build_compiler, self.target);
1321
1322 let rust_analyzer = builder.ensure(tool::RustAnalyzer::from_compilers(compilers));
1323
1324 let mut tarball = Tarball::new(builder, "rust-analyzer", &target.triple);
1325 tarball.set_overlay(OverlayKind::RustAnalyzer);
1326 tarball.is_preview(true);
1327 tarball.add_file(&rust_analyzer.tool_path, "bin", FileType::Executable);
1328 tarball.add_legal_and_readme_to("share/doc/rust-analyzer");
1329 Some(tarball.generate())
1330 }
1331}
1332
1333#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1334pub struct Clippy {
1335 pub build_compiler: Compiler,
1336 pub target: TargetSelection,
1337}
1338
1339impl Step for Clippy {
1340 type Output = Option<GeneratedTarball>;
1341 const DEFAULT: bool = true;
1342 const IS_HOST: bool = true;
1343
1344 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1345 let default = should_build_extended_tool(run.builder, "clippy");
1346 run.alias("clippy").default_condition(default)
1347 }
1348
1349 fn make_run(run: RunConfig<'_>) {
1350 run.builder.ensure(Clippy {
1351 build_compiler: run.builder.compiler_for(
1352 run.builder.top_stage,
1353 run.builder.config.host_target,
1354 run.target,
1355 ),
1356 target: run.target,
1357 });
1358 }
1359
1360 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1361 let target = self.target;
1362 let compilers =
1363 RustcPrivateCompilers::from_build_compiler(builder, self.build_compiler, target);
1364
1365 let clippy = builder.ensure(tool::Clippy::from_compilers(compilers));
1369 let cargoclippy = builder.ensure(tool::CargoClippy::from_compilers(compilers));
1370
1371 let mut tarball = Tarball::new(builder, "clippy", &target.triple);
1372 tarball.set_overlay(OverlayKind::Clippy);
1373 tarball.is_preview(true);
1374 tarball.add_file(&clippy.tool_path, "bin", FileType::Executable);
1375 tarball.add_file(&cargoclippy.tool_path, "bin", FileType::Executable);
1376 tarball.add_legal_and_readme_to("share/doc/clippy");
1377 Some(tarball.generate())
1378 }
1379}
1380
1381#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1382pub struct Miri {
1383 pub build_compiler: Compiler,
1384 pub target: TargetSelection,
1385}
1386
1387impl Step for Miri {
1388 type Output = Option<GeneratedTarball>;
1389 const DEFAULT: bool = true;
1390 const IS_HOST: bool = true;
1391
1392 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1393 let default = should_build_extended_tool(run.builder, "miri");
1394 run.alias("miri").default_condition(default)
1395 }
1396
1397 fn make_run(run: RunConfig<'_>) {
1398 run.builder.ensure(Miri {
1399 build_compiler: run.builder.compiler_for(
1400 run.builder.top_stage,
1401 run.builder.config.host_target,
1402 run.target,
1403 ),
1404 target: run.target,
1405 });
1406 }
1407
1408 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1409 if !builder.build.unstable_features() {
1413 return None;
1414 }
1415
1416 let compilers =
1417 RustcPrivateCompilers::from_build_compiler(builder, self.build_compiler, self.target);
1418 let miri = builder.ensure(tool::Miri::from_compilers(compilers));
1419 let cargomiri = builder.ensure(tool::CargoMiri::from_compilers(compilers));
1420
1421 let mut tarball = Tarball::new(builder, "miri", &self.target.triple);
1422 tarball.set_overlay(OverlayKind::Miri);
1423 tarball.is_preview(true);
1424 tarball.add_file(&miri.tool_path, "bin", FileType::Executable);
1425 tarball.add_file(&cargomiri.tool_path, "bin", FileType::Executable);
1426 tarball.add_legal_and_readme_to("share/doc/miri");
1427 Some(tarball.generate())
1428 }
1429}
1430
1431#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1432pub struct CraneliftCodegenBackend {
1433 pub build_compiler: Compiler,
1434 pub target: TargetSelection,
1435}
1436
1437impl Step for CraneliftCodegenBackend {
1438 type Output = Option<GeneratedTarball>;
1439 const DEFAULT: bool = true;
1440 const IS_HOST: bool = true;
1441
1442 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1443 let clif_enabled_by_default = run
1448 .builder
1449 .config
1450 .enabled_codegen_backends(run.builder.host_target)
1451 .contains(&CodegenBackendKind::Cranelift);
1452 run.alias("rustc_codegen_cranelift").default_condition(clif_enabled_by_default)
1453 }
1454
1455 fn make_run(run: RunConfig<'_>) {
1456 run.builder.ensure(CraneliftCodegenBackend {
1457 build_compiler: run.builder.compiler_for(
1458 run.builder.top_stage,
1459 run.builder.config.host_target,
1460 run.target,
1461 ),
1462 target: run.target,
1463 });
1464 }
1465
1466 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1467 if !builder.build.unstable_features() {
1471 return None;
1472 }
1473
1474 let target = self.target;
1475 let compilers =
1476 RustcPrivateCompilers::from_build_compiler(builder, self.build_compiler, target);
1477 if !target_supports_cranelift_backend(target) {
1478 builder.info("target not supported by rustc_codegen_cranelift. skipping");
1479 return None;
1480 }
1481
1482 let mut tarball = Tarball::new(builder, "rustc-codegen-cranelift", &target.triple);
1483 tarball.set_overlay(OverlayKind::RustcCodegenCranelift);
1484 tarball.is_preview(true);
1485 tarball.add_legal_and_readme_to("share/doc/rustc_codegen_cranelift");
1486
1487 let stamp = builder.ensure(compile::CraneliftCodegenBackend { compilers });
1488
1489 if builder.config.dry_run() {
1490 return None;
1491 }
1492
1493 let backends_dst = builder.sysroot_codegen_backends(compilers.target_compiler());
1495 let backends_rel = backends_dst
1496 .strip_prefix(builder.sysroot(compilers.target_compiler()))
1497 .unwrap()
1498 .strip_prefix(builder.sysroot_libdir_relative(compilers.target_compiler()))
1499 .unwrap();
1500 let backends_dst = PathBuf::from("lib").join(backends_rel);
1502
1503 let codegen_backend_dylib = get_codegen_backend_file(&stamp);
1504 tarball.add_renamed_file(
1505 &codegen_backend_dylib,
1506 &backends_dst,
1507 &normalize_codegen_backend_name(builder, &codegen_backend_dylib),
1508 FileType::NativeLibrary,
1509 );
1510
1511 Some(tarball.generate())
1512 }
1513
1514 fn metadata(&self) -> Option<StepMetadata> {
1515 Some(
1516 StepMetadata::dist("rustc_codegen_cranelift", self.build_compiler.host)
1517 .built_by(self.build_compiler),
1518 )
1519 }
1520}
1521
1522#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1523pub struct Rustfmt {
1524 pub build_compiler: Compiler,
1525 pub target: TargetSelection,
1526}
1527
1528impl Step for Rustfmt {
1529 type Output = Option<GeneratedTarball>;
1530 const DEFAULT: bool = true;
1531 const IS_HOST: bool = true;
1532
1533 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1534 let default = should_build_extended_tool(run.builder, "rustfmt");
1535 run.alias("rustfmt").default_condition(default)
1536 }
1537
1538 fn make_run(run: RunConfig<'_>) {
1539 run.builder.ensure(Rustfmt {
1540 build_compiler: run.builder.compiler_for(
1541 run.builder.top_stage,
1542 run.builder.config.host_target,
1543 run.target,
1544 ),
1545 target: run.target,
1546 });
1547 }
1548
1549 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1550 let compilers =
1551 RustcPrivateCompilers::from_build_compiler(builder, self.build_compiler, self.target);
1552
1553 let rustfmt = builder.ensure(tool::Rustfmt::from_compilers(compilers));
1554 let cargofmt = builder.ensure(tool::Cargofmt::from_compilers(compilers));
1555
1556 let mut tarball = Tarball::new(builder, "rustfmt", &self.target.triple);
1557 tarball.set_overlay(OverlayKind::Rustfmt);
1558 tarball.is_preview(true);
1559 tarball.add_file(&rustfmt.tool_path, "bin", FileType::Executable);
1560 tarball.add_file(&cargofmt.tool_path, "bin", FileType::Executable);
1561 tarball.add_legal_and_readme_to("share/doc/rustfmt");
1562 Some(tarball.generate())
1563 }
1564}
1565
1566#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
1567pub struct Extended {
1568 stage: u32,
1569 host: TargetSelection,
1570 target: TargetSelection,
1571}
1572
1573impl Step for Extended {
1574 type Output = ();
1575 const DEFAULT: bool = true;
1576 const IS_HOST: bool = true;
1577
1578 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1579 let builder = run.builder;
1580 run.alias("extended").default_condition(builder.config.extended)
1581 }
1582
1583 fn make_run(run: RunConfig<'_>) {
1584 run.builder.ensure(Extended {
1585 stage: run.builder.top_stage,
1586 host: run.builder.config.host_target,
1587 target: run.target,
1588 });
1589 }
1590
1591 fn run(self, builder: &Builder<'_>) {
1593 let target = self.target;
1594 let stage = self.stage;
1595 let compiler = builder.compiler_for(self.stage, self.host, self.target);
1596
1597 builder.info(&format!("Dist extended stage{} ({})", compiler.stage, target));
1598
1599 let mut tarballs = Vec::new();
1600 let mut built_tools = HashSet::new();
1601 macro_rules! add_component {
1602 ($name:expr => $step:expr) => {
1603 if let Some(Some(tarball)) = builder.ensure_if_default($step, Kind::Dist) {
1604 tarballs.push(tarball);
1605 built_tools.insert($name);
1606 }
1607 };
1608 }
1609
1610 let target_compiler = builder.compiler(stage, target);
1611 tarballs.push(builder.ensure(Rustc { compiler: target_compiler }));
1616 tarballs.push(builder.ensure(Std { compiler, target }).expect("missing std"));
1617
1618 if target.is_windows_gnu() {
1619 tarballs.push(builder.ensure(Mingw { host: target }).expect("missing mingw"));
1620 }
1621
1622 add_component!("rust-docs" => Docs { host: target });
1623 add_component!("rust-json-docs" => JsonDocs { build_compiler: target_compiler, target });
1625 add_component!("cargo" => Cargo { build_compiler: compiler, target });
1626 add_component!("rustfmt" => Rustfmt { build_compiler: compiler, target });
1627 add_component!("rust-analyzer" => RustAnalyzer { build_compiler: compiler, target });
1628 add_component!("llvm-components" => LlvmTools { target });
1629 add_component!("clippy" => Clippy { build_compiler: compiler, target });
1630 add_component!("miri" => Miri { build_compiler: compiler, target });
1631 add_component!("analysis" => Analysis { compiler, target });
1632 add_component!("rustc-codegen-cranelift" => CraneliftCodegenBackend {
1633 build_compiler: compiler,
1634 target
1635 });
1636 add_component!("llvm-bitcode-linker" => LlvmBitcodeLinker {
1637 build_compiler: compiler,
1638 target
1639 });
1640
1641 let etc = builder.src.join("src/etc/installer");
1642
1643 if builder.config.dry_run() {
1645 return;
1646 }
1647
1648 let tarball = Tarball::new(builder, "rust", &target.triple);
1649 let generated = tarball.combine(&tarballs);
1650
1651 let tmp = tmpdir(builder).join("combined-tarball");
1652 let work = generated.work_dir();
1653
1654 let mut license = String::new();
1655 license += &builder.read(&builder.src.join("COPYRIGHT"));
1656 license += &builder.read(&builder.src.join("LICENSE-APACHE"));
1657 license += &builder.read(&builder.src.join("LICENSE-MIT"));
1658 license.push('\n');
1659 license.push('\n');
1660
1661 let rtf = r"{\rtf1\ansi\deff0{\fonttbl{\f0\fnil\fcharset0 Arial;}}\nowwrap\fs18";
1662 let mut rtf = rtf.to_string();
1663 rtf.push('\n');
1664 for line in license.lines() {
1665 rtf.push_str(line);
1666 rtf.push_str("\\line ");
1667 }
1668 rtf.push('}');
1669
1670 fn filter(contents: &str, marker: &str) -> String {
1671 let start = format!("tool-{marker}-start");
1672 let end = format!("tool-{marker}-end");
1673 let mut lines = Vec::new();
1674 let mut omitted = false;
1675 for line in contents.lines() {
1676 if line.contains(&start) {
1677 omitted = true;
1678 } else if line.contains(&end) {
1679 omitted = false;
1680 } else if !omitted {
1681 lines.push(line);
1682 }
1683 }
1684
1685 lines.join("\n")
1686 }
1687
1688 let xform = |p: &Path| {
1689 let mut contents = t!(fs::read_to_string(p));
1690 for tool in &["miri", "rust-docs"] {
1691 if !built_tools.contains(tool) {
1692 contents = filter(&contents, tool);
1693 }
1694 }
1695 let ret = tmp.join(p.file_name().unwrap());
1696 t!(fs::write(&ret, &contents));
1697 ret
1698 };
1699
1700 if target.contains("apple-darwin") {
1701 builder.info("building pkg installer");
1702 let pkg = tmp.join("pkg");
1703 let _ = fs::remove_dir_all(&pkg);
1704
1705 let pkgbuild = |component: &str| {
1706 let mut cmd = command("pkgbuild");
1707 cmd.arg("--identifier")
1708 .arg(format!("org.rust-lang.{component}"))
1709 .arg("--scripts")
1710 .arg(pkg.join(component))
1711 .arg("--nopayload")
1712 .arg(pkg.join(component).with_extension("pkg"));
1713 cmd.run(builder);
1714 };
1715
1716 let prepare = |name: &str| {
1717 builder.create_dir(&pkg.join(name));
1718 builder.cp_link_r(
1719 &work.join(format!("{}-{}", pkgname(builder, name), target.triple)),
1720 &pkg.join(name),
1721 );
1722 builder.install(&etc.join("pkg/postinstall"), &pkg.join(name), FileType::Script);
1723 pkgbuild(name);
1724 };
1725 prepare("rustc");
1726 prepare("cargo");
1727 prepare("rust-std");
1728 prepare("rust-analysis");
1729
1730 for tool in &[
1731 "clippy",
1732 "rustfmt",
1733 "rust-analyzer",
1734 "rust-docs",
1735 "miri",
1736 "rustc-codegen-cranelift",
1737 ] {
1738 if built_tools.contains(tool) {
1739 prepare(tool);
1740 }
1741 }
1742 builder.install(&etc.join("pkg/postinstall"), &pkg.join("uninstall"), FileType::Script);
1744 pkgbuild("uninstall");
1745
1746 builder.create_dir(&pkg.join("res"));
1747 builder.create(&pkg.join("res/LICENSE.txt"), &license);
1748 builder.install(&etc.join("gfx/rust-logo.png"), &pkg.join("res"), FileType::Regular);
1749 let mut cmd = command("productbuild");
1750 cmd.arg("--distribution")
1751 .arg(xform(&etc.join("pkg/Distribution.xml")))
1752 .arg("--resources")
1753 .arg(pkg.join("res"))
1754 .arg(distdir(builder).join(format!(
1755 "{}-{}.pkg",
1756 pkgname(builder, "rust"),
1757 target.triple
1758 )))
1759 .arg("--package-path")
1760 .arg(&pkg);
1761 let _time = timeit(builder);
1762 cmd.run(builder);
1763 }
1764
1765 if target.is_windows() && !target.contains("gnullvm") {
1767 let exe = tmp.join("exe");
1768 let _ = fs::remove_dir_all(&exe);
1769
1770 let prepare = |name: &str| {
1771 builder.create_dir(&exe.join(name));
1772 let dir = if name == "rust-std" || name == "rust-analysis" {
1773 format!("{}-{}", name, target.triple)
1774 } else if name == "rust-analyzer" {
1775 "rust-analyzer-preview".to_string()
1776 } else if name == "clippy" {
1777 "clippy-preview".to_string()
1778 } else if name == "rustfmt" {
1779 "rustfmt-preview".to_string()
1780 } else if name == "miri" {
1781 "miri-preview".to_string()
1782 } else if name == "rustc-codegen-cranelift" {
1783 unreachable!("cg_clif shouldn't be built for windows");
1786 } else {
1787 name.to_string()
1788 };
1789 builder.cp_link_r(
1790 &work.join(format!("{}-{}", pkgname(builder, name), target.triple)).join(dir),
1791 &exe.join(name),
1792 );
1793 builder.remove(&exe.join(name).join("manifest.in"));
1794 };
1795 prepare("rustc");
1796 prepare("cargo");
1797 prepare("rust-analysis");
1798 prepare("rust-std");
1799 for tool in &["clippy", "rustfmt", "rust-analyzer", "rust-docs", "miri"] {
1800 if built_tools.contains(tool) {
1801 prepare(tool);
1802 }
1803 }
1804 if target.is_windows_gnu() {
1805 prepare("rust-mingw");
1806 }
1807
1808 builder.install(&etc.join("gfx/rust-logo.ico"), &exe, FileType::Regular);
1809
1810 let wix_path = env::var_os("WIX")
1812 .expect("`WIX` environment variable must be set for generating MSI installer(s).");
1813 let wix = PathBuf::from(wix_path);
1814 let heat = wix.join("bin/heat.exe");
1815 let candle = wix.join("bin/candle.exe");
1816 let light = wix.join("bin/light.exe");
1817
1818 let heat_flags = ["-nologo", "-gg", "-sfrag", "-srd", "-sreg"];
1819 command(&heat)
1820 .current_dir(&exe)
1821 .arg("dir")
1822 .arg("rustc")
1823 .args(heat_flags)
1824 .arg("-cg")
1825 .arg("RustcGroup")
1826 .arg("-dr")
1827 .arg("Rustc")
1828 .arg("-var")
1829 .arg("var.RustcDir")
1830 .arg("-out")
1831 .arg(exe.join("RustcGroup.wxs"))
1832 .run(builder);
1833 if built_tools.contains("rust-docs") {
1834 command(&heat)
1835 .current_dir(&exe)
1836 .arg("dir")
1837 .arg("rust-docs")
1838 .args(heat_flags)
1839 .arg("-cg")
1840 .arg("DocsGroup")
1841 .arg("-dr")
1842 .arg("Docs")
1843 .arg("-var")
1844 .arg("var.DocsDir")
1845 .arg("-out")
1846 .arg(exe.join("DocsGroup.wxs"))
1847 .arg("-t")
1848 .arg(etc.join("msi/squash-components.xsl"))
1849 .run(builder);
1850 }
1851 command(&heat)
1852 .current_dir(&exe)
1853 .arg("dir")
1854 .arg("cargo")
1855 .args(heat_flags)
1856 .arg("-cg")
1857 .arg("CargoGroup")
1858 .arg("-dr")
1859 .arg("Cargo")
1860 .arg("-var")
1861 .arg("var.CargoDir")
1862 .arg("-out")
1863 .arg(exe.join("CargoGroup.wxs"))
1864 .arg("-t")
1865 .arg(etc.join("msi/remove-duplicates.xsl"))
1866 .run(builder);
1867 command(&heat)
1868 .current_dir(&exe)
1869 .arg("dir")
1870 .arg("rust-std")
1871 .args(heat_flags)
1872 .arg("-cg")
1873 .arg("StdGroup")
1874 .arg("-dr")
1875 .arg("Std")
1876 .arg("-var")
1877 .arg("var.StdDir")
1878 .arg("-out")
1879 .arg(exe.join("StdGroup.wxs"))
1880 .run(builder);
1881 if built_tools.contains("rust-analyzer") {
1882 command(&heat)
1883 .current_dir(&exe)
1884 .arg("dir")
1885 .arg("rust-analyzer")
1886 .args(heat_flags)
1887 .arg("-cg")
1888 .arg("RustAnalyzerGroup")
1889 .arg("-dr")
1890 .arg("RustAnalyzer")
1891 .arg("-var")
1892 .arg("var.RustAnalyzerDir")
1893 .arg("-out")
1894 .arg(exe.join("RustAnalyzerGroup.wxs"))
1895 .arg("-t")
1896 .arg(etc.join("msi/remove-duplicates.xsl"))
1897 .run(builder);
1898 }
1899 if built_tools.contains("clippy") {
1900 command(&heat)
1901 .current_dir(&exe)
1902 .arg("dir")
1903 .arg("clippy")
1904 .args(heat_flags)
1905 .arg("-cg")
1906 .arg("ClippyGroup")
1907 .arg("-dr")
1908 .arg("Clippy")
1909 .arg("-var")
1910 .arg("var.ClippyDir")
1911 .arg("-out")
1912 .arg(exe.join("ClippyGroup.wxs"))
1913 .arg("-t")
1914 .arg(etc.join("msi/remove-duplicates.xsl"))
1915 .run(builder);
1916 }
1917 if built_tools.contains("rustfmt") {
1918 command(&heat)
1919 .current_dir(&exe)
1920 .arg("dir")
1921 .arg("rustfmt")
1922 .args(heat_flags)
1923 .arg("-cg")
1924 .arg("RustFmtGroup")
1925 .arg("-dr")
1926 .arg("RustFmt")
1927 .arg("-var")
1928 .arg("var.RustFmtDir")
1929 .arg("-out")
1930 .arg(exe.join("RustFmtGroup.wxs"))
1931 .arg("-t")
1932 .arg(etc.join("msi/remove-duplicates.xsl"))
1933 .run(builder);
1934 }
1935 if built_tools.contains("miri") {
1936 command(&heat)
1937 .current_dir(&exe)
1938 .arg("dir")
1939 .arg("miri")
1940 .args(heat_flags)
1941 .arg("-cg")
1942 .arg("MiriGroup")
1943 .arg("-dr")
1944 .arg("Miri")
1945 .arg("-var")
1946 .arg("var.MiriDir")
1947 .arg("-out")
1948 .arg(exe.join("MiriGroup.wxs"))
1949 .arg("-t")
1950 .arg(etc.join("msi/remove-duplicates.xsl"))
1951 .run(builder);
1952 }
1953 command(&heat)
1954 .current_dir(&exe)
1955 .arg("dir")
1956 .arg("rust-analysis")
1957 .args(heat_flags)
1958 .arg("-cg")
1959 .arg("AnalysisGroup")
1960 .arg("-dr")
1961 .arg("Analysis")
1962 .arg("-var")
1963 .arg("var.AnalysisDir")
1964 .arg("-out")
1965 .arg(exe.join("AnalysisGroup.wxs"))
1966 .arg("-t")
1967 .arg(etc.join("msi/remove-duplicates.xsl"))
1968 .run(builder);
1969 if target.is_windows_gnu() {
1970 command(&heat)
1971 .current_dir(&exe)
1972 .arg("dir")
1973 .arg("rust-mingw")
1974 .args(heat_flags)
1975 .arg("-cg")
1976 .arg("GccGroup")
1977 .arg("-dr")
1978 .arg("Gcc")
1979 .arg("-var")
1980 .arg("var.GccDir")
1981 .arg("-out")
1982 .arg(exe.join("GccGroup.wxs"))
1983 .run(builder);
1984 }
1985
1986 let candle = |input: &Path| {
1987 let output = exe.join(input.file_stem().unwrap()).with_extension("wixobj");
1988 let arch = if target.contains("x86_64") { "x64" } else { "x86" };
1989 let mut cmd = command(&candle);
1990 cmd.current_dir(&exe)
1991 .arg("-nologo")
1992 .arg("-dRustcDir=rustc")
1993 .arg("-dCargoDir=cargo")
1994 .arg("-dStdDir=rust-std")
1995 .arg("-dAnalysisDir=rust-analysis")
1996 .arg("-arch")
1997 .arg(arch)
1998 .arg("-out")
1999 .arg(&output)
2000 .arg(input);
2001 add_env(builder, &mut cmd, target, &built_tools);
2002
2003 if built_tools.contains("clippy") {
2004 cmd.arg("-dClippyDir=clippy");
2005 }
2006 if built_tools.contains("rustfmt") {
2007 cmd.arg("-dRustFmtDir=rustfmt");
2008 }
2009 if built_tools.contains("rust-docs") {
2010 cmd.arg("-dDocsDir=rust-docs");
2011 }
2012 if built_tools.contains("rust-analyzer") {
2013 cmd.arg("-dRustAnalyzerDir=rust-analyzer");
2014 }
2015 if built_tools.contains("miri") {
2016 cmd.arg("-dMiriDir=miri");
2017 }
2018 if target.is_windows_gnu() {
2019 cmd.arg("-dGccDir=rust-mingw");
2020 }
2021 cmd.run(builder);
2022 };
2023 candle(&xform(&etc.join("msi/rust.wxs")));
2024 candle(&etc.join("msi/ui.wxs"));
2025 candle(&etc.join("msi/rustwelcomedlg.wxs"));
2026 candle("RustcGroup.wxs".as_ref());
2027 if built_tools.contains("rust-docs") {
2028 candle("DocsGroup.wxs".as_ref());
2029 }
2030 candle("CargoGroup.wxs".as_ref());
2031 candle("StdGroup.wxs".as_ref());
2032 if built_tools.contains("clippy") {
2033 candle("ClippyGroup.wxs".as_ref());
2034 }
2035 if built_tools.contains("rustfmt") {
2036 candle("RustFmtGroup.wxs".as_ref());
2037 }
2038 if built_tools.contains("miri") {
2039 candle("MiriGroup.wxs".as_ref());
2040 }
2041 if built_tools.contains("rust-analyzer") {
2042 candle("RustAnalyzerGroup.wxs".as_ref());
2043 }
2044 candle("AnalysisGroup.wxs".as_ref());
2045
2046 if target.is_windows_gnu() {
2047 candle("GccGroup.wxs".as_ref());
2048 }
2049
2050 builder.create(&exe.join("LICENSE.rtf"), &rtf);
2051 builder.install(&etc.join("gfx/banner.bmp"), &exe, FileType::Regular);
2052 builder.install(&etc.join("gfx/dialogbg.bmp"), &exe, FileType::Regular);
2053
2054 builder.info(&format!("building `msi` installer with {light:?}"));
2055 let filename = format!("{}-{}.msi", pkgname(builder, "rust"), target.triple);
2056 let mut cmd = command(&light);
2057 cmd.arg("-nologo")
2058 .arg("-ext")
2059 .arg("WixUIExtension")
2060 .arg("-ext")
2061 .arg("WixUtilExtension")
2062 .arg("-out")
2063 .arg(exe.join(&filename))
2064 .arg("rust.wixobj")
2065 .arg("ui.wixobj")
2066 .arg("rustwelcomedlg.wixobj")
2067 .arg("RustcGroup.wixobj")
2068 .arg("CargoGroup.wixobj")
2069 .arg("StdGroup.wixobj")
2070 .arg("AnalysisGroup.wixobj")
2071 .current_dir(&exe);
2072
2073 if built_tools.contains("clippy") {
2074 cmd.arg("ClippyGroup.wixobj");
2075 }
2076 if built_tools.contains("rustfmt") {
2077 cmd.arg("RustFmtGroup.wixobj");
2078 }
2079 if built_tools.contains("miri") {
2080 cmd.arg("MiriGroup.wixobj");
2081 }
2082 if built_tools.contains("rust-analyzer") {
2083 cmd.arg("RustAnalyzerGroup.wixobj");
2084 }
2085 if built_tools.contains("rust-docs") {
2086 cmd.arg("DocsGroup.wixobj");
2087 }
2088
2089 if target.is_windows_gnu() {
2090 cmd.arg("GccGroup.wixobj");
2091 }
2092 cmd.arg("-sice:ICE57");
2094
2095 let _time = timeit(builder);
2096 cmd.run(builder);
2097
2098 if !builder.config.dry_run() {
2099 t!(move_file(exe.join(&filename), distdir(builder).join(&filename)));
2100 }
2101 }
2102 }
2103}
2104
2105fn add_env(
2106 builder: &Builder<'_>,
2107 cmd: &mut BootstrapCommand,
2108 target: TargetSelection,
2109 built_tools: &HashSet<&'static str>,
2110) {
2111 let mut parts = builder.version.split('.');
2112 cmd.env("CFG_RELEASE_INFO", builder.rust_version())
2113 .env("CFG_RELEASE_NUM", &builder.version)
2114 .env("CFG_RELEASE", builder.rust_release())
2115 .env("CFG_VER_MAJOR", parts.next().unwrap())
2116 .env("CFG_VER_MINOR", parts.next().unwrap())
2117 .env("CFG_VER_PATCH", parts.next().unwrap())
2118 .env("CFG_VER_BUILD", "0") .env("CFG_PACKAGE_VERS", builder.rust_package_vers())
2120 .env("CFG_PACKAGE_NAME", pkgname(builder, "rust"))
2121 .env("CFG_BUILD", target.triple)
2122 .env("CFG_CHANNEL", &builder.config.channel);
2123
2124 if target.contains("windows-gnullvm") {
2125 cmd.env("CFG_MINGW", "1").env("CFG_ABI", "LLVM");
2126 } else if target.is_windows_gnu() {
2127 cmd.env("CFG_MINGW", "1").env("CFG_ABI", "GNU");
2128 } else {
2129 cmd.env("CFG_MINGW", "0").env("CFG_ABI", "MSVC");
2130 }
2131
2132 let mut define_optional_tool = |tool_name: &str, env_name: &str| {
2134 cmd.env(env_name, if built_tools.contains(tool_name) { "1" } else { "0" });
2135 };
2136 define_optional_tool("rustfmt", "CFG_RUSTFMT");
2137 define_optional_tool("clippy", "CFG_CLIPPY");
2138 define_optional_tool("miri", "CFG_MIRI");
2139 define_optional_tool("rust-analyzer", "CFG_RA");
2140}
2141
2142fn install_llvm_file(
2143 builder: &Builder<'_>,
2144 source: &Path,
2145 destination: &Path,
2146 install_symlink: bool,
2147) {
2148 if builder.config.dry_run() {
2149 return;
2150 }
2151
2152 if source.is_symlink() {
2153 builder.install(&t!(fs::canonicalize(source)), destination, FileType::NativeLibrary);
2156
2157 let full_dest = destination.join(source.file_name().unwrap());
2158 if install_symlink {
2159 builder.copy_link(source, &full_dest, FileType::NativeLibrary);
2162 } else {
2163 let link = t!(fs::read_link(source));
2167 let mut linker_script = t!(fs::File::create(full_dest));
2168 t!(write!(linker_script, "INPUT({})\n", link.display()));
2169
2170 let meta = t!(fs::metadata(source));
2173 if let Ok(mtime) = meta.modified() {
2174 t!(linker_script.set_modified(mtime));
2175 }
2176 }
2177 } else {
2178 builder.install(source, destination, FileType::NativeLibrary);
2179 }
2180}
2181
2182#[cfg_attr(
2186 feature = "tracing",
2187 instrument(
2188 level = "trace",
2189 name = "maybe_install_llvm",
2190 skip_all,
2191 fields(target = ?target, dst_libdir = ?dst_libdir, install_symlink = install_symlink),
2192 ),
2193)]
2194fn maybe_install_llvm(
2195 builder: &Builder<'_>,
2196 target: TargetSelection,
2197 dst_libdir: &Path,
2198 install_symlink: bool,
2199) -> bool {
2200 if builder.config.is_system_llvm(target) {
2217 trace!("system LLVM requested, no install");
2218 return false;
2219 }
2220
2221 if target.contains("apple-darwin") && builder.llvm_link_shared() {
2227 let src_libdir = builder.llvm_out(target).join("lib");
2228 let llvm_dylib_path = src_libdir.join("libLLVM.dylib");
2229 if llvm_dylib_path.exists() {
2230 builder.install(&llvm_dylib_path, dst_libdir, FileType::NativeLibrary);
2231 }
2232 !builder.config.dry_run()
2233 } else if let llvm::LlvmBuildStatus::AlreadyBuilt(llvm::LlvmResult { llvm_config, .. }) =
2234 llvm::prebuilt_llvm_config(builder, target, true)
2235 {
2236 trace!("LLVM already built, installing LLVM files");
2237 let mut cmd = command(llvm_config);
2238 cmd.arg("--libfiles");
2239 builder.verbose(|| println!("running {cmd:?}"));
2240 let files = cmd.run_capture_stdout(builder).stdout();
2241 let build_llvm_out = &builder.llvm_out(builder.config.host_target);
2242 let target_llvm_out = &builder.llvm_out(target);
2243 for file in files.trim_end().split(' ') {
2244 let file = if let Ok(relative_path) = Path::new(file).strip_prefix(build_llvm_out) {
2246 target_llvm_out.join(relative_path)
2247 } else {
2248 PathBuf::from(file)
2249 };
2250 install_llvm_file(builder, &file, dst_libdir, install_symlink);
2251 }
2252 !builder.config.dry_run()
2253 } else {
2254 false
2255 }
2256}
2257
2258#[cfg_attr(
2260 feature = "tracing",
2261 instrument(
2262 level = "trace",
2263 name = "maybe_install_llvm_target",
2264 skip_all,
2265 fields(
2266 llvm_link_shared = ?builder.llvm_link_shared(),
2267 target = ?target,
2268 sysroot = ?sysroot,
2269 ),
2270 ),
2271)]
2272pub fn maybe_install_llvm_target(builder: &Builder<'_>, target: TargetSelection, sysroot: &Path) {
2273 let dst_libdir = sysroot.join("lib/rustlib").join(target).join("lib");
2274 if builder.llvm_link_shared() {
2278 maybe_install_llvm(builder, target, &dst_libdir, false);
2279 }
2280}
2281
2282#[cfg_attr(
2284 feature = "tracing",
2285 instrument(
2286 level = "trace",
2287 name = "maybe_install_llvm_runtime",
2288 skip_all,
2289 fields(
2290 llvm_link_shared = ?builder.llvm_link_shared(),
2291 target = ?target,
2292 sysroot = ?sysroot,
2293 ),
2294 ),
2295)]
2296pub fn maybe_install_llvm_runtime(builder: &Builder<'_>, target: TargetSelection, sysroot: &Path) {
2297 let dst_libdir = sysroot.join(builder.sysroot_libdir_relative(Compiler::new(1, target)));
2298 if builder.llvm_link_shared() {
2302 maybe_install_llvm(builder, target, &dst_libdir, false);
2303 }
2304}
2305
2306#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2307pub struct LlvmTools {
2308 pub target: TargetSelection,
2309}
2310
2311impl Step for LlvmTools {
2312 type Output = Option<GeneratedTarball>;
2313 const IS_HOST: bool = true;
2314 const DEFAULT: bool = true;
2315
2316 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2317 let default = should_build_extended_tool(run.builder, "llvm-tools");
2318
2319 let mut run = run.alias("llvm-tools");
2320 for tool in LLVM_TOOLS {
2321 run = run.alias(tool);
2322 }
2323
2324 run.default_condition(default)
2325 }
2326
2327 fn make_run(run: RunConfig<'_>) {
2328 run.builder.ensure(LlvmTools { target: run.target });
2329 }
2330
2331 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2332 fn tools_to_install(paths: &[PathBuf]) -> Vec<&'static str> {
2333 let mut tools = vec![];
2334
2335 for path in paths {
2336 let path = path.to_str().unwrap();
2337
2338 if path == "llvm-tools" {
2340 return LLVM_TOOLS.to_owned();
2341 }
2342
2343 for tool in LLVM_TOOLS {
2344 if path == *tool {
2345 tools.push(*tool);
2346 }
2347 }
2348 }
2349
2350 if tools.is_empty() {
2352 tools = LLVM_TOOLS.to_owned();
2353 }
2354
2355 tools
2356 }
2357
2358 let target = self.target;
2359
2360 if let Some(config) = builder.config.target_config.get(&target)
2362 && !builder.config.llvm_from_ci
2363 && config.llvm_config.is_some()
2364 {
2365 builder.info(&format!("Skipping LlvmTools ({target}): external LLVM"));
2366 return None;
2367 }
2368
2369 if !builder.config.dry_run() {
2370 builder.require_submodule("src/llvm-project", None);
2371 }
2372
2373 builder.ensure(crate::core::build_steps::llvm::Llvm { target });
2374
2375 let mut tarball = Tarball::new(builder, "llvm-tools", &target.triple);
2376 tarball.set_overlay(OverlayKind::Llvm);
2377 tarball.is_preview(true);
2378
2379 if builder.config.llvm_tools_enabled {
2380 let src_bindir = builder.llvm_out(target).join("bin");
2382 let dst_bindir = format!("lib/rustlib/{}/bin", target.triple);
2383 for tool in tools_to_install(&builder.paths) {
2384 let exe = src_bindir.join(exe(tool, target));
2385 if !exe.exists() && builder.config.llvm_from_ci {
2387 eprintln!("{} does not exist; skipping copy", exe.display());
2388 continue;
2389 }
2390
2391 tarball.add_file(&exe, &dst_bindir, FileType::Executable);
2392 }
2393 }
2394
2395 maybe_install_llvm_target(builder, target, tarball.image_dir());
2400
2401 Some(tarball.generate())
2402 }
2403}
2404
2405#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
2408pub struct LlvmBitcodeLinker {
2409 pub build_compiler: Compiler,
2411 pub target: TargetSelection,
2413}
2414
2415impl Step for LlvmBitcodeLinker {
2416 type Output = Option<GeneratedTarball>;
2417 const DEFAULT: bool = true;
2418 const IS_HOST: bool = true;
2419
2420 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2421 let default = should_build_extended_tool(run.builder, "llvm-bitcode-linker");
2422 run.alias("llvm-bitcode-linker").default_condition(default)
2423 }
2424
2425 fn make_run(run: RunConfig<'_>) {
2426 run.builder.ensure(LlvmBitcodeLinker {
2427 build_compiler: tool::LlvmBitcodeLinker::get_build_compiler_for_target(
2428 run.builder,
2429 run.target,
2430 ),
2431 target: run.target,
2432 });
2433 }
2434
2435 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2436 let target = self.target;
2437
2438 let llbc_linker = builder
2439 .ensure(tool::LlvmBitcodeLinker::from_build_compiler(self.build_compiler, target));
2440
2441 let self_contained_bin_dir = format!("lib/rustlib/{}/bin/self-contained", target.triple);
2442
2443 let mut tarball = Tarball::new(builder, "llvm-bitcode-linker", &target.triple);
2445 tarball.set_overlay(OverlayKind::LlvmBitcodeLinker);
2446 tarball.is_preview(true);
2447
2448 tarball.add_file(&llbc_linker.tool_path, self_contained_bin_dir, FileType::Executable);
2449
2450 Some(tarball.generate())
2451 }
2452}
2453
2454#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2463pub struct RustDev {
2464 pub target: TargetSelection,
2465}
2466
2467impl Step for RustDev {
2468 type Output = Option<GeneratedTarball>;
2469 const DEFAULT: bool = true;
2470 const IS_HOST: bool = true;
2471
2472 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2473 run.alias("rust-dev")
2474 }
2475
2476 fn make_run(run: RunConfig<'_>) {
2477 run.builder.ensure(RustDev { target: run.target });
2478 }
2479
2480 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2481 let target = self.target;
2482
2483 if let Some(config) = builder.config.target_config.get(&target)
2485 && let Some(ref _s) = config.llvm_config
2486 {
2487 builder.info(&format!("Skipping RustDev ({target}): external LLVM"));
2488 return None;
2489 }
2490
2491 if !builder.config.dry_run() {
2492 builder.require_submodule("src/llvm-project", None);
2493 }
2494
2495 let mut tarball = Tarball::new(builder, "rust-dev", &target.triple);
2496 tarball.set_overlay(OverlayKind::Llvm);
2497 tarball.permit_symlinks(true);
2499
2500 builder.ensure(crate::core::build_steps::llvm::Llvm { target });
2501
2502 let src_bindir = builder.llvm_out(target).join("bin");
2503 if src_bindir.exists() {
2509 for entry in walkdir::WalkDir::new(&src_bindir) {
2510 let entry = t!(entry);
2511 if entry.file_type().is_file() && !entry.path_is_symlink() {
2512 let name = entry.file_name().to_str().unwrap();
2513 tarball.add_file(src_bindir.join(name), "bin", FileType::Executable);
2514 }
2515 }
2516 }
2517
2518 if builder.config.lld_enabled {
2519 let lld_out = builder.ensure(crate::core::build_steps::llvm::Lld { target });
2521
2522 let lld_path = lld_out.join("bin").join(exe("lld", target));
2524 if lld_path.exists() {
2525 tarball.add_file(&lld_path, "bin", FileType::Executable);
2526 }
2527 }
2528
2529 tarball.add_file(builder.llvm_filecheck(target), "bin", FileType::Executable);
2530
2531 tarball.add_dir(builder.llvm_out(target).join("include"), "include");
2535
2536 let dst_libdir = tarball.image_dir().join("lib");
2541 maybe_install_llvm(builder, target, &dst_libdir, true);
2542 let link_type = if builder.llvm_link_shared() { "dynamic" } else { "static" };
2543 t!(std::fs::write(tarball.image_dir().join("link-type.txt"), link_type), dst_libdir);
2544
2545 copy_src_dirs(
2549 builder,
2550 &builder.src.join("src").join("llvm-project"),
2551 &["compiler-rt"],
2552 &["compiler-rt/test"],
2555 tarball.image_dir(),
2556 );
2557
2558 Some(tarball.generate())
2559 }
2560}
2561
2562#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2566pub struct Bootstrap {
2567 pub target: TargetSelection,
2568}
2569
2570impl Step for Bootstrap {
2571 type Output = Option<GeneratedTarball>;
2572 const DEFAULT: bool = false;
2573 const IS_HOST: bool = true;
2574
2575 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2576 run.alias("bootstrap")
2577 }
2578
2579 fn make_run(run: RunConfig<'_>) {
2580 run.builder.ensure(Bootstrap { target: run.target });
2581 }
2582
2583 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2584 let target = self.target;
2585
2586 let tarball = Tarball::new(builder, "bootstrap", &target.triple);
2587
2588 let bootstrap_outdir = &builder.bootstrap_out;
2589 for file in &["bootstrap", "rustc", "rustdoc"] {
2590 tarball.add_file(
2591 bootstrap_outdir.join(exe(file, target)),
2592 "bootstrap/bin",
2593 FileType::Executable,
2594 );
2595 }
2596
2597 Some(tarball.generate())
2598 }
2599}
2600
2601#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2606pub struct BuildManifest {
2607 pub target: TargetSelection,
2608}
2609
2610impl Step for BuildManifest {
2611 type Output = GeneratedTarball;
2612 const DEFAULT: bool = false;
2613 const IS_HOST: bool = true;
2614
2615 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2616 run.alias("build-manifest")
2617 }
2618
2619 fn make_run(run: RunConfig<'_>) {
2620 run.builder.ensure(BuildManifest { target: run.target });
2621 }
2622
2623 fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
2624 let build_manifest = builder.tool_exe(Tool::BuildManifest);
2625
2626 let tarball = Tarball::new(builder, "build-manifest", &self.target.triple);
2627 tarball.add_file(&build_manifest, "bin", FileType::Executable);
2628 tarball.generate()
2629 }
2630}
2631
2632#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2638pub struct ReproducibleArtifacts {
2639 pub target: TargetSelection,
2640}
2641
2642impl Step for ReproducibleArtifacts {
2643 type Output = Option<GeneratedTarball>;
2644 const DEFAULT: bool = true;
2645 const IS_HOST: bool = true;
2646
2647 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2648 run.alias("reproducible-artifacts")
2649 }
2650
2651 fn make_run(run: RunConfig<'_>) {
2652 run.builder.ensure(ReproducibleArtifacts { target: run.target });
2653 }
2654
2655 fn run(self, builder: &Builder<'_>) -> Self::Output {
2656 let mut added_anything = false;
2657 let tarball = Tarball::new(builder, "reproducible-artifacts", &self.target.triple);
2658 if let Some(path) = builder.config.rust_profile_use.as_ref() {
2659 tarball.add_file(path, ".", FileType::Regular);
2660 added_anything = true;
2661 }
2662 if let Some(path) = builder.config.llvm_profile_use.as_ref() {
2663 tarball.add_file(path, ".", FileType::Regular);
2664 added_anything = true;
2665 }
2666 for profile in &builder.config.reproducible_artifacts {
2667 tarball.add_file(profile, ".", FileType::Regular);
2668 added_anything = true;
2669 }
2670 if added_anything { Some(tarball.generate()) } else { None }
2671 }
2672}
2673
2674#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2678pub struct Gcc {
2679 pub target: TargetSelection,
2680}
2681
2682impl Step for Gcc {
2683 type Output = GeneratedTarball;
2684
2685 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2686 run.alias("gcc")
2687 }
2688
2689 fn make_run(run: RunConfig<'_>) {
2690 run.builder.ensure(Gcc { target: run.target });
2691 }
2692
2693 fn run(self, builder: &Builder<'_>) -> Self::Output {
2694 let tarball = Tarball::new(builder, "gcc", &self.target.triple);
2695 let output = builder.ensure(super::gcc::Gcc { target: self.target });
2696 tarball.add_file(&output.libgccjit, "lib", FileType::NativeLibrary);
2697 tarball.generate()
2698 }
2699}