]> git.lizzy.rs Git - rust.git/blob - src/bootstrap/dist.rs
Deal with spaces in the rust version.
[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");
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");
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 = line[(idx + 1)..].trim_start_matches(trim_chars).split(';').map(PathBuf::from);
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         }
651     }
652 }
653
654 fn skip_host_target_lib(builder: &Builder<'_>, compiler: Compiler) -> bool {
655     // The only true set of target libraries came from the build triple, so
656     // let's reduce redundant work by only producing archives from that host.
657     if compiler.host != builder.config.build {
658         builder.info("\tskipping, not a build host");
659         true
660     } else {
661         false
662     }
663 }
664
665 /// Copy stamped files into an image's `target/lib` directory.
666 fn copy_target_libs(builder: &Builder<'_>, target: TargetSelection, image: &Path, stamp: &Path) {
667     let dst = image.join("lib/rustlib").join(target.triple).join("lib");
668     let self_contained_dst = dst.join("self-contained");
669     t!(fs::create_dir_all(&dst));
670     t!(fs::create_dir_all(&self_contained_dst));
671     for (path, dependency_type) in builder.read_stamp_file(stamp) {
672         if dependency_type == DependencyType::TargetSelfContained {
673             builder.copy(&path, &self_contained_dst.join(path.file_name().unwrap()));
674         } else if dependency_type == DependencyType::Target || builder.config.build == target {
675             builder.copy(&path, &dst.join(path.file_name().unwrap()));
676         }
677     }
678 }
679
680 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
681 pub struct Std {
682     pub compiler: Compiler,
683     pub target: TargetSelection,
684 }
685
686 impl Step for Std {
687     type Output = PathBuf;
688     const DEFAULT: bool = true;
689
690     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
691         run.path("library/std")
692     }
693
694     fn make_run(run: RunConfig<'_>) {
695         run.builder.ensure(Std {
696             compiler: run.builder.compiler_for(
697                 run.builder.top_stage,
698                 run.builder.config.build,
699                 run.target,
700             ),
701             target: run.target,
702         });
703     }
704
705     fn run(self, builder: &Builder<'_>) -> PathBuf {
706         let compiler = self.compiler;
707         let target = self.target;
708
709         let name = pkgname(builder, "rust-std");
710         let archive = distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple));
711         if skip_host_target_lib(builder, compiler) {
712             return archive;
713         }
714
715         builder.ensure(compile::Std { compiler, target });
716
717         let image = tmpdir(builder).join(format!("{}-{}-image", name, target.triple));
718         let _ = fs::remove_dir_all(&image);
719
720         let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target);
721         let stamp = compile::libstd_stamp(builder, compiler_to_use, target);
722         copy_target_libs(builder, target, &image, &stamp);
723
724         let mut cmd = rust_installer(builder);
725         cmd.arg("generate")
726             .arg("--product-name=Rust")
727             .arg("--rel-manifest-dir=rustlib")
728             .arg("--success-message=std-is-standing-at-the-ready.")
729             .arg("--image-dir")
730             .arg(&image)
731             .arg("--work-dir")
732             .arg(&tmpdir(builder))
733             .arg("--output-dir")
734             .arg(&distdir(builder))
735             .arg(format!("--package-name={}-{}", name, target.triple))
736             .arg(format!("--component-name=rust-std-{}", target.triple))
737             .arg("--legacy-manifest-dirs=rustlib,cargo");
738
739         builder
740             .info(&format!("Dist std stage{} ({} -> {})", compiler.stage, &compiler.host, target));
741         let _time = timeit(builder);
742         builder.run(&mut cmd);
743         builder.remove_dir(&image);
744         archive
745     }
746 }
747
748 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
749 pub struct RustcDev {
750     pub compiler: Compiler,
751     pub target: TargetSelection,
752 }
753
754 impl Step for RustcDev {
755     type Output = PathBuf;
756     const DEFAULT: bool = true;
757     const ONLY_HOSTS: bool = true;
758
759     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
760         run.path("rustc-dev")
761     }
762
763     fn make_run(run: RunConfig<'_>) {
764         run.builder.ensure(RustcDev {
765             compiler: run.builder.compiler_for(
766                 run.builder.top_stage,
767                 run.builder.config.build,
768                 run.target,
769             ),
770             target: run.target,
771         });
772     }
773
774     fn run(self, builder: &Builder<'_>) -> PathBuf {
775         let compiler = self.compiler;
776         let target = self.target;
777
778         let name = pkgname(builder, "rustc-dev");
779         let archive = distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple));
780         if skip_host_target_lib(builder, compiler) {
781             return archive;
782         }
783
784         builder.ensure(compile::Rustc { compiler, target });
785
786         let image = tmpdir(builder).join(format!("{}-{}-image", name, target.triple));
787         let _ = fs::remove_dir_all(&image);
788
789         let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target);
790         let stamp = compile::librustc_stamp(builder, compiler_to_use, target);
791         copy_target_libs(builder, target, &image, &stamp);
792
793         let mut cmd = rust_installer(builder);
794         cmd.arg("generate")
795             .arg("--product-name=Rust")
796             .arg("--rel-manifest-dir=rustlib")
797             .arg("--success-message=Rust-is-ready-to-develop.")
798             .arg("--image-dir")
799             .arg(&image)
800             .arg("--work-dir")
801             .arg(&tmpdir(builder))
802             .arg("--output-dir")
803             .arg(&distdir(builder))
804             .arg(format!("--package-name={}-{}", name, target.triple))
805             .arg(format!("--component-name=rustc-dev-{}", target.triple))
806             .arg("--legacy-manifest-dirs=rustlib,cargo");
807
808         builder.info(&format!(
809             "Dist rustc-dev stage{} ({} -> {})",
810             compiler.stage, &compiler.host, target
811         ));
812         let _time = timeit(builder);
813         builder.run(&mut cmd);
814         builder.remove_dir(&image);
815         archive
816     }
817 }
818
819 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
820 pub struct Analysis {
821     pub compiler: Compiler,
822     pub target: TargetSelection,
823 }
824
825 impl Step for Analysis {
826     type Output = PathBuf;
827     const DEFAULT: bool = true;
828
829     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
830         let builder = run.builder;
831         run.path("analysis").default_condition(builder.config.extended)
832     }
833
834     fn make_run(run: RunConfig<'_>) {
835         run.builder.ensure(Analysis {
836             // Find the actual compiler (handling the full bootstrap option) which
837             // produced the save-analysis data because that data isn't copied
838             // through the sysroot uplifting.
839             compiler: run.builder.compiler_for(
840                 run.builder.top_stage,
841                 run.builder.config.build,
842                 run.target,
843             ),
844             target: run.target,
845         });
846     }
847
848     /// Creates a tarball of save-analysis metadata, if available.
849     fn run(self, builder: &Builder<'_>) -> PathBuf {
850         let compiler = self.compiler;
851         let target = self.target;
852         assert!(builder.config.extended);
853         let name = pkgname(builder, "rust-analysis");
854
855         if compiler.host != builder.config.build {
856             return distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple));
857         }
858
859         builder.ensure(compile::Std { compiler, target });
860
861         let image = tmpdir(builder).join(format!("{}-{}-image", name, target.triple));
862
863         let src = builder
864             .stage_out(compiler, Mode::Std)
865             .join(target.triple)
866             .join(builder.cargo_dir())
867             .join("deps");
868
869         let image_src = src.join("save-analysis");
870         let dst = image.join("lib/rustlib").join(target.triple).join("analysis");
871         t!(fs::create_dir_all(&dst));
872         builder.info(&format!("image_src: {:?}, dst: {:?}", image_src, dst));
873         builder.cp_r(&image_src, &dst);
874
875         let mut cmd = rust_installer(builder);
876         cmd.arg("generate")
877             .arg("--product-name=Rust")
878             .arg("--rel-manifest-dir=rustlib")
879             .arg("--success-message=save-analysis-saved.")
880             .arg("--image-dir")
881             .arg(&image)
882             .arg("--work-dir")
883             .arg(&tmpdir(builder))
884             .arg("--output-dir")
885             .arg(&distdir(builder))
886             .arg(format!("--package-name={}-{}", name, target.triple))
887             .arg(format!("--component-name=rust-analysis-{}", target.triple))
888             .arg("--legacy-manifest-dirs=rustlib,cargo");
889
890         builder.info("Dist analysis");
891         let _time = timeit(builder);
892         builder.run(&mut cmd);
893         builder.remove_dir(&image);
894         distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple))
895     }
896 }
897
898 /// Use the `builder` to make a filtered copy of `base`/X for X in (`src_dirs` - `exclude_dirs`) to
899 /// `dst_dir`.
900 fn copy_src_dirs(
901     builder: &Builder<'_>,
902     base: &Path,
903     src_dirs: &[&str],
904     exclude_dirs: &[&str],
905     dst_dir: &Path,
906 ) {
907     fn filter_fn(exclude_dirs: &[&str], dir: &str, path: &Path) -> bool {
908         let spath = match path.to_str() {
909             Some(path) => path,
910             None => return false,
911         };
912         if spath.ends_with('~') || spath.ends_with(".pyc") {
913             return false;
914         }
915
916         const LLVM_PROJECTS: &[&str] = &[
917             "llvm-project/clang",
918             "llvm-project\\clang",
919             "llvm-project/libunwind",
920             "llvm-project\\libunwind",
921             "llvm-project/lld",
922             "llvm-project\\lld",
923             "llvm-project/lldb",
924             "llvm-project\\lldb",
925             "llvm-project/llvm",
926             "llvm-project\\llvm",
927             "llvm-project/compiler-rt",
928             "llvm-project\\compiler-rt",
929         ];
930         if spath.contains("llvm-project")
931             && !spath.ends_with("llvm-project")
932             && !LLVM_PROJECTS.iter().any(|path| spath.contains(path))
933         {
934             return false;
935         }
936
937         const LLVM_TEST: &[&str] = &["llvm-project/llvm/test", "llvm-project\\llvm\\test"];
938         if LLVM_TEST.iter().any(|path| spath.contains(path))
939             && (spath.ends_with(".ll") || spath.ends_with(".td") || spath.ends_with(".s"))
940         {
941             return false;
942         }
943
944         let full_path = Path::new(dir).join(path);
945         if exclude_dirs.iter().any(|excl| full_path == Path::new(excl)) {
946             return false;
947         }
948
949         let excludes = [
950             "CVS",
951             "RCS",
952             "SCCS",
953             ".git",
954             ".gitignore",
955             ".gitmodules",
956             ".gitattributes",
957             ".cvsignore",
958             ".svn",
959             ".arch-ids",
960             "{arch}",
961             "=RELEASE-ID",
962             "=meta-update",
963             "=update",
964             ".bzr",
965             ".bzrignore",
966             ".bzrtags",
967             ".hg",
968             ".hgignore",
969             ".hgrags",
970             "_darcs",
971         ];
972         !path.iter().map(|s| s.to_str().unwrap()).any(|s| excludes.contains(&s))
973     }
974
975     // Copy the directories using our filter
976     for item in src_dirs {
977         let dst = &dst_dir.join(item);
978         t!(fs::create_dir_all(dst));
979         builder.cp_filtered(&base.join(item), dst, &|path| filter_fn(exclude_dirs, item, path));
980     }
981 }
982
983 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
984 pub struct Src;
985
986 impl Step for Src {
987     /// The output path of the src installer tarball
988     type Output = PathBuf;
989     const DEFAULT: bool = true;
990     const ONLY_HOSTS: bool = true;
991
992     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
993         run.path("src")
994     }
995
996     fn make_run(run: RunConfig<'_>) {
997         run.builder.ensure(Src);
998     }
999
1000     /// Creates the `rust-src` installer component
1001     fn run(self, builder: &Builder<'_>) -> PathBuf {
1002         let name = pkgname(builder, "rust-src");
1003         let image = tmpdir(builder).join(format!("{}-image", name));
1004         let _ = fs::remove_dir_all(&image);
1005
1006         // A lot of tools expect the rust-src component to be entirely in this directory, so if you
1007         // change that (e.g. by adding another directory `lib/rustlib/src/foo` or
1008         // `lib/rustlib/src/rust/foo`), you will need to go around hunting for implicit assumptions
1009         // and fix them...
1010         //
1011         // NOTE: if you update the paths here, you also should update the "virtual" path
1012         // translation code in `imported_source_files` in `src/librustc_metadata/rmeta/decoder.rs`
1013         let dst_src = image.join("lib/rustlib/src/rust");
1014         t!(fs::create_dir_all(&dst_src));
1015
1016         let src_files = ["Cargo.lock"];
1017         // This is the reduced set of paths which will become the rust-src component
1018         // (essentially libstd and all of its path dependencies).
1019         copy_src_dirs(
1020             builder,
1021             &builder.src,
1022             &["library"],
1023             &[
1024                 // not needed and contains symlinks which rustup currently
1025                 // chokes on when unpacking.
1026                 "library/backtrace/crates",
1027             ],
1028             &dst_src,
1029         );
1030         for file in src_files.iter() {
1031             builder.copy(&builder.src.join(file), &dst_src.join(file));
1032         }
1033
1034         // Create source tarball in rust-installer format
1035         let mut cmd = rust_installer(builder);
1036         cmd.arg("generate")
1037             .arg("--product-name=Rust")
1038             .arg("--rel-manifest-dir=rustlib")
1039             .arg("--success-message=Awesome-Source.")
1040             .arg("--image-dir")
1041             .arg(&image)
1042             .arg("--work-dir")
1043             .arg(&tmpdir(builder))
1044             .arg("--output-dir")
1045             .arg(&distdir(builder))
1046             .arg(format!("--package-name={}", name))
1047             .arg("--component-name=rust-src")
1048             .arg("--legacy-manifest-dirs=rustlib,cargo");
1049
1050         builder.info("Dist src");
1051         let _time = timeit(builder);
1052         builder.run(&mut cmd);
1053
1054         builder.remove_dir(&image);
1055         distdir(builder).join(&format!("{}.tar.gz", name))
1056     }
1057 }
1058
1059 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
1060 pub struct PlainSourceTarball;
1061
1062 impl Step for PlainSourceTarball {
1063     /// Produces the location of the tarball generated
1064     type Output = PathBuf;
1065     const DEFAULT: bool = true;
1066     const ONLY_HOSTS: bool = true;
1067
1068     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1069         let builder = run.builder;
1070         run.path("src").default_condition(builder.config.rust_dist_src)
1071     }
1072
1073     fn make_run(run: RunConfig<'_>) {
1074         run.builder.ensure(PlainSourceTarball);
1075     }
1076
1077     /// Creates the plain source tarball
1078     fn run(self, builder: &Builder<'_>) -> PathBuf {
1079         // Make sure that the root folder of tarball has the correct name
1080         let plain_name = format!("{}-src", pkgname(builder, "rustc"));
1081         let plain_dst_src = tmpdir(builder).join(&plain_name);
1082         let _ = fs::remove_dir_all(&plain_dst_src);
1083         t!(fs::create_dir_all(&plain_dst_src));
1084
1085         // This is the set of root paths which will become part of the source package
1086         let src_files = [
1087             "COPYRIGHT",
1088             "LICENSE-APACHE",
1089             "LICENSE-MIT",
1090             "CONTRIBUTING.md",
1091             "README.md",
1092             "RELEASES.md",
1093             "configure",
1094             "x.py",
1095             "config.toml.example",
1096             "Cargo.toml",
1097             "Cargo.lock",
1098         ];
1099         let src_dirs = ["src", "library"];
1100
1101         copy_src_dirs(builder, &builder.src, &src_dirs, &[], &plain_dst_src);
1102
1103         // Copy the files normally
1104         for item in &src_files {
1105             builder.copy(&builder.src.join(item), &plain_dst_src.join(item));
1106         }
1107
1108         // Create the version file
1109         builder.create(&plain_dst_src.join("version"), &builder.rust_version());
1110         if let Some(sha) = builder.rust_sha() {
1111             builder.create(&plain_dst_src.join("git-commit-hash"), &sha);
1112         }
1113
1114         // If we're building from git sources, we need to vendor a complete distribution.
1115         if builder.rust_info.is_git() {
1116             // Vendor all Cargo dependencies
1117             let mut cmd = Command::new(&builder.initial_cargo);
1118             cmd.arg("vendor")
1119                 .arg("--sync")
1120                 .arg(builder.src.join("./src/tools/rust-analyzer/Cargo.toml"))
1121                 .current_dir(&plain_dst_src);
1122             builder.run(&mut cmd);
1123         }
1124
1125         // Create plain source tarball
1126         let plain_name = format!("rustc-{}-src", builder.rust_package_vers());
1127         let mut tarball = distdir(builder).join(&format!("{}.tar.gz", plain_name));
1128         tarball.set_extension(""); // strip .gz
1129         tarball.set_extension(""); // strip .tar
1130         if let Some(dir) = tarball.parent() {
1131             builder.create_dir(&dir);
1132         }
1133         builder.info("running installer");
1134         let mut cmd = rust_installer(builder);
1135         cmd.arg("tarball")
1136             .arg("--input")
1137             .arg(&plain_name)
1138             .arg("--output")
1139             .arg(&tarball)
1140             .arg("--work-dir=.")
1141             .current_dir(tmpdir(builder));
1142
1143         builder.info("Create plain source tarball");
1144         let _time = timeit(builder);
1145         builder.run(&mut cmd);
1146         distdir(builder).join(&format!("{}.tar.gz", plain_name))
1147     }
1148 }
1149
1150 // We have to run a few shell scripts, which choke quite a bit on both `\`
1151 // characters and on `C:\` paths, so normalize both of them away.
1152 pub fn sanitize_sh(path: &Path) -> String {
1153     let path = path.to_str().unwrap().replace("\\", "/");
1154     return change_drive(&path).unwrap_or(path);
1155
1156     fn change_drive(s: &str) -> Option<String> {
1157         let mut ch = s.chars();
1158         let drive = ch.next().unwrap_or('C');
1159         if ch.next() != Some(':') {
1160             return None;
1161         }
1162         if ch.next() != Some('/') {
1163             return None;
1164         }
1165         Some(format!("/{}/{}", drive, &s[drive.len_utf8() + 2..]))
1166     }
1167 }
1168
1169 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
1170 pub struct Cargo {
1171     pub compiler: Compiler,
1172     pub target: TargetSelection,
1173 }
1174
1175 impl Step for Cargo {
1176     type Output = PathBuf;
1177     const ONLY_HOSTS: bool = true;
1178
1179     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1180         run.path("cargo")
1181     }
1182
1183     fn make_run(run: RunConfig<'_>) {
1184         run.builder.ensure(Cargo {
1185             compiler: run.builder.compiler_for(
1186                 run.builder.top_stage,
1187                 run.builder.config.build,
1188                 run.target,
1189             ),
1190             target: run.target,
1191         });
1192     }
1193
1194     fn run(self, builder: &Builder<'_>) -> PathBuf {
1195         let compiler = self.compiler;
1196         let target = self.target;
1197
1198         let src = builder.src.join("src/tools/cargo");
1199         let etc = src.join("src/etc");
1200         let release_num = builder.release_num("cargo");
1201         let name = pkgname(builder, "cargo");
1202         let version = builder.cargo_info.version(builder, &release_num);
1203
1204         let tmp = tmpdir(builder);
1205         let image = tmp.join("cargo-image");
1206         drop(fs::remove_dir_all(&image));
1207         builder.create_dir(&image);
1208
1209         // Prepare the image directory
1210         builder.create_dir(&image.join("share/zsh/site-functions"));
1211         builder.create_dir(&image.join("etc/bash_completion.d"));
1212         let cargo = builder.ensure(tool::Cargo { compiler, target });
1213         builder.install(&cargo, &image.join("bin"), 0o755);
1214         for man in t!(etc.join("man").read_dir()) {
1215             let man = t!(man);
1216             builder.install(&man.path(), &image.join("share/man/man1"), 0o644);
1217         }
1218         builder.install(&etc.join("_cargo"), &image.join("share/zsh/site-functions"), 0o644);
1219         builder.copy(&etc.join("cargo.bashcomp.sh"), &image.join("etc/bash_completion.d/cargo"));
1220         let doc = image.join("share/doc/cargo");
1221         builder.install(&src.join("README.md"), &doc, 0o644);
1222         builder.install(&src.join("LICENSE-MIT"), &doc, 0o644);
1223         builder.install(&src.join("LICENSE-APACHE"), &doc, 0o644);
1224         builder.install(&src.join("LICENSE-THIRD-PARTY"), &doc, 0o644);
1225
1226         // Prepare the overlay
1227         let overlay = tmp.join("cargo-overlay");
1228         drop(fs::remove_dir_all(&overlay));
1229         builder.create_dir(&overlay);
1230         builder.install(&src.join("README.md"), &overlay, 0o644);
1231         builder.install(&src.join("LICENSE-MIT"), &overlay, 0o644);
1232         builder.install(&src.join("LICENSE-APACHE"), &overlay, 0o644);
1233         builder.install(&src.join("LICENSE-THIRD-PARTY"), &overlay, 0o644);
1234         builder.create(&overlay.join("version"), &version);
1235
1236         // Generate the installer tarball
1237         let mut cmd = rust_installer(builder);
1238         cmd.arg("generate")
1239             .arg("--product-name=Rust")
1240             .arg("--rel-manifest-dir=rustlib")
1241             .arg("--success-message=Rust-is-ready-to-roll.")
1242             .arg("--image-dir")
1243             .arg(&image)
1244             .arg("--work-dir")
1245             .arg(&tmpdir(builder))
1246             .arg("--output-dir")
1247             .arg(&distdir(builder))
1248             .arg("--non-installed-overlay")
1249             .arg(&overlay)
1250             .arg(format!("--package-name={}-{}", name, target.triple))
1251             .arg("--component-name=cargo")
1252             .arg("--legacy-manifest-dirs=rustlib,cargo");
1253
1254         builder.info(&format!("Dist cargo stage{} ({})", compiler.stage, target));
1255         let _time = timeit(builder);
1256         builder.run(&mut cmd);
1257         distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple))
1258     }
1259 }
1260
1261 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
1262 pub struct Rls {
1263     pub compiler: Compiler,
1264     pub target: TargetSelection,
1265 }
1266
1267 impl Step for Rls {
1268     type Output = Option<PathBuf>;
1269     const ONLY_HOSTS: bool = true;
1270
1271     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1272         run.path("rls")
1273     }
1274
1275     fn make_run(run: RunConfig<'_>) {
1276         run.builder.ensure(Rls {
1277             compiler: run.builder.compiler_for(
1278                 run.builder.top_stage,
1279                 run.builder.config.build,
1280                 run.target,
1281             ),
1282             target: run.target,
1283         });
1284     }
1285
1286     fn run(self, builder: &Builder<'_>) -> Option<PathBuf> {
1287         let compiler = self.compiler;
1288         let target = self.target;
1289         assert!(builder.config.extended);
1290
1291         let src = builder.src.join("src/tools/rls");
1292         let release_num = builder.release_num("rls");
1293         let name = pkgname(builder, "rls");
1294         let version = builder.rls_info.version(builder, &release_num);
1295
1296         let tmp = tmpdir(builder);
1297         let image = tmp.join("rls-image");
1298         drop(fs::remove_dir_all(&image));
1299         t!(fs::create_dir_all(&image));
1300
1301         // Prepare the image directory
1302         // We expect RLS to build, because we've exited this step above if tool
1303         // state for RLS isn't testing.
1304         let rls = builder
1305             .ensure(tool::Rls { compiler, target, extra_features: Vec::new() })
1306             .or_else(|| {
1307                 missing_tool("RLS", builder.build.config.missing_tools);
1308                 None
1309             })?;
1310
1311         builder.install(&rls, &image.join("bin"), 0o755);
1312         let doc = image.join("share/doc/rls");
1313         builder.install(&src.join("README.md"), &doc, 0o644);
1314         builder.install(&src.join("LICENSE-MIT"), &doc, 0o644);
1315         builder.install(&src.join("LICENSE-APACHE"), &doc, 0o644);
1316
1317         // Prepare the overlay
1318         let overlay = tmp.join("rls-overlay");
1319         drop(fs::remove_dir_all(&overlay));
1320         t!(fs::create_dir_all(&overlay));
1321         builder.install(&src.join("README.md"), &overlay, 0o644);
1322         builder.install(&src.join("LICENSE-MIT"), &overlay, 0o644);
1323         builder.install(&src.join("LICENSE-APACHE"), &overlay, 0o644);
1324         builder.create(&overlay.join("version"), &version);
1325
1326         // Generate the installer tarball
1327         let mut cmd = rust_installer(builder);
1328         cmd.arg("generate")
1329             .arg("--product-name=Rust")
1330             .arg("--rel-manifest-dir=rustlib")
1331             .arg("--success-message=RLS-ready-to-serve.")
1332             .arg("--image-dir")
1333             .arg(&image)
1334             .arg("--work-dir")
1335             .arg(&tmpdir(builder))
1336             .arg("--output-dir")
1337             .arg(&distdir(builder))
1338             .arg("--non-installed-overlay")
1339             .arg(&overlay)
1340             .arg(format!("--package-name={}-{}", name, target.triple))
1341             .arg("--legacy-manifest-dirs=rustlib,cargo")
1342             .arg("--component-name=rls-preview");
1343
1344         builder.info(&format!("Dist RLS stage{} ({})", compiler.stage, target.triple));
1345         let _time = timeit(builder);
1346         builder.run(&mut cmd);
1347         Some(distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple)))
1348     }
1349 }
1350
1351 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
1352 pub struct RustAnalyzer {
1353     pub compiler: Compiler,
1354     pub target: TargetSelection,
1355 }
1356
1357 impl Step for RustAnalyzer {
1358     type Output = Option<PathBuf>;
1359     const ONLY_HOSTS: bool = true;
1360
1361     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1362         run.path("rust-analyzer")
1363     }
1364
1365     fn make_run(run: RunConfig<'_>) {
1366         run.builder.ensure(RustAnalyzer {
1367             compiler: run.builder.compiler_for(
1368                 run.builder.top_stage,
1369                 run.builder.config.build,
1370                 run.target,
1371             ),
1372             target: run.target,
1373         });
1374     }
1375
1376     fn run(self, builder: &Builder<'_>) -> Option<PathBuf> {
1377         let compiler = self.compiler;
1378         let target = self.target;
1379         assert!(builder.config.extended);
1380
1381         if target.contains("riscv64") {
1382             // riscv64 currently has an LLVM bug that makes rust-analyzer unable
1383             // to build. See #74813 for details.
1384             return None;
1385         }
1386
1387         let src = builder.src.join("src/tools/rust-analyzer");
1388         let release_num = builder.release_num("rust-analyzer/crates/rust-analyzer");
1389         let name = pkgname(builder, "rust-analyzer");
1390         let version = builder.rust_analyzer_info.version(builder, &release_num);
1391
1392         let tmp = tmpdir(builder);
1393         let image = tmp.join("rust-analyzer-image");
1394         drop(fs::remove_dir_all(&image));
1395         builder.create_dir(&image);
1396
1397         // Prepare the image directory
1398         // We expect rust-analyer to always build, as it doesn't depend on rustc internals
1399         // and doesn't have associated toolstate.
1400         let rust_analyzer = builder
1401             .ensure(tool::RustAnalyzer { compiler, target, extra_features: Vec::new() })
1402             .expect("rust-analyzer always builds");
1403
1404         builder.install(&rust_analyzer, &image.join("bin"), 0o755);
1405         let doc = image.join("share/doc/rust-analyzer");
1406         builder.install(&src.join("README.md"), &doc, 0o644);
1407         builder.install(&src.join("LICENSE-APACHE"), &doc, 0o644);
1408         builder.install(&src.join("LICENSE-MIT"), &doc, 0o644);
1409
1410         // Prepare the overlay
1411         let overlay = tmp.join("rust-analyzer-overlay");
1412         drop(fs::remove_dir_all(&overlay));
1413         t!(fs::create_dir_all(&overlay));
1414         builder.install(&src.join("README.md"), &overlay, 0o644);
1415         builder.install(&src.join("LICENSE-APACHE"), &doc, 0o644);
1416         builder.install(&src.join("LICENSE-MIT"), &doc, 0o644);
1417         builder.create(&overlay.join("version"), &version);
1418
1419         // Generate the installer tarball
1420         let mut cmd = rust_installer(builder);
1421         cmd.arg("generate")
1422             .arg("--product-name=Rust")
1423             .arg("--rel-manifest-dir=rustlib")
1424             .arg("--success-message=rust-analyzer-ready-to-serve.")
1425             .arg("--image-dir")
1426             .arg(&image)
1427             .arg("--work-dir")
1428             .arg(&tmpdir(builder))
1429             .arg("--output-dir")
1430             .arg(&distdir(builder))
1431             .arg("--non-installed-overlay")
1432             .arg(&overlay)
1433             .arg(format!("--package-name={}-{}", name, target.triple))
1434             .arg("--legacy-manifest-dirs=rustlib,cargo")
1435             .arg("--component-name=rust-analyzer-preview");
1436
1437         builder.info(&format!("Dist rust-analyzer stage{} ({})", compiler.stage, target));
1438         let _time = timeit(builder);
1439         builder.run(&mut cmd);
1440         Some(distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple)))
1441     }
1442 }
1443
1444 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
1445 pub struct Clippy {
1446     pub compiler: Compiler,
1447     pub target: TargetSelection,
1448 }
1449
1450 impl Step for Clippy {
1451     type Output = PathBuf;
1452     const ONLY_HOSTS: bool = true;
1453
1454     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1455         run.path("clippy")
1456     }
1457
1458     fn make_run(run: RunConfig<'_>) {
1459         run.builder.ensure(Clippy {
1460             compiler: run.builder.compiler_for(
1461                 run.builder.top_stage,
1462                 run.builder.config.build,
1463                 run.target,
1464             ),
1465             target: run.target,
1466         });
1467     }
1468
1469     fn run(self, builder: &Builder<'_>) -> PathBuf {
1470         let compiler = self.compiler;
1471         let target = self.target;
1472         assert!(builder.config.extended);
1473
1474         let src = builder.src.join("src/tools/clippy");
1475         let release_num = builder.release_num("clippy");
1476         let name = pkgname(builder, "clippy");
1477         let version = builder.clippy_info.version(builder, &release_num);
1478
1479         let tmp = tmpdir(builder);
1480         let image = tmp.join("clippy-image");
1481         drop(fs::remove_dir_all(&image));
1482         builder.create_dir(&image);
1483
1484         // Prepare the image directory
1485         // We expect clippy to build, because we've exited this step above if tool
1486         // state for clippy isn't testing.
1487         let clippy = builder
1488             .ensure(tool::Clippy { compiler, target, extra_features: Vec::new() })
1489             .expect("clippy expected to build - essential tool");
1490         let cargoclippy = builder
1491             .ensure(tool::CargoClippy { compiler, target, extra_features: Vec::new() })
1492             .expect("clippy expected to build - essential tool");
1493
1494         builder.install(&clippy, &image.join("bin"), 0o755);
1495         builder.install(&cargoclippy, &image.join("bin"), 0o755);
1496         let doc = image.join("share/doc/clippy");
1497         builder.install(&src.join("README.md"), &doc, 0o644);
1498         builder.install(&src.join("LICENSE-APACHE"), &doc, 0o644);
1499         builder.install(&src.join("LICENSE-MIT"), &doc, 0o644);
1500
1501         // Prepare the overlay
1502         let overlay = tmp.join("clippy-overlay");
1503         drop(fs::remove_dir_all(&overlay));
1504         t!(fs::create_dir_all(&overlay));
1505         builder.install(&src.join("README.md"), &overlay, 0o644);
1506         builder.install(&src.join("LICENSE-APACHE"), &doc, 0o644);
1507         builder.install(&src.join("LICENSE-MIT"), &doc, 0o644);
1508         builder.create(&overlay.join("version"), &version);
1509
1510         // Generate the installer tarball
1511         let mut cmd = rust_installer(builder);
1512         cmd.arg("generate")
1513             .arg("--product-name=Rust")
1514             .arg("--rel-manifest-dir=rustlib")
1515             .arg("--success-message=clippy-ready-to-serve.")
1516             .arg("--image-dir")
1517             .arg(&image)
1518             .arg("--work-dir")
1519             .arg(&tmpdir(builder))
1520             .arg("--output-dir")
1521             .arg(&distdir(builder))
1522             .arg("--non-installed-overlay")
1523             .arg(&overlay)
1524             .arg(format!("--package-name={}-{}", name, target.triple))
1525             .arg("--legacy-manifest-dirs=rustlib,cargo")
1526             .arg("--component-name=clippy-preview");
1527
1528         builder.info(&format!("Dist clippy stage{} ({})", compiler.stage, target));
1529         let _time = timeit(builder);
1530         builder.run(&mut cmd);
1531         distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple))
1532     }
1533 }
1534
1535 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
1536 pub struct Miri {
1537     pub compiler: Compiler,
1538     pub target: TargetSelection,
1539 }
1540
1541 impl Step for Miri {
1542     type Output = Option<PathBuf>;
1543     const ONLY_HOSTS: bool = true;
1544
1545     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1546         run.path("miri")
1547     }
1548
1549     fn make_run(run: RunConfig<'_>) {
1550         run.builder.ensure(Miri {
1551             compiler: run.builder.compiler_for(
1552                 run.builder.top_stage,
1553                 run.builder.config.build,
1554                 run.target,
1555             ),
1556             target: run.target,
1557         });
1558     }
1559
1560     fn run(self, builder: &Builder<'_>) -> Option<PathBuf> {
1561         let compiler = self.compiler;
1562         let target = self.target;
1563         assert!(builder.config.extended);
1564
1565         let src = builder.src.join("src/tools/miri");
1566         let release_num = builder.release_num("miri");
1567         let name = pkgname(builder, "miri");
1568         let version = builder.miri_info.version(builder, &release_num);
1569
1570         let tmp = tmpdir(builder);
1571         let image = tmp.join("miri-image");
1572         drop(fs::remove_dir_all(&image));
1573         builder.create_dir(&image);
1574
1575         // Prepare the image directory
1576         // We expect miri to build, because we've exited this step above if tool
1577         // state for miri isn't testing.
1578         let miri = builder
1579             .ensure(tool::Miri { compiler, target, extra_features: Vec::new() })
1580             .or_else(|| {
1581                 missing_tool("miri", builder.build.config.missing_tools);
1582                 None
1583             })?;
1584         let cargomiri = builder
1585             .ensure(tool::CargoMiri { compiler, target, extra_features: Vec::new() })
1586             .or_else(|| {
1587                 missing_tool("cargo miri", builder.build.config.missing_tools);
1588                 None
1589             })?;
1590
1591         builder.install(&miri, &image.join("bin"), 0o755);
1592         builder.install(&cargomiri, &image.join("bin"), 0o755);
1593         let doc = image.join("share/doc/miri");
1594         builder.install(&src.join("README.md"), &doc, 0o644);
1595         builder.install(&src.join("LICENSE-APACHE"), &doc, 0o644);
1596         builder.install(&src.join("LICENSE-MIT"), &doc, 0o644);
1597
1598         // Prepare the overlay
1599         let overlay = tmp.join("miri-overlay");
1600         drop(fs::remove_dir_all(&overlay));
1601         t!(fs::create_dir_all(&overlay));
1602         builder.install(&src.join("README.md"), &overlay, 0o644);
1603         builder.install(&src.join("LICENSE-APACHE"), &doc, 0o644);
1604         builder.install(&src.join("LICENSE-MIT"), &doc, 0o644);
1605         builder.create(&overlay.join("version"), &version);
1606
1607         // Generate the installer tarball
1608         let mut cmd = rust_installer(builder);
1609         cmd.arg("generate")
1610             .arg("--product-name=Rust")
1611             .arg("--rel-manifest-dir=rustlib")
1612             .arg("--success-message=miri-ready-to-serve.")
1613             .arg("--image-dir")
1614             .arg(&image)
1615             .arg("--work-dir")
1616             .arg(&tmpdir(builder))
1617             .arg("--output-dir")
1618             .arg(&distdir(builder))
1619             .arg("--non-installed-overlay")
1620             .arg(&overlay)
1621             .arg(format!("--package-name={}-{}", name, target.triple))
1622             .arg("--legacy-manifest-dirs=rustlib,cargo")
1623             .arg("--component-name=miri-preview");
1624
1625         builder.info(&format!("Dist miri stage{} ({})", compiler.stage, target));
1626         let _time = timeit(builder);
1627         builder.run(&mut cmd);
1628         Some(distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple)))
1629     }
1630 }
1631
1632 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
1633 pub struct Rustfmt {
1634     pub compiler: Compiler,
1635     pub target: TargetSelection,
1636 }
1637
1638 impl Step for Rustfmt {
1639     type Output = Option<PathBuf>;
1640     const ONLY_HOSTS: bool = true;
1641
1642     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1643         run.path("rustfmt")
1644     }
1645
1646     fn make_run(run: RunConfig<'_>) {
1647         run.builder.ensure(Rustfmt {
1648             compiler: run.builder.compiler_for(
1649                 run.builder.top_stage,
1650                 run.builder.config.build,
1651                 run.target,
1652             ),
1653             target: run.target,
1654         });
1655     }
1656
1657     fn run(self, builder: &Builder<'_>) -> Option<PathBuf> {
1658         let compiler = self.compiler;
1659         let target = self.target;
1660
1661         let src = builder.src.join("src/tools/rustfmt");
1662         let release_num = builder.release_num("rustfmt");
1663         let name = pkgname(builder, "rustfmt");
1664         let version = builder.rustfmt_info.version(builder, &release_num);
1665
1666         let tmp = tmpdir(builder);
1667         let image = tmp.join("rustfmt-image");
1668         drop(fs::remove_dir_all(&image));
1669         builder.create_dir(&image);
1670
1671         // Prepare the image directory
1672         let rustfmt = builder
1673             .ensure(tool::Rustfmt { compiler, target, extra_features: Vec::new() })
1674             .or_else(|| {
1675                 missing_tool("Rustfmt", builder.build.config.missing_tools);
1676                 None
1677             })?;
1678         let cargofmt = builder
1679             .ensure(tool::Cargofmt { compiler, target, extra_features: Vec::new() })
1680             .or_else(|| {
1681                 missing_tool("Cargofmt", builder.build.config.missing_tools);
1682                 None
1683             })?;
1684
1685         builder.install(&rustfmt, &image.join("bin"), 0o755);
1686         builder.install(&cargofmt, &image.join("bin"), 0o755);
1687         let doc = image.join("share/doc/rustfmt");
1688         builder.install(&src.join("README.md"), &doc, 0o644);
1689         builder.install(&src.join("LICENSE-MIT"), &doc, 0o644);
1690         builder.install(&src.join("LICENSE-APACHE"), &doc, 0o644);
1691
1692         // Prepare the overlay
1693         let overlay = tmp.join("rustfmt-overlay");
1694         drop(fs::remove_dir_all(&overlay));
1695         builder.create_dir(&overlay);
1696         builder.install(&src.join("README.md"), &overlay, 0o644);
1697         builder.install(&src.join("LICENSE-MIT"), &overlay, 0o644);
1698         builder.install(&src.join("LICENSE-APACHE"), &overlay, 0o644);
1699         builder.create(&overlay.join("version"), &version);
1700
1701         // Generate the installer tarball
1702         let mut cmd = rust_installer(builder);
1703         cmd.arg("generate")
1704             .arg("--product-name=Rust")
1705             .arg("--rel-manifest-dir=rustlib")
1706             .arg("--success-message=rustfmt-ready-to-fmt.")
1707             .arg("--image-dir")
1708             .arg(&image)
1709             .arg("--work-dir")
1710             .arg(&tmpdir(builder))
1711             .arg("--output-dir")
1712             .arg(&distdir(builder))
1713             .arg("--non-installed-overlay")
1714             .arg(&overlay)
1715             .arg(format!("--package-name={}-{}", name, target.triple))
1716             .arg("--legacy-manifest-dirs=rustlib,cargo")
1717             .arg("--component-name=rustfmt-preview");
1718
1719         builder.info(&format!("Dist Rustfmt stage{} ({})", compiler.stage, target));
1720         let _time = timeit(builder);
1721         builder.run(&mut cmd);
1722         Some(distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple)))
1723     }
1724 }
1725
1726 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
1727 pub struct Extended {
1728     stage: u32,
1729     host: TargetSelection,
1730     target: TargetSelection,
1731 }
1732
1733 impl Step for Extended {
1734     type Output = ();
1735     const DEFAULT: bool = true;
1736     const ONLY_HOSTS: bool = true;
1737
1738     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1739         let builder = run.builder;
1740         run.path("extended").default_condition(builder.config.extended)
1741     }
1742
1743     fn make_run(run: RunConfig<'_>) {
1744         run.builder.ensure(Extended {
1745             stage: run.builder.top_stage,
1746             host: run.builder.config.build,
1747             target: run.target,
1748         });
1749     }
1750
1751     /// Creates a combined installer for the specified target in the provided stage.
1752     fn run(self, builder: &Builder<'_>) {
1753         let target = self.target;
1754         let stage = self.stage;
1755         let compiler = builder.compiler_for(self.stage, self.host, self.target);
1756
1757         builder.info(&format!("Dist extended stage{} ({})", compiler.stage, target));
1758
1759         let rustc_installer = builder.ensure(Rustc { compiler: builder.compiler(stage, target) });
1760         let cargo_installer = builder.ensure(Cargo { compiler, target });
1761         let rustfmt_installer = builder.ensure(Rustfmt { compiler, target });
1762         let rls_installer = builder.ensure(Rls { compiler, target });
1763         let rust_analyzer_installer = builder.ensure(RustAnalyzer { compiler, target });
1764         let llvm_tools_installer = builder.ensure(LlvmTools { target });
1765         let clippy_installer = builder.ensure(Clippy { compiler, target });
1766         let miri_installer = builder.ensure(Miri { compiler, target });
1767         let mingw_installer = builder.ensure(Mingw { host: target });
1768         let analysis_installer = builder.ensure(Analysis { compiler, target });
1769
1770         let docs_installer = builder.ensure(Docs { host: target });
1771         let std_installer =
1772             builder.ensure(Std { compiler: builder.compiler(stage, target), target });
1773
1774         let tmp = tmpdir(builder);
1775         let overlay = tmp.join("extended-overlay");
1776         let etc = builder.src.join("src/etc/installer");
1777         let work = tmp.join("work");
1778
1779         let _ = fs::remove_dir_all(&overlay);
1780         builder.install(&builder.src.join("COPYRIGHT"), &overlay, 0o644);
1781         builder.install(&builder.src.join("LICENSE-APACHE"), &overlay, 0o644);
1782         builder.install(&builder.src.join("LICENSE-MIT"), &overlay, 0o644);
1783         let version = builder.rust_version();
1784         builder.create(&overlay.join("version"), &version);
1785         if let Some(sha) = builder.rust_sha() {
1786             builder.create(&overlay.join("git-commit-hash"), &sha);
1787         }
1788         builder.install(&etc.join("README.md"), &overlay, 0o644);
1789
1790         // When rust-std package split from rustc, we needed to ensure that during
1791         // upgrades rustc was upgraded before rust-std. To avoid rustc clobbering
1792         // the std files during uninstall. To do this ensure that rustc comes
1793         // before rust-std in the list below.
1794         let mut tarballs = Vec::new();
1795         tarballs.push(rustc_installer);
1796         tarballs.push(cargo_installer);
1797         tarballs.extend(rls_installer.clone());
1798         tarballs.extend(rust_analyzer_installer.clone());
1799         tarballs.push(clippy_installer);
1800         tarballs.extend(miri_installer.clone());
1801         tarballs.extend(rustfmt_installer.clone());
1802         tarballs.extend(llvm_tools_installer);
1803         tarballs.push(analysis_installer);
1804         tarballs.push(std_installer);
1805         if builder.config.docs {
1806             tarballs.push(docs_installer);
1807         }
1808         if target.contains("pc-windows-gnu") {
1809             tarballs.push(mingw_installer.unwrap());
1810         }
1811         let mut input_tarballs = tarballs[0].as_os_str().to_owned();
1812         for tarball in &tarballs[1..] {
1813             input_tarballs.push(",");
1814             input_tarballs.push(tarball);
1815         }
1816
1817         builder.info("building combined installer");
1818         let mut cmd = rust_installer(builder);
1819         cmd.arg("combine")
1820             .arg("--product-name=Rust")
1821             .arg("--rel-manifest-dir=rustlib")
1822             .arg("--success-message=Rust-is-ready-to-roll.")
1823             .arg("--work-dir")
1824             .arg(&work)
1825             .arg("--output-dir")
1826             .arg(&distdir(builder))
1827             .arg(format!("--package-name={}-{}", pkgname(builder, "rust"), target.triple))
1828             .arg("--legacy-manifest-dirs=rustlib,cargo")
1829             .arg("--input-tarballs")
1830             .arg(input_tarballs)
1831             .arg("--non-installed-overlay")
1832             .arg(&overlay);
1833         let time = timeit(&builder);
1834         builder.run(&mut cmd);
1835         drop(time);
1836
1837         let mut license = String::new();
1838         license += &builder.read(&builder.src.join("COPYRIGHT"));
1839         license += &builder.read(&builder.src.join("LICENSE-APACHE"));
1840         license += &builder.read(&builder.src.join("LICENSE-MIT"));
1841         license.push_str("\n");
1842         license.push_str("\n");
1843
1844         let rtf = r"{\rtf1\ansi\deff0{\fonttbl{\f0\fnil\fcharset0 Arial;}}\nowwrap\fs18";
1845         let mut rtf = rtf.to_string();
1846         rtf.push_str("\n");
1847         for line in license.lines() {
1848             rtf.push_str(line);
1849             rtf.push_str("\\line ");
1850         }
1851         rtf.push_str("}");
1852
1853         fn filter(contents: &str, marker: &str) -> String {
1854             let start = format!("tool-{}-start", marker);
1855             let end = format!("tool-{}-end", marker);
1856             let mut lines = Vec::new();
1857             let mut omitted = false;
1858             for line in contents.lines() {
1859                 if line.contains(&start) {
1860                     omitted = true;
1861                 } else if line.contains(&end) {
1862                     omitted = false;
1863                 } else if !omitted {
1864                     lines.push(line);
1865                 }
1866             }
1867
1868             lines.join("\n")
1869         }
1870
1871         let xform = |p: &Path| {
1872             let mut contents = t!(fs::read_to_string(p));
1873             if rls_installer.is_none() {
1874                 contents = filter(&contents, "rls");
1875             }
1876             if rust_analyzer_installer.is_none() {
1877                 contents = filter(&contents, "rust-analyzer");
1878             }
1879             if miri_installer.is_none() {
1880                 contents = filter(&contents, "miri");
1881             }
1882             if rustfmt_installer.is_none() {
1883                 contents = filter(&contents, "rustfmt");
1884             }
1885             let ret = tmp.join(p.file_name().unwrap());
1886             t!(fs::write(&ret, &contents));
1887             ret
1888         };
1889
1890         if target.contains("apple-darwin") {
1891             builder.info("building pkg installer");
1892             let pkg = tmp.join("pkg");
1893             let _ = fs::remove_dir_all(&pkg);
1894
1895             let pkgbuild = |component: &str| {
1896                 let mut cmd = Command::new("pkgbuild");
1897                 cmd.arg("--identifier")
1898                     .arg(format!("org.rust-lang.{}", component))
1899                     .arg("--scripts")
1900                     .arg(pkg.join(component))
1901                     .arg("--nopayload")
1902                     .arg(pkg.join(component).with_extension("pkg"));
1903                 builder.run(&mut cmd);
1904             };
1905
1906             let prepare = |name: &str| {
1907                 builder.create_dir(&pkg.join(name));
1908                 builder.cp_r(
1909                     &work.join(&format!("{}-{}", pkgname(builder, name), target.triple)),
1910                     &pkg.join(name),
1911                 );
1912                 builder.install(&etc.join("pkg/postinstall"), &pkg.join(name), 0o755);
1913                 pkgbuild(name);
1914             };
1915             prepare("rustc");
1916             prepare("cargo");
1917             prepare("rust-docs");
1918             prepare("rust-std");
1919             prepare("rust-analysis");
1920             prepare("clippy");
1921
1922             if rls_installer.is_some() {
1923                 prepare("rls");
1924             }
1925             if rust_analyzer_installer.is_some() {
1926                 prepare("rust-analyzer");
1927             }
1928             if miri_installer.is_some() {
1929                 prepare("miri");
1930             }
1931
1932             // create an 'uninstall' package
1933             builder.install(&etc.join("pkg/postinstall"), &pkg.join("uninstall"), 0o755);
1934             pkgbuild("uninstall");
1935
1936             builder.create_dir(&pkg.join("res"));
1937             builder.create(&pkg.join("res/LICENSE.txt"), &license);
1938             builder.install(&etc.join("gfx/rust-logo.png"), &pkg.join("res"), 0o644);
1939             let mut cmd = Command::new("productbuild");
1940             cmd.arg("--distribution")
1941                 .arg(xform(&etc.join("pkg/Distribution.xml")))
1942                 .arg("--resources")
1943                 .arg(pkg.join("res"))
1944                 .arg(distdir(builder).join(format!(
1945                     "{}-{}.pkg",
1946                     pkgname(builder, "rust"),
1947                     target.triple
1948                 )))
1949                 .arg("--package-path")
1950                 .arg(&pkg);
1951             let _time = timeit(builder);
1952             builder.run(&mut cmd);
1953         }
1954
1955         if target.contains("windows") {
1956             let exe = tmp.join("exe");
1957             let _ = fs::remove_dir_all(&exe);
1958
1959             let prepare = |name: &str| {
1960                 builder.create_dir(&exe.join(name));
1961                 let dir = if name == "rust-std" || name == "rust-analysis" {
1962                     format!("{}-{}", name, target.triple)
1963                 } else if name == "rls" {
1964                     "rls-preview".to_string()
1965                 } else if name == "rust-analyzer" {
1966                     "rust-analyzer-preview".to_string()
1967                 } else if name == "clippy" {
1968                     "clippy-preview".to_string()
1969                 } else if name == "miri" {
1970                     "miri-preview".to_string()
1971                 } else {
1972                     name.to_string()
1973                 };
1974                 builder.cp_r(
1975                     &work.join(&format!("{}-{}", pkgname(builder, name), target.triple)).join(dir),
1976                     &exe.join(name),
1977                 );
1978                 builder.remove(&exe.join(name).join("manifest.in"));
1979             };
1980             prepare("rustc");
1981             prepare("cargo");
1982             prepare("rust-analysis");
1983             prepare("rust-docs");
1984             prepare("rust-std");
1985             prepare("clippy");
1986             if rls_installer.is_some() {
1987                 prepare("rls");
1988             }
1989             if rust_analyzer_installer.is_some() {
1990                 prepare("rust-analyzer");
1991             }
1992             if miri_installer.is_some() {
1993                 prepare("miri");
1994             }
1995             if target.contains("windows-gnu") {
1996                 prepare("rust-mingw");
1997             }
1998
1999             builder.install(&etc.join("gfx/rust-logo.ico"), &exe, 0o644);
2000
2001             // Generate msi installer
2002             let wix = PathBuf::from(env::var_os("WIX").unwrap());
2003             let heat = wix.join("bin/heat.exe");
2004             let candle = wix.join("bin/candle.exe");
2005             let light = wix.join("bin/light.exe");
2006
2007             let heat_flags = ["-nologo", "-gg", "-sfrag", "-srd", "-sreg"];
2008             builder.run(
2009                 Command::new(&heat)
2010                     .current_dir(&exe)
2011                     .arg("dir")
2012                     .arg("rustc")
2013                     .args(&heat_flags)
2014                     .arg("-cg")
2015                     .arg("RustcGroup")
2016                     .arg("-dr")
2017                     .arg("Rustc")
2018                     .arg("-var")
2019                     .arg("var.RustcDir")
2020                     .arg("-out")
2021                     .arg(exe.join("RustcGroup.wxs")),
2022             );
2023             builder.run(
2024                 Command::new(&heat)
2025                     .current_dir(&exe)
2026                     .arg("dir")
2027                     .arg("rust-docs")
2028                     .args(&heat_flags)
2029                     .arg("-cg")
2030                     .arg("DocsGroup")
2031                     .arg("-dr")
2032                     .arg("Docs")
2033                     .arg("-var")
2034                     .arg("var.DocsDir")
2035                     .arg("-out")
2036                     .arg(exe.join("DocsGroup.wxs"))
2037                     .arg("-t")
2038                     .arg(etc.join("msi/squash-components.xsl")),
2039             );
2040             builder.run(
2041                 Command::new(&heat)
2042                     .current_dir(&exe)
2043                     .arg("dir")
2044                     .arg("cargo")
2045                     .args(&heat_flags)
2046                     .arg("-cg")
2047                     .arg("CargoGroup")
2048                     .arg("-dr")
2049                     .arg("Cargo")
2050                     .arg("-var")
2051                     .arg("var.CargoDir")
2052                     .arg("-out")
2053                     .arg(exe.join("CargoGroup.wxs"))
2054                     .arg("-t")
2055                     .arg(etc.join("msi/remove-duplicates.xsl")),
2056             );
2057             builder.run(
2058                 Command::new(&heat)
2059                     .current_dir(&exe)
2060                     .arg("dir")
2061                     .arg("rust-std")
2062                     .args(&heat_flags)
2063                     .arg("-cg")
2064                     .arg("StdGroup")
2065                     .arg("-dr")
2066                     .arg("Std")
2067                     .arg("-var")
2068                     .arg("var.StdDir")
2069                     .arg("-out")
2070                     .arg(exe.join("StdGroup.wxs")),
2071             );
2072             if rls_installer.is_some() {
2073                 builder.run(
2074                     Command::new(&heat)
2075                         .current_dir(&exe)
2076                         .arg("dir")
2077                         .arg("rls")
2078                         .args(&heat_flags)
2079                         .arg("-cg")
2080                         .arg("RlsGroup")
2081                         .arg("-dr")
2082                         .arg("Rls")
2083                         .arg("-var")
2084                         .arg("var.RlsDir")
2085                         .arg("-out")
2086                         .arg(exe.join("RlsGroup.wxs"))
2087                         .arg("-t")
2088                         .arg(etc.join("msi/remove-duplicates.xsl")),
2089                 );
2090             }
2091             if rust_analyzer_installer.is_some() {
2092                 builder.run(
2093                     Command::new(&heat)
2094                         .current_dir(&exe)
2095                         .arg("dir")
2096                         .arg("rust-analyzer")
2097                         .args(&heat_flags)
2098                         .arg("-cg")
2099                         .arg("RustAnalyzerGroup")
2100                         .arg("-dr")
2101                         .arg("RustAnalyzer")
2102                         .arg("-var")
2103                         .arg("var.RustAnalyzerDir")
2104                         .arg("-out")
2105                         .arg(exe.join("RustAnalyzerGroup.wxs"))
2106                         .arg("-t")
2107                         .arg(etc.join("msi/remove-duplicates.xsl")),
2108                 );
2109             }
2110             builder.run(
2111                 Command::new(&heat)
2112                     .current_dir(&exe)
2113                     .arg("dir")
2114                     .arg("clippy")
2115                     .args(&heat_flags)
2116                     .arg("-cg")
2117                     .arg("ClippyGroup")
2118                     .arg("-dr")
2119                     .arg("Clippy")
2120                     .arg("-var")
2121                     .arg("var.ClippyDir")
2122                     .arg("-out")
2123                     .arg(exe.join("ClippyGroup.wxs"))
2124                     .arg("-t")
2125                     .arg(etc.join("msi/remove-duplicates.xsl")),
2126             );
2127             if miri_installer.is_some() {
2128                 builder.run(
2129                     Command::new(&heat)
2130                         .current_dir(&exe)
2131                         .arg("dir")
2132                         .arg("miri")
2133                         .args(&heat_flags)
2134                         .arg("-cg")
2135                         .arg("MiriGroup")
2136                         .arg("-dr")
2137                         .arg("Miri")
2138                         .arg("-var")
2139                         .arg("var.MiriDir")
2140                         .arg("-out")
2141                         .arg(exe.join("MiriGroup.wxs"))
2142                         .arg("-t")
2143                         .arg(etc.join("msi/remove-duplicates.xsl")),
2144                 );
2145             }
2146             builder.run(
2147                 Command::new(&heat)
2148                     .current_dir(&exe)
2149                     .arg("dir")
2150                     .arg("rust-analysis")
2151                     .args(&heat_flags)
2152                     .arg("-cg")
2153                     .arg("AnalysisGroup")
2154                     .arg("-dr")
2155                     .arg("Analysis")
2156                     .arg("-var")
2157                     .arg("var.AnalysisDir")
2158                     .arg("-out")
2159                     .arg(exe.join("AnalysisGroup.wxs"))
2160                     .arg("-t")
2161                     .arg(etc.join("msi/remove-duplicates.xsl")),
2162             );
2163             if target.contains("windows-gnu") {
2164                 builder.run(
2165                     Command::new(&heat)
2166                         .current_dir(&exe)
2167                         .arg("dir")
2168                         .arg("rust-mingw")
2169                         .args(&heat_flags)
2170                         .arg("-cg")
2171                         .arg("GccGroup")
2172                         .arg("-dr")
2173                         .arg("Gcc")
2174                         .arg("-var")
2175                         .arg("var.GccDir")
2176                         .arg("-out")
2177                         .arg(exe.join("GccGroup.wxs")),
2178                 );
2179             }
2180
2181             let candle = |input: &Path| {
2182                 let output = exe.join(input.file_stem().unwrap()).with_extension("wixobj");
2183                 let arch = if target.contains("x86_64") { "x64" } else { "x86" };
2184                 let mut cmd = Command::new(&candle);
2185                 cmd.current_dir(&exe)
2186                     .arg("-nologo")
2187                     .arg("-dRustcDir=rustc")
2188                     .arg("-dDocsDir=rust-docs")
2189                     .arg("-dCargoDir=cargo")
2190                     .arg("-dStdDir=rust-std")
2191                     .arg("-dAnalysisDir=rust-analysis")
2192                     .arg("-dClippyDir=clippy")
2193                     .arg("-arch")
2194                     .arg(&arch)
2195                     .arg("-out")
2196                     .arg(&output)
2197                     .arg(&input);
2198                 add_env(builder, &mut cmd, target);
2199
2200                 if rls_installer.is_some() {
2201                     cmd.arg("-dRlsDir=rls");
2202                 }
2203                 if rust_analyzer_installer.is_some() {
2204                     cmd.arg("-dRustAnalyzerDir=rust-analyzer");
2205                 }
2206                 if miri_installer.is_some() {
2207                     cmd.arg("-dMiriDir=miri");
2208                 }
2209                 if target.contains("windows-gnu") {
2210                     cmd.arg("-dGccDir=rust-mingw");
2211                 }
2212                 builder.run(&mut cmd);
2213             };
2214             candle(&xform(&etc.join("msi/rust.wxs")));
2215             candle(&etc.join("msi/ui.wxs"));
2216             candle(&etc.join("msi/rustwelcomedlg.wxs"));
2217             candle("RustcGroup.wxs".as_ref());
2218             candle("DocsGroup.wxs".as_ref());
2219             candle("CargoGroup.wxs".as_ref());
2220             candle("StdGroup.wxs".as_ref());
2221             candle("ClippyGroup.wxs".as_ref());
2222             if rls_installer.is_some() {
2223                 candle("RlsGroup.wxs".as_ref());
2224             }
2225             if rust_analyzer_installer.is_some() {
2226                 candle("RustAnalyzerGroup.wxs".as_ref());
2227             }
2228             if miri_installer.is_some() {
2229                 candle("MiriGroup.wxs".as_ref());
2230             }
2231             candle("AnalysisGroup.wxs".as_ref());
2232
2233             if target.contains("windows-gnu") {
2234                 candle("GccGroup.wxs".as_ref());
2235             }
2236
2237             builder.create(&exe.join("LICENSE.rtf"), &rtf);
2238             builder.install(&etc.join("gfx/banner.bmp"), &exe, 0o644);
2239             builder.install(&etc.join("gfx/dialogbg.bmp"), &exe, 0o644);
2240
2241             builder.info(&format!("building `msi` installer with {:?}", light));
2242             let filename = format!("{}-{}.msi", pkgname(builder, "rust"), target.triple);
2243             let mut cmd = Command::new(&light);
2244             cmd.arg("-nologo")
2245                 .arg("-ext")
2246                 .arg("WixUIExtension")
2247                 .arg("-ext")
2248                 .arg("WixUtilExtension")
2249                 .arg("-out")
2250                 .arg(exe.join(&filename))
2251                 .arg("rust.wixobj")
2252                 .arg("ui.wixobj")
2253                 .arg("rustwelcomedlg.wixobj")
2254                 .arg("RustcGroup.wixobj")
2255                 .arg("DocsGroup.wixobj")
2256                 .arg("CargoGroup.wixobj")
2257                 .arg("StdGroup.wixobj")
2258                 .arg("AnalysisGroup.wixobj")
2259                 .arg("ClippyGroup.wixobj")
2260                 .current_dir(&exe);
2261
2262             if rls_installer.is_some() {
2263                 cmd.arg("RlsGroup.wixobj");
2264             }
2265             if rust_analyzer_installer.is_some() {
2266                 cmd.arg("RustAnalyzerGroup.wixobj");
2267             }
2268             if miri_installer.is_some() {
2269                 cmd.arg("MiriGroup.wixobj");
2270             }
2271
2272             if target.contains("windows-gnu") {
2273                 cmd.arg("GccGroup.wixobj");
2274             }
2275             // ICE57 wrongly complains about the shortcuts
2276             cmd.arg("-sice:ICE57");
2277
2278             let _time = timeit(builder);
2279             builder.run(&mut cmd);
2280
2281             if !builder.config.dry_run {
2282                 t!(fs::rename(exe.join(&filename), distdir(builder).join(&filename)));
2283             }
2284         }
2285     }
2286 }
2287
2288 fn add_env(builder: &Builder<'_>, cmd: &mut Command, target: TargetSelection) {
2289     let mut parts = channel::CFG_RELEASE_NUM.split('.');
2290     cmd.env("CFG_RELEASE_INFO", builder.rust_version())
2291         .env("CFG_RELEASE_NUM", channel::CFG_RELEASE_NUM)
2292         .env("CFG_RELEASE", builder.rust_release())
2293         .env("CFG_VER_MAJOR", parts.next().unwrap())
2294         .env("CFG_VER_MINOR", parts.next().unwrap())
2295         .env("CFG_VER_PATCH", parts.next().unwrap())
2296         .env("CFG_VER_BUILD", "0") // just needed to build
2297         .env("CFG_PACKAGE_VERS", builder.rust_package_vers())
2298         .env("CFG_PACKAGE_NAME", pkgname(builder, "rust"))
2299         .env("CFG_BUILD", target.triple)
2300         .env("CFG_CHANNEL", &builder.config.channel);
2301
2302     if target.contains("windows-gnu") {
2303         cmd.env("CFG_MINGW", "1").env("CFG_ABI", "GNU");
2304     } else {
2305         cmd.env("CFG_MINGW", "0").env("CFG_ABI", "MSVC");
2306     }
2307
2308     if target.contains("x86_64") {
2309         cmd.env("CFG_PLATFORM", "x64");
2310     } else {
2311         cmd.env("CFG_PLATFORM", "x86");
2312     }
2313 }
2314
2315 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
2316 pub struct HashSign;
2317
2318 impl Step for HashSign {
2319     type Output = ();
2320     const ONLY_HOSTS: bool = true;
2321
2322     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2323         run.path("hash-and-sign")
2324     }
2325
2326     fn make_run(run: RunConfig<'_>) {
2327         run.builder.ensure(HashSign);
2328     }
2329
2330     fn run(self, builder: &Builder<'_>) {
2331         // This gets called by `promote-release`
2332         // (https://github.com/rust-lang/rust-central-station/tree/master/promote-release).
2333         let mut cmd = builder.tool_cmd(Tool::BuildManifest);
2334         if builder.config.dry_run {
2335             return;
2336         }
2337         let sign = builder.config.dist_sign_folder.as_ref().unwrap_or_else(|| {
2338             panic!("\n\nfailed to specify `dist.sign-folder` in `config.toml`\n\n")
2339         });
2340         let addr = builder.config.dist_upload_addr.as_ref().unwrap_or_else(|| {
2341             panic!("\n\nfailed to specify `dist.upload-addr` in `config.toml`\n\n")
2342         });
2343         let pass = if env::var("BUILD_MANIFEST_DISABLE_SIGNING").is_err() {
2344             let file = builder.config.dist_gpg_password_file.as_ref().unwrap_or_else(|| {
2345                 panic!("\n\nfailed to specify `dist.gpg-password-file` in `config.toml`\n\n")
2346             });
2347             t!(fs::read_to_string(&file))
2348         } else {
2349             String::new()
2350         };
2351
2352         let today = output(Command::new("date").arg("+%Y-%m-%d"));
2353
2354         cmd.arg(sign);
2355         cmd.arg(distdir(builder));
2356         cmd.arg(today.trim());
2357         cmd.arg(builder.rust_package_vers());
2358         cmd.arg(addr);
2359         cmd.arg(builder.package_vers(&builder.release_num("cargo")));
2360         cmd.arg(builder.package_vers(&builder.release_num("rls")));
2361         cmd.arg(builder.package_vers(&builder.release_num("rust-analyzer/crates/rust-analyzer")));
2362         cmd.arg(builder.package_vers(&builder.release_num("clippy")));
2363         cmd.arg(builder.package_vers(&builder.release_num("miri")));
2364         cmd.arg(builder.package_vers(&builder.release_num("rustfmt")));
2365         cmd.arg(builder.llvm_tools_package_vers());
2366
2367         builder.create_dir(&distdir(builder));
2368
2369         let mut child = t!(cmd.stdin(Stdio::piped()).spawn());
2370         t!(child.stdin.take().unwrap().write_all(pass.as_bytes()));
2371         let status = t!(child.wait());
2372         assert!(status.success());
2373     }
2374 }
2375
2376 /// Maybe add libLLVM.so to the given destination lib-dir. It will only have
2377 /// been built if LLVM tools are linked dynamically.
2378 ///
2379 /// Note: This function does not yet support Windows, but we also don't support
2380 ///       linking LLVM tools dynamically on Windows yet.
2381 fn maybe_install_llvm(builder: &Builder<'_>, target: TargetSelection, dst_libdir: &Path) {
2382     let src_libdir = builder.llvm_out(target).join("lib");
2383
2384     if target.contains("apple-darwin") {
2385         let llvm_dylib_path = src_libdir.join("libLLVM.dylib");
2386         if llvm_dylib_path.exists() {
2387             builder.install(&llvm_dylib_path, dst_libdir, 0o644);
2388         }
2389         return;
2390     }
2391
2392     // Usually libLLVM.so is a symlink to something like libLLVM-6.0.so.
2393     // Since tools link to the latter rather than the former, we have to
2394     // follow the symlink to find out what to distribute.
2395     let llvm_dylib_path = src_libdir.join("libLLVM.so");
2396     if llvm_dylib_path.exists() {
2397         let llvm_dylib_path = llvm_dylib_path.canonicalize().unwrap_or_else(|e| {
2398             panic!("dist: Error calling canonicalize path `{}`: {}", llvm_dylib_path.display(), e);
2399         });
2400
2401         builder.install(&llvm_dylib_path, dst_libdir, 0o644);
2402     }
2403 }
2404
2405 /// Maybe add libLLVM.so to the target lib-dir for linking.
2406 pub fn maybe_install_llvm_target(builder: &Builder<'_>, target: TargetSelection, sysroot: &Path) {
2407     let dst_libdir = sysroot.join("lib/rustlib").join(&*target.triple).join("lib");
2408     maybe_install_llvm(builder, target, &dst_libdir);
2409 }
2410
2411 /// Maybe add libLLVM.so to the runtime lib-dir for rustc itself.
2412 pub fn maybe_install_llvm_runtime(builder: &Builder<'_>, target: TargetSelection, sysroot: &Path) {
2413     let dst_libdir =
2414         sysroot.join(builder.sysroot_libdir_relative(Compiler { stage: 1, host: target }));
2415     maybe_install_llvm(builder, target, &dst_libdir);
2416 }
2417
2418 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
2419 pub struct LlvmTools {
2420     pub target: TargetSelection,
2421 }
2422
2423 impl Step for LlvmTools {
2424     type Output = Option<PathBuf>;
2425     const ONLY_HOSTS: bool = true;
2426
2427     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2428         run.path("llvm-tools")
2429     }
2430
2431     fn make_run(run: RunConfig<'_>) {
2432         run.builder.ensure(LlvmTools { target: run.target });
2433     }
2434
2435     fn run(self, builder: &Builder<'_>) -> Option<PathBuf> {
2436         let target = self.target;
2437         assert!(builder.config.extended);
2438
2439         /* run only if llvm-config isn't used */
2440         if let Some(config) = builder.config.target_config.get(&target) {
2441             if let Some(ref _s) = config.llvm_config {
2442                 builder.info(&format!("Skipping LlvmTools ({}): external LLVM", target));
2443                 return None;
2444             }
2445         }
2446
2447         builder.info(&format!("Dist LlvmTools ({})", target));
2448         let _time = timeit(builder);
2449         let src = builder.src.join("src/llvm-project/llvm");
2450         let name = pkgname(builder, "llvm-tools");
2451
2452         let tmp = tmpdir(builder);
2453         let image = tmp.join("llvm-tools-image");
2454         drop(fs::remove_dir_all(&image));
2455
2456         // Prepare the image directory
2457         let src_bindir = builder.llvm_out(target).join("bin");
2458         let dst_bindir = image.join("lib/rustlib").join(&*target.triple).join("bin");
2459         t!(fs::create_dir_all(&dst_bindir));
2460         for tool in LLVM_TOOLS {
2461             let exe = src_bindir.join(exe(tool, target));
2462             builder.install(&exe, &dst_bindir, 0o755);
2463         }
2464
2465         // Copy libLLVM.so to the target lib dir as well, so the RPATH like
2466         // `$ORIGIN/../lib` can find it. It may also be used as a dependency
2467         // of `rustc-dev` to support the inherited `-lLLVM` when using the
2468         // compiler libraries.
2469         maybe_install_llvm_target(builder, target, &image);
2470
2471         // Prepare the overlay
2472         let overlay = tmp.join("llvm-tools-overlay");
2473         drop(fs::remove_dir_all(&overlay));
2474         builder.create_dir(&overlay);
2475         builder.install(&src.join("README.txt"), &overlay, 0o644);
2476         builder.install(&src.join("LICENSE.TXT"), &overlay, 0o644);
2477         builder.create(&overlay.join("version"), &builder.llvm_tools_vers());
2478
2479         // Generate the installer tarball
2480         let mut cmd = rust_installer(builder);
2481         cmd.arg("generate")
2482             .arg("--product-name=Rust")
2483             .arg("--rel-manifest-dir=rustlib")
2484             .arg("--success-message=llvm-tools-installed.")
2485             .arg("--image-dir")
2486             .arg(&image)
2487             .arg("--work-dir")
2488             .arg(&tmpdir(builder))
2489             .arg("--output-dir")
2490             .arg(&distdir(builder))
2491             .arg("--non-installed-overlay")
2492             .arg(&overlay)
2493             .arg(format!("--package-name={}-{}", name, target.triple))
2494             .arg("--legacy-manifest-dirs=rustlib,cargo")
2495             .arg("--component-name=llvm-tools-preview");
2496
2497         builder.run(&mut cmd);
2498         Some(distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple)))
2499     }
2500 }