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