]> git.proxmox.com Git - rustc.git/blob - src/bootstrap/dist.rs
New upstream version 1.62.1+dfsg1
[rustc.git] / src / bootstrap / dist.rs
1 //! Implementation of the various distribution aspects of the compiler.
2 //!
3 //! This module is responsible for creating tarballs of the standard library,
4 //! compiler, and documentation. This ends up being what we distribute to
5 //! everyone as well.
6 //!
7 //! No tarball is actually created literally in this file, but rather we shell
8 //! out to `rust-installer` still. This may one day be replaced with bits and
9 //! pieces of `rustup.rs`!
10
11 use std::collections::HashSet;
12 use std::env;
13 use std::fs;
14 use std::path::{Path, PathBuf};
15 use std::process::Command;
16
17 use crate::builder::{Builder, Kind, RunConfig, ShouldRun, Step};
18 use crate::cache::{Interned, INTERNER};
19 use crate::compile;
20 use crate::config::TargetSelection;
21 use crate::tarball::{GeneratedTarball, OverlayKind, Tarball};
22 use crate::tool::{self, Tool};
23 use crate::util::{exe, is_dylib, output, t, timeit};
24 use crate::{Compiler, DependencyType, Mode, LLVM_TOOLS};
25
26 pub fn pkgname(builder: &Builder<'_>, component: &str) -> String {
27 format!("{}-{}", component, builder.rust_package_vers())
28 }
29
30 pub(crate) fn distdir(builder: &Builder<'_>) -> PathBuf {
31 builder.out.join("dist")
32 }
33
34 pub fn tmpdir(builder: &Builder<'_>) -> PathBuf {
35 builder.out.join("tmp/dist")
36 }
37
38 fn missing_tool(tool_name: &str, skip: bool) {
39 if skip {
40 println!("Unable to build {}, skipping dist", tool_name)
41 } else {
42 panic!("Unable to build {}", tool_name)
43 }
44 }
45
46 fn should_build_extended_tool(builder: &Builder<'_>, tool: &str) -> bool {
47 if !builder.config.extended {
48 return false;
49 }
50 builder.config.tools.as_ref().map_or(true, |tools| tools.contains(tool))
51 }
52
53 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
54 pub struct Docs {
55 pub host: TargetSelection,
56 }
57
58 impl Step for Docs {
59 type Output = Option<GeneratedTarball>;
60 const DEFAULT: bool = true;
61
62 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
63 let default = run.builder.config.docs;
64 run.alias("rust-docs").default_condition(default)
65 }
66
67 fn make_run(run: RunConfig<'_>) {
68 run.builder.ensure(Docs { host: run.target });
69 }
70
71 /// Builds the `rust-docs` installer component.
72 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
73 let host = self.host;
74 builder.default_doc(&[]);
75
76 let dest = "share/doc/rust/html";
77
78 let mut tarball = Tarball::new(builder, "rust-docs", &host.triple);
79 tarball.set_product_name("Rust Documentation");
80 tarball.add_bulk_dir(&builder.doc_out(host), dest);
81 tarball.add_file(&builder.src.join("src/doc/robots.txt"), dest, 0o644);
82 Some(tarball.generate())
83 }
84 }
85
86 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
87 pub struct RustcDocs {
88 pub host: TargetSelection,
89 }
90
91 impl Step for RustcDocs {
92 type Output = Option<GeneratedTarball>;
93 const DEFAULT: bool = true;
94
95 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
96 let builder = run.builder;
97 run.alias("rustc-docs").default_condition(builder.config.compiler_docs)
98 }
99
100 fn make_run(run: RunConfig<'_>) {
101 run.builder.ensure(RustcDocs { host: run.target });
102 }
103
104 /// Builds the `rustc-docs` installer component.
105 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
106 let host = self.host;
107 builder.default_doc(&[]);
108
109 let mut tarball = Tarball::new(builder, "rustc-docs", &host.triple);
110 tarball.set_product_name("Rustc Documentation");
111 tarball.add_bulk_dir(&builder.compiler_doc_out(host), "share/doc/rust/html/rustc");
112 Some(tarball.generate())
113 }
114 }
115
116 fn find_files(files: &[&str], path: &[PathBuf]) -> Vec<PathBuf> {
117 let mut found = Vec::with_capacity(files.len());
118
119 for file in files {
120 let file_path = path.iter().map(|dir| dir.join(file)).find(|p| p.exists());
121
122 if let Some(file_path) = file_path {
123 found.push(file_path);
124 } else {
125 panic!("Could not find '{}' in {:?}", file, path);
126 }
127 }
128
129 found
130 }
131
132 fn make_win_dist(
133 rust_root: &Path,
134 plat_root: &Path,
135 target: TargetSelection,
136 builder: &Builder<'_>,
137 ) {
138 //Ask gcc where it keeps its stuff
139 let mut cmd = Command::new(builder.cc(target));
140 cmd.arg("-print-search-dirs");
141 let gcc_out = output(&mut cmd);
142
143 let mut bin_path: Vec<_> = env::split_paths(&env::var_os("PATH").unwrap_or_default()).collect();
144 let mut lib_path = Vec::new();
145
146 for line in gcc_out.lines() {
147 let idx = line.find(':').unwrap();
148 let key = &line[..idx];
149 let trim_chars: &[_] = &[' ', '='];
150 let value = env::split_paths(line[(idx + 1)..].trim_start_matches(trim_chars));
151
152 if key == "programs" {
153 bin_path.extend(value);
154 } else if key == "libraries" {
155 lib_path.extend(value);
156 }
157 }
158
159 let compiler = if target == "i686-pc-windows-gnu" {
160 "i686-w64-mingw32-gcc.exe"
161 } else if target == "x86_64-pc-windows-gnu" {
162 "x86_64-w64-mingw32-gcc.exe"
163 } else {
164 "gcc.exe"
165 };
166 let target_tools = [compiler, "ld.exe", "dlltool.exe", "libwinpthread-1.dll"];
167 let mut rustc_dlls = vec!["libwinpthread-1.dll"];
168 if target.starts_with("i686-") {
169 rustc_dlls.push("libgcc_s_dw2-1.dll");
170 } else {
171 rustc_dlls.push("libgcc_s_seh-1.dll");
172 }
173
174 let target_libs = [
175 //MinGW libs
176 "libgcc.a",
177 "libgcc_eh.a",
178 "libgcc_s.a",
179 "libm.a",
180 "libmingw32.a",
181 "libmingwex.a",
182 "libstdc++.a",
183 "libiconv.a",
184 "libmoldname.a",
185 "libpthread.a",
186 //Windows import libs
187 "libadvapi32.a",
188 "libbcrypt.a",
189 "libcomctl32.a",
190 "libcomdlg32.a",
191 "libcredui.a",
192 "libcrypt32.a",
193 "libdbghelp.a",
194 "libgdi32.a",
195 "libimagehlp.a",
196 "libiphlpapi.a",
197 "libkernel32.a",
198 "libmsimg32.a",
199 "libmsvcrt.a",
200 "libodbc32.a",
201 "libole32.a",
202 "liboleaut32.a",
203 "libopengl32.a",
204 "libpsapi.a",
205 "librpcrt4.a",
206 "libsecur32.a",
207 "libsetupapi.a",
208 "libshell32.a",
209 "libsynchronization.a",
210 "libuser32.a",
211 "libuserenv.a",
212 "libuuid.a",
213 "libwinhttp.a",
214 "libwinmm.a",
215 "libwinspool.a",
216 "libws2_32.a",
217 "libwsock32.a",
218 ];
219
220 //Find mingw artifacts we want to bundle
221 let target_tools = find_files(&target_tools, &bin_path);
222 let rustc_dlls = find_files(&rustc_dlls, &bin_path);
223 let target_libs = find_files(&target_libs, &lib_path);
224
225 // Copy runtime dlls next to rustc.exe
226 let dist_bin_dir = rust_root.join("bin/");
227 fs::create_dir_all(&dist_bin_dir).expect("creating dist_bin_dir failed");
228 for src in rustc_dlls {
229 builder.copy_to_folder(&src, &dist_bin_dir);
230 }
231
232 //Copy platform tools to platform-specific bin directory
233 let target_bin_dir = plat_root
234 .join("lib")
235 .join("rustlib")
236 .join(target.triple)
237 .join("bin")
238 .join("self-contained");
239 fs::create_dir_all(&target_bin_dir).expect("creating target_bin_dir failed");
240 for src in target_tools {
241 builder.copy_to_folder(&src, &target_bin_dir);
242 }
243
244 // Warn windows-gnu users that the bundled GCC cannot compile C files
245 builder.create(
246 &target_bin_dir.join("GCC-WARNING.txt"),
247 "gcc.exe contained in this folder cannot be used for compiling C files - it is only \
248 used as a linker. In order to be able to compile projects containing C code use \
249 the GCC provided by MinGW or Cygwin.",
250 );
251
252 //Copy platform libs to platform-specific lib directory
253 let target_lib_dir = plat_root
254 .join("lib")
255 .join("rustlib")
256 .join(target.triple)
257 .join("lib")
258 .join("self-contained");
259 fs::create_dir_all(&target_lib_dir).expect("creating target_lib_dir failed");
260 for src in target_libs {
261 builder.copy_to_folder(&src, &target_lib_dir);
262 }
263 }
264
265 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
266 pub struct Mingw {
267 pub host: TargetSelection,
268 }
269
270 impl Step for Mingw {
271 type Output = Option<GeneratedTarball>;
272 const DEFAULT: bool = true;
273
274 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
275 run.alias("rust-mingw")
276 }
277
278 fn make_run(run: RunConfig<'_>) {
279 run.builder.ensure(Mingw { host: run.target });
280 }
281
282 /// Builds the `rust-mingw` installer component.
283 ///
284 /// This contains all the bits and pieces to run the MinGW Windows targets
285 /// without any extra installed software (e.g., we bundle gcc, libraries, etc).
286 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
287 let host = self.host;
288 if !host.ends_with("pc-windows-gnu") {
289 return None;
290 }
291
292 let mut tarball = Tarball::new(builder, "rust-mingw", &host.triple);
293 tarball.set_product_name("Rust MinGW");
294
295 // The first argument is a "temporary directory" which is just
296 // thrown away (this contains the runtime DLLs included in the rustc package
297 // above) and the second argument is where to place all the MinGW components
298 // (which is what we want).
299 make_win_dist(&tmpdir(builder), tarball.image_dir(), host, &builder);
300
301 Some(tarball.generate())
302 }
303 }
304
305 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
306 pub struct Rustc {
307 pub compiler: Compiler,
308 }
309
310 impl Step for Rustc {
311 type Output = GeneratedTarball;
312 const DEFAULT: bool = true;
313 const ONLY_HOSTS: bool = true;
314
315 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
316 run.alias("rustc")
317 }
318
319 fn make_run(run: RunConfig<'_>) {
320 run.builder
321 .ensure(Rustc { compiler: run.builder.compiler(run.builder.top_stage, run.target) });
322 }
323
324 /// Creates the `rustc` installer component.
325 fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
326 let compiler = self.compiler;
327 let host = self.compiler.host;
328
329 let tarball = Tarball::new(builder, "rustc", &host.triple);
330
331 // Prepare the rustc "image", what will actually end up getting installed
332 prepare_image(builder, compiler, tarball.image_dir());
333
334 // On MinGW we've got a few runtime DLL dependencies that we need to
335 // include. The first argument to this script is where to put these DLLs
336 // (the image we're creating), and the second argument is a junk directory
337 // to ignore all other MinGW stuff the script creates.
338 //
339 // On 32-bit MinGW we're always including a DLL which needs some extra
340 // licenses to distribute. On 64-bit MinGW we don't actually distribute
341 // anything requiring us to distribute a license, but it's likely the
342 // install will *also* include the rust-mingw package, which also needs
343 // licenses, so to be safe we just include it here in all MinGW packages.
344 if host.ends_with("pc-windows-gnu") {
345 make_win_dist(tarball.image_dir(), &tmpdir(builder), host, builder);
346 tarball.add_dir(builder.src.join("src/etc/third-party"), "share/doc");
347 }
348
349 return tarball.generate();
350
351 fn prepare_image(builder: &Builder<'_>, compiler: Compiler, image: &Path) {
352 let host = compiler.host;
353 let src = builder.sysroot(compiler);
354
355 // Copy rustc/rustdoc binaries
356 t!(fs::create_dir_all(image.join("bin")));
357 builder.cp_r(&src.join("bin"), &image.join("bin"));
358
359 builder.install(&builder.rustdoc(compiler), &image.join("bin"), 0o755);
360
361 let libdir_relative = builder.libdir_relative(compiler);
362
363 // Copy runtime DLLs needed by the compiler
364 if libdir_relative.to_str() != Some("bin") {
365 let libdir = builder.rustc_libdir(compiler);
366 for entry in builder.read_dir(&libdir) {
367 let name = entry.file_name();
368 if let Some(s) = name.to_str() {
369 if is_dylib(s) {
370 // Don't use custom libdir here because ^lib/ will be resolved again
371 // with installer
372 builder.install(&entry.path(), &image.join("lib"), 0o644);
373 }
374 }
375 }
376 }
377
378 // Copy over the codegen backends
379 let backends_src = builder.sysroot_codegen_backends(compiler);
380 let backends_rel = backends_src
381 .strip_prefix(&src)
382 .unwrap()
383 .strip_prefix(builder.sysroot_libdir_relative(compiler))
384 .unwrap();
385 // Don't use custom libdir here because ^lib/ will be resolved again with installer
386 let backends_dst = image.join("lib").join(&backends_rel);
387
388 t!(fs::create_dir_all(&backends_dst));
389 builder.cp_r(&backends_src, &backends_dst);
390
391 // Copy libLLVM.so to the lib dir as well, if needed. While not
392 // technically needed by rustc itself it's needed by lots of other
393 // components like the llvm tools and LLD. LLD is included below and
394 // tools/LLDB come later, so let's just throw it in the rustc
395 // component for now.
396 maybe_install_llvm_runtime(builder, host, image);
397
398 let dst_dir = image.join("lib/rustlib").join(&*host.triple).join("bin");
399 t!(fs::create_dir_all(&dst_dir));
400
401 // Copy over lld if it's there
402 if builder.config.lld_enabled {
403 let src_dir = builder.sysroot_libdir(compiler, host).parent().unwrap().join("bin");
404 let rust_lld = exe("rust-lld", compiler.host);
405 builder.copy(&src_dir.join(&rust_lld), &dst_dir.join(&rust_lld));
406 // for `-Z gcc-ld=lld`
407 let gcc_lld_src_dir = src_dir.join("gcc-ld");
408 let gcc_lld_dst_dir = dst_dir.join("gcc-ld");
409 t!(fs::create_dir(&gcc_lld_dst_dir));
410 for flavor in ["ld", "ld64"] {
411 let exe_name = exe(flavor, compiler.host);
412 builder
413 .copy(&gcc_lld_src_dir.join(&exe_name), &gcc_lld_dst_dir.join(&exe_name));
414 }
415 }
416
417 // Man pages
418 t!(fs::create_dir_all(image.join("share/man/man1")));
419 let man_src = builder.src.join("src/doc/man");
420 let man_dst = image.join("share/man/man1");
421
422 // don't use our `bootstrap::util::{copy, cp_r}`, because those try
423 // to hardlink, and we don't want to edit the source templates
424 for file_entry in builder.read_dir(&man_src) {
425 let page_src = file_entry.path();
426 let page_dst = man_dst.join(file_entry.file_name());
427 let src_text = t!(std::fs::read_to_string(&page_src));
428 let new_text = src_text.replace("<INSERT VERSION HERE>", &builder.version);
429 t!(std::fs::write(&page_dst, &new_text));
430 t!(fs::copy(&page_src, &page_dst));
431 }
432
433 // Debugger scripts
434 builder
435 .ensure(DebuggerScripts { sysroot: INTERNER.intern_path(image.to_owned()), host });
436
437 // Misc license info
438 let cp = |file: &str| {
439 builder.install(&builder.src.join(file), &image.join("share/doc/rust"), 0o644);
440 };
441 cp("COPYRIGHT");
442 cp("LICENSE-APACHE");
443 cp("LICENSE-MIT");
444 cp("README.md");
445 }
446 }
447 }
448
449 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
450 pub struct DebuggerScripts {
451 pub sysroot: Interned<PathBuf>,
452 pub host: TargetSelection,
453 }
454
455 impl Step for DebuggerScripts {
456 type Output = ();
457
458 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
459 run.never()
460 }
461
462 /// Copies debugger scripts for `target` into the `sysroot` specified.
463 fn run(self, builder: &Builder<'_>) {
464 let host = self.host;
465 let sysroot = self.sysroot;
466 let dst = sysroot.join("lib/rustlib/etc");
467 t!(fs::create_dir_all(&dst));
468 let cp_debugger_script = |file: &str| {
469 builder.install(&builder.src.join("src/etc/").join(file), &dst, 0o644);
470 };
471 if host.contains("windows-msvc") {
472 // windbg debugger scripts
473 builder.install(
474 &builder.src.join("src/etc/rust-windbg.cmd"),
475 &sysroot.join("bin"),
476 0o755,
477 );
478
479 cp_debugger_script("natvis/intrinsic.natvis");
480 cp_debugger_script("natvis/liballoc.natvis");
481 cp_debugger_script("natvis/libcore.natvis");
482 cp_debugger_script("natvis/libstd.natvis");
483 } else {
484 cp_debugger_script("rust_types.py");
485
486 // gdb debugger scripts
487 builder.install(&builder.src.join("src/etc/rust-gdb"), &sysroot.join("bin"), 0o755);
488 builder.install(&builder.src.join("src/etc/rust-gdbgui"), &sysroot.join("bin"), 0o755);
489
490 cp_debugger_script("gdb_load_rust_pretty_printers.py");
491 cp_debugger_script("gdb_lookup.py");
492 cp_debugger_script("gdb_providers.py");
493
494 // lldb debugger scripts
495 builder.install(&builder.src.join("src/etc/rust-lldb"), &sysroot.join("bin"), 0o755);
496
497 cp_debugger_script("lldb_lookup.py");
498 cp_debugger_script("lldb_providers.py");
499 cp_debugger_script("lldb_commands")
500 }
501 }
502 }
503
504 fn skip_host_target_lib(builder: &Builder<'_>, compiler: Compiler) -> bool {
505 // The only true set of target libraries came from the build triple, so
506 // let's reduce redundant work by only producing archives from that host.
507 if compiler.host != builder.config.build {
508 builder.info("\tskipping, not a build host");
509 true
510 } else {
511 false
512 }
513 }
514
515 /// Copy stamped files into an image's `target/lib` directory.
516 fn copy_target_libs(builder: &Builder<'_>, target: TargetSelection, image: &Path, stamp: &Path) {
517 let dst = image.join("lib/rustlib").join(target.triple).join("lib");
518 let self_contained_dst = dst.join("self-contained");
519 t!(fs::create_dir_all(&dst));
520 t!(fs::create_dir_all(&self_contained_dst));
521 for (path, dependency_type) in builder.read_stamp_file(stamp) {
522 if dependency_type == DependencyType::TargetSelfContained {
523 builder.copy(&path, &self_contained_dst.join(path.file_name().unwrap()));
524 } else if dependency_type == DependencyType::Target || builder.config.build == target {
525 builder.copy(&path, &dst.join(path.file_name().unwrap()));
526 }
527 }
528 }
529
530 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
531 pub struct Std {
532 pub compiler: Compiler,
533 pub target: TargetSelection,
534 }
535
536 impl Step for Std {
537 type Output = Option<GeneratedTarball>;
538 const DEFAULT: bool = true;
539
540 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
541 run.alias("rust-std")
542 }
543
544 fn make_run(run: RunConfig<'_>) {
545 run.builder.ensure(Std {
546 compiler: run.builder.compiler_for(
547 run.builder.top_stage,
548 run.builder.config.build,
549 run.target,
550 ),
551 target: run.target,
552 });
553 }
554
555 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
556 let compiler = self.compiler;
557 let target = self.target;
558
559 if skip_host_target_lib(builder, compiler) {
560 return None;
561 }
562
563 builder.ensure(compile::Std { compiler, target });
564
565 let mut tarball = Tarball::new(builder, "rust-std", &target.triple);
566 tarball.include_target_in_component_name(true);
567
568 let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target);
569 let stamp = compile::libstd_stamp(builder, compiler_to_use, target);
570 copy_target_libs(builder, target, &tarball.image_dir(), &stamp);
571
572 Some(tarball.generate())
573 }
574 }
575
576 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
577 pub struct RustcDev {
578 pub compiler: Compiler,
579 pub target: TargetSelection,
580 }
581
582 impl Step for RustcDev {
583 type Output = Option<GeneratedTarball>;
584 const DEFAULT: bool = true;
585 const ONLY_HOSTS: bool = true;
586
587 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
588 run.alias("rustc-dev")
589 }
590
591 fn make_run(run: RunConfig<'_>) {
592 run.builder.ensure(RustcDev {
593 compiler: run.builder.compiler_for(
594 run.builder.top_stage,
595 run.builder.config.build,
596 run.target,
597 ),
598 target: run.target,
599 });
600 }
601
602 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
603 let compiler = self.compiler;
604 let target = self.target;
605 if skip_host_target_lib(builder, compiler) {
606 return None;
607 }
608
609 builder.ensure(compile::Rustc { compiler, target });
610
611 let tarball = Tarball::new(builder, "rustc-dev", &target.triple);
612
613 let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target);
614 let stamp = compile::librustc_stamp(builder, compiler_to_use, target);
615 copy_target_libs(builder, target, tarball.image_dir(), &stamp);
616
617 let src_files = &["Cargo.lock"];
618 // This is the reduced set of paths which will become the rustc-dev component
619 // (essentially the compiler crates and all of their path dependencies).
620 copy_src_dirs(
621 builder,
622 &builder.src,
623 &["compiler"],
624 &[],
625 &tarball.image_dir().join("lib/rustlib/rustc-src/rust"),
626 );
627 for file in src_files {
628 tarball.add_file(builder.src.join(file), "lib/rustlib/rustc-src/rust", 0o644);
629 }
630
631 Some(tarball.generate())
632 }
633 }
634
635 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
636 pub struct Analysis {
637 pub compiler: Compiler,
638 pub target: TargetSelection,
639 }
640
641 impl Step for Analysis {
642 type Output = Option<GeneratedTarball>;
643 const DEFAULT: bool = true;
644
645 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
646 let default = should_build_extended_tool(&run.builder, "analysis");
647 run.alias("rust-analysis").default_condition(default)
648 }
649
650 fn make_run(run: RunConfig<'_>) {
651 run.builder.ensure(Analysis {
652 // Find the actual compiler (handling the full bootstrap option) which
653 // produced the save-analysis data because that data isn't copied
654 // through the sysroot uplifting.
655 compiler: run.builder.compiler_for(
656 run.builder.top_stage,
657 run.builder.config.build,
658 run.target,
659 ),
660 target: run.target,
661 });
662 }
663
664 /// Creates a tarball of save-analysis metadata, if available.
665 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
666 let compiler = self.compiler;
667 let target = self.target;
668 if compiler.host != builder.config.build {
669 return None;
670 }
671
672 builder.ensure(compile::Std { compiler, target });
673 let src = builder
674 .stage_out(compiler, Mode::Std)
675 .join(target.triple)
676 .join(builder.cargo_dir())
677 .join("deps")
678 .join("save-analysis");
679
680 let mut tarball = Tarball::new(builder, "rust-analysis", &target.triple);
681 tarball.include_target_in_component_name(true);
682 tarball.add_dir(src, format!("lib/rustlib/{}/analysis", target.triple));
683 Some(tarball.generate())
684 }
685 }
686
687 /// Use the `builder` to make a filtered copy of `base`/X for X in (`src_dirs` - `exclude_dirs`) to
688 /// `dst_dir`.
689 fn copy_src_dirs(
690 builder: &Builder<'_>,
691 base: &Path,
692 src_dirs: &[&str],
693 exclude_dirs: &[&str],
694 dst_dir: &Path,
695 ) {
696 fn filter_fn(exclude_dirs: &[&str], dir: &str, path: &Path) -> bool {
697 let spath = match path.to_str() {
698 Some(path) => path,
699 None => return false,
700 };
701 if spath.ends_with('~') || spath.ends_with(".pyc") {
702 return false;
703 }
704
705 const LLVM_PROJECTS: &[&str] = &[
706 "llvm-project/clang",
707 "llvm-project\\clang",
708 "llvm-project/libunwind",
709 "llvm-project\\libunwind",
710 "llvm-project/lld",
711 "llvm-project\\lld",
712 "llvm-project/lldb",
713 "llvm-project\\lldb",
714 "llvm-project/llvm",
715 "llvm-project\\llvm",
716 "llvm-project/compiler-rt",
717 "llvm-project\\compiler-rt",
718 "llvm-project/cmake",
719 "llvm-project\\cmake",
720 ];
721 if spath.contains("llvm-project")
722 && !spath.ends_with("llvm-project")
723 && !LLVM_PROJECTS.iter().any(|path| spath.contains(path))
724 {
725 return false;
726 }
727
728 const LLVM_TEST: &[&str] = &["llvm-project/llvm/test", "llvm-project\\llvm\\test"];
729 if LLVM_TEST.iter().any(|path| spath.contains(path))
730 && (spath.ends_with(".ll") || spath.ends_with(".td") || spath.ends_with(".s"))
731 {
732 return false;
733 }
734
735 let full_path = Path::new(dir).join(path);
736 if exclude_dirs.iter().any(|excl| full_path == Path::new(excl)) {
737 return false;
738 }
739
740 let excludes = [
741 "CVS",
742 "RCS",
743 "SCCS",
744 ".git",
745 ".gitignore",
746 ".gitmodules",
747 ".gitattributes",
748 ".cvsignore",
749 ".svn",
750 ".arch-ids",
751 "{arch}",
752 "=RELEASE-ID",
753 "=meta-update",
754 "=update",
755 ".bzr",
756 ".bzrignore",
757 ".bzrtags",
758 ".hg",
759 ".hgignore",
760 ".hgrags",
761 "_darcs",
762 ];
763 !path.iter().map(|s| s.to_str().unwrap()).any(|s| excludes.contains(&s))
764 }
765
766 // Copy the directories using our filter
767 for item in src_dirs {
768 let dst = &dst_dir.join(item);
769 t!(fs::create_dir_all(dst));
770 builder.cp_filtered(&base.join(item), dst, &|path| filter_fn(exclude_dirs, item, path));
771 }
772 }
773
774 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
775 pub struct Src;
776
777 impl Step for Src {
778 /// The output path of the src installer tarball
779 type Output = GeneratedTarball;
780 const DEFAULT: bool = true;
781 const ONLY_HOSTS: bool = true;
782
783 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
784 run.alias("rust-src")
785 }
786
787 fn make_run(run: RunConfig<'_>) {
788 run.builder.ensure(Src);
789 }
790
791 /// Creates the `rust-src` installer component
792 fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
793 let tarball = Tarball::new_targetless(builder, "rust-src");
794
795 // A lot of tools expect the rust-src component to be entirely in this directory, so if you
796 // change that (e.g. by adding another directory `lib/rustlib/src/foo` or
797 // `lib/rustlib/src/rust/foo`), you will need to go around hunting for implicit assumptions
798 // and fix them...
799 //
800 // NOTE: if you update the paths here, you also should update the "virtual" path
801 // translation code in `imported_source_files` in `src/librustc_metadata/rmeta/decoder.rs`
802 let dst_src = tarball.image_dir().join("lib/rustlib/src/rust");
803
804 let src_files = ["Cargo.lock"];
805 // This is the reduced set of paths which will become the rust-src component
806 // (essentially libstd and all of its path dependencies).
807 copy_src_dirs(
808 builder,
809 &builder.src,
810 &["library", "src/llvm-project/libunwind"],
811 &[
812 // not needed and contains symlinks which rustup currently
813 // chokes on when unpacking.
814 "library/backtrace/crates",
815 // these are 30MB combined and aren't necessary for building
816 // the standard library.
817 "library/stdarch/crates/Cargo.toml",
818 "library/stdarch/crates/stdarch-verify",
819 "library/stdarch/crates/intrinsic-test",
820 ],
821 &dst_src,
822 );
823 for file in src_files.iter() {
824 builder.copy(&builder.src.join(file), &dst_src.join(file));
825 }
826
827 tarball.generate()
828 }
829 }
830
831 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
832 pub struct PlainSourceTarball;
833
834 impl Step for PlainSourceTarball {
835 /// Produces the location of the tarball generated
836 type Output = GeneratedTarball;
837 const DEFAULT: bool = true;
838 const ONLY_HOSTS: bool = true;
839
840 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
841 let builder = run.builder;
842 run.alias("rustc-src").default_condition(builder.config.rust_dist_src)
843 }
844
845 fn make_run(run: RunConfig<'_>) {
846 run.builder.ensure(PlainSourceTarball);
847 }
848
849 /// Creates the plain source tarball
850 fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
851 let tarball = Tarball::new(builder, "rustc", "src");
852 let plain_dst_src = tarball.image_dir();
853
854 // This is the set of root paths which will become part of the source package
855 let src_files = [
856 "COPYRIGHT",
857 "LICENSE-APACHE",
858 "LICENSE-MIT",
859 "CONTRIBUTING.md",
860 "README.md",
861 "RELEASES.md",
862 "configure",
863 "x.py",
864 "config.toml.example",
865 "Cargo.toml",
866 "Cargo.lock",
867 ];
868 let src_dirs = ["src", "compiler", "library"];
869
870 copy_src_dirs(builder, &builder.src, &src_dirs, &[], &plain_dst_src);
871
872 // Copy the files normally
873 for item in &src_files {
874 builder.copy(&builder.src.join(item), &plain_dst_src.join(item));
875 }
876
877 // Create the version file
878 builder.create(&plain_dst_src.join("version"), &builder.rust_version());
879 if let Some(sha) = builder.rust_sha() {
880 builder.create(&plain_dst_src.join("git-commit-hash"), &sha);
881 }
882
883 // If we're building from git sources, we need to vendor a complete distribution.
884 if builder.rust_info.is_git() {
885 // Vendor all Cargo dependencies
886 let mut cmd = Command::new(&builder.initial_cargo);
887 cmd.arg("vendor")
888 .arg("--sync")
889 .arg(builder.src.join("./src/tools/rust-analyzer/Cargo.toml"))
890 .arg("--sync")
891 .arg(builder.src.join("./compiler/rustc_codegen_cranelift/Cargo.toml"))
892 .current_dir(&plain_dst_src);
893 builder.run(&mut cmd);
894 }
895
896 tarball.bare()
897 }
898 }
899
900 // We have to run a few shell scripts, which choke quite a bit on both `\`
901 // characters and on `C:\` paths, so normalize both of them away.
902 pub fn sanitize_sh(path: &Path) -> String {
903 let path = path.to_str().unwrap().replace("\\", "/");
904 return change_drive(unc_to_lfs(&path)).unwrap_or(path);
905
906 fn unc_to_lfs(s: &str) -> &str {
907 s.strip_prefix("//?/").unwrap_or(s)
908 }
909
910 fn change_drive(s: &str) -> Option<String> {
911 let mut ch = s.chars();
912 let drive = ch.next().unwrap_or('C');
913 if ch.next() != Some(':') {
914 return None;
915 }
916 if ch.next() != Some('/') {
917 return None;
918 }
919 Some(format!("/{}/{}", drive, &s[drive.len_utf8() + 2..]))
920 }
921 }
922
923 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
924 pub struct Cargo {
925 pub compiler: Compiler,
926 pub target: TargetSelection,
927 }
928
929 impl Step for Cargo {
930 type Output = Option<GeneratedTarball>;
931 const DEFAULT: bool = true;
932 const ONLY_HOSTS: bool = true;
933
934 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
935 let default = should_build_extended_tool(&run.builder, "cargo");
936 run.alias("cargo").default_condition(default)
937 }
938
939 fn make_run(run: RunConfig<'_>) {
940 run.builder.ensure(Cargo {
941 compiler: run.builder.compiler_for(
942 run.builder.top_stage,
943 run.builder.config.build,
944 run.target,
945 ),
946 target: run.target,
947 });
948 }
949
950 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
951 let compiler = self.compiler;
952 let target = self.target;
953
954 let cargo = builder.ensure(tool::Cargo { compiler, target });
955 let src = builder.src.join("src/tools/cargo");
956 let etc = src.join("src/etc");
957
958 // Prepare the image directory
959 let mut tarball = Tarball::new(builder, "cargo", &target.triple);
960 tarball.set_overlay(OverlayKind::Cargo);
961
962 tarball.add_file(&cargo, "bin", 0o755);
963 tarball.add_file(etc.join("_cargo"), "share/zsh/site-functions", 0o644);
964 tarball.add_renamed_file(etc.join("cargo.bashcomp.sh"), "etc/bash_completion.d", "cargo");
965 tarball.add_dir(etc.join("man"), "share/man/man1");
966 tarball.add_legal_and_readme_to("share/doc/cargo");
967
968 for dirent in fs::read_dir(cargo.parent().unwrap()).expect("read_dir") {
969 let dirent = dirent.expect("read dir entry");
970 if dirent.file_name().to_str().expect("utf8").starts_with("cargo-credential-") {
971 tarball.add_file(&dirent.path(), "libexec", 0o755);
972 }
973 }
974
975 Some(tarball.generate())
976 }
977 }
978
979 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
980 pub struct Rls {
981 pub compiler: Compiler,
982 pub target: TargetSelection,
983 }
984
985 impl Step for Rls {
986 type Output = Option<GeneratedTarball>;
987 const ONLY_HOSTS: bool = true;
988 const DEFAULT: bool = true;
989
990 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
991 let default = should_build_extended_tool(&run.builder, "rls");
992 run.alias("rls").default_condition(default)
993 }
994
995 fn make_run(run: RunConfig<'_>) {
996 run.builder.ensure(Rls {
997 compiler: run.builder.compiler_for(
998 run.builder.top_stage,
999 run.builder.config.build,
1000 run.target,
1001 ),
1002 target: run.target,
1003 });
1004 }
1005
1006 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1007 let compiler = self.compiler;
1008 let target = self.target;
1009
1010 let rls = builder
1011 .ensure(tool::Rls { compiler, target, extra_features: Vec::new() })
1012 .or_else(|| {
1013 missing_tool("RLS", builder.build.config.missing_tools);
1014 None
1015 })?;
1016
1017 let mut tarball = Tarball::new(builder, "rls", &target.triple);
1018 tarball.set_overlay(OverlayKind::RLS);
1019 tarball.is_preview(true);
1020 tarball.add_file(rls, "bin", 0o755);
1021 tarball.add_legal_and_readme_to("share/doc/rls");
1022 Some(tarball.generate())
1023 }
1024 }
1025
1026 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
1027 pub struct RustAnalyzer {
1028 pub compiler: Compiler,
1029 pub target: TargetSelection,
1030 }
1031
1032 impl Step for RustAnalyzer {
1033 type Output = Option<GeneratedTarball>;
1034 const DEFAULT: bool = true;
1035 const ONLY_HOSTS: bool = true;
1036
1037 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1038 let default = should_build_extended_tool(&run.builder, "rust-analyzer");
1039 run.alias("rust-analyzer").default_condition(default)
1040 }
1041
1042 fn make_run(run: RunConfig<'_>) {
1043 run.builder.ensure(RustAnalyzer {
1044 compiler: run.builder.compiler_for(
1045 run.builder.top_stage,
1046 run.builder.config.build,
1047 run.target,
1048 ),
1049 target: run.target,
1050 });
1051 }
1052
1053 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1054 // This prevents rust-analyzer from being built for "dist" or "install"
1055 // on the stable/beta channels. It is a nightly-only tool and should
1056 // not be included.
1057 if !builder.build.unstable_features() {
1058 return None;
1059 }
1060 let compiler = self.compiler;
1061 let target = self.target;
1062
1063 if target.contains("riscv64") {
1064 // riscv64 currently has an LLVM bug that makes rust-analyzer unable
1065 // to build. See #74813 for details.
1066 return None;
1067 }
1068
1069 let rust_analyzer = builder
1070 .ensure(tool::RustAnalyzer { compiler, target, extra_features: Vec::new() })
1071 .expect("rust-analyzer always builds");
1072
1073 let mut tarball = Tarball::new(builder, "rust-analyzer", &target.triple);
1074 tarball.set_overlay(OverlayKind::RustAnalyzer);
1075 tarball.is_preview(true);
1076 tarball.add_file(rust_analyzer, "bin", 0o755);
1077 tarball.add_legal_and_readme_to("share/doc/rust-analyzer");
1078 Some(tarball.generate())
1079 }
1080 }
1081
1082 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
1083 pub struct Clippy {
1084 pub compiler: Compiler,
1085 pub target: TargetSelection,
1086 }
1087
1088 impl Step for Clippy {
1089 type Output = Option<GeneratedTarball>;
1090 const DEFAULT: bool = true;
1091 const ONLY_HOSTS: bool = true;
1092
1093 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1094 let default = should_build_extended_tool(&run.builder, "clippy");
1095 run.alias("clippy").default_condition(default)
1096 }
1097
1098 fn make_run(run: RunConfig<'_>) {
1099 run.builder.ensure(Clippy {
1100 compiler: run.builder.compiler_for(
1101 run.builder.top_stage,
1102 run.builder.config.build,
1103 run.target,
1104 ),
1105 target: run.target,
1106 });
1107 }
1108
1109 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1110 let compiler = self.compiler;
1111 let target = self.target;
1112
1113 // Prepare the image directory
1114 // We expect clippy to build, because we've exited this step above if tool
1115 // state for clippy isn't testing.
1116 let clippy = builder
1117 .ensure(tool::Clippy { compiler, target, extra_features: Vec::new() })
1118 .expect("clippy expected to build - essential tool");
1119 let cargoclippy = builder
1120 .ensure(tool::CargoClippy { compiler, target, extra_features: Vec::new() })
1121 .expect("clippy expected to build - essential tool");
1122
1123 let mut tarball = Tarball::new(builder, "clippy", &target.triple);
1124 tarball.set_overlay(OverlayKind::Clippy);
1125 tarball.is_preview(true);
1126 tarball.add_file(clippy, "bin", 0o755);
1127 tarball.add_file(cargoclippy, "bin", 0o755);
1128 tarball.add_legal_and_readme_to("share/doc/clippy");
1129 Some(tarball.generate())
1130 }
1131 }
1132
1133 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
1134 pub struct Miri {
1135 pub compiler: Compiler,
1136 pub target: TargetSelection,
1137 }
1138
1139 impl Step for Miri {
1140 type Output = Option<GeneratedTarball>;
1141 const DEFAULT: bool = true;
1142 const ONLY_HOSTS: bool = true;
1143
1144 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1145 let default = should_build_extended_tool(&run.builder, "miri");
1146 run.alias("miri").default_condition(default)
1147 }
1148
1149 fn make_run(run: RunConfig<'_>) {
1150 run.builder.ensure(Miri {
1151 compiler: run.builder.compiler_for(
1152 run.builder.top_stage,
1153 run.builder.config.build,
1154 run.target,
1155 ),
1156 target: run.target,
1157 });
1158 }
1159
1160 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1161 // This prevents miri from being built for "dist" or "install"
1162 // on the stable/beta channels. It is a nightly-only tool and should
1163 // not be included.
1164 if !builder.build.unstable_features() {
1165 return None;
1166 }
1167 let compiler = self.compiler;
1168 let target = self.target;
1169
1170 let miri = builder
1171 .ensure(tool::Miri { compiler, target, extra_features: Vec::new() })
1172 .or_else(|| {
1173 missing_tool("miri", builder.build.config.missing_tools);
1174 None
1175 })?;
1176 let cargomiri = builder
1177 .ensure(tool::CargoMiri { compiler, target, extra_features: Vec::new() })
1178 .or_else(|| {
1179 missing_tool("cargo miri", builder.build.config.missing_tools);
1180 None
1181 })?;
1182
1183 let mut tarball = Tarball::new(builder, "miri", &target.triple);
1184 tarball.set_overlay(OverlayKind::Miri);
1185 tarball.is_preview(true);
1186 tarball.add_file(miri, "bin", 0o755);
1187 tarball.add_file(cargomiri, "bin", 0o755);
1188 tarball.add_legal_and_readme_to("share/doc/miri");
1189 Some(tarball.generate())
1190 }
1191 }
1192
1193 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
1194 pub struct Rustfmt {
1195 pub compiler: Compiler,
1196 pub target: TargetSelection,
1197 }
1198
1199 impl Step for Rustfmt {
1200 type Output = Option<GeneratedTarball>;
1201 const DEFAULT: bool = true;
1202 const ONLY_HOSTS: bool = true;
1203
1204 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1205 let default = should_build_extended_tool(&run.builder, "rustfmt");
1206 run.alias("rustfmt").default_condition(default)
1207 }
1208
1209 fn make_run(run: RunConfig<'_>) {
1210 run.builder.ensure(Rustfmt {
1211 compiler: run.builder.compiler_for(
1212 run.builder.top_stage,
1213 run.builder.config.build,
1214 run.target,
1215 ),
1216 target: run.target,
1217 });
1218 }
1219
1220 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1221 let compiler = self.compiler;
1222 let target = self.target;
1223
1224 let rustfmt = builder
1225 .ensure(tool::Rustfmt { compiler, target, extra_features: Vec::new() })
1226 .or_else(|| {
1227 missing_tool("Rustfmt", builder.build.config.missing_tools);
1228 None
1229 })?;
1230 let cargofmt = builder
1231 .ensure(tool::Cargofmt { compiler, target, extra_features: Vec::new() })
1232 .or_else(|| {
1233 missing_tool("Cargofmt", builder.build.config.missing_tools);
1234 None
1235 })?;
1236
1237 let mut tarball = Tarball::new(builder, "rustfmt", &target.triple);
1238 tarball.set_overlay(OverlayKind::Rustfmt);
1239 tarball.is_preview(true);
1240 tarball.add_file(rustfmt, "bin", 0o755);
1241 tarball.add_file(cargofmt, "bin", 0o755);
1242 tarball.add_legal_and_readme_to("share/doc/rustfmt");
1243 Some(tarball.generate())
1244 }
1245 }
1246
1247 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
1248 pub struct RustDemangler {
1249 pub compiler: Compiler,
1250 pub target: TargetSelection,
1251 }
1252
1253 impl Step for RustDemangler {
1254 type Output = Option<GeneratedTarball>;
1255 const DEFAULT: bool = true;
1256 const ONLY_HOSTS: bool = true;
1257
1258 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1259 // While other tools use `should_build_extended_tool` to decide whether to be run by
1260 // default or not, `rust-demangler` must be build when *either* it's enabled as a tool like
1261 // the other ones or if `profiler = true`. Because we don't know the target at this stage
1262 // we run the step by default when only `extended = true`, and decide whether to actually
1263 // run it or not later.
1264 let default = run.builder.config.extended;
1265 run.alias("rust-demangler").default_condition(default)
1266 }
1267
1268 fn make_run(run: RunConfig<'_>) {
1269 run.builder.ensure(RustDemangler {
1270 compiler: run.builder.compiler_for(
1271 run.builder.top_stage,
1272 run.builder.config.build,
1273 run.target,
1274 ),
1275 target: run.target,
1276 });
1277 }
1278
1279 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1280 let compiler = self.compiler;
1281 let target = self.target;
1282
1283 // Only build this extended tool if explicitly included in `tools`, or if `profiler = true`
1284 let condition = should_build_extended_tool(builder, "rust-demangler")
1285 || builder.config.profiler_enabled(target);
1286 if builder.config.extended && !condition {
1287 return None;
1288 }
1289
1290 let rust_demangler = builder
1291 .ensure(tool::RustDemangler { compiler, target, extra_features: Vec::new() })
1292 .expect("rust-demangler expected to build - in-tree tool");
1293
1294 // Prepare the image directory
1295 let mut tarball = Tarball::new(builder, "rust-demangler", &target.triple);
1296 tarball.set_overlay(OverlayKind::RustDemangler);
1297 tarball.is_preview(true);
1298 tarball.add_file(&rust_demangler, "bin", 0o755);
1299 tarball.add_legal_and_readme_to("share/doc/rust-demangler");
1300 Some(tarball.generate())
1301 }
1302 }
1303
1304 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
1305 pub struct Extended {
1306 stage: u32,
1307 host: TargetSelection,
1308 target: TargetSelection,
1309 }
1310
1311 impl Step for Extended {
1312 type Output = ();
1313 const DEFAULT: bool = true;
1314 const ONLY_HOSTS: bool = true;
1315
1316 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1317 let builder = run.builder;
1318 run.alias("extended").default_condition(builder.config.extended)
1319 }
1320
1321 fn make_run(run: RunConfig<'_>) {
1322 run.builder.ensure(Extended {
1323 stage: run.builder.top_stage,
1324 host: run.builder.config.build,
1325 target: run.target,
1326 });
1327 }
1328
1329 /// Creates a combined installer for the specified target in the provided stage.
1330 fn run(self, builder: &Builder<'_>) {
1331 let target = self.target;
1332 let stage = self.stage;
1333 let compiler = builder.compiler_for(self.stage, self.host, self.target);
1334
1335 builder.info(&format!("Dist extended stage{} ({})", compiler.stage, target));
1336
1337 let mut tarballs = Vec::new();
1338 let mut built_tools = HashSet::new();
1339 macro_rules! add_component {
1340 ($name:expr => $step:expr) => {
1341 if let Some(tarball) = builder.ensure_if_default($step, Kind::Dist) {
1342 tarballs.push(tarball);
1343 built_tools.insert($name);
1344 }
1345 };
1346 }
1347
1348 // When rust-std package split from rustc, we needed to ensure that during
1349 // upgrades rustc was upgraded before rust-std. To avoid rustc clobbering
1350 // the std files during uninstall. To do this ensure that rustc comes
1351 // before rust-std in the list below.
1352 tarballs.push(builder.ensure(Rustc { compiler: builder.compiler(stage, target) }));
1353 tarballs.push(builder.ensure(Std { compiler, target }).expect("missing std"));
1354
1355 if target.ends_with("windows-gnu") {
1356 tarballs.push(builder.ensure(Mingw { host: target }).expect("missing mingw"));
1357 }
1358
1359 add_component!("rust-docs" => Docs { host: target });
1360 add_component!("rust-demangler"=> RustDemangler { compiler, target });
1361 add_component!("cargo" => Cargo { compiler, target });
1362 add_component!("rustfmt" => Rustfmt { compiler, target });
1363 add_component!("rls" => Rls { compiler, target });
1364 add_component!("rust-analyzer" => RustAnalyzer { compiler, target });
1365 add_component!("llvm-components" => LlvmTools { target });
1366 add_component!("clippy" => Clippy { compiler, target });
1367 add_component!("miri" => Miri { compiler, target });
1368 add_component!("analysis" => Analysis { compiler, target });
1369
1370 let etc = builder.src.join("src/etc/installer");
1371
1372 // Avoid producing tarballs during a dry run.
1373 if builder.config.dry_run {
1374 return;
1375 }
1376
1377 let tarball = Tarball::new(builder, "rust", &target.triple);
1378 let generated = tarball.combine(&tarballs);
1379
1380 let tmp = tmpdir(builder).join("combined-tarball");
1381 let work = generated.work_dir();
1382
1383 let mut license = String::new();
1384 license += &builder.read(&builder.src.join("COPYRIGHT"));
1385 license += &builder.read(&builder.src.join("LICENSE-APACHE"));
1386 license += &builder.read(&builder.src.join("LICENSE-MIT"));
1387 license.push('\n');
1388 license.push('\n');
1389
1390 let rtf = r"{\rtf1\ansi\deff0{\fonttbl{\f0\fnil\fcharset0 Arial;}}\nowwrap\fs18";
1391 let mut rtf = rtf.to_string();
1392 rtf.push('\n');
1393 for line in license.lines() {
1394 rtf.push_str(line);
1395 rtf.push_str("\\line ");
1396 }
1397 rtf.push('}');
1398
1399 fn filter(contents: &str, marker: &str) -> String {
1400 let start = format!("tool-{}-start", marker);
1401 let end = format!("tool-{}-end", marker);
1402 let mut lines = Vec::new();
1403 let mut omitted = false;
1404 for line in contents.lines() {
1405 if line.contains(&start) {
1406 omitted = true;
1407 } else if line.contains(&end) {
1408 omitted = false;
1409 } else if !omitted {
1410 lines.push(line);
1411 }
1412 }
1413
1414 lines.join("\n")
1415 }
1416
1417 let xform = |p: &Path| {
1418 let mut contents = t!(fs::read_to_string(p));
1419 for tool in &["rust-demangler", "rls", "rust-analyzer", "miri", "rustfmt"] {
1420 if !built_tools.contains(tool) {
1421 contents = filter(&contents, tool);
1422 }
1423 }
1424 let ret = tmp.join(p.file_name().unwrap());
1425 t!(fs::write(&ret, &contents));
1426 ret
1427 };
1428
1429 if target.contains("apple-darwin") {
1430 builder.info("building pkg installer");
1431 let pkg = tmp.join("pkg");
1432 let _ = fs::remove_dir_all(&pkg);
1433
1434 let pkgbuild = |component: &str| {
1435 let mut cmd = Command::new("pkgbuild");
1436 cmd.arg("--identifier")
1437 .arg(format!("org.rust-lang.{}", component))
1438 .arg("--scripts")
1439 .arg(pkg.join(component))
1440 .arg("--nopayload")
1441 .arg(pkg.join(component).with_extension("pkg"));
1442 builder.run(&mut cmd);
1443 };
1444
1445 let prepare = |name: &str| {
1446 builder.create_dir(&pkg.join(name));
1447 builder.cp_r(
1448 &work.join(&format!("{}-{}", pkgname(builder, name), target.triple)),
1449 &pkg.join(name),
1450 );
1451 builder.install(&etc.join("pkg/postinstall"), &pkg.join(name), 0o755);
1452 pkgbuild(name);
1453 };
1454 prepare("rustc");
1455 prepare("cargo");
1456 prepare("rust-std");
1457 prepare("rust-analysis");
1458 prepare("clippy");
1459 for tool in &["rust-docs", "rust-demangler", "rls", "rust-analyzer", "miri"] {
1460 if built_tools.contains(tool) {
1461 prepare(tool);
1462 }
1463 }
1464 // create an 'uninstall' package
1465 builder.install(&etc.join("pkg/postinstall"), &pkg.join("uninstall"), 0o755);
1466 pkgbuild("uninstall");
1467
1468 builder.create_dir(&pkg.join("res"));
1469 builder.create(&pkg.join("res/LICENSE.txt"), &license);
1470 builder.install(&etc.join("gfx/rust-logo.png"), &pkg.join("res"), 0o644);
1471 let mut cmd = Command::new("productbuild");
1472 cmd.arg("--distribution")
1473 .arg(xform(&etc.join("pkg/Distribution.xml")))
1474 .arg("--resources")
1475 .arg(pkg.join("res"))
1476 .arg(distdir(builder).join(format!(
1477 "{}-{}.pkg",
1478 pkgname(builder, "rust"),
1479 target.triple
1480 )))
1481 .arg("--package-path")
1482 .arg(&pkg);
1483 let _time = timeit(builder);
1484 builder.run(&mut cmd);
1485 }
1486
1487 if target.contains("windows") {
1488 let exe = tmp.join("exe");
1489 let _ = fs::remove_dir_all(&exe);
1490
1491 let prepare = |name: &str| {
1492 builder.create_dir(&exe.join(name));
1493 let dir = if name == "rust-std" || name == "rust-analysis" {
1494 format!("{}-{}", name, target.triple)
1495 } else if name == "rls" {
1496 "rls-preview".to_string()
1497 } else if name == "rust-analyzer" {
1498 "rust-analyzer-preview".to_string()
1499 } else if name == "clippy" {
1500 "clippy-preview".to_string()
1501 } else if name == "rust-demangler" {
1502 "rust-demangler-preview".to_string()
1503 } else if name == "miri" {
1504 "miri-preview".to_string()
1505 } else {
1506 name.to_string()
1507 };
1508 builder.cp_r(
1509 &work.join(&format!("{}-{}", pkgname(builder, name), target.triple)).join(dir),
1510 &exe.join(name),
1511 );
1512 builder.remove(&exe.join(name).join("manifest.in"));
1513 };
1514 prepare("rustc");
1515 prepare("cargo");
1516 prepare("rust-analysis");
1517 prepare("rust-docs");
1518 prepare("rust-std");
1519 prepare("clippy");
1520 for tool in &["rust-demangler", "rls", "rust-analyzer", "miri"] {
1521 if built_tools.contains(tool) {
1522 prepare(tool);
1523 }
1524 }
1525 if target.ends_with("windows-gnu") {
1526 prepare("rust-mingw");
1527 }
1528
1529 builder.install(&etc.join("gfx/rust-logo.ico"), &exe, 0o644);
1530
1531 // Generate msi installer
1532 let wix_path = env::var_os("WIX")
1533 .expect("`WIX` environment variable must be set for generating MSI installer(s).");
1534 let wix = PathBuf::from(wix_path);
1535 let heat = wix.join("bin/heat.exe");
1536 let candle = wix.join("bin/candle.exe");
1537 let light = wix.join("bin/light.exe");
1538
1539 let heat_flags = ["-nologo", "-gg", "-sfrag", "-srd", "-sreg"];
1540 builder.run(
1541 Command::new(&heat)
1542 .current_dir(&exe)
1543 .arg("dir")
1544 .arg("rustc")
1545 .args(&heat_flags)
1546 .arg("-cg")
1547 .arg("RustcGroup")
1548 .arg("-dr")
1549 .arg("Rustc")
1550 .arg("-var")
1551 .arg("var.RustcDir")
1552 .arg("-out")
1553 .arg(exe.join("RustcGroup.wxs")),
1554 );
1555 builder.run(
1556 Command::new(&heat)
1557 .current_dir(&exe)
1558 .arg("dir")
1559 .arg("rust-docs")
1560 .args(&heat_flags)
1561 .arg("-cg")
1562 .arg("DocsGroup")
1563 .arg("-dr")
1564 .arg("Docs")
1565 .arg("-var")
1566 .arg("var.DocsDir")
1567 .arg("-out")
1568 .arg(exe.join("DocsGroup.wxs"))
1569 .arg("-t")
1570 .arg(etc.join("msi/squash-components.xsl")),
1571 );
1572 builder.run(
1573 Command::new(&heat)
1574 .current_dir(&exe)
1575 .arg("dir")
1576 .arg("cargo")
1577 .args(&heat_flags)
1578 .arg("-cg")
1579 .arg("CargoGroup")
1580 .arg("-dr")
1581 .arg("Cargo")
1582 .arg("-var")
1583 .arg("var.CargoDir")
1584 .arg("-out")
1585 .arg(exe.join("CargoGroup.wxs"))
1586 .arg("-t")
1587 .arg(etc.join("msi/remove-duplicates.xsl")),
1588 );
1589 builder.run(
1590 Command::new(&heat)
1591 .current_dir(&exe)
1592 .arg("dir")
1593 .arg("rust-std")
1594 .args(&heat_flags)
1595 .arg("-cg")
1596 .arg("StdGroup")
1597 .arg("-dr")
1598 .arg("Std")
1599 .arg("-var")
1600 .arg("var.StdDir")
1601 .arg("-out")
1602 .arg(exe.join("StdGroup.wxs")),
1603 );
1604 if built_tools.contains("rls") {
1605 builder.run(
1606 Command::new(&heat)
1607 .current_dir(&exe)
1608 .arg("dir")
1609 .arg("rls")
1610 .args(&heat_flags)
1611 .arg("-cg")
1612 .arg("RlsGroup")
1613 .arg("-dr")
1614 .arg("Rls")
1615 .arg("-var")
1616 .arg("var.RlsDir")
1617 .arg("-out")
1618 .arg(exe.join("RlsGroup.wxs"))
1619 .arg("-t")
1620 .arg(etc.join("msi/remove-duplicates.xsl")),
1621 );
1622 }
1623 if built_tools.contains("rust-analyzer") {
1624 builder.run(
1625 Command::new(&heat)
1626 .current_dir(&exe)
1627 .arg("dir")
1628 .arg("rust-analyzer")
1629 .args(&heat_flags)
1630 .arg("-cg")
1631 .arg("RustAnalyzerGroup")
1632 .arg("-dr")
1633 .arg("RustAnalyzer")
1634 .arg("-var")
1635 .arg("var.RustAnalyzerDir")
1636 .arg("-out")
1637 .arg(exe.join("RustAnalyzerGroup.wxs"))
1638 .arg("-t")
1639 .arg(etc.join("msi/remove-duplicates.xsl")),
1640 );
1641 }
1642 builder.run(
1643 Command::new(&heat)
1644 .current_dir(&exe)
1645 .arg("dir")
1646 .arg("clippy")
1647 .args(&heat_flags)
1648 .arg("-cg")
1649 .arg("ClippyGroup")
1650 .arg("-dr")
1651 .arg("Clippy")
1652 .arg("-var")
1653 .arg("var.ClippyDir")
1654 .arg("-out")
1655 .arg(exe.join("ClippyGroup.wxs"))
1656 .arg("-t")
1657 .arg(etc.join("msi/remove-duplicates.xsl")),
1658 );
1659 if built_tools.contains("rust-demangler") {
1660 builder.run(
1661 Command::new(&heat)
1662 .current_dir(&exe)
1663 .arg("dir")
1664 .arg("rust-demangler")
1665 .args(&heat_flags)
1666 .arg("-cg")
1667 .arg("RustDemanglerGroup")
1668 .arg("-dr")
1669 .arg("RustDemangler")
1670 .arg("-var")
1671 .arg("var.RustDemanglerDir")
1672 .arg("-out")
1673 .arg(exe.join("RustDemanglerGroup.wxs"))
1674 .arg("-t")
1675 .arg(etc.join("msi/remove-duplicates.xsl")),
1676 );
1677 }
1678 if built_tools.contains("miri") {
1679 builder.run(
1680 Command::new(&heat)
1681 .current_dir(&exe)
1682 .arg("dir")
1683 .arg("miri")
1684 .args(&heat_flags)
1685 .arg("-cg")
1686 .arg("MiriGroup")
1687 .arg("-dr")
1688 .arg("Miri")
1689 .arg("-var")
1690 .arg("var.MiriDir")
1691 .arg("-out")
1692 .arg(exe.join("MiriGroup.wxs"))
1693 .arg("-t")
1694 .arg(etc.join("msi/remove-duplicates.xsl")),
1695 );
1696 }
1697 builder.run(
1698 Command::new(&heat)
1699 .current_dir(&exe)
1700 .arg("dir")
1701 .arg("rust-analysis")
1702 .args(&heat_flags)
1703 .arg("-cg")
1704 .arg("AnalysisGroup")
1705 .arg("-dr")
1706 .arg("Analysis")
1707 .arg("-var")
1708 .arg("var.AnalysisDir")
1709 .arg("-out")
1710 .arg(exe.join("AnalysisGroup.wxs"))
1711 .arg("-t")
1712 .arg(etc.join("msi/remove-duplicates.xsl")),
1713 );
1714 if target.ends_with("windows-gnu") {
1715 builder.run(
1716 Command::new(&heat)
1717 .current_dir(&exe)
1718 .arg("dir")
1719 .arg("rust-mingw")
1720 .args(&heat_flags)
1721 .arg("-cg")
1722 .arg("GccGroup")
1723 .arg("-dr")
1724 .arg("Gcc")
1725 .arg("-var")
1726 .arg("var.GccDir")
1727 .arg("-out")
1728 .arg(exe.join("GccGroup.wxs")),
1729 );
1730 }
1731
1732 let candle = |input: &Path| {
1733 let output = exe.join(input.file_stem().unwrap()).with_extension("wixobj");
1734 let arch = if target.contains("x86_64") { "x64" } else { "x86" };
1735 let mut cmd = Command::new(&candle);
1736 cmd.current_dir(&exe)
1737 .arg("-nologo")
1738 .arg("-dRustcDir=rustc")
1739 .arg("-dDocsDir=rust-docs")
1740 .arg("-dCargoDir=cargo")
1741 .arg("-dStdDir=rust-std")
1742 .arg("-dAnalysisDir=rust-analysis")
1743 .arg("-dClippyDir=clippy")
1744 .arg("-arch")
1745 .arg(&arch)
1746 .arg("-out")
1747 .arg(&output)
1748 .arg(&input);
1749 add_env(builder, &mut cmd, target);
1750
1751 if built_tools.contains("rust-demangler") {
1752 cmd.arg("-dRustDemanglerDir=rust-demangler");
1753 }
1754 if built_tools.contains("rls") {
1755 cmd.arg("-dRlsDir=rls");
1756 }
1757 if built_tools.contains("rust-analyzer") {
1758 cmd.arg("-dRustAnalyzerDir=rust-analyzer");
1759 }
1760 if built_tools.contains("miri") {
1761 cmd.arg("-dMiriDir=miri");
1762 }
1763 if target.ends_with("windows-gnu") {
1764 cmd.arg("-dGccDir=rust-mingw");
1765 }
1766 builder.run(&mut cmd);
1767 };
1768 candle(&xform(&etc.join("msi/rust.wxs")));
1769 candle(&etc.join("msi/ui.wxs"));
1770 candle(&etc.join("msi/rustwelcomedlg.wxs"));
1771 candle("RustcGroup.wxs".as_ref());
1772 candle("DocsGroup.wxs".as_ref());
1773 candle("CargoGroup.wxs".as_ref());
1774 candle("StdGroup.wxs".as_ref());
1775 candle("ClippyGroup.wxs".as_ref());
1776 if built_tools.contains("rust-demangler") {
1777 candle("RustDemanglerGroup.wxs".as_ref());
1778 }
1779 if built_tools.contains("rls") {
1780 candle("RlsGroup.wxs".as_ref());
1781 }
1782 if built_tools.contains("rust-analyzer") {
1783 candle("RustAnalyzerGroup.wxs".as_ref());
1784 }
1785 if built_tools.contains("miri") {
1786 candle("MiriGroup.wxs".as_ref());
1787 }
1788 candle("AnalysisGroup.wxs".as_ref());
1789
1790 if target.ends_with("windows-gnu") {
1791 candle("GccGroup.wxs".as_ref());
1792 }
1793
1794 builder.create(&exe.join("LICENSE.rtf"), &rtf);
1795 builder.install(&etc.join("gfx/banner.bmp"), &exe, 0o644);
1796 builder.install(&etc.join("gfx/dialogbg.bmp"), &exe, 0o644);
1797
1798 builder.info(&format!("building `msi` installer with {:?}", light));
1799 let filename = format!("{}-{}.msi", pkgname(builder, "rust"), target.triple);
1800 let mut cmd = Command::new(&light);
1801 cmd.arg("-nologo")
1802 .arg("-ext")
1803 .arg("WixUIExtension")
1804 .arg("-ext")
1805 .arg("WixUtilExtension")
1806 .arg("-out")
1807 .arg(exe.join(&filename))
1808 .arg("rust.wixobj")
1809 .arg("ui.wixobj")
1810 .arg("rustwelcomedlg.wixobj")
1811 .arg("RustcGroup.wixobj")
1812 .arg("DocsGroup.wixobj")
1813 .arg("CargoGroup.wixobj")
1814 .arg("StdGroup.wixobj")
1815 .arg("AnalysisGroup.wixobj")
1816 .arg("ClippyGroup.wixobj")
1817 .current_dir(&exe);
1818
1819 if built_tools.contains("rls") {
1820 cmd.arg("RlsGroup.wixobj");
1821 }
1822 if built_tools.contains("rust-analyzer") {
1823 cmd.arg("RustAnalyzerGroup.wixobj");
1824 }
1825 if built_tools.contains("rust-demangler") {
1826 cmd.arg("RustDemanglerGroup.wixobj");
1827 }
1828 if built_tools.contains("miri") {
1829 cmd.arg("MiriGroup.wixobj");
1830 }
1831
1832 if target.ends_with("windows-gnu") {
1833 cmd.arg("GccGroup.wixobj");
1834 }
1835 // ICE57 wrongly complains about the shortcuts
1836 cmd.arg("-sice:ICE57");
1837
1838 let _time = timeit(builder);
1839 builder.run(&mut cmd);
1840
1841 if !builder.config.dry_run {
1842 t!(fs::rename(exe.join(&filename), distdir(builder).join(&filename)));
1843 }
1844 }
1845 }
1846 }
1847
1848 fn add_env(builder: &Builder<'_>, cmd: &mut Command, target: TargetSelection) {
1849 let mut parts = builder.version.split('.');
1850 cmd.env("CFG_RELEASE_INFO", builder.rust_version())
1851 .env("CFG_RELEASE_NUM", &builder.version)
1852 .env("CFG_RELEASE", builder.rust_release())
1853 .env("CFG_VER_MAJOR", parts.next().unwrap())
1854 .env("CFG_VER_MINOR", parts.next().unwrap())
1855 .env("CFG_VER_PATCH", parts.next().unwrap())
1856 .env("CFG_VER_BUILD", "0") // just needed to build
1857 .env("CFG_PACKAGE_VERS", builder.rust_package_vers())
1858 .env("CFG_PACKAGE_NAME", pkgname(builder, "rust"))
1859 .env("CFG_BUILD", target.triple)
1860 .env("CFG_CHANNEL", &builder.config.channel);
1861
1862 if target.contains("windows-gnullvm") {
1863 cmd.env("CFG_MINGW", "1").env("CFG_ABI", "LLVM");
1864 } else if target.contains("windows-gnu") {
1865 cmd.env("CFG_MINGW", "1").env("CFG_ABI", "GNU");
1866 } else {
1867 cmd.env("CFG_MINGW", "0").env("CFG_ABI", "MSVC");
1868 }
1869 }
1870
1871 /// Maybe add LLVM object files to the given destination lib-dir. Allows either static or dynamic linking.
1872 ///
1873
1874 /// Returns whether the files were actually copied.
1875 fn maybe_install_llvm(builder: &Builder<'_>, target: TargetSelection, dst_libdir: &Path) -> bool {
1876 if let Some(config) = builder.config.target_config.get(&target) {
1877 if config.llvm_config.is_some() && !builder.config.llvm_from_ci {
1878 // If the LLVM was externally provided, then we don't currently copy
1879 // artifacts into the sysroot. This is not necessarily the right
1880 // choice (in particular, it will require the LLVM dylib to be in
1881 // the linker's load path at runtime), but the common use case for
1882 // external LLVMs is distribution provided LLVMs, and in that case
1883 // they're usually in the standard search path (e.g., /usr/lib) and
1884 // copying them here is going to cause problems as we may end up
1885 // with the wrong files and isn't what distributions want.
1886 //
1887 // This behavior may be revisited in the future though.
1888 //
1889 // If the LLVM is coming from ourselves (just from CI) though, we
1890 // still want to install it, as it otherwise won't be available.
1891 return false;
1892 }
1893 }
1894
1895 // On macOS, rustc (and LLVM tools) link to an unversioned libLLVM.dylib
1896 // instead of libLLVM-11-rust-....dylib, as on linux. It's not entirely
1897 // clear why this is the case, though. llvm-config will emit the versioned
1898 // paths and we don't want those in the sysroot (as we're expecting
1899 // unversioned paths).
1900 if target.contains("apple-darwin") && builder.llvm_link_shared() {
1901 let src_libdir = builder.llvm_out(target).join("lib");
1902 let llvm_dylib_path = src_libdir.join("libLLVM.dylib");
1903 if llvm_dylib_path.exists() {
1904 builder.install(&llvm_dylib_path, dst_libdir, 0o644);
1905 }
1906 !builder.config.dry_run
1907 } else if let Ok(llvm_config) = crate::native::prebuilt_llvm_config(builder, target) {
1908 let mut cmd = Command::new(llvm_config);
1909 cmd.arg("--libfiles");
1910 builder.verbose(&format!("running {:?}", cmd));
1911 let files = output(&mut cmd);
1912 let build_llvm_out = &builder.llvm_out(builder.config.build);
1913 let target_llvm_out = &builder.llvm_out(target);
1914 for file in files.trim_end().split(' ') {
1915 // If we're not using a custom LLVM, make sure we package for the target.
1916 let file = if let Ok(relative_path) = Path::new(file).strip_prefix(build_llvm_out) {
1917 target_llvm_out.join(relative_path)
1918 } else {
1919 PathBuf::from(file)
1920 };
1921 builder.install(&file, dst_libdir, 0o644);
1922 }
1923 !builder.config.dry_run
1924 } else {
1925 false
1926 }
1927 }
1928
1929 /// Maybe add libLLVM.so to the target lib-dir for linking.
1930 pub fn maybe_install_llvm_target(builder: &Builder<'_>, target: TargetSelection, sysroot: &Path) {
1931 let dst_libdir = sysroot.join("lib/rustlib").join(&*target.triple).join("lib");
1932 // We do not need to copy LLVM files into the sysroot if it is not
1933 // dynamically linked; it is already included into librustc_llvm
1934 // statically.
1935 if builder.llvm_link_shared() {
1936 maybe_install_llvm(builder, target, &dst_libdir);
1937 }
1938 }
1939
1940 /// Maybe add libLLVM.so to the runtime lib-dir for rustc itself.
1941 pub fn maybe_install_llvm_runtime(builder: &Builder<'_>, target: TargetSelection, sysroot: &Path) {
1942 let dst_libdir =
1943 sysroot.join(builder.sysroot_libdir_relative(Compiler { stage: 1, host: target }));
1944 // We do not need to copy LLVM files into the sysroot if it is not
1945 // dynamically linked; it is already included into librustc_llvm
1946 // statically.
1947 if builder.llvm_link_shared() {
1948 maybe_install_llvm(builder, target, &dst_libdir);
1949 }
1950 }
1951
1952 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1953 pub struct LlvmTools {
1954 pub target: TargetSelection,
1955 }
1956
1957 impl Step for LlvmTools {
1958 type Output = Option<GeneratedTarball>;
1959 const ONLY_HOSTS: bool = true;
1960 const DEFAULT: bool = true;
1961
1962 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1963 let default = should_build_extended_tool(&run.builder, "llvm-tools");
1964 // FIXME: allow using the names of the tools themselves?
1965 run.alias("llvm-tools").default_condition(default)
1966 }
1967
1968 fn make_run(run: RunConfig<'_>) {
1969 run.builder.ensure(LlvmTools { target: run.target });
1970 }
1971
1972 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
1973 let target = self.target;
1974
1975 /* run only if llvm-config isn't used */
1976 if let Some(config) = builder.config.target_config.get(&target) {
1977 if let Some(ref _s) = config.llvm_config {
1978 builder.info(&format!("Skipping LlvmTools ({}): external LLVM", target));
1979 return None;
1980 }
1981 }
1982
1983 let mut tarball = Tarball::new(builder, "llvm-tools", &target.triple);
1984 tarball.set_overlay(OverlayKind::LLVM);
1985 tarball.is_preview(true);
1986
1987 // Prepare the image directory
1988 let src_bindir = builder.llvm_out(target).join("bin");
1989 let dst_bindir = format!("lib/rustlib/{}/bin", target.triple);
1990 for tool in LLVM_TOOLS {
1991 let exe = src_bindir.join(exe(tool, target));
1992 tarball.add_file(&exe, &dst_bindir, 0o755);
1993 }
1994
1995 // Copy libLLVM.so to the target lib dir as well, so the RPATH like
1996 // `$ORIGIN/../lib` can find it. It may also be used as a dependency
1997 // of `rustc-dev` to support the inherited `-lLLVM` when using the
1998 // compiler libraries.
1999 maybe_install_llvm_target(builder, target, tarball.image_dir());
2000
2001 Some(tarball.generate())
2002 }
2003 }
2004
2005 // Tarball intended for internal consumption to ease rustc/std development.
2006 //
2007 // Should not be considered stable by end users.
2008 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
2009 pub struct RustDev {
2010 pub target: TargetSelection,
2011 }
2012
2013 impl Step for RustDev {
2014 type Output = Option<GeneratedTarball>;
2015 const DEFAULT: bool = true;
2016 const ONLY_HOSTS: bool = true;
2017
2018 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2019 run.alias("rust-dev")
2020 }
2021
2022 fn make_run(run: RunConfig<'_>) {
2023 run.builder.ensure(RustDev { target: run.target });
2024 }
2025
2026 fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
2027 let target = self.target;
2028
2029 /* run only if llvm-config isn't used */
2030 if let Some(config) = builder.config.target_config.get(&target) {
2031 if let Some(ref _s) = config.llvm_config {
2032 builder.info(&format!("Skipping RustDev ({}): external LLVM", target));
2033 return None;
2034 }
2035 }
2036
2037 let mut tarball = Tarball::new(builder, "rust-dev", &target.triple);
2038 tarball.set_overlay(OverlayKind::LLVM);
2039
2040 let src_bindir = builder.llvm_out(target).join("bin");
2041 for bin in &[
2042 "llvm-config",
2043 "llvm-ar",
2044 "llvm-objdump",
2045 "llvm-profdata",
2046 "llvm-bcanalyzer",
2047 "llvm-cov",
2048 "llvm-dwp",
2049 "llvm-nm",
2050 ] {
2051 tarball.add_file(src_bindir.join(exe(bin, target)), "bin", 0o755);
2052 }
2053
2054 // We don't build LLD on some platforms, so only add it if it exists
2055 let lld_path = builder.lld_out(target).join("bin").join(exe("lld", target));
2056 if lld_path.exists() {
2057 tarball.add_file(lld_path, "bin", 0o755);
2058 }
2059
2060 tarball.add_file(&builder.llvm_filecheck(target), "bin", 0o755);
2061
2062 // Copy the include directory as well; needed mostly to build
2063 // librustc_llvm properly (e.g., llvm-config.h is in here). But also
2064 // just broadly useful to be able to link against the bundled LLVM.
2065 tarball.add_dir(&builder.llvm_out(target).join("include"), "include");
2066
2067 // Copy libLLVM.so to the target lib dir as well, so the RPATH like
2068 // `$ORIGIN/../lib` can find it. It may also be used as a dependency
2069 // of `rustc-dev` to support the inherited `-lLLVM` when using the
2070 // compiler libraries.
2071 let dst_libdir = tarball.image_dir().join("lib");
2072 maybe_install_llvm(builder, target, &dst_libdir);
2073 let link_type = if builder.llvm_link_shared() { "dynamic" } else { "static" };
2074 t!(std::fs::write(tarball.image_dir().join("link-type.txt"), link_type), dst_libdir);
2075
2076 Some(tarball.generate())
2077 }
2078 }
2079
2080 /// Tarball containing a prebuilt version of the build-manifest tool, intended to be used by the
2081 /// release process to avoid cloning the monorepo and building stuff.
2082 ///
2083 /// Should not be considered stable by end users.
2084 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
2085 pub struct BuildManifest {
2086 pub target: TargetSelection,
2087 }
2088
2089 impl Step for BuildManifest {
2090 type Output = GeneratedTarball;
2091 const DEFAULT: bool = false;
2092 const ONLY_HOSTS: bool = true;
2093
2094 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2095 run.alias("build-manifest")
2096 }
2097
2098 fn make_run(run: RunConfig<'_>) {
2099 run.builder.ensure(BuildManifest { target: run.target });
2100 }
2101
2102 fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
2103 let build_manifest = builder.tool_exe(Tool::BuildManifest);
2104
2105 let tarball = Tarball::new(builder, "build-manifest", &self.target.triple);
2106 tarball.add_file(&build_manifest, "bin", 0o755);
2107 tarball.generate()
2108 }
2109 }
2110
2111 /// Tarball containing artifacts necessary to reproduce the build of rustc.
2112 ///
2113 /// Currently this is the PGO profile data.
2114 ///
2115 /// Should not be considered stable by end users.
2116 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
2117 pub struct ReproducibleArtifacts {
2118 pub target: TargetSelection,
2119 }
2120
2121 impl Step for ReproducibleArtifacts {
2122 type Output = Option<GeneratedTarball>;
2123 const DEFAULT: bool = true;
2124 const ONLY_HOSTS: bool = true;
2125
2126 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2127 run.alias("reproducible-artifacts")
2128 }
2129
2130 fn make_run(run: RunConfig<'_>) {
2131 run.builder.ensure(ReproducibleArtifacts { target: run.target });
2132 }
2133
2134 fn run(self, builder: &Builder<'_>) -> Self::Output {
2135 let mut added_anything = false;
2136 let tarball = Tarball::new(builder, "reproducible-artifacts", &self.target.triple);
2137 if let Some(path) = builder.config.rust_profile_use.as_ref() {
2138 tarball.add_file(path, ".", 0o644);
2139 added_anything = true;
2140 }
2141 if let Some(path) = builder.config.llvm_profile_use.as_ref() {
2142 tarball.add_file(path, ".", 0o644);
2143 added_anything = true;
2144 }
2145 if added_anything { Some(tarball.generate()) } else { None }
2146 }
2147 }