]> git.lizzy.rs Git - rust.git/blob - src/bootstrap/dist.rs
Ensure StorageDead is created even if variable initialization fails
[rust.git] / src / bootstrap / dist.rs
1 // Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 //! Implementation of the various distribution aspects of the compiler.
12 //!
13 //! This module is responsible for creating tarballs of the standard library,
14 //! compiler, and documentation. This ends up being what we distribute to
15 //! everyone as well.
16 //!
17 //! No tarball is actually created literally in this file, but rather we shell
18 //! out to `rust-installer` still. This may one day be replaced with bits and
19 //! pieces of `rustup.rs`!
20
21 use std::env;
22 use std::fs::{self, File};
23 use std::io::{Read, Write};
24 use std::path::{PathBuf, Path};
25 use std::process::{Command, Stdio};
26
27 use build_helper::output;
28
29 use {Compiler, Mode, LLVM_TOOLS};
30 use channel;
31 use util::{libdir, is_dylib, exe};
32 use builder::{Builder, RunConfig, ShouldRun, Step};
33 use compile;
34 use native;
35 use tool::{self, Tool};
36 use cache::{INTERNER, Interned};
37 use time;
38
39 pub fn pkgname(builder: &Builder, component: &str) -> String {
40     if component == "cargo" {
41         format!("{}-{}", component, builder.cargo_package_vers())
42     } else if component == "rls" {
43         format!("{}-{}", component, builder.rls_package_vers())
44     } else if component == "clippy" {
45         format!("{}-{}", component, builder.clippy_package_vers())
46     } else if component == "rustfmt" {
47         format!("{}-{}", component, builder.rustfmt_package_vers())
48     } else if component == "llvm-tools" {
49         format!("{}-{}", component, builder.llvm_tools_package_vers())
50     } else {
51         assert!(component.starts_with("rust"));
52         format!("{}-{}", component, builder.rust_package_vers())
53     }
54 }
55
56 fn distdir(builder: &Builder) -> PathBuf {
57     builder.out.join("dist")
58 }
59
60 pub fn tmpdir(builder: &Builder) -> PathBuf {
61     builder.out.join("tmp/dist")
62 }
63
64 fn rust_installer(builder: &Builder) -> Command {
65     builder.tool_cmd(Tool::RustInstaller)
66 }
67
68 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
69 pub struct Docs {
70     pub stage: u32,
71     pub host: Interned<String>,
72 }
73
74 impl Step for Docs {
75     type Output = PathBuf;
76     const DEFAULT: bool = true;
77
78     fn should_run(run: ShouldRun) -> ShouldRun {
79         run.path("src/doc")
80     }
81
82     fn make_run(run: RunConfig) {
83         run.builder.ensure(Docs {
84             stage: run.builder.top_stage,
85             host: run.target,
86         });
87     }
88
89     /// Builds the `rust-docs` installer component.
90     fn run(self, builder: &Builder) -> PathBuf {
91         let host = self.host;
92
93         let name = pkgname(builder, "rust-docs");
94
95         builder.info(&format!("Dist docs ({})", host));
96         if !builder.config.docs {
97             builder.info(&format!("\tskipping - docs disabled"));
98             return distdir(builder).join(format!("{}-{}.tar.gz", name, host));
99         }
100
101         builder.default_doc(None);
102
103         let image = tmpdir(builder).join(format!("{}-{}-image", name, host));
104         let _ = fs::remove_dir_all(&image);
105
106         let dst = image.join("share/doc/rust/html");
107         t!(fs::create_dir_all(&dst));
108         let src = builder.doc_out(host);
109         builder.cp_r(&src, &dst);
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").arg(&image)
117            .arg("--work-dir").arg(&tmpdir(builder))
118            .arg("--output-dir").arg(&distdir(builder))
119            .arg(format!("--package-name={}-{}", name, host))
120            .arg("--component-name=rust-docs")
121            .arg("--legacy-manifest-dirs=rustlib,cargo")
122            .arg("--bulk-dirs=share/doc/rust/html");
123         builder.run(&mut cmd);
124         builder.remove_dir(&image);
125
126         distdir(builder).join(format!("{}-{}.tar.gz", name, host))
127     }
128 }
129
130 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
131 pub struct RustcDocs {
132     pub stage: u32,
133     pub host: Interned<String>,
134 }
135
136 impl Step for RustcDocs {
137     type Output = PathBuf;
138     const DEFAULT: bool = true;
139
140     fn should_run(run: ShouldRun) -> ShouldRun {
141         run.path("src/librustc")
142     }
143
144     fn make_run(run: RunConfig) {
145         run.builder.ensure(RustcDocs {
146             stage: run.builder.top_stage,
147             host: run.target,
148         });
149     }
150
151     /// Builds the `rustc-docs` installer component.
152     fn run(self, builder: &Builder) -> PathBuf {
153         let host = self.host;
154
155         let name = pkgname(builder, "rustc-docs");
156
157         builder.info(&format!("Dist compiler docs ({})", host));
158         if !builder.config.compiler_docs {
159             builder.info(&format!("\tskipping - compiler docs disabled"));
160             return distdir(builder).join(format!("{}-{}.tar.gz", name, host));
161         }
162
163         builder.default_doc(None);
164
165         let image = tmpdir(builder).join(format!("{}-{}-image", name, host));
166         let _ = fs::remove_dir_all(&image);
167
168         let dst = image.join("share/doc/rust/html");
169         t!(fs::create_dir_all(&dst));
170         let src = builder.compiler_doc_out(host);
171         builder.cp_r(&src, &dst);
172
173         let mut cmd = rust_installer(builder);
174         cmd.arg("generate")
175            .arg("--product-name=Rustc-Documentation")
176            .arg("--rel-manifest-dir=rustlib")
177            .arg("--success-message=Rustc-documentation-is-installed.")
178            .arg("--image-dir").arg(&image)
179            .arg("--work-dir").arg(&tmpdir(builder))
180            .arg("--output-dir").arg(&distdir(builder))
181            .arg(format!("--package-name={}-{}", name, host))
182            .arg("--component-name=rustc-docs")
183            .arg("--legacy-manifest-dirs=rustlib,cargo")
184            .arg("--bulk-dirs=share/doc/rust/html");
185         builder.run(&mut cmd);
186         builder.remove_dir(&image);
187
188         distdir(builder).join(format!("{}-{}.tar.gz", name, host))
189     }
190 }
191
192 fn find_files(files: &[&str], path: &[PathBuf]) -> Vec<PathBuf> {
193     let mut found = Vec::with_capacity(files.len());
194
195     for file in files {
196         let file_path =
197             path.iter()
198                 .map(|dir| dir.join(file))
199                 .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, plat_root: &Path, target_triple: Interned<String>, builder: &Builder
213 ) {
214     //Ask gcc where it keeps its stuff
215     let mut cmd = Command::new(builder.cc(target_triple));
216     cmd.arg("-print-search-dirs");
217     let gcc_out = output(&mut cmd);
218
219     let mut bin_path: Vec<_> = env::split_paths(&env::var_os("PATH").unwrap_or_default()).collect();
220     let mut lib_path = Vec::new();
221
222     for line in gcc_out.lines() {
223         let idx = line.find(':').unwrap();
224         let key = &line[..idx];
225         let trim_chars: &[_] = &[' ', '='];
226         let value =
227             line[(idx + 1)..]
228                 .trim_left_matches(trim_chars)
229                 .split(';')
230                 .map(PathBuf::from);
231
232         if key == "programs" {
233             bin_path.extend(value);
234         } else if key == "libraries" {
235             lib_path.extend(value);
236         }
237     }
238
239     let target_tools = ["gcc.exe", "ld.exe", "dlltool.exe", "libwinpthread-1.dll"];
240     let mut rustc_dlls = vec!["libstdc++-6.dll", "libwinpthread-1.dll"];
241     if target_triple.starts_with("i686-") {
242         rustc_dlls.push("libgcc_s_dw2-1.dll");
243     } else {
244         rustc_dlls.push("libgcc_s_seh-1.dll");
245     }
246
247     let target_libs = [ //MinGW libs
248         "libgcc.a",
249         "libgcc_eh.a",
250         "libgcc_s.a",
251         "libm.a",
252         "libmingw32.a",
253         "libmingwex.a",
254         "libstdc++.a",
255         "libiconv.a",
256         "libmoldname.a",
257         "libpthread.a",
258         //Windows import libs
259         "libadvapi32.a",
260         "libbcrypt.a",
261         "libcomctl32.a",
262         "libcomdlg32.a",
263         "libcredui.a",
264         "libcrypt32.a",
265         "libdbghelp.a",
266         "libgdi32.a",
267         "libimagehlp.a",
268         "libiphlpapi.a",
269         "libkernel32.a",
270         "libmsimg32.a",
271         "libmsvcrt.a",
272         "libodbc32.a",
273         "libole32.a",
274         "liboleaut32.a",
275         "libopengl32.a",
276         "libpsapi.a",
277         "librpcrt4.a",
278         "libsecur32.a",
279         "libsetupapi.a",
280         "libshell32.a",
281         "libsynchronization.a",
282         "libuser32.a",
283         "libuserenv.a",
284         "libuuid.a",
285         "libwinhttp.a",
286         "libwinmm.a",
287         "libwinspool.a",
288         "libws2_32.a",
289         "libwsock32.a",
290     ];
291
292     //Find mingw artifacts we want to bundle
293     let target_tools = find_files(&target_tools, &bin_path);
294     let rustc_dlls = find_files(&rustc_dlls, &bin_path);
295     let target_libs = find_files(&target_libs, &lib_path);
296
297     // Copy runtime dlls next to rustc.exe
298     let dist_bin_dir = rust_root.join("bin/");
299     fs::create_dir_all(&dist_bin_dir).expect("creating dist_bin_dir failed");
300     for src in rustc_dlls {
301         builder.copy_to_folder(&src, &dist_bin_dir);
302     }
303
304     //Copy platform tools to platform-specific bin directory
305     let target_bin_dir = plat_root.join("lib").join("rustlib").join(target_triple).join("bin");
306     fs::create_dir_all(&target_bin_dir).expect("creating target_bin_dir failed");
307     for src in target_tools {
308         builder.copy_to_folder(&src, &target_bin_dir);
309     }
310
311     //Copy platform libs to platform-specific lib directory
312     let target_lib_dir = plat_root.join("lib").join("rustlib").join(target_triple).join("lib");
313     fs::create_dir_all(&target_lib_dir).expect("creating target_lib_dir failed");
314     for src in target_libs {
315         builder.copy_to_folder(&src, &target_lib_dir);
316     }
317 }
318
319 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
320 pub struct Mingw {
321     pub host: Interned<String>,
322 }
323
324 impl Step for Mingw {
325     type Output = Option<PathBuf>;
326     const DEFAULT: bool = true;
327
328     fn should_run(run: ShouldRun) -> ShouldRun {
329         run.never()
330     }
331
332     fn make_run(run: RunConfig) {
333         run.builder.ensure(Mingw { host: run.target });
334     }
335
336     /// Build the `rust-mingw` installer component.
337     ///
338     /// This contains all the bits and pieces to run the MinGW Windows targets
339     /// without any extra installed software (e.g. we bundle gcc, libraries, etc).
340     fn run(self, builder: &Builder) -> Option<PathBuf> {
341         let host = self.host;
342
343         if !host.contains("pc-windows-gnu") {
344             return None;
345         }
346
347         builder.info(&format!("Dist mingw ({})", host));
348         let name = pkgname(builder, "rust-mingw");
349         let image = tmpdir(builder).join(format!("{}-{}-image", name, host));
350         let _ = fs::remove_dir_all(&image);
351         t!(fs::create_dir_all(&image));
352
353         // The first argument is a "temporary directory" which is just
354         // thrown away (this contains the runtime DLLs included in the rustc package
355         // above) and the second argument is where to place all the MinGW components
356         // (which is what we want).
357         make_win_dist(&tmpdir(builder), &image, host, &builder);
358
359         let mut cmd = rust_installer(builder);
360         cmd.arg("generate")
361            .arg("--product-name=Rust-MinGW")
362            .arg("--rel-manifest-dir=rustlib")
363            .arg("--success-message=Rust-MinGW-is-installed.")
364            .arg("--image-dir").arg(&image)
365            .arg("--work-dir").arg(&tmpdir(builder))
366            .arg("--output-dir").arg(&distdir(builder))
367            .arg(format!("--package-name={}-{}", name, host))
368            .arg("--component-name=rust-mingw")
369            .arg("--legacy-manifest-dirs=rustlib,cargo");
370         builder.run(&mut cmd);
371         t!(fs::remove_dir_all(&image));
372         Some(distdir(builder).join(format!("{}-{}.tar.gz", name, host)))
373     }
374 }
375
376 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
377 pub struct Rustc {
378     pub compiler: Compiler,
379 }
380
381 impl Step for Rustc {
382     type Output = PathBuf;
383     const DEFAULT: bool = true;
384     const ONLY_HOSTS: bool = true;
385
386     fn should_run(run: ShouldRun) -> ShouldRun {
387         run.path("src/librustc")
388     }
389
390     fn make_run(run: RunConfig) {
391         run.builder.ensure(Rustc {
392             compiler: run.builder.compiler(run.builder.top_stage, run.target),
393         });
394     }
395
396     /// Creates the `rustc` installer component.
397     fn run(self, builder: &Builder) -> PathBuf {
398         let compiler = self.compiler;
399         let host = self.compiler.host;
400
401         builder.info(&format!("Dist rustc stage{} ({})", compiler.stage, host));
402         let name = pkgname(builder, "rustc");
403         let image = tmpdir(builder).join(format!("{}-{}-image", name, host));
404         let _ = fs::remove_dir_all(&image);
405         let overlay = tmpdir(builder).join(format!("{}-{}-overlay", name, host));
406         let _ = fs::remove_dir_all(&overlay);
407
408         // Prepare the rustc "image", what will actually end up getting installed
409         prepare_image(builder, compiler, &image);
410
411         // Prepare the overlay which is part of the tarball but won't actually be
412         // installed
413         let cp = |file: &str| {
414             builder.install(&builder.src.join(file), &overlay, 0o644);
415         };
416         cp("COPYRIGHT");
417         cp("LICENSE-APACHE");
418         cp("LICENSE-MIT");
419         cp("README.md");
420         // tiny morsel of metadata is used by rust-packaging
421         let version = builder.rust_version();
422         builder.create(&overlay.join("version"), &version);
423         if let Some(sha) = builder.rust_sha() {
424             builder.create(&overlay.join("git-commit-hash"), &sha);
425         }
426
427         // On MinGW we've got a few runtime DLL dependencies that we need to
428         // include. The first argument to this script is where to put these DLLs
429         // (the image we're creating), and the second argument is a junk directory
430         // to ignore all other MinGW stuff the script creates.
431         //
432         // On 32-bit MinGW we're always including a DLL which needs some extra
433         // licenses to distribute. On 64-bit MinGW we don't actually distribute
434         // anything requiring us to distribute a license, but it's likely the
435         // install will *also* include the rust-mingw package, which also needs
436         // licenses, so to be safe we just include it here in all MinGW packages.
437         if host.contains("pc-windows-gnu") {
438             make_win_dist(&image, &tmpdir(builder), host, builder);
439
440             let dst = image.join("share/doc");
441             t!(fs::create_dir_all(&dst));
442             builder.cp_r(&builder.src.join("src/etc/third-party"), &dst);
443         }
444
445         // Finally, wrap everything up in a nice tarball!
446         let mut cmd = rust_installer(builder);
447         cmd.arg("generate")
448            .arg("--product-name=Rust")
449            .arg("--rel-manifest-dir=rustlib")
450            .arg("--success-message=Rust-is-ready-to-roll.")
451            .arg("--image-dir").arg(&image)
452            .arg("--work-dir").arg(&tmpdir(builder))
453            .arg("--output-dir").arg(&distdir(builder))
454            .arg("--non-installed-overlay").arg(&overlay)
455            .arg(format!("--package-name={}-{}", name, host))
456            .arg("--component-name=rustc")
457            .arg("--legacy-manifest-dirs=rustlib,cargo");
458         builder.run(&mut cmd);
459         builder.remove_dir(&image);
460         builder.remove_dir(&overlay);
461
462         return distdir(builder).join(format!("{}-{}.tar.gz", name, host));
463
464         fn prepare_image(builder: &Builder, compiler: Compiler, image: &Path) {
465             let host = compiler.host;
466             let src = builder.sysroot(compiler);
467             let libdir = libdir(&host);
468
469             // Copy rustc/rustdoc binaries
470             t!(fs::create_dir_all(image.join("bin")));
471             builder.cp_r(&src.join("bin"), &image.join("bin"));
472
473             builder.install(&builder.rustdoc(compiler.host), &image.join("bin"), 0o755);
474
475             // Copy runtime DLLs needed by the compiler
476             if libdir != "bin" {
477                 for entry in builder.read_dir(&src.join(libdir)) {
478                     let name = entry.file_name();
479                     if let Some(s) = name.to_str() {
480                         if is_dylib(s) {
481                             builder.install(&entry.path(), &image.join(libdir), 0o644);
482                         }
483                     }
484                 }
485             }
486
487             // Copy over the codegen backends
488             let backends_src = builder.sysroot_codegen_backends(compiler);
489             let backends_rel = backends_src.strip_prefix(&src).unwrap();
490             let backends_dst = image.join(&backends_rel);
491             t!(fs::create_dir_all(&backends_dst));
492             builder.cp_r(&backends_src, &backends_dst);
493
494             // Copy over lld if it's there
495             if builder.config.lld_enabled {
496                 let exe = exe("lld", &compiler.host);
497                 let src = builder.sysroot_libdir(compiler, host)
498                     .parent()
499                     .unwrap()
500                     .join("bin")
501                     .join(&exe);
502                 let dst = image.join("lib/rustlib")
503                     .join(&*host)
504                     .join("bin")
505                     .join(&exe);
506                 t!(fs::create_dir_all(&dst.parent().unwrap()));
507                 builder.copy(&src, &dst);
508             }
509
510             // Man pages
511             t!(fs::create_dir_all(image.join("share/man/man1")));
512             let man_src = builder.src.join("src/doc/man");
513             let man_dst = image.join("share/man/man1");
514             let month_year = t!(time::strftime("%B %Y", &time::now()));
515             // don't use our `bootstrap::util::{copy, cp_r}`, because those try
516             // to hardlink, and we don't want to edit the source templates
517             for file_entry in builder.read_dir(&man_src) {
518                 let page_src = file_entry.path();
519                 let page_dst = man_dst.join(file_entry.file_name());
520                 t!(fs::copy(&page_src, &page_dst));
521                 // template in month/year and version number
522                 builder.replace_in_file(&page_dst,
523                                 &[("<INSERT DATE HERE>", &month_year),
524                                   ("<INSERT VERSION HERE>", channel::CFG_RELEASE_NUM)]);
525             }
526
527             // Debugger scripts
528             builder.ensure(DebuggerScripts {
529                 sysroot: INTERNER.intern_path(image.to_owned()),
530                 host,
531             });
532
533             // Misc license info
534             let cp = |file: &str| {
535                 builder.install(&builder.src.join(file), &image.join("share/doc/rust"), 0o644);
536             };
537             cp("COPYRIGHT");
538             cp("LICENSE-APACHE");
539             cp("LICENSE-MIT");
540             cp("README.md");
541         }
542     }
543 }
544
545 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
546 pub struct DebuggerScripts {
547     pub sysroot: Interned<PathBuf>,
548     pub host: Interned<String>,
549 }
550
551 impl Step for DebuggerScripts {
552     type Output = ();
553
554     fn should_run(run: ShouldRun) -> ShouldRun {
555         run.path("src/lldb_batchmode.py")
556     }
557
558     fn make_run(run: RunConfig) {
559         run.builder.ensure(DebuggerScripts {
560             sysroot: run.builder.sysroot(run.builder.compiler(run.builder.top_stage, run.host)),
561             host: run.target,
562         });
563     }
564
565     /// Copies debugger scripts for `target` into the `sysroot` specified.
566     fn run(self, builder: &Builder) {
567         let host = self.host;
568         let sysroot = self.sysroot;
569         let dst = sysroot.join("lib/rustlib/etc");
570         t!(fs::create_dir_all(&dst));
571         let cp_debugger_script = |file: &str| {
572             builder.install(&builder.src.join("src/etc/").join(file), &dst, 0o644);
573         };
574         if host.contains("windows-msvc") {
575             // windbg debugger scripts
576             builder.install(&builder.src.join("src/etc/rust-windbg.cmd"), &sysroot.join("bin"),
577                 0o755);
578
579             cp_debugger_script("natvis/intrinsic.natvis");
580             cp_debugger_script("natvis/liballoc.natvis");
581             cp_debugger_script("natvis/libcore.natvis");
582         } else {
583             cp_debugger_script("debugger_pretty_printers_common.py");
584
585             // gdb debugger scripts
586             builder.install(&builder.src.join("src/etc/rust-gdb"), &sysroot.join("bin"),
587                     0o755);
588
589             cp_debugger_script("gdb_load_rust_pretty_printers.py");
590             cp_debugger_script("gdb_rust_pretty_printing.py");
591
592             // lldb debugger scripts
593             builder.install(&builder.src.join("src/etc/rust-lldb"), &sysroot.join("bin"),
594                     0o755);
595
596             cp_debugger_script("lldb_rust_formatters.py");
597         }
598     }
599 }
600
601 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
602 pub struct Std {
603     pub compiler: Compiler,
604     pub target: Interned<String>,
605 }
606
607 impl Step for Std {
608     type Output = PathBuf;
609     const DEFAULT: bool = true;
610
611     fn should_run(run: ShouldRun) -> ShouldRun {
612         run.path("src/libstd")
613     }
614
615     fn make_run(run: RunConfig) {
616         run.builder.ensure(Std {
617             compiler: run.builder.compiler(run.builder.top_stage, run.builder.config.build),
618             target: run.target,
619         });
620     }
621
622     fn run(self, builder: &Builder) -> PathBuf {
623         let compiler = self.compiler;
624         let target = self.target;
625
626         let name = pkgname(builder, "rust-std");
627         builder.info(&format!("Dist std stage{} ({} -> {})",
628             compiler.stage, &compiler.host, target));
629
630         // The only true set of target libraries came from the build triple, so
631         // let's reduce redundant work by only producing archives from that host.
632         if compiler.host != builder.config.build {
633             builder.info(&format!("\tskipping, not a build host"));
634             return distdir(builder).join(format!("{}-{}.tar.gz", name, target));
635         }
636
637         // We want to package up as many target libraries as possible
638         // for the `rust-std` package, so if this is a host target we
639         // depend on librustc and otherwise we just depend on libtest.
640         if builder.hosts.iter().any(|t| t == target) {
641             builder.ensure(compile::Rustc { compiler, target });
642         } else {
643             if builder.no_std(target) == Some(true) {
644                 // the `test` doesn't compile for no-std targets
645                 builder.ensure(compile::Std { compiler, target });
646             } else {
647                 builder.ensure(compile::Test { compiler, target });
648             }
649         }
650
651         let image = tmpdir(builder).join(format!("{}-{}-image", name, target));
652         let _ = fs::remove_dir_all(&image);
653
654         let dst = image.join("lib/rustlib").join(target);
655         t!(fs::create_dir_all(&dst));
656         let mut src = builder.sysroot_libdir(compiler, target).to_path_buf();
657         src.pop(); // Remove the trailing /lib folder from the sysroot_libdir
658         builder.cp_filtered(&src, &dst, &|path| {
659             let name = path.file_name().and_then(|s| s.to_str());
660             name != Some(builder.config.rust_codegen_backends_dir.as_str()) &&
661                 name != Some("bin")
662
663         });
664
665         let mut cmd = rust_installer(builder);
666         cmd.arg("generate")
667            .arg("--product-name=Rust")
668            .arg("--rel-manifest-dir=rustlib")
669            .arg("--success-message=std-is-standing-at-the-ready.")
670            .arg("--image-dir").arg(&image)
671            .arg("--work-dir").arg(&tmpdir(builder))
672            .arg("--output-dir").arg(&distdir(builder))
673            .arg(format!("--package-name={}-{}", name, target))
674            .arg(format!("--component-name=rust-std-{}", target))
675            .arg("--legacy-manifest-dirs=rustlib,cargo");
676         builder.run(&mut cmd);
677         builder.remove_dir(&image);
678         distdir(builder).join(format!("{}-{}.tar.gz", name, target))
679     }
680 }
681
682 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
683 pub struct Analysis {
684     pub compiler: Compiler,
685     pub target: Interned<String>,
686 }
687
688 impl Step for Analysis {
689     type Output = PathBuf;
690     const DEFAULT: bool = true;
691
692     fn should_run(run: ShouldRun) -> ShouldRun {
693         let builder = run.builder;
694         run.path("analysis").default_condition(builder.config.extended)
695     }
696
697     fn make_run(run: RunConfig) {
698         run.builder.ensure(Analysis {
699             compiler: run.builder.compiler(run.builder.top_stage, run.builder.config.build),
700             target: run.target,
701         });
702     }
703
704     /// Creates a tarball of save-analysis metadata, if available.
705     fn run(self, builder: &Builder) -> PathBuf {
706         let compiler = self.compiler;
707         let target = self.target;
708         assert!(builder.config.extended);
709         builder.info(&format!("Dist analysis"));
710         let name = pkgname(builder, "rust-analysis");
711
712         if &compiler.host != builder.config.build {
713             builder.info(&format!("\tskipping, not a build host"));
714             return distdir(builder).join(format!("{}-{}.tar.gz", name, target));
715         }
716
717         builder.ensure(Std { compiler, target });
718
719         // Package save-analysis from stage1 if not doing a full bootstrap, as the
720         // stage2 artifacts is simply copied from stage1 in that case.
721         let compiler = if builder.force_use_stage1(compiler, target) {
722             builder.compiler(1, compiler.host)
723         } else {
724             compiler.clone()
725         };
726
727         let image = tmpdir(builder).join(format!("{}-{}-image", name, target));
728
729         let src = builder.stage_out(compiler, Mode::Std)
730             .join(target).join(builder.cargo_dir()).join("deps");
731
732         let image_src = src.join("save-analysis");
733         let dst = image.join("lib/rustlib").join(target).join("analysis");
734         t!(fs::create_dir_all(&dst));
735         builder.info(&format!("image_src: {:?}, dst: {:?}", image_src, dst));
736         builder.cp_r(&image_src, &dst);
737
738         let mut cmd = rust_installer(builder);
739         cmd.arg("generate")
740            .arg("--product-name=Rust")
741            .arg("--rel-manifest-dir=rustlib")
742            .arg("--success-message=save-analysis-saved.")
743            .arg("--image-dir").arg(&image)
744            .arg("--work-dir").arg(&tmpdir(builder))
745            .arg("--output-dir").arg(&distdir(builder))
746            .arg(format!("--package-name={}-{}", name, target))
747            .arg(format!("--component-name=rust-analysis-{}", target))
748            .arg("--legacy-manifest-dirs=rustlib,cargo");
749         builder.run(&mut cmd);
750         builder.remove_dir(&image);
751         distdir(builder).join(format!("{}-{}.tar.gz", name, target))
752     }
753 }
754
755 fn copy_src_dirs(builder: &Builder, src_dirs: &[&str], exclude_dirs: &[&str], dst_dir: &Path) {
756     fn filter_fn(exclude_dirs: &[&str], dir: &str, path: &Path) -> bool {
757         let spath = match path.to_str() {
758             Some(path) => path,
759             None => return false,
760         };
761         if spath.ends_with("~") || spath.ends_with(".pyc") {
762             return false
763         }
764         if (spath.contains("llvm/test") || spath.contains("llvm\\test")) &&
765             (spath.ends_with(".ll") ||
766              spath.ends_with(".td") ||
767              spath.ends_with(".s")) {
768             return false
769         }
770         if spath.contains("test/emscripten") || spath.contains("test\\emscripten") {
771             return false
772         }
773
774         let full_path = Path::new(dir).join(path);
775         if exclude_dirs.iter().any(|excl| full_path == Path::new(excl)) {
776             return false;
777         }
778
779         let excludes = [
780             "CVS", "RCS", "SCCS", ".git", ".gitignore", ".gitmodules",
781             ".gitattributes", ".cvsignore", ".svn", ".arch-ids", "{arch}",
782             "=RELEASE-ID", "=meta-update", "=update", ".bzr", ".bzrignore",
783             ".bzrtags", ".hg", ".hgignore", ".hgrags", "_darcs",
784         ];
785         !path.iter()
786              .map(|s| s.to_str().unwrap())
787              .any(|s| excludes.contains(&s))
788     }
789
790     // Copy the directories using our filter
791     for item in src_dirs {
792         let dst = &dst_dir.join(item);
793         t!(fs::create_dir_all(dst));
794         builder.cp_filtered(
795             &builder.src.join(item), dst, &|path| filter_fn(exclude_dirs, item, path));
796     }
797 }
798
799 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
800 pub struct Src;
801
802 impl Step for Src {
803     /// The output path of the src installer tarball
804     type Output = PathBuf;
805     const DEFAULT: bool = true;
806     const ONLY_HOSTS: bool = true;
807
808     fn should_run(run: ShouldRun) -> ShouldRun {
809         run.path("src")
810     }
811
812     fn make_run(run: RunConfig) {
813         run.builder.ensure(Src);
814     }
815
816     /// Creates the `rust-src` installer component
817     fn run(self, builder: &Builder) -> PathBuf {
818         builder.info(&format!("Dist src"));
819
820         let name = pkgname(builder, "rust-src");
821         let image = tmpdir(builder).join(format!("{}-image", name));
822         let _ = fs::remove_dir_all(&image);
823
824         let dst = image.join("lib/rustlib/src");
825         let dst_src = dst.join("rust");
826         t!(fs::create_dir_all(&dst_src));
827
828         let src_files = [
829             "src/Cargo.lock",
830         ];
831         // This is the reduced set of paths which will become the rust-src component
832         // (essentially libstd and all of its path dependencies)
833         let std_src_dirs = [
834             "src/build_helper",
835             "src/dlmalloc",
836             "src/liballoc",
837             "src/liballoc_jemalloc",
838             "src/liballoc_system",
839             "src/libbacktrace",
840             "src/libcompiler_builtins",
841             "src/libcore",
842             "src/liblibc",
843             "src/libpanic_abort",
844             "src/libpanic_unwind",
845             "src/librustc_asan",
846             "src/librustc_lsan",
847             "src/librustc_msan",
848             "src/librustc_tsan",
849             "src/libstd",
850             "src/libstd_unicode",
851             "src/libunwind",
852             "src/rustc/compiler_builtins_shim",
853             "src/rustc/libc_shim",
854             "src/rustc/dlmalloc_shim",
855             "src/libtest",
856             "src/libterm",
857             "src/jemalloc",
858             "src/libprofiler_builtins",
859             "src/stdsimd",
860         ];
861         let std_src_dirs_exclude = [
862             "src/libcompiler_builtins/compiler-rt/test",
863             "src/jemalloc/test/unit",
864         ];
865
866         copy_src_dirs(builder, &std_src_dirs[..], &std_src_dirs_exclude[..], &dst_src);
867         for file in src_files.iter() {
868             builder.copy(&builder.src.join(file), &dst_src.join(file));
869         }
870
871         // Create source tarball in rust-installer format
872         let mut cmd = rust_installer(builder);
873         cmd.arg("generate")
874            .arg("--product-name=Rust")
875            .arg("--rel-manifest-dir=rustlib")
876            .arg("--success-message=Awesome-Source.")
877            .arg("--image-dir").arg(&image)
878            .arg("--work-dir").arg(&tmpdir(builder))
879            .arg("--output-dir").arg(&distdir(builder))
880            .arg(format!("--package-name={}", name))
881            .arg("--component-name=rust-src")
882            .arg("--legacy-manifest-dirs=rustlib,cargo");
883         builder.run(&mut cmd);
884
885         builder.remove_dir(&image);
886         distdir(builder).join(&format!("{}.tar.gz", name))
887     }
888 }
889
890 const CARGO_VENDOR_VERSION: &str = "0.1.4";
891
892 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
893 pub struct PlainSourceTarball;
894
895 impl Step for PlainSourceTarball {
896     /// Produces the location of the tarball generated
897     type Output = PathBuf;
898     const DEFAULT: bool = true;
899     const ONLY_HOSTS: bool = true;
900
901     fn should_run(run: ShouldRun) -> ShouldRun {
902         let builder = run.builder;
903         run.path("src").default_condition(builder.config.rust_dist_src)
904     }
905
906     fn make_run(run: RunConfig) {
907         run.builder.ensure(PlainSourceTarball);
908     }
909
910     /// Creates the plain source tarball
911     fn run(self, builder: &Builder) -> PathBuf {
912         builder.info(&format!("Create plain source tarball"));
913
914         // Make sure that the root folder of tarball has the correct name
915         let plain_name = format!("{}-src", pkgname(builder, "rustc"));
916         let plain_dst_src = tmpdir(builder).join(&plain_name);
917         let _ = fs::remove_dir_all(&plain_dst_src);
918         t!(fs::create_dir_all(&plain_dst_src));
919
920         // This is the set of root paths which will become part of the source package
921         let src_files = [
922             "COPYRIGHT",
923             "LICENSE-APACHE",
924             "LICENSE-MIT",
925             "CONTRIBUTING.md",
926             "README.md",
927             "RELEASES.md",
928             "configure",
929             "x.py",
930             "config.toml.example",
931         ];
932         let src_dirs = [
933             "src",
934         ];
935
936         copy_src_dirs(builder, &src_dirs[..], &[], &plain_dst_src);
937
938         // Copy the files normally
939         for item in &src_files {
940             builder.copy(&builder.src.join(item), &plain_dst_src.join(item));
941         }
942
943         // Create the version file
944         builder.create(&plain_dst_src.join("version"), &builder.rust_version());
945         if let Some(sha) = builder.rust_sha() {
946             builder.create(&plain_dst_src.join("git-commit-hash"), &sha);
947         }
948
949         // If we're building from git sources, we need to vendor a complete distribution.
950         if builder.rust_info.is_git() {
951             // Get cargo-vendor installed, if it isn't already.
952             let mut has_cargo_vendor = false;
953             let mut cmd = Command::new(&builder.initial_cargo);
954             for line in output(cmd.arg("install").arg("--list")).lines() {
955                 has_cargo_vendor |= line.starts_with("cargo-vendor ");
956             }
957             if !has_cargo_vendor {
958                 let mut cmd = builder.cargo(
959                     builder.compiler(0, builder.config.build),
960                     Mode::ToolRustc,
961                     builder.config.build,
962                     "install"
963                 );
964                 cmd.arg("--force")
965                    .arg("--debug")
966                    .arg("--vers").arg(CARGO_VENDOR_VERSION)
967                    .arg("cargo-vendor");
968                 if let Some(dir) = builder.openssl_install_dir(builder.config.build) {
969                     builder.ensure(native::Openssl {
970                         target: builder.config.build,
971                     });
972                     cmd.env("OPENSSL_DIR", dir);
973                 }
974                 builder.run(&mut cmd);
975             }
976
977             // Vendor all Cargo dependencies
978             let mut cmd = Command::new(&builder.initial_cargo);
979             cmd.arg("vendor")
980                .current_dir(&plain_dst_src.join("src"));
981             builder.run(&mut cmd);
982         }
983
984         // Create plain source tarball
985         let plain_name = format!("rustc-{}-src", builder.rust_package_vers());
986         let mut tarball = distdir(builder).join(&format!("{}.tar.gz", plain_name));
987         tarball.set_extension(""); // strip .gz
988         tarball.set_extension(""); // strip .tar
989         if let Some(dir) = tarball.parent() {
990             builder.create_dir(&dir);
991         }
992         builder.info(&format!("running installer"));
993         let mut cmd = rust_installer(builder);
994         cmd.arg("tarball")
995            .arg("--input").arg(&plain_name)
996            .arg("--output").arg(&tarball)
997            .arg("--work-dir=.")
998            .current_dir(tmpdir(builder));
999         builder.run(&mut cmd);
1000         distdir(builder).join(&format!("{}.tar.gz", plain_name))
1001     }
1002 }
1003
1004 // We have to run a few shell scripts, which choke quite a bit on both `\`
1005 // characters and on `C:\` paths, so normalize both of them away.
1006 pub fn sanitize_sh(path: &Path) -> String {
1007     let path = path.to_str().unwrap().replace("\\", "/");
1008     return change_drive(&path).unwrap_or(path);
1009
1010     fn change_drive(s: &str) -> Option<String> {
1011         let mut ch = s.chars();
1012         let drive = ch.next().unwrap_or('C');
1013         if ch.next() != Some(':') {
1014             return None
1015         }
1016         if ch.next() != Some('/') {
1017             return None
1018         }
1019         Some(format!("/{}/{}", drive, &s[drive.len_utf8() + 2..]))
1020     }
1021 }
1022
1023 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
1024 pub struct Cargo {
1025     pub stage: u32,
1026     pub target: Interned<String>,
1027 }
1028
1029 impl Step for Cargo {
1030     type Output = PathBuf;
1031     const ONLY_HOSTS: bool = true;
1032
1033     fn should_run(run: ShouldRun) -> ShouldRun {
1034         run.path("cargo")
1035     }
1036
1037     fn make_run(run: RunConfig) {
1038         run.builder.ensure(Cargo {
1039             stage: run.builder.top_stage,
1040             target: run.target,
1041         });
1042     }
1043
1044     fn run(self, builder: &Builder) -> PathBuf {
1045         let stage = self.stage;
1046         let target = self.target;
1047
1048         builder.info(&format!("Dist cargo stage{} ({})", stage, target));
1049         let src = builder.src.join("src/tools/cargo");
1050         let etc = src.join("src/etc");
1051         let release_num = builder.release_num("cargo");
1052         let name = pkgname(builder, "cargo");
1053         let version = builder.cargo_info.version(builder, &release_num);
1054
1055         let tmp = tmpdir(builder);
1056         let image = tmp.join("cargo-image");
1057         drop(fs::remove_dir_all(&image));
1058         builder.create_dir(&image);
1059
1060         // Prepare the image directory
1061         builder.create_dir(&image.join("share/zsh/site-functions"));
1062         builder.create_dir(&image.join("etc/bash_completion.d"));
1063         let cargo = builder.ensure(tool::Cargo {
1064             compiler: builder.compiler(stage, builder.config.build),
1065             target
1066         });
1067         builder.install(&cargo, &image.join("bin"), 0o755);
1068         for man in t!(etc.join("man").read_dir()) {
1069             let man = t!(man);
1070             builder.install(&man.path(), &image.join("share/man/man1"), 0o644);
1071         }
1072         builder.install(&etc.join("_cargo"), &image.join("share/zsh/site-functions"), 0o644);
1073         builder.copy(&etc.join("cargo.bashcomp.sh"),
1074              &image.join("etc/bash_completion.d/cargo"));
1075         let doc = image.join("share/doc/cargo");
1076         builder.install(&src.join("README.md"), &doc, 0o644);
1077         builder.install(&src.join("LICENSE-MIT"), &doc, 0o644);
1078         builder.install(&src.join("LICENSE-APACHE"), &doc, 0o644);
1079         builder.install(&src.join("LICENSE-THIRD-PARTY"), &doc, 0o644);
1080
1081         // Prepare the overlay
1082         let overlay = tmp.join("cargo-overlay");
1083         drop(fs::remove_dir_all(&overlay));
1084         builder.create_dir(&overlay);
1085         builder.install(&src.join("README.md"), &overlay, 0o644);
1086         builder.install(&src.join("LICENSE-MIT"), &overlay, 0o644);
1087         builder.install(&src.join("LICENSE-APACHE"), &overlay, 0o644);
1088         builder.install(&src.join("LICENSE-THIRD-PARTY"), &overlay, 0o644);
1089         builder.create(&overlay.join("version"), &version);
1090
1091         // Generate the installer tarball
1092         let mut cmd = rust_installer(builder);
1093         cmd.arg("generate")
1094            .arg("--product-name=Rust")
1095            .arg("--rel-manifest-dir=rustlib")
1096            .arg("--success-message=Rust-is-ready-to-roll.")
1097            .arg("--image-dir").arg(&image)
1098            .arg("--work-dir").arg(&tmpdir(builder))
1099            .arg("--output-dir").arg(&distdir(builder))
1100            .arg("--non-installed-overlay").arg(&overlay)
1101            .arg(format!("--package-name={}-{}", name, target))
1102            .arg("--component-name=cargo")
1103            .arg("--legacy-manifest-dirs=rustlib,cargo");
1104         builder.run(&mut cmd);
1105         distdir(builder).join(format!("{}-{}.tar.gz", name, target))
1106     }
1107 }
1108
1109 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
1110 pub struct Rls {
1111     pub stage: u32,
1112     pub target: Interned<String>,
1113 }
1114
1115 impl Step for Rls {
1116     type Output = Option<PathBuf>;
1117     const ONLY_HOSTS: bool = true;
1118
1119     fn should_run(run: ShouldRun) -> ShouldRun {
1120         run.path("rls")
1121     }
1122
1123     fn make_run(run: RunConfig) {
1124         run.builder.ensure(Rls {
1125             stage: run.builder.top_stage,
1126             target: run.target,
1127         });
1128     }
1129
1130     fn run(self, builder: &Builder) -> Option<PathBuf> {
1131         let stage = self.stage;
1132         let target = self.target;
1133         assert!(builder.config.extended);
1134
1135         builder.info(&format!("Dist RLS stage{} ({})", stage, target));
1136         let src = builder.src.join("src/tools/rls");
1137         let release_num = builder.release_num("rls");
1138         let name = pkgname(builder, "rls");
1139         let version = builder.rls_info.version(builder, &release_num);
1140
1141         let tmp = tmpdir(builder);
1142         let image = tmp.join("rls-image");
1143         drop(fs::remove_dir_all(&image));
1144         t!(fs::create_dir_all(&image));
1145
1146         // Prepare the image directory
1147         // We expect RLS to build, because we've exited this step above if tool
1148         // state for RLS isn't testing.
1149         let rls = builder.ensure(tool::Rls {
1150             compiler: builder.compiler(stage, builder.config.build),
1151             target, extra_features: Vec::new()
1152         }).or_else(|| { println!("Unable to build RLS, skipping dist"); None })?;
1153
1154         builder.install(&rls, &image.join("bin"), 0o755);
1155         let doc = image.join("share/doc/rls");
1156         builder.install(&src.join("README.md"), &doc, 0o644);
1157         builder.install(&src.join("LICENSE-MIT"), &doc, 0o644);
1158         builder.install(&src.join("LICENSE-APACHE"), &doc, 0o644);
1159
1160         // Prepare the overlay
1161         let overlay = tmp.join("rls-overlay");
1162         drop(fs::remove_dir_all(&overlay));
1163         t!(fs::create_dir_all(&overlay));
1164         builder.install(&src.join("README.md"), &overlay, 0o644);
1165         builder.install(&src.join("LICENSE-MIT"), &overlay, 0o644);
1166         builder.install(&src.join("LICENSE-APACHE"), &overlay, 0o644);
1167         builder.create(&overlay.join("version"), &version);
1168
1169         // Generate the installer tarball
1170         let mut cmd = rust_installer(builder);
1171         cmd.arg("generate")
1172            .arg("--product-name=Rust")
1173            .arg("--rel-manifest-dir=rustlib")
1174            .arg("--success-message=RLS-ready-to-serve.")
1175            .arg("--image-dir").arg(&image)
1176            .arg("--work-dir").arg(&tmpdir(builder))
1177            .arg("--output-dir").arg(&distdir(builder))
1178            .arg("--non-installed-overlay").arg(&overlay)
1179            .arg(format!("--package-name={}-{}", name, target))
1180            .arg("--legacy-manifest-dirs=rustlib,cargo")
1181            .arg("--component-name=rls-preview");
1182
1183         builder.run(&mut cmd);
1184         Some(distdir(builder).join(format!("{}-{}.tar.gz", name, target)))
1185     }
1186 }
1187
1188 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
1189 pub struct Clippy {
1190     pub stage: u32,
1191     pub target: Interned<String>,
1192 }
1193
1194 impl Step for Clippy {
1195     type Output = Option<PathBuf>;
1196     const ONLY_HOSTS: bool = true;
1197
1198     fn should_run(run: ShouldRun) -> ShouldRun {
1199         run.path("clippy")
1200     }
1201
1202     fn make_run(run: RunConfig) {
1203         run.builder.ensure(Clippy {
1204             stage: run.builder.top_stage,
1205             target: run.target,
1206         });
1207     }
1208
1209     fn run(self, builder: &Builder) -> Option<PathBuf> {
1210         let stage = self.stage;
1211         let target = self.target;
1212         assert!(builder.config.extended);
1213
1214         builder.info(&format!("Dist clippy stage{} ({})", stage, target));
1215         let src = builder.src.join("src/tools/clippy");
1216         let release_num = builder.release_num("clippy");
1217         let name = pkgname(builder, "clippy");
1218         let version = builder.clippy_info.version(builder, &release_num);
1219
1220         let tmp = tmpdir(builder);
1221         let image = tmp.join("clippy-image");
1222         drop(fs::remove_dir_all(&image));
1223         t!(fs::create_dir_all(&image));
1224
1225         // Prepare the image directory
1226         // We expect clippy to build, because we've exited this step above if tool
1227         // state for clippy isn't testing.
1228         let clippy = builder.ensure(tool::Clippy {
1229             compiler: builder.compiler(stage, builder.config.build),
1230             target, extra_features: Vec::new()
1231         }).or_else(|| { println!("Unable to build clippy, skipping dist"); None })?;
1232
1233         builder.install(&clippy, &image.join("bin"), 0o755);
1234         let doc = image.join("share/doc/clippy");
1235         builder.install(&src.join("README.md"), &doc, 0o644);
1236         builder.install(&src.join("LICENSE"), &doc, 0o644);
1237
1238         // Prepare the overlay
1239         let overlay = tmp.join("clippy-overlay");
1240         drop(fs::remove_dir_all(&overlay));
1241         t!(fs::create_dir_all(&overlay));
1242         builder.install(&src.join("README.md"), &overlay, 0o644);
1243         builder.install(&src.join("LICENSE"), &doc, 0o644);
1244         builder.create(&overlay.join("version"), &version);
1245
1246         // Generate the installer tarball
1247         let mut cmd = rust_installer(builder);
1248         cmd.arg("generate")
1249            .arg("--product-name=Rust")
1250            .arg("--rel-manifest-dir=rustlib")
1251            .arg("--success-message=clippy-ready-to-serve.")
1252            .arg("--image-dir").arg(&image)
1253            .arg("--work-dir").arg(&tmpdir(builder))
1254            .arg("--output-dir").arg(&distdir(builder))
1255            .arg("--non-installed-overlay").arg(&overlay)
1256            .arg(format!("--package-name={}-{}", name, target))
1257            .arg("--legacy-manifest-dirs=rustlib,cargo")
1258            .arg("--component-name=clippy-preview");
1259
1260         builder.run(&mut cmd);
1261         Some(distdir(builder).join(format!("{}-{}.tar.gz", name, target)))
1262     }
1263 }
1264
1265 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
1266 pub struct Rustfmt {
1267     pub stage: u32,
1268     pub target: Interned<String>,
1269 }
1270
1271 impl Step for Rustfmt {
1272     type Output = Option<PathBuf>;
1273     const ONLY_HOSTS: bool = true;
1274
1275     fn should_run(run: ShouldRun) -> ShouldRun {
1276         run.path("rustfmt")
1277     }
1278
1279     fn make_run(run: RunConfig) {
1280         run.builder.ensure(Rustfmt {
1281             stage: run.builder.top_stage,
1282             target: run.target,
1283         });
1284     }
1285
1286     fn run(self, builder: &Builder) -> Option<PathBuf> {
1287         let stage = self.stage;
1288         let target = self.target;
1289
1290         builder.info(&format!("Dist Rustfmt stage{} ({})", stage, target));
1291         let src = builder.src.join("src/tools/rustfmt");
1292         let release_num = builder.release_num("rustfmt");
1293         let name = pkgname(builder, "rustfmt");
1294         let version = builder.rustfmt_info.version(builder, &release_num);
1295
1296         let tmp = tmpdir(builder);
1297         let image = tmp.join("rustfmt-image");
1298         drop(fs::remove_dir_all(&image));
1299         builder.create_dir(&image);
1300
1301         // Prepare the image directory
1302         let rustfmt = builder.ensure(tool::Rustfmt {
1303             compiler: builder.compiler(stage, builder.config.build),
1304             target, extra_features: Vec::new()
1305         }).or_else(|| { println!("Unable to build Rustfmt, skipping dist"); None })?;
1306         let cargofmt = builder.ensure(tool::Cargofmt {
1307             compiler: builder.compiler(stage, builder.config.build),
1308             target, extra_features: Vec::new()
1309         }).or_else(|| { println!("Unable to build Cargofmt, skipping dist"); None })?;
1310
1311         builder.install(&rustfmt, &image.join("bin"), 0o755);
1312         builder.install(&cargofmt, &image.join("bin"), 0o755);
1313         let doc = image.join("share/doc/rustfmt");
1314         builder.install(&src.join("README.md"), &doc, 0o644);
1315         builder.install(&src.join("LICENSE-MIT"), &doc, 0o644);
1316         builder.install(&src.join("LICENSE-APACHE"), &doc, 0o644);
1317
1318         // Prepare the overlay
1319         let overlay = tmp.join("rustfmt-overlay");
1320         drop(fs::remove_dir_all(&overlay));
1321         builder.create_dir(&overlay);
1322         builder.install(&src.join("README.md"), &overlay, 0o644);
1323         builder.install(&src.join("LICENSE-MIT"), &overlay, 0o644);
1324         builder.install(&src.join("LICENSE-APACHE"), &overlay, 0o644);
1325         builder.create(&overlay.join("version"), &version);
1326
1327         // Generate the installer tarball
1328         let mut cmd = rust_installer(builder);
1329         cmd.arg("generate")
1330            .arg("--product-name=Rust")
1331            .arg("--rel-manifest-dir=rustlib")
1332            .arg("--success-message=rustfmt-ready-to-fmt.")
1333            .arg("--image-dir").arg(&image)
1334            .arg("--work-dir").arg(&tmpdir(builder))
1335            .arg("--output-dir").arg(&distdir(builder))
1336            .arg("--non-installed-overlay").arg(&overlay)
1337            .arg(format!("--package-name={}-{}", name, target))
1338            .arg("--legacy-manifest-dirs=rustlib,cargo")
1339            .arg("--component-name=rustfmt-preview");
1340
1341         builder.run(&mut cmd);
1342         Some(distdir(builder).join(format!("{}-{}.tar.gz", name, target)))
1343     }
1344 }
1345
1346 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
1347 pub struct Extended {
1348     stage: u32,
1349     host: Interned<String>,
1350     target: Interned<String>,
1351 }
1352
1353 impl Step for Extended {
1354     type Output = ();
1355     const DEFAULT: bool = true;
1356     const ONLY_HOSTS: bool = true;
1357
1358     fn should_run(run: ShouldRun) -> ShouldRun {
1359         let builder = run.builder;
1360         run.path("extended").default_condition(builder.config.extended)
1361     }
1362
1363     fn make_run(run: RunConfig) {
1364         run.builder.ensure(Extended {
1365             stage: run.builder.top_stage,
1366             host: run.builder.config.build,
1367             target: run.target,
1368         });
1369     }
1370
1371     /// Creates a combined installer for the specified target in the provided stage.
1372     fn run(self, builder: &Builder) {
1373         let stage = self.stage;
1374         let target = self.target;
1375
1376         builder.info(&format!("Dist extended stage{} ({})", stage, target));
1377
1378         let rustc_installer = builder.ensure(Rustc {
1379             compiler: builder.compiler(stage, target),
1380         });
1381         let cargo_installer = builder.ensure(Cargo { stage, target });
1382         let rustfmt_installer = builder.ensure(Rustfmt { stage, target });
1383         let rls_installer = builder.ensure(Rls { stage, target });
1384         let llvm_tools_installer = builder.ensure(LlvmTools { stage, target });
1385         let clippy_installer = builder.ensure(Clippy { stage, target });
1386         let mingw_installer = builder.ensure(Mingw { host: target });
1387         let analysis_installer = builder.ensure(Analysis {
1388             compiler: builder.compiler(stage, self.host),
1389             target
1390         });
1391
1392         let docs_installer = builder.ensure(Docs { stage, host: target, });
1393         let std_installer = builder.ensure(Std {
1394             compiler: builder.compiler(stage, self.host),
1395             target,
1396         });
1397
1398         let tmp = tmpdir(builder);
1399         let overlay = tmp.join("extended-overlay");
1400         let etc = builder.src.join("src/etc/installer");
1401         let work = tmp.join("work");
1402
1403         let _ = fs::remove_dir_all(&overlay);
1404         builder.install(&builder.src.join("COPYRIGHT"), &overlay, 0o644);
1405         builder.install(&builder.src.join("LICENSE-APACHE"), &overlay, 0o644);
1406         builder.install(&builder.src.join("LICENSE-MIT"), &overlay, 0o644);
1407         let version = builder.rust_version();
1408         builder.create(&overlay.join("version"), &version);
1409         if let Some(sha) = builder.rust_sha() {
1410             builder.create(&overlay.join("git-commit-hash"), &sha);
1411         }
1412         builder.install(&etc.join("README.md"), &overlay, 0o644);
1413
1414         // When rust-std package split from rustc, we needed to ensure that during
1415         // upgrades rustc was upgraded before rust-std. To avoid rustc clobbering
1416         // the std files during uninstall. To do this ensure that rustc comes
1417         // before rust-std in the list below.
1418         let mut tarballs = Vec::new();
1419         tarballs.push(rustc_installer);
1420         tarballs.push(cargo_installer);
1421         tarballs.extend(rls_installer.clone());
1422         tarballs.extend(clippy_installer.clone());
1423         tarballs.extend(rustfmt_installer.clone());
1424         tarballs.extend(llvm_tools_installer.clone());
1425         tarballs.push(analysis_installer);
1426         tarballs.push(std_installer);
1427         if builder.config.docs {
1428             tarballs.push(docs_installer);
1429         }
1430         if target.contains("pc-windows-gnu") {
1431             tarballs.push(mingw_installer.unwrap());
1432         }
1433         let mut input_tarballs = tarballs[0].as_os_str().to_owned();
1434         for tarball in &tarballs[1..] {
1435             input_tarballs.push(",");
1436             input_tarballs.push(tarball);
1437         }
1438
1439         let mut cmd = rust_installer(builder);
1440         cmd.arg("combine")
1441             .arg("--product-name=Rust")
1442             .arg("--rel-manifest-dir=rustlib")
1443             .arg("--success-message=Rust-is-ready-to-roll.")
1444             .arg("--work-dir").arg(&work)
1445             .arg("--output-dir").arg(&distdir(builder))
1446             .arg(format!("--package-name={}-{}", pkgname(builder, "rust"), target))
1447             .arg("--legacy-manifest-dirs=rustlib,cargo")
1448             .arg("--input-tarballs").arg(input_tarballs)
1449             .arg("--non-installed-overlay").arg(&overlay);
1450         builder.run(&mut cmd);
1451
1452         let mut license = String::new();
1453         license += &builder.read(&builder.src.join("COPYRIGHT"));
1454         license += &builder.read(&builder.src.join("LICENSE-APACHE"));
1455         license += &builder.read(&builder.src.join("LICENSE-MIT"));
1456         license.push_str("\n");
1457         license.push_str("\n");
1458
1459         let rtf = r"{\rtf1\ansi\deff0{\fonttbl{\f0\fnil\fcharset0 Arial;}}\nowwrap\fs18";
1460         let mut rtf = rtf.to_string();
1461         rtf.push_str("\n");
1462         for line in license.lines() {
1463             rtf.push_str(line);
1464             rtf.push_str("\\line ");
1465         }
1466         rtf.push_str("}");
1467
1468         fn filter(contents: &str, marker: &str) -> String {
1469             let start = format!("tool-{}-start", marker);
1470             let end = format!("tool-{}-end", marker);
1471             let mut lines = Vec::new();
1472             let mut omitted = false;
1473             for line in contents.lines() {
1474                 if line.contains(&start) {
1475                     omitted = true;
1476                 } else if line.contains(&end) {
1477                     omitted = false;
1478                 } else if !omitted {
1479                     lines.push(line);
1480                 }
1481             }
1482
1483             lines.join("\n")
1484         }
1485
1486         let xform = |p: &Path| {
1487             let mut contents = String::new();
1488             t!(t!(File::open(p)).read_to_string(&mut contents));
1489             if rls_installer.is_none() {
1490                 contents = filter(&contents, "rls");
1491             }
1492             if clippy_installer.is_none() {
1493                 contents = filter(&contents, "clippy");
1494             }
1495             if rustfmt_installer.is_none() {
1496                 contents = filter(&contents, "rustfmt");
1497             }
1498             let ret = tmp.join(p.file_name().unwrap());
1499             t!(t!(File::create(&ret)).write_all(contents.as_bytes()));
1500             return ret
1501         };
1502
1503         if target.contains("apple-darwin") {
1504             let pkg = tmp.join("pkg");
1505             let _ = fs::remove_dir_all(&pkg);
1506
1507             let pkgbuild = |component: &str| {
1508                 let mut cmd = Command::new("pkgbuild");
1509                 cmd.arg("--identifier").arg(format!("org.rust-lang.{}", component))
1510                     .arg("--scripts").arg(pkg.join(component))
1511                     .arg("--nopayload")
1512                     .arg(pkg.join(component).with_extension("pkg"));
1513                 builder.run(&mut cmd);
1514             };
1515
1516             let prepare = |name: &str| {
1517                 builder.create_dir(&pkg.join(name));
1518                 builder.cp_r(&work.join(&format!("{}-{}", pkgname(builder, name), target)),
1519                         &pkg.join(name));
1520                 builder.install(&etc.join("pkg/postinstall"), &pkg.join(name), 0o755);
1521                 pkgbuild(name);
1522             };
1523             prepare("rustc");
1524             prepare("cargo");
1525             prepare("rust-docs");
1526             prepare("rust-std");
1527             prepare("rust-analysis");
1528
1529             if rls_installer.is_some() {
1530                 prepare("rls");
1531             }
1532             if clippy_installer.is_some() {
1533                 prepare("clippy");
1534             }
1535
1536             // create an 'uninstall' package
1537             builder.install(&etc.join("pkg/postinstall"), &pkg.join("uninstall"), 0o755);
1538             pkgbuild("uninstall");
1539
1540             builder.create_dir(&pkg.join("res"));
1541             builder.create(&pkg.join("res/LICENSE.txt"), &license);
1542             builder.install(&etc.join("gfx/rust-logo.png"), &pkg.join("res"), 0o644);
1543             let mut cmd = Command::new("productbuild");
1544             cmd.arg("--distribution").arg(xform(&etc.join("pkg/Distribution.xml")))
1545                 .arg("--resources").arg(pkg.join("res"))
1546                 .arg(distdir(builder).join(format!("{}-{}.pkg",
1547                                                     pkgname(builder, "rust"),
1548                                                     target)))
1549                 .arg("--package-path").arg(&pkg);
1550             builder.run(&mut cmd);
1551         }
1552
1553         if target.contains("windows") {
1554             let exe = tmp.join("exe");
1555             let _ = fs::remove_dir_all(&exe);
1556
1557             let prepare = |name: &str| {
1558                 builder.create_dir(&exe.join(name));
1559                 let dir = if name == "rust-std" || name == "rust-analysis" {
1560                     format!("{}-{}", name, target)
1561                 } else if name == "rls" {
1562                     "rls-preview".to_string()
1563                 } else if name == "clippy" {
1564                     "clippy-preview".to_string()
1565                 } else {
1566                     name.to_string()
1567                 };
1568                 builder.cp_r(&work.join(&format!("{}-{}", pkgname(builder, name), target))
1569                             .join(dir),
1570                         &exe.join(name));
1571                 builder.remove(&exe.join(name).join("manifest.in"));
1572             };
1573             prepare("rustc");
1574             prepare("cargo");
1575             prepare("rust-analysis");
1576             prepare("rust-docs");
1577             prepare("rust-std");
1578             if rls_installer.is_some() {
1579                 prepare("rls");
1580             }
1581             if clippy_installer.is_some() {
1582                 prepare("clippy");
1583             }
1584             if target.contains("windows-gnu") {
1585                 prepare("rust-mingw");
1586             }
1587
1588             builder.install(&xform(&etc.join("exe/rust.iss")), &exe, 0o644);
1589             builder.install(&etc.join("exe/modpath.iss"), &exe, 0o644);
1590             builder.install(&etc.join("exe/upgrade.iss"), &exe, 0o644);
1591             builder.install(&etc.join("gfx/rust-logo.ico"), &exe, 0o644);
1592             builder.create(&exe.join("LICENSE.txt"), &license);
1593
1594             // Generate exe installer
1595             let mut cmd = Command::new("iscc");
1596             cmd.arg("rust.iss")
1597                 .current_dir(&exe);
1598             if target.contains("windows-gnu") {
1599                 cmd.arg("/dMINGW");
1600             }
1601             add_env(builder, &mut cmd, target);
1602             builder.run(&mut cmd);
1603             builder.install(&exe.join(format!("{}-{}.exe", pkgname(builder, "rust"), target)),
1604                     &distdir(builder),
1605                     0o755);
1606
1607             // Generate msi installer
1608             let wix = PathBuf::from(env::var_os("WIX").unwrap());
1609             let heat = wix.join("bin/heat.exe");
1610             let candle = wix.join("bin/candle.exe");
1611             let light = wix.join("bin/light.exe");
1612
1613             let heat_flags = ["-nologo", "-gg", "-sfrag", "-srd", "-sreg"];
1614             builder.run(Command::new(&heat)
1615                             .current_dir(&exe)
1616                             .arg("dir")
1617                             .arg("rustc")
1618                             .args(&heat_flags)
1619                             .arg("-cg").arg("RustcGroup")
1620                             .arg("-dr").arg("Rustc")
1621                             .arg("-var").arg("var.RustcDir")
1622                             .arg("-out").arg(exe.join("RustcGroup.wxs")));
1623             builder.run(Command::new(&heat)
1624                             .current_dir(&exe)
1625                             .arg("dir")
1626                             .arg("rust-docs")
1627                             .args(&heat_flags)
1628                             .arg("-cg").arg("DocsGroup")
1629                             .arg("-dr").arg("Docs")
1630                             .arg("-var").arg("var.DocsDir")
1631                             .arg("-out").arg(exe.join("DocsGroup.wxs"))
1632                             .arg("-t").arg(etc.join("msi/squash-components.xsl")));
1633             builder.run(Command::new(&heat)
1634                             .current_dir(&exe)
1635                             .arg("dir")
1636                             .arg("cargo")
1637                             .args(&heat_flags)
1638                             .arg("-cg").arg("CargoGroup")
1639                             .arg("-dr").arg("Cargo")
1640                             .arg("-var").arg("var.CargoDir")
1641                             .arg("-out").arg(exe.join("CargoGroup.wxs"))
1642                             .arg("-t").arg(etc.join("msi/remove-duplicates.xsl")));
1643             builder.run(Command::new(&heat)
1644                             .current_dir(&exe)
1645                             .arg("dir")
1646                             .arg("rust-std")
1647                             .args(&heat_flags)
1648                             .arg("-cg").arg("StdGroup")
1649                             .arg("-dr").arg("Std")
1650                             .arg("-var").arg("var.StdDir")
1651                             .arg("-out").arg(exe.join("StdGroup.wxs")));
1652             if rls_installer.is_some() {
1653                 builder.run(Command::new(&heat)
1654                                 .current_dir(&exe)
1655                                 .arg("dir")
1656                                 .arg("rls")
1657                                 .args(&heat_flags)
1658                                 .arg("-cg").arg("RlsGroup")
1659                                 .arg("-dr").arg("Rls")
1660                                 .arg("-var").arg("var.RlsDir")
1661                                 .arg("-out").arg(exe.join("RlsGroup.wxs"))
1662                                 .arg("-t").arg(etc.join("msi/remove-duplicates.xsl")));
1663             }
1664             if clippy_installer.is_some() {
1665                 builder.run(Command::new(&heat)
1666                                 .current_dir(&exe)
1667                                 .arg("dir")
1668                                 .arg("clippy")
1669                                 .args(&heat_flags)
1670                                 .arg("-cg").arg("ClippyGroup")
1671                                 .arg("-dr").arg("Clippy")
1672                                 .arg("-var").arg("var.ClippyDir")
1673                                 .arg("-out").arg(exe.join("ClippyGroup.wxs"))
1674                                 .arg("-t").arg(etc.join("msi/remove-duplicates.xsl")));
1675             }
1676             builder.run(Command::new(&heat)
1677                             .current_dir(&exe)
1678                             .arg("dir")
1679                             .arg("rust-analysis")
1680                             .args(&heat_flags)
1681                             .arg("-cg").arg("AnalysisGroup")
1682                             .arg("-dr").arg("Analysis")
1683                             .arg("-var").arg("var.AnalysisDir")
1684                             .arg("-out").arg(exe.join("AnalysisGroup.wxs"))
1685                             .arg("-t").arg(etc.join("msi/remove-duplicates.xsl")));
1686             if target.contains("windows-gnu") {
1687                 builder.run(Command::new(&heat)
1688                                 .current_dir(&exe)
1689                                 .arg("dir")
1690                                 .arg("rust-mingw")
1691                                 .args(&heat_flags)
1692                                 .arg("-cg").arg("GccGroup")
1693                                 .arg("-dr").arg("Gcc")
1694                                 .arg("-var").arg("var.GccDir")
1695                                 .arg("-out").arg(exe.join("GccGroup.wxs")));
1696             }
1697
1698             let candle = |input: &Path| {
1699                 let output = exe.join(input.file_stem().unwrap())
1700                                 .with_extension("wixobj");
1701                 let arch = if target.contains("x86_64") {"x64"} else {"x86"};
1702                 let mut cmd = Command::new(&candle);
1703                 cmd.current_dir(&exe)
1704                     .arg("-nologo")
1705                     .arg("-dRustcDir=rustc")
1706                     .arg("-dDocsDir=rust-docs")
1707                     .arg("-dCargoDir=cargo")
1708                     .arg("-dStdDir=rust-std")
1709                     .arg("-dAnalysisDir=rust-analysis")
1710                     .arg("-arch").arg(&arch)
1711                     .arg("-out").arg(&output)
1712                     .arg(&input);
1713                 add_env(builder, &mut cmd, target);
1714
1715                 if rls_installer.is_some() {
1716                     cmd.arg("-dRlsDir=rls");
1717                 }
1718                 if clippy_installer.is_some() {
1719                     cmd.arg("-dClippyDir=clippy");
1720                 }
1721                 if target.contains("windows-gnu") {
1722                     cmd.arg("-dGccDir=rust-mingw");
1723                 }
1724                 builder.run(&mut cmd);
1725             };
1726             candle(&xform(&etc.join("msi/rust.wxs")));
1727             candle(&etc.join("msi/ui.wxs"));
1728             candle(&etc.join("msi/rustwelcomedlg.wxs"));
1729             candle("RustcGroup.wxs".as_ref());
1730             candle("DocsGroup.wxs".as_ref());
1731             candle("CargoGroup.wxs".as_ref());
1732             candle("StdGroup.wxs".as_ref());
1733             if rls_installer.is_some() {
1734                 candle("RlsGroup.wxs".as_ref());
1735             }
1736             if clippy_installer.is_some() {
1737                 candle("ClippyGroup.wxs".as_ref());
1738             }
1739             candle("AnalysisGroup.wxs".as_ref());
1740
1741             if target.contains("windows-gnu") {
1742                 candle("GccGroup.wxs".as_ref());
1743             }
1744
1745             builder.create(&exe.join("LICENSE.rtf"), &rtf);
1746             builder.install(&etc.join("gfx/banner.bmp"), &exe, 0o644);
1747             builder.install(&etc.join("gfx/dialogbg.bmp"), &exe, 0o644);
1748
1749             let filename = format!("{}-{}.msi", pkgname(builder, "rust"), target);
1750             let mut cmd = Command::new(&light);
1751             cmd.arg("-nologo")
1752                 .arg("-ext").arg("WixUIExtension")
1753                 .arg("-ext").arg("WixUtilExtension")
1754                 .arg("-out").arg(exe.join(&filename))
1755                 .arg("rust.wixobj")
1756                 .arg("ui.wixobj")
1757                 .arg("rustwelcomedlg.wixobj")
1758                 .arg("RustcGroup.wixobj")
1759                 .arg("DocsGroup.wixobj")
1760                 .arg("CargoGroup.wixobj")
1761                 .arg("StdGroup.wixobj")
1762                 .arg("AnalysisGroup.wixobj")
1763                 .current_dir(&exe);
1764
1765             if rls_installer.is_some() {
1766                 cmd.arg("RlsGroup.wixobj");
1767             }
1768             if clippy_installer.is_some() {
1769                 cmd.arg("ClippyGroup.wixobj");
1770             }
1771
1772             if target.contains("windows-gnu") {
1773                 cmd.arg("GccGroup.wixobj");
1774             }
1775             // ICE57 wrongly complains about the shortcuts
1776             cmd.arg("-sice:ICE57");
1777
1778             builder.run(&mut cmd);
1779
1780             if !builder.config.dry_run {
1781                 t!(fs::rename(exe.join(&filename), distdir(builder).join(&filename)));
1782             }
1783         }
1784     }
1785 }
1786
1787 fn add_env(builder: &Builder, cmd: &mut Command, target: Interned<String>) {
1788     let mut parts = channel::CFG_RELEASE_NUM.split('.');
1789     cmd.env("CFG_RELEASE_INFO", builder.rust_version())
1790        .env("CFG_RELEASE_NUM", channel::CFG_RELEASE_NUM)
1791        .env("CFG_RELEASE", builder.rust_release())
1792        .env("CFG_VER_MAJOR", parts.next().unwrap())
1793        .env("CFG_VER_MINOR", parts.next().unwrap())
1794        .env("CFG_VER_PATCH", parts.next().unwrap())
1795        .env("CFG_VER_BUILD", "0") // just needed to build
1796        .env("CFG_PACKAGE_VERS", builder.rust_package_vers())
1797        .env("CFG_PACKAGE_NAME", pkgname(builder, "rust"))
1798        .env("CFG_BUILD", target)
1799        .env("CFG_CHANNEL", &builder.config.channel);
1800
1801     if target.contains("windows-gnu") {
1802        cmd.env("CFG_MINGW", "1")
1803           .env("CFG_ABI", "GNU");
1804     } else {
1805        cmd.env("CFG_MINGW", "0")
1806           .env("CFG_ABI", "MSVC");
1807     }
1808
1809     if target.contains("x86_64") {
1810        cmd.env("CFG_PLATFORM", "x64");
1811     } else {
1812        cmd.env("CFG_PLATFORM", "x86");
1813     }
1814 }
1815
1816 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
1817 pub struct HashSign;
1818
1819 impl Step for HashSign {
1820     type Output = ();
1821     const ONLY_HOSTS: bool = true;
1822
1823     fn should_run(run: ShouldRun) -> ShouldRun {
1824         run.path("hash-and-sign")
1825     }
1826
1827     fn make_run(run: RunConfig) {
1828         run.builder.ensure(HashSign);
1829     }
1830
1831     fn run(self, builder: &Builder) {
1832         let mut cmd = builder.tool_cmd(Tool::BuildManifest);
1833         if builder.config.dry_run {
1834             return;
1835         }
1836         let sign = builder.config.dist_sign_folder.as_ref().unwrap_or_else(|| {
1837             panic!("\n\nfailed to specify `dist.sign-folder` in `config.toml`\n\n")
1838         });
1839         let addr = builder.config.dist_upload_addr.as_ref().unwrap_or_else(|| {
1840             panic!("\n\nfailed to specify `dist.upload-addr` in `config.toml`\n\n")
1841         });
1842         let file = builder.config.dist_gpg_password_file.as_ref().unwrap_or_else(|| {
1843             panic!("\n\nfailed to specify `dist.gpg-password-file` in `config.toml`\n\n")
1844         });
1845         let mut pass = String::new();
1846         t!(t!(File::open(&file)).read_to_string(&mut pass));
1847
1848         let today = output(Command::new("date").arg("+%Y-%m-%d"));
1849
1850         cmd.arg(sign);
1851         cmd.arg(distdir(builder));
1852         cmd.arg(today.trim());
1853         cmd.arg(builder.rust_package_vers());
1854         cmd.arg(builder.package_vers(&builder.release_num("cargo")));
1855         cmd.arg(builder.package_vers(&builder.release_num("rls")));
1856         cmd.arg(builder.package_vers(&builder.release_num("clippy")));
1857         cmd.arg(builder.package_vers(&builder.release_num("rustfmt")));
1858         cmd.arg(builder.llvm_tools_package_vers());
1859         cmd.arg(addr);
1860
1861         builder.create_dir(&distdir(builder));
1862
1863         let mut child = t!(cmd.stdin(Stdio::piped()).spawn());
1864         t!(child.stdin.take().unwrap().write_all(pass.as_bytes()));
1865         let status = t!(child.wait());
1866         assert!(status.success());
1867     }
1868 }
1869
1870 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1871 pub struct LlvmTools {
1872     pub stage: u32,
1873     pub target: Interned<String>,
1874 }
1875
1876 impl Step for LlvmTools {
1877     type Output = Option<PathBuf>;
1878     const ONLY_HOSTS: bool = true;
1879
1880     fn should_run(run: ShouldRun) -> ShouldRun {
1881         run.path("llvm-tools")
1882     }
1883
1884     fn make_run(run: RunConfig) {
1885         run.builder.ensure(LlvmTools {
1886             stage: run.builder.top_stage,
1887             target: run.target,
1888         });
1889     }
1890
1891     fn run(self, builder: &Builder) -> Option<PathBuf> {
1892         let stage = self.stage;
1893         let target = self.target;
1894         assert!(builder.config.extended);
1895
1896         builder.info(&format!("Dist LlvmTools stage{} ({})", stage, target));
1897         let src = builder.src.join("src/llvm");
1898         let name = pkgname(builder, "llvm-tools");
1899
1900         let tmp = tmpdir(builder);
1901         let image = tmp.join("llvm-tools-image");
1902         drop(fs::remove_dir_all(&image));
1903
1904         // Prepare the image directory
1905         let bindir = builder
1906             .llvm_out(target)
1907             .join("bin");
1908         let dst = image.join("lib/rustlib")
1909             .join(target)
1910             .join("bin");
1911         t!(fs::create_dir_all(&dst));
1912         for tool in LLVM_TOOLS {
1913             let exe = bindir.join(exe(tool, &target));
1914             builder.install(&exe, &dst, 0o755);
1915         }
1916
1917         // Prepare the overlay
1918         let overlay = tmp.join("llvm-tools-overlay");
1919         drop(fs::remove_dir_all(&overlay));
1920         builder.create_dir(&overlay);
1921         builder.install(&src.join("README.txt"), &overlay, 0o644);
1922         builder.install(&src.join("LICENSE.TXT"), &overlay, 0o644);
1923         builder.create(&overlay.join("version"), &builder.llvm_tools_vers());
1924
1925         // Generate the installer tarball
1926         let mut cmd = rust_installer(builder);
1927         cmd.arg("generate")
1928             .arg("--product-name=Rust")
1929             .arg("--rel-manifest-dir=rustlib")
1930             .arg("--success-message=llvm-tools-installed.")
1931             .arg("--image-dir").arg(&image)
1932             .arg("--work-dir").arg(&tmpdir(builder))
1933             .arg("--output-dir").arg(&distdir(builder))
1934             .arg("--non-installed-overlay").arg(&overlay)
1935             .arg(format!("--package-name={}-{}", name, target))
1936             .arg("--legacy-manifest-dirs=rustlib,cargo")
1937             .arg("--component-name=llvm-tools-preview");
1938
1939
1940         builder.run(&mut cmd);
1941         Some(distdir(builder).join(format!("{}-{}.tar.gz", name, target)))
1942     }
1943 }