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