]> git.lizzy.rs Git - rust.git/blob - src/bootstrap/dist.rs
Auto merge of #42541 - gilescope:patch-1, r=alexcrichton
[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 {Build, Compiler, Mode};
30 use channel;
31 use util::{cp_r, libdir, is_dylib, cp_filtered, copy, exe};
32
33 pub fn pkgname(build: &Build, component: &str) -> String {
34     if component == "cargo" {
35         format!("{}-{}", component, build.cargo_package_vers())
36     } else if component == "rls" {
37         format!("{}-{}", component, build.rls_package_vers())
38     } else {
39         assert!(component.starts_with("rust"));
40         format!("{}-{}", component, build.rust_package_vers())
41     }
42 }
43
44 fn distdir(build: &Build) -> PathBuf {
45     build.out.join("dist")
46 }
47
48 pub fn tmpdir(build: &Build) -> PathBuf {
49     build.out.join("tmp/dist")
50 }
51
52 fn rust_installer(build: &Build) -> Command {
53     build.tool_cmd(&Compiler::new(0, &build.config.build), "rust-installer")
54 }
55
56 /// Builds the `rust-docs` installer component.
57 ///
58 /// Slurps up documentation from the `stage`'s `host`.
59 pub fn docs(build: &Build, stage: u32, host: &str) {
60     println!("Dist docs stage{} ({})", stage, host);
61     if !build.config.docs {
62         println!("\tskipping - docs disabled");
63         return
64     }
65
66     let name = pkgname(build, "rust-docs");
67     let image = tmpdir(build).join(format!("{}-{}-image", name, host));
68     let _ = fs::remove_dir_all(&image);
69
70     let dst = image.join("share/doc/rust/html");
71     t!(fs::create_dir_all(&dst));
72     let src = build.out.join(host).join("doc");
73     cp_r(&src, &dst);
74
75     let mut cmd = rust_installer(build);
76     cmd.arg("generate")
77        .arg("--product-name=Rust-Documentation")
78        .arg("--rel-manifest-dir=rustlib")
79        .arg("--success-message=Rust-documentation-is-installed.")
80        .arg("--image-dir").arg(&image)
81        .arg("--work-dir").arg(&tmpdir(build))
82        .arg("--output-dir").arg(&distdir(build))
83        .arg(format!("--package-name={}-{}", name, host))
84        .arg("--component-name=rust-docs")
85        .arg("--legacy-manifest-dirs=rustlib,cargo")
86        .arg("--bulk-dirs=share/doc/rust/html");
87     build.run(&mut cmd);
88     t!(fs::remove_dir_all(&image));
89
90     // As part of this step, *also* copy the docs directory to a directory which
91     // buildbot typically uploads.
92     if host == build.config.build {
93         let dst = distdir(build).join("doc").join(build.rust_package_vers());
94         t!(fs::create_dir_all(&dst));
95         cp_r(&src, &dst);
96     }
97 }
98
99 fn find_files(files: &[&str], path: &[PathBuf]) -> Vec<PathBuf> {
100     let mut found = Vec::new();
101
102     for file in files {
103         let file_path =
104             path.iter()
105                 .map(|dir| dir.join(file))
106                 .find(|p| p.exists());
107
108         if let Some(file_path) = file_path {
109             found.push(file_path);
110         } else {
111             panic!("Could not find '{}' in {:?}", file, path);
112         }
113     }
114
115     found
116 }
117
118 fn make_win_dist(rust_root: &Path, plat_root: &Path, target_triple: &str, build: &Build) {
119     //Ask gcc where it keeps its stuff
120     let mut cmd = Command::new(build.cc(target_triple));
121     cmd.arg("-print-search-dirs");
122     build.run_quiet(&mut cmd);
123     let gcc_out =
124         String::from_utf8(
125                 cmd
126                 .output()
127                 .expect("failed to execute gcc")
128                 .stdout).expect("gcc.exe output was not utf8");
129
130     let mut bin_path: Vec<_> =
131         env::split_paths(&env::var_os("PATH").unwrap_or_default())
132         .collect();
133     let mut lib_path = Vec::new();
134
135     for line in gcc_out.lines() {
136         let idx = line.find(':').unwrap();
137         let key = &line[..idx];
138         let trim_chars: &[_] = &[' ', '='];
139         let value =
140             line[(idx + 1)..]
141                 .trim_left_matches(trim_chars)
142                 .split(';')
143                 .map(|s| PathBuf::from(s));
144
145         if key == "programs" {
146             bin_path.extend(value);
147         } else if key == "libraries" {
148             lib_path.extend(value);
149         }
150     }
151
152     let target_tools = vec!["gcc.exe", "ld.exe", "ar.exe", "dlltool.exe", "libwinpthread-1.dll"];
153     let mut rustc_dlls = vec!["libstdc++-6.dll", "libwinpthread-1.dll"];
154     if target_triple.starts_with("i686-") {
155         rustc_dlls.push("libgcc_s_dw2-1.dll");
156     } else {
157         rustc_dlls.push("libgcc_s_seh-1.dll");
158     }
159
160     let target_libs = vec![ //MinGW libs
161         "libgcc.a",
162         "libgcc_eh.a",
163         "libgcc_s.a",
164         "libm.a",
165         "libmingw32.a",
166         "libmingwex.a",
167         "libstdc++.a",
168         "libiconv.a",
169         "libmoldname.a",
170         "libpthread.a",
171         //Windows import libs
172         "libadvapi32.a",
173         "libbcrypt.a",
174         "libcomctl32.a",
175         "libcomdlg32.a",
176         "libcrypt32.a",
177         "libgdi32.a",
178         "libimagehlp.a",
179         "libiphlpapi.a",
180         "libkernel32.a",
181         "libmsvcrt.a",
182         "libodbc32.a",
183         "libole32.a",
184         "liboleaut32.a",
185         "libopengl32.a",
186         "libpsapi.a",
187         "librpcrt4.a",
188         "libsetupapi.a",
189         "libshell32.a",
190         "libuser32.a",
191         "libuserenv.a",
192         "libuuid.a",
193         "libwinhttp.a",
194         "libwinmm.a",
195         "libwinspool.a",
196         "libws2_32.a",
197         "libwsock32.a",
198     ];
199
200     //Find mingw artifacts we want to bundle
201     let target_tools = find_files(&target_tools, &bin_path);
202     let rustc_dlls = find_files(&rustc_dlls, &bin_path);
203     let target_libs = find_files(&target_libs, &lib_path);
204
205     fn copy_to_folder(src: &Path, dest_folder: &Path) {
206         let file_name = src.file_name().unwrap().to_os_string();
207         let dest = dest_folder.join(file_name);
208         copy(src, &dest);
209     }
210
211     //Copy runtime dlls next to rustc.exe
212     let dist_bin_dir = rust_root.join("bin/");
213     fs::create_dir_all(&dist_bin_dir).expect("creating dist_bin_dir failed");
214     for src in rustc_dlls {
215         copy_to_folder(&src, &dist_bin_dir);
216     }
217
218     //Copy platform tools to platform-specific bin directory
219     let target_bin_dir = plat_root.join("lib").join("rustlib").join(target_triple).join("bin");
220     fs::create_dir_all(&target_bin_dir).expect("creating target_bin_dir failed");
221     for src in target_tools {
222         copy_to_folder(&src, &target_bin_dir);
223     }
224
225     //Copy platform libs to platform-specific lib directory
226     let target_lib_dir = plat_root.join("lib").join("rustlib").join(target_triple).join("lib");
227     fs::create_dir_all(&target_lib_dir).expect("creating target_lib_dir failed");
228     for src in target_libs {
229         copy_to_folder(&src, &target_lib_dir);
230     }
231 }
232
233 /// Build the `rust-mingw` installer component.
234 ///
235 /// This contains all the bits and pieces to run the MinGW Windows targets
236 /// without any extra installed software (e.g. we bundle gcc, libraries, etc).
237 /// Currently just shells out to a python script, but that should be rewritten
238 /// in Rust.
239 pub fn mingw(build: &Build, host: &str) {
240     println!("Dist mingw ({})", host);
241     let name = pkgname(build, "rust-mingw");
242     let image = tmpdir(build).join(format!("{}-{}-image", name, host));
243     let _ = fs::remove_dir_all(&image);
244     t!(fs::create_dir_all(&image));
245
246     // The first argument is a "temporary directory" which is just
247     // thrown away (this contains the runtime DLLs included in the rustc package
248     // above) and the second argument is where to place all the MinGW components
249     // (which is what we want).
250     make_win_dist(&tmpdir(build), &image, host, &build);
251
252     let mut cmd = rust_installer(build);
253     cmd.arg("generate")
254        .arg("--product-name=Rust-MinGW")
255        .arg("--rel-manifest-dir=rustlib")
256        .arg("--success-message=Rust-MinGW-is-installed.")
257        .arg("--image-dir").arg(&image)
258        .arg("--work-dir").arg(&tmpdir(build))
259        .arg("--output-dir").arg(&distdir(build))
260        .arg(format!("--package-name={}-{}", name, host))
261        .arg("--component-name=rust-mingw")
262        .arg("--legacy-manifest-dirs=rustlib,cargo");
263     build.run(&mut cmd);
264     t!(fs::remove_dir_all(&image));
265 }
266
267 /// Creates the `rustc` installer component.
268 pub fn rustc(build: &Build, stage: u32, host: &str) {
269     println!("Dist rustc stage{} ({})", stage, host);
270     let name = pkgname(build, "rustc");
271     let image = tmpdir(build).join(format!("{}-{}-image", name, host));
272     let _ = fs::remove_dir_all(&image);
273     let overlay = tmpdir(build).join(format!("{}-{}-overlay", name, host));
274     let _ = fs::remove_dir_all(&overlay);
275
276     // Prepare the rustc "image", what will actually end up getting installed
277     prepare_image(build, stage, host, &image);
278
279     // Prepare the overlay which is part of the tarball but won't actually be
280     // installed
281     let cp = |file: &str| {
282         install(&build.src.join(file), &overlay, 0o644);
283     };
284     cp("COPYRIGHT");
285     cp("LICENSE-APACHE");
286     cp("LICENSE-MIT");
287     cp("README.md");
288     // tiny morsel of metadata is used by rust-packaging
289     let version = build.rust_version();
290     t!(t!(File::create(overlay.join("version"))).write_all(version.as_bytes()));
291
292     // On MinGW we've got a few runtime DLL dependencies that we need to
293     // include. The first argument to this script is where to put these DLLs
294     // (the image we're creating), and the second argument is a junk directory
295     // to ignore all other MinGW stuff the script creates.
296     //
297     // On 32-bit MinGW we're always including a DLL which needs some extra
298     // licenses to distribute. On 64-bit MinGW we don't actually distribute
299     // anything requiring us to distribute a license, but it's likely the
300     // install will *also* include the rust-mingw package, which also needs
301     // licenses, so to be safe we just include it here in all MinGW packages.
302     if host.contains("pc-windows-gnu") {
303         make_win_dist(&image, &tmpdir(build), host, build);
304
305         let dst = image.join("share/doc");
306         t!(fs::create_dir_all(&dst));
307         cp_r(&build.src.join("src/etc/third-party"), &dst);
308     }
309
310     // Finally, wrap everything up in a nice tarball!
311     let mut cmd = rust_installer(build);
312     cmd.arg("generate")
313        .arg("--product-name=Rust")
314        .arg("--rel-manifest-dir=rustlib")
315        .arg("--success-message=Rust-is-ready-to-roll.")
316        .arg("--image-dir").arg(&image)
317        .arg("--work-dir").arg(&tmpdir(build))
318        .arg("--output-dir").arg(&distdir(build))
319        .arg("--non-installed-overlay").arg(&overlay)
320        .arg(format!("--package-name={}-{}", name, host))
321        .arg("--component-name=rustc")
322        .arg("--legacy-manifest-dirs=rustlib,cargo");
323     build.run(&mut cmd);
324     t!(fs::remove_dir_all(&image));
325     t!(fs::remove_dir_all(&overlay));
326
327     fn prepare_image(build: &Build, stage: u32, host: &str, image: &Path) {
328         let src = build.sysroot(&Compiler::new(stage, host));
329         let libdir = libdir(host);
330
331         // Copy rustc/rustdoc binaries
332         t!(fs::create_dir_all(image.join("bin")));
333         cp_r(&src.join("bin"), &image.join("bin"));
334
335         // Copy runtime DLLs needed by the compiler
336         if libdir != "bin" {
337             for entry in t!(src.join(libdir).read_dir()).map(|e| t!(e)) {
338                 let name = entry.file_name();
339                 if let Some(s) = name.to_str() {
340                     if is_dylib(s) {
341                         install(&entry.path(), &image.join(libdir), 0o644);
342                     }
343                 }
344             }
345         }
346
347         // Man pages
348         t!(fs::create_dir_all(image.join("share/man/man1")));
349         cp_r(&build.src.join("man"), &image.join("share/man/man1"));
350
351         // Debugger scripts
352         debugger_scripts(build, &image, host);
353
354         // Misc license info
355         let cp = |file: &str| {
356             install(&build.src.join(file), &image.join("share/doc/rust"), 0o644);
357         };
358         cp("COPYRIGHT");
359         cp("LICENSE-APACHE");
360         cp("LICENSE-MIT");
361         cp("README.md");
362     }
363 }
364
365 /// Copies debugger scripts for `host` into the `sysroot` specified.
366 pub fn debugger_scripts(build: &Build,
367                         sysroot: &Path,
368                         host: &str) {
369     let cp_debugger_script = |file: &str| {
370         let dst = sysroot.join("lib/rustlib/etc");
371         t!(fs::create_dir_all(&dst));
372         install(&build.src.join("src/etc/").join(file), &dst, 0o644);
373     };
374     if host.contains("windows-msvc") {
375         // windbg debugger scripts
376         install(&build.src.join("src/etc/rust-windbg.cmd"), &sysroot.join("bin"),
377             0o755);
378
379         cp_debugger_script("natvis/liballoc.natvis");
380         cp_debugger_script("natvis/libcore.natvis");
381     } else {
382         cp_debugger_script("debugger_pretty_printers_common.py");
383
384         // gdb debugger scripts
385         install(&build.src.join("src/etc/rust-gdb"), &sysroot.join("bin"),
386                 0o755);
387
388         cp_debugger_script("gdb_load_rust_pretty_printers.py");
389         cp_debugger_script("gdb_rust_pretty_printing.py");
390
391         // lldb debugger scripts
392         install(&build.src.join("src/etc/rust-lldb"), &sysroot.join("bin"),
393                 0o755);
394
395         cp_debugger_script("lldb_rust_formatters.py");
396     }
397 }
398
399 /// Creates the `rust-std` installer component as compiled by `compiler` for the
400 /// target `target`.
401 pub fn std(build: &Build, compiler: &Compiler, target: &str) {
402     println!("Dist std stage{} ({} -> {})", compiler.stage, compiler.host,
403              target);
404
405     // The only true set of target libraries came from the build triple, so
406     // let's reduce redundant work by only producing archives from that host.
407     if compiler.host != build.config.build {
408         println!("\tskipping, not a build host");
409         return
410     }
411
412     let name = pkgname(build, "rust-std");
413     let image = tmpdir(build).join(format!("{}-{}-image", name, target));
414     let _ = fs::remove_dir_all(&image);
415
416     let dst = image.join("lib/rustlib").join(target);
417     t!(fs::create_dir_all(&dst));
418     let src = build.sysroot(compiler).join("lib/rustlib");
419     cp_r(&src.join(target), &dst);
420
421     let mut cmd = rust_installer(build);
422     cmd.arg("generate")
423        .arg("--product-name=Rust")
424        .arg("--rel-manifest-dir=rustlib")
425        .arg("--success-message=std-is-standing-at-the-ready.")
426        .arg("--image-dir").arg(&image)
427        .arg("--work-dir").arg(&tmpdir(build))
428        .arg("--output-dir").arg(&distdir(build))
429        .arg(format!("--package-name={}-{}", name, target))
430        .arg(format!("--component-name=rust-std-{}", target))
431        .arg("--legacy-manifest-dirs=rustlib,cargo");
432     build.run(&mut cmd);
433     t!(fs::remove_dir_all(&image));
434 }
435
436 /// The path to the complete rustc-src tarball
437 pub fn rust_src_location(build: &Build) -> PathBuf {
438     let plain_name = format!("rustc-{}-src", build.rust_package_vers());
439     distdir(build).join(&format!("{}.tar.gz", plain_name))
440 }
441
442 /// The path to the rust-src component installer
443 pub fn rust_src_installer(build: &Build) -> PathBuf {
444     let name = pkgname(build, "rust-src");
445     distdir(build).join(&format!("{}.tar.gz", name))
446 }
447
448 /// Creates a tarball of save-analysis metadata, if available.
449 pub fn analysis(build: &Build, compiler: &Compiler, target: &str) {
450     assert!(build.config.extended);
451     println!("Dist analysis");
452
453     if compiler.host != build.config.build {
454         println!("\tskipping, not a build host");
455         return;
456     }
457
458     // Package save-analysis from stage1 if not doing a full bootstrap, as the
459     // stage2 artifacts is simply copied from stage1 in that case.
460     let compiler = if build.force_use_stage1(compiler, target) {
461         Compiler::new(1, compiler.host)
462     } else {
463         compiler.clone()
464     };
465
466     let name = pkgname(build, "rust-analysis");
467     let image = tmpdir(build).join(format!("{}-{}-image", name, target));
468
469     let src = build.stage_out(&compiler, Mode::Libstd).join(target).join("release").join("deps");
470
471     let image_src = src.join("save-analysis");
472     let dst = image.join("lib/rustlib").join(target).join("analysis");
473     t!(fs::create_dir_all(&dst));
474     println!("image_src: {:?}, dst: {:?}", image_src, dst);
475     cp_r(&image_src, &dst);
476
477     let mut cmd = rust_installer(build);
478     cmd.arg("generate")
479        .arg("--product-name=Rust")
480        .arg("--rel-manifest-dir=rustlib")
481        .arg("--success-message=save-analysis-saved.")
482        .arg("--image-dir").arg(&image)
483        .arg("--work-dir").arg(&tmpdir(build))
484        .arg("--output-dir").arg(&distdir(build))
485        .arg(format!("--package-name={}-{}", name, target))
486        .arg(format!("--component-name=rust-analysis-{}", target))
487        .arg("--legacy-manifest-dirs=rustlib,cargo");
488     build.run(&mut cmd);
489     t!(fs::remove_dir_all(&image));
490 }
491
492 fn copy_src_dirs(build: &Build, src_dirs: &[&str], exclude_dirs: &[&str], dst_dir: &Path) {
493     fn filter_fn(exclude_dirs: &[&str], dir: &str, path: &Path) -> bool {
494         let spath = match path.to_str() {
495             Some(path) => path,
496             None => return false,
497         };
498         if spath.ends_with("~") || spath.ends_with(".pyc") {
499             return false
500         }
501         if spath.contains("llvm/test") || spath.contains("llvm\\test") {
502             if spath.ends_with(".ll") ||
503                spath.ends_with(".td") ||
504                spath.ends_with(".s") {
505                 return false
506             }
507         }
508
509         let full_path = Path::new(dir).join(path);
510         if exclude_dirs.iter().any(|excl| full_path == Path::new(excl)) {
511             return false;
512         }
513
514         let excludes = [
515             "CVS", "RCS", "SCCS", ".git", ".gitignore", ".gitmodules",
516             ".gitattributes", ".cvsignore", ".svn", ".arch-ids", "{arch}",
517             "=RELEASE-ID", "=meta-update", "=update", ".bzr", ".bzrignore",
518             ".bzrtags", ".hg", ".hgignore", ".hgrags", "_darcs",
519         ];
520         !path.iter()
521              .map(|s| s.to_str().unwrap())
522              .any(|s| excludes.contains(&s))
523     }
524
525     // Copy the directories using our filter
526     for item in src_dirs {
527         let dst = &dst_dir.join(item);
528         t!(fs::create_dir_all(dst));
529         cp_filtered(&build.src.join(item), dst, &|path| filter_fn(exclude_dirs, item, path));
530     }
531 }
532
533 /// Creates the `rust-src` installer component
534 pub fn rust_src(build: &Build) {
535     println!("Dist src");
536
537     let name = pkgname(build, "rust-src");
538     let image = tmpdir(build).join(format!("{}-image", name));
539     let _ = fs::remove_dir_all(&image);
540
541     let dst = image.join("lib/rustlib/src");
542     let dst_src = dst.join("rust");
543     t!(fs::create_dir_all(&dst_src));
544
545     // This is the reduced set of paths which will become the rust-src component
546     // (essentially libstd and all of its path dependencies)
547     let std_src_dirs = [
548         "src/build_helper",
549         "src/liballoc",
550         "src/liballoc_jemalloc",
551         "src/liballoc_system",
552         "src/libbacktrace",
553         "src/libcollections",
554         "src/libcompiler_builtins",
555         "src/libcore",
556         "src/liblibc",
557         "src/libpanic_abort",
558         "src/libpanic_unwind",
559         "src/librand",
560         "src/librustc_asan",
561         "src/librustc_lsan",
562         "src/librustc_msan",
563         "src/librustc_tsan",
564         "src/libstd",
565         "src/libstd_unicode",
566         "src/libunwind",
567         "src/rustc/libc_shim",
568         "src/libtest",
569         "src/libterm",
570         "src/compiler-rt",
571         "src/jemalloc",
572         "src/libprofiler_builtins",
573     ];
574     let std_src_dirs_exclude = [
575         "src/compiler-rt/test",
576         "src/jemalloc/test/unit",
577     ];
578
579     copy_src_dirs(build, &std_src_dirs[..], &std_src_dirs_exclude[..], &dst_src);
580
581     // Create source tarball in rust-installer format
582     let mut cmd = rust_installer(build);
583     cmd.arg("generate")
584        .arg("--product-name=Rust")
585        .arg("--rel-manifest-dir=rustlib")
586        .arg("--success-message=Awesome-Source.")
587        .arg("--image-dir").arg(&image)
588        .arg("--work-dir").arg(&tmpdir(build))
589        .arg("--output-dir").arg(&distdir(build))
590        .arg(format!("--package-name={}", name))
591        .arg("--component-name=rust-src")
592        .arg("--legacy-manifest-dirs=rustlib,cargo");
593     build.run(&mut cmd);
594
595     t!(fs::remove_dir_all(&image));
596 }
597
598 const CARGO_VENDOR_VERSION: &'static str = "0.1.4";
599
600 /// Creates the plain source tarball
601 pub fn plain_source_tarball(build: &Build) {
602     println!("Create plain source tarball");
603
604     // Make sure that the root folder of tarball has the correct name
605     let plain_name = format!("{}-src", pkgname(build, "rustc"));
606     let plain_dst_src = tmpdir(build).join(&plain_name);
607     let _ = fs::remove_dir_all(&plain_dst_src);
608     t!(fs::create_dir_all(&plain_dst_src));
609
610     // This is the set of root paths which will become part of the source package
611     let src_files = [
612         "COPYRIGHT",
613         "LICENSE-APACHE",
614         "LICENSE-MIT",
615         "CONTRIBUTING.md",
616         "README.md",
617         "RELEASES.md",
618         "configure",
619         "x.py",
620     ];
621     let src_dirs = [
622         "man",
623         "src",
624     ];
625
626     copy_src_dirs(build, &src_dirs[..], &[], &plain_dst_src);
627
628     // Copy the files normally
629     for item in &src_files {
630         copy(&build.src.join(item), &plain_dst_src.join(item));
631     }
632
633     // Create the version file
634     write_file(&plain_dst_src.join("version"), build.rust_version().as_bytes());
635
636     // If we're building from git sources, we need to vendor a complete distribution.
637     if build.src_is_git {
638         // Get cargo-vendor installed, if it isn't already.
639         let mut has_cargo_vendor = false;
640         let mut cmd = Command::new(&build.cargo);
641         for line in output(cmd.arg("install").arg("--list")).lines() {
642             has_cargo_vendor |= line.starts_with("cargo-vendor ");
643         }
644         if !has_cargo_vendor {
645             let mut cmd = Command::new(&build.cargo);
646             cmd.arg("install")
647                .arg("--force")
648                .arg("--debug")
649                .arg("--vers").arg(CARGO_VENDOR_VERSION)
650                .arg("cargo-vendor")
651                .env("RUSTC", &build.rustc);
652             build.run(&mut cmd);
653         }
654
655         // Vendor all Cargo dependencies
656         let mut cmd = Command::new(&build.cargo);
657         cmd.arg("vendor")
658            .current_dir(&plain_dst_src.join("src"));
659         build.run(&mut cmd);
660     }
661
662     // Create plain source tarball
663     let mut tarball = rust_src_location(build);
664     tarball.set_extension(""); // strip .gz
665     tarball.set_extension(""); // strip .tar
666     if let Some(dir) = tarball.parent() {
667         t!(fs::create_dir_all(dir));
668     }
669     let mut cmd = rust_installer(build);
670     cmd.arg("tarball")
671        .arg("--input").arg(&plain_name)
672        .arg("--output").arg(&tarball)
673        .arg("--work-dir=.")
674        .current_dir(tmpdir(build));
675     build.run(&mut cmd);
676 }
677
678 fn install(src: &Path, dstdir: &Path, perms: u32) {
679     let dst = dstdir.join(src.file_name().unwrap());
680     t!(fs::create_dir_all(dstdir));
681     t!(fs::copy(src, &dst));
682     chmod(&dst, perms);
683 }
684
685 #[cfg(unix)]
686 fn chmod(path: &Path, perms: u32) {
687     use std::os::unix::fs::*;
688     t!(fs::set_permissions(path, fs::Permissions::from_mode(perms)));
689 }
690 #[cfg(windows)]
691 fn chmod(_path: &Path, _perms: u32) {}
692
693 // We have to run a few shell scripts, which choke quite a bit on both `\`
694 // characters and on `C:\` paths, so normalize both of them away.
695 pub fn sanitize_sh(path: &Path) -> String {
696     let path = path.to_str().unwrap().replace("\\", "/");
697     return change_drive(&path).unwrap_or(path);
698
699     fn change_drive(s: &str) -> Option<String> {
700         let mut ch = s.chars();
701         let drive = ch.next().unwrap_or('C');
702         if ch.next() != Some(':') {
703             return None
704         }
705         if ch.next() != Some('/') {
706             return None
707         }
708         Some(format!("/{}/{}", drive, &s[drive.len_utf8() + 2..]))
709     }
710 }
711
712 fn write_file(path: &Path, data: &[u8]) {
713     let mut vf = t!(fs::File::create(path));
714     t!(vf.write_all(data));
715 }
716
717 pub fn cargo(build: &Build, stage: u32, target: &str) {
718     println!("Dist cargo stage{} ({})", stage, target);
719     let compiler = Compiler::new(stage, &build.config.build);
720
721     let src = build.src.join("src/tools/cargo");
722     let etc = src.join("src/etc");
723     let release_num = build.release_num("cargo");
724     let name = pkgname(build, "cargo");
725     let version = build.cargo_info.version(build, &release_num);
726
727     let tmp = tmpdir(build);
728     let image = tmp.join("cargo-image");
729     drop(fs::remove_dir_all(&image));
730     t!(fs::create_dir_all(&image));
731
732     // Prepare the image directory
733     t!(fs::create_dir_all(image.join("share/zsh/site-functions")));
734     t!(fs::create_dir_all(image.join("etc/bash_completion.d")));
735     let cargo = build.cargo_out(&compiler, Mode::Tool, target)
736                      .join(exe("cargo", target));
737     install(&cargo, &image.join("bin"), 0o755);
738     for man in t!(etc.join("man").read_dir()) {
739         let man = t!(man);
740         install(&man.path(), &image.join("share/man/man1"), 0o644);
741     }
742     install(&etc.join("_cargo"), &image.join("share/zsh/site-functions"), 0o644);
743     copy(&etc.join("cargo.bashcomp.sh"),
744          &image.join("etc/bash_completion.d/cargo"));
745     let doc = image.join("share/doc/cargo");
746     install(&src.join("README.md"), &doc, 0o644);
747     install(&src.join("LICENSE-MIT"), &doc, 0o644);
748     install(&src.join("LICENSE-APACHE"), &doc, 0o644);
749     install(&src.join("LICENSE-THIRD-PARTY"), &doc, 0o644);
750
751     // Prepare the overlay
752     let overlay = tmp.join("cargo-overlay");
753     drop(fs::remove_dir_all(&overlay));
754     t!(fs::create_dir_all(&overlay));
755     install(&src.join("README.md"), &overlay, 0o644);
756     install(&src.join("LICENSE-MIT"), &overlay, 0o644);
757     install(&src.join("LICENSE-APACHE"), &overlay, 0o644);
758     install(&src.join("LICENSE-THIRD-PARTY"), &overlay, 0o644);
759     t!(t!(File::create(overlay.join("version"))).write_all(version.as_bytes()));
760
761     // Generate the installer tarball
762     let mut cmd = rust_installer(build);
763     cmd.arg("generate")
764        .arg("--product-name=Rust")
765        .arg("--rel-manifest-dir=rustlib")
766        .arg("--success-message=Rust-is-ready-to-roll.")
767        .arg("--image-dir").arg(&image)
768        .arg("--work-dir").arg(&tmpdir(build))
769        .arg("--output-dir").arg(&distdir(build))
770        .arg("--non-installed-overlay").arg(&overlay)
771        .arg(format!("--package-name={}-{}", name, target))
772        .arg("--component-name=cargo")
773        .arg("--legacy-manifest-dirs=rustlib,cargo");
774     build.run(&mut cmd);
775 }
776
777 pub fn rls(build: &Build, stage: u32, target: &str) {
778     assert!(build.config.extended);
779     println!("Dist RLS stage{} ({})", stage, target);
780     let compiler = Compiler::new(stage, &build.config.build);
781
782     let src = build.src.join("src/tools/rls");
783     let release_num = build.release_num("rls");
784     let name = pkgname(build, "rls");
785     let version = build.rls_info.version(build, &release_num);
786
787     let tmp = tmpdir(build);
788     let image = tmp.join("rls-image");
789     drop(fs::remove_dir_all(&image));
790     t!(fs::create_dir_all(&image));
791
792     // Prepare the image directory
793     let rls = build.cargo_out(&compiler, Mode::Tool, target)
794                      .join(exe("rls", target));
795     install(&rls, &image.join("bin"), 0o755);
796     let doc = image.join("share/doc/rls");
797     install(&src.join("README.md"), &doc, 0o644);
798     install(&src.join("LICENSE-MIT"), &doc, 0o644);
799     install(&src.join("LICENSE-APACHE"), &doc, 0o644);
800
801     // Prepare the overlay
802     let overlay = tmp.join("rls-overlay");
803     drop(fs::remove_dir_all(&overlay));
804     t!(fs::create_dir_all(&overlay));
805     install(&src.join("README.md"), &overlay, 0o644);
806     install(&src.join("LICENSE-MIT"), &overlay, 0o644);
807     install(&src.join("LICENSE-APACHE"), &overlay, 0o644);
808     t!(t!(File::create(overlay.join("version"))).write_all(version.as_bytes()));
809
810     // Generate the installer tarball
811     let mut cmd = rust_installer(build);
812     cmd.arg("generate")
813        .arg("--product-name=Rust")
814        .arg("--rel-manifest-dir=rustlib")
815        .arg("--success-message=RLS-ready-to-serve.")
816        .arg("--image-dir").arg(&image)
817        .arg("--work-dir").arg(&tmpdir(build))
818        .arg("--output-dir").arg(&distdir(build))
819        .arg("--non-installed-overlay").arg(&overlay)
820        .arg(format!("--package-name={}-{}", name, target))
821        .arg("--component-name=rls")
822        .arg("--legacy-manifest-dirs=rustlib,cargo");
823     build.run(&mut cmd);
824 }
825
826 /// Creates a combined installer for the specified target in the provided stage.
827 pub fn extended(build: &Build, stage: u32, target: &str) {
828     println!("Dist extended stage{} ({})", stage, target);
829
830     let dist = distdir(build);
831     let rustc_installer = dist.join(format!("{}-{}.tar.gz",
832                                             pkgname(build, "rustc"),
833                                             target));
834     let cargo_installer = dist.join(format!("{}-{}.tar.gz",
835                                             pkgname(build, "cargo"),
836                                             target));
837     let rls_installer = dist.join(format!("{}-{}.tar.gz",
838                                           pkgname(build, "rls"),
839                                           target));
840     let analysis_installer = dist.join(format!("{}-{}.tar.gz",
841                                                pkgname(build, "rust-analysis"),
842                                                target));
843     let docs_installer = dist.join(format!("{}-{}.tar.gz",
844                                            pkgname(build, "rust-docs"),
845                                            target));
846     let mingw_installer = dist.join(format!("{}-{}.tar.gz",
847                                             pkgname(build, "rust-mingw"),
848                                             target));
849     let std_installer = dist.join(format!("{}-{}.tar.gz",
850                                           pkgname(build, "rust-std"),
851                                           target));
852
853     let tmp = tmpdir(build);
854     let overlay = tmp.join("extended-overlay");
855     let etc = build.src.join("src/etc/installer");
856     let work = tmp.join("work");
857
858     let _ = fs::remove_dir_all(&overlay);
859     install(&build.src.join("COPYRIGHT"), &overlay, 0o644);
860     install(&build.src.join("LICENSE-APACHE"), &overlay, 0o644);
861     install(&build.src.join("LICENSE-MIT"), &overlay, 0o644);
862     let version = build.rust_version();
863     t!(t!(File::create(overlay.join("version"))).write_all(version.as_bytes()));
864     install(&etc.join("README.md"), &overlay, 0o644);
865
866     // When rust-std package split from rustc, we needed to ensure that during
867     // upgrades rustc was upgraded before rust-std. To avoid rustc clobbering
868     // the std files during uninstall. To do this ensure that rustc comes
869     // before rust-std in the list below.
870     let mut tarballs = vec![rustc_installer, cargo_installer, rls_installer,
871                             analysis_installer, docs_installer, std_installer];
872     if target.contains("pc-windows-gnu") {
873         tarballs.push(mingw_installer);
874     }
875     let mut input_tarballs = tarballs[0].as_os_str().to_owned();
876     for tarball in &tarballs[1..] {
877         input_tarballs.push(",");
878         input_tarballs.push(tarball);
879     }
880
881     let mut cmd = rust_installer(build);
882     cmd.arg("combine")
883        .arg("--product-name=Rust")
884        .arg("--rel-manifest-dir=rustlib")
885        .arg("--success-message=Rust-is-ready-to-roll.")
886        .arg("--work-dir").arg(&work)
887        .arg("--output-dir").arg(&distdir(build))
888        .arg(format!("--package-name={}-{}", pkgname(build, "rust"), target))
889        .arg("--legacy-manifest-dirs=rustlib,cargo")
890        .arg("--input-tarballs").arg(input_tarballs)
891        .arg("--non-installed-overlay").arg(&overlay);
892     build.run(&mut cmd);
893
894     let mut license = String::new();
895     t!(t!(File::open(build.src.join("COPYRIGHT"))).read_to_string(&mut license));
896     license.push_str("\n");
897     t!(t!(File::open(build.src.join("LICENSE-APACHE"))).read_to_string(&mut license));
898     license.push_str("\n");
899     t!(t!(File::open(build.src.join("LICENSE-MIT"))).read_to_string(&mut license));
900
901     let rtf = r"{\rtf1\ansi\deff0{\fonttbl{\f0\fnil\fcharset0 Arial;}}\nowwrap\fs18";
902     let mut rtf = rtf.to_string();
903     rtf.push_str("\n");
904     for line in license.lines() {
905         rtf.push_str(line);
906         rtf.push_str("\\line ");
907     }
908     rtf.push_str("}");
909
910     if target.contains("apple-darwin") {
911         let pkg = tmp.join("pkg");
912         let _ = fs::remove_dir_all(&pkg);
913         t!(fs::create_dir_all(pkg.join("rustc")));
914         t!(fs::create_dir_all(pkg.join("cargo")));
915         t!(fs::create_dir_all(pkg.join("rust-docs")));
916         t!(fs::create_dir_all(pkg.join("rust-std")));
917         t!(fs::create_dir_all(pkg.join("rls")));
918         t!(fs::create_dir_all(pkg.join("rust-analysis")));
919
920         cp_r(&work.join(&format!("{}-{}", pkgname(build, "rustc"), target)),
921              &pkg.join("rustc"));
922         cp_r(&work.join(&format!("{}-{}", pkgname(build, "cargo"), target)),
923              &pkg.join("cargo"));
924         cp_r(&work.join(&format!("{}-{}", pkgname(build, "rust-docs"), target)),
925              &pkg.join("rust-docs"));
926         cp_r(&work.join(&format!("{}-{}", pkgname(build, "rust-std"), target)),
927              &pkg.join("rust-std"));
928         cp_r(&work.join(&format!("{}-{}", pkgname(build, "rls"), target)),
929              &pkg.join("rls"));
930         cp_r(&work.join(&format!("{}-{}", pkgname(build, "rust-analysis"), target)),
931              &pkg.join("rust-analysis"));
932
933         install(&etc.join("pkg/postinstall"), &pkg.join("rustc"), 0o755);
934         install(&etc.join("pkg/postinstall"), &pkg.join("cargo"), 0o755);
935         install(&etc.join("pkg/postinstall"), &pkg.join("rust-docs"), 0o755);
936         install(&etc.join("pkg/postinstall"), &pkg.join("rust-std"), 0o755);
937         install(&etc.join("pkg/postinstall"), &pkg.join("rls"), 0o755);
938         install(&etc.join("pkg/postinstall"), &pkg.join("rust-analysis"), 0o755);
939
940         let pkgbuild = |component: &str| {
941             let mut cmd = Command::new("pkgbuild");
942             cmd.arg("--identifier").arg(format!("org.rust-lang.{}", component))
943                .arg("--scripts").arg(pkg.join(component))
944                .arg("--nopayload")
945                .arg(pkg.join(component).with_extension("pkg"));
946             build.run(&mut cmd);
947         };
948         pkgbuild("rustc");
949         pkgbuild("cargo");
950         pkgbuild("rust-docs");
951         pkgbuild("rust-std");
952         pkgbuild("rls");
953         pkgbuild("rust-analysis");
954
955         // create an 'uninstall' package
956         install(&etc.join("pkg/postinstall"), &pkg.join("uninstall"), 0o755);
957         pkgbuild("uninstall");
958
959         t!(fs::create_dir_all(pkg.join("res")));
960         t!(t!(File::create(pkg.join("res/LICENSE.txt"))).write_all(license.as_bytes()));
961         install(&etc.join("gfx/rust-logo.png"), &pkg.join("res"), 0o644);
962         let mut cmd = Command::new("productbuild");
963         cmd.arg("--distribution").arg(etc.join("pkg/Distribution.xml"))
964            .arg("--resources").arg(pkg.join("res"))
965            .arg(distdir(build).join(format!("{}-{}.pkg",
966                                              pkgname(build, "rust"),
967                                              target)))
968            .arg("--package-path").arg(&pkg);
969         build.run(&mut cmd);
970     }
971
972     if target.contains("windows") {
973         let exe = tmp.join("exe");
974         let _ = fs::remove_dir_all(&exe);
975         t!(fs::create_dir_all(exe.join("rustc")));
976         t!(fs::create_dir_all(exe.join("cargo")));
977         t!(fs::create_dir_all(exe.join("rls")));
978         t!(fs::create_dir_all(exe.join("rust-analysis")));
979         t!(fs::create_dir_all(exe.join("rust-docs")));
980         t!(fs::create_dir_all(exe.join("rust-std")));
981         cp_r(&work.join(&format!("{}-{}", pkgname(build, "rustc"), target))
982                   .join("rustc"),
983              &exe.join("rustc"));
984         cp_r(&work.join(&format!("{}-{}", pkgname(build, "cargo"), target))
985                   .join("cargo"),
986              &exe.join("cargo"));
987         cp_r(&work.join(&format!("{}-{}", pkgname(build, "rust-docs"), target))
988                   .join("rust-docs"),
989              &exe.join("rust-docs"));
990         cp_r(&work.join(&format!("{}-{}", pkgname(build, "rust-std"), target))
991                   .join(format!("rust-std-{}", target)),
992              &exe.join("rust-std"));
993         cp_r(&work.join(&format!("{}-{}", pkgname(build, "rls"), target))
994                   .join("rls"),
995              &exe.join("rls"));
996         cp_r(&work.join(&format!("{}-{}", pkgname(build, "rust-analysis"), target))
997                   .join(format!("rust-analysis-{}", target)),
998              &exe.join("rust-analysis"));
999
1000         t!(fs::remove_file(exe.join("rustc/manifest.in")));
1001         t!(fs::remove_file(exe.join("cargo/manifest.in")));
1002         t!(fs::remove_file(exe.join("rust-docs/manifest.in")));
1003         t!(fs::remove_file(exe.join("rust-std/manifest.in")));
1004         t!(fs::remove_file(exe.join("rls/manifest.in")));
1005         t!(fs::remove_file(exe.join("rust-analysis/manifest.in")));
1006
1007         if target.contains("windows-gnu") {
1008             t!(fs::create_dir_all(exe.join("rust-mingw")));
1009             cp_r(&work.join(&format!("{}-{}", pkgname(build, "rust-mingw"), target))
1010                       .join("rust-mingw"),
1011                  &exe.join("rust-mingw"));
1012             t!(fs::remove_file(exe.join("rust-mingw/manifest.in")));
1013         }
1014
1015         install(&etc.join("exe/rust.iss"), &exe, 0o644);
1016         install(&etc.join("exe/modpath.iss"), &exe, 0o644);
1017         install(&etc.join("exe/upgrade.iss"), &exe, 0o644);
1018         install(&etc.join("gfx/rust-logo.ico"), &exe, 0o644);
1019         t!(t!(File::create(exe.join("LICENSE.txt"))).write_all(license.as_bytes()));
1020
1021         // Generate exe installer
1022         let mut cmd = Command::new("iscc");
1023         cmd.arg("rust.iss")
1024            .current_dir(&exe);
1025         if target.contains("windows-gnu") {
1026             cmd.arg("/dMINGW");
1027         }
1028         add_env(build, &mut cmd, target);
1029         build.run(&mut cmd);
1030         install(&exe.join(format!("{}-{}.exe", pkgname(build, "rust"), target)),
1031                 &distdir(build),
1032                 0o755);
1033
1034         // Generate msi installer
1035         let wix = PathBuf::from(env::var_os("WIX").unwrap());
1036         let heat = wix.join("bin/heat.exe");
1037         let candle = wix.join("bin/candle.exe");
1038         let light = wix.join("bin/light.exe");
1039
1040         let heat_flags = ["-nologo", "-gg", "-sfrag", "-srd", "-sreg"];
1041         build.run(Command::new(&heat)
1042                         .current_dir(&exe)
1043                         .arg("dir")
1044                         .arg("rustc")
1045                         .args(&heat_flags)
1046                         .arg("-cg").arg("RustcGroup")
1047                         .arg("-dr").arg("Rustc")
1048                         .arg("-var").arg("var.RustcDir")
1049                         .arg("-out").arg(exe.join("RustcGroup.wxs")));
1050         build.run(Command::new(&heat)
1051                         .current_dir(&exe)
1052                         .arg("dir")
1053                         .arg("rust-docs")
1054                         .args(&heat_flags)
1055                         .arg("-cg").arg("DocsGroup")
1056                         .arg("-dr").arg("Docs")
1057                         .arg("-var").arg("var.DocsDir")
1058                         .arg("-out").arg(exe.join("DocsGroup.wxs"))
1059                         .arg("-t").arg(etc.join("msi/squash-components.xsl")));
1060         build.run(Command::new(&heat)
1061                         .current_dir(&exe)
1062                         .arg("dir")
1063                         .arg("cargo")
1064                         .args(&heat_flags)
1065                         .arg("-cg").arg("CargoGroup")
1066                         .arg("-dr").arg("Cargo")
1067                         .arg("-var").arg("var.CargoDir")
1068                         .arg("-out").arg(exe.join("CargoGroup.wxs"))
1069                         .arg("-t").arg(etc.join("msi/remove-duplicates.xsl")));
1070         build.run(Command::new(&heat)
1071                         .current_dir(&exe)
1072                         .arg("dir")
1073                         .arg("rust-std")
1074                         .args(&heat_flags)
1075                         .arg("-cg").arg("StdGroup")
1076                         .arg("-dr").arg("Std")
1077                         .arg("-var").arg("var.StdDir")
1078                         .arg("-out").arg(exe.join("StdGroup.wxs")));
1079         build.run(Command::new(&heat)
1080                         .current_dir(&exe)
1081                         .arg("dir")
1082                         .arg("rls")
1083                         .args(&heat_flags)
1084                         .arg("-cg").arg("RlsGroup")
1085                         .arg("-dr").arg("Rls")
1086                         .arg("-var").arg("var.RlsDir")
1087                         .arg("-out").arg(exe.join("RlsGroup.wxs"))
1088                         .arg("-t").arg(etc.join("msi/remove-duplicates.xsl")));
1089         build.run(Command::new(&heat)
1090                         .current_dir(&exe)
1091                         .arg("dir")
1092                         .arg("rust-analysis")
1093                         .args(&heat_flags)
1094                         .arg("-cg").arg("AnalysisGroup")
1095                         .arg("-dr").arg("Analysis")
1096                         .arg("-var").arg("var.AnalysisDir")
1097                         .arg("-out").arg(exe.join("AnalysisGroup.wxs"))
1098                         .arg("-t").arg(etc.join("msi/remove-duplicates.xsl")));
1099         if target.contains("windows-gnu") {
1100             build.run(Command::new(&heat)
1101                             .current_dir(&exe)
1102                             .arg("dir")
1103                             .arg("rust-mingw")
1104                             .args(&heat_flags)
1105                             .arg("-cg").arg("GccGroup")
1106                             .arg("-dr").arg("Gcc")
1107                             .arg("-var").arg("var.GccDir")
1108                             .arg("-out").arg(exe.join("GccGroup.wxs")));
1109         }
1110
1111         let candle = |input: &Path| {
1112             let output = exe.join(input.file_stem().unwrap())
1113                             .with_extension("wixobj");
1114             let arch = if target.contains("x86_64") {"x64"} else {"x86"};
1115             let mut cmd = Command::new(&candle);
1116             cmd.current_dir(&exe)
1117                .arg("-nologo")
1118                .arg("-dRustcDir=rustc")
1119                .arg("-dDocsDir=rust-docs")
1120                .arg("-dCargoDir=cargo")
1121                .arg("-dStdDir=rust-std")
1122                .arg("-dRlsDir=rls")
1123                .arg("-dAnalysisDir=rust-analysis")
1124                .arg("-arch").arg(&arch)
1125                .arg("-out").arg(&output)
1126                .arg(&input);
1127             add_env(build, &mut cmd, target);
1128
1129             if target.contains("windows-gnu") {
1130                cmd.arg("-dGccDir=rust-mingw");
1131             }
1132             build.run(&mut cmd);
1133         };
1134         candle(&etc.join("msi/rust.wxs"));
1135         candle(&etc.join("msi/ui.wxs"));
1136         candle(&etc.join("msi/rustwelcomedlg.wxs"));
1137         candle("RustcGroup.wxs".as_ref());
1138         candle("DocsGroup.wxs".as_ref());
1139         candle("CargoGroup.wxs".as_ref());
1140         candle("StdGroup.wxs".as_ref());
1141         candle("RlsGroup.wxs".as_ref());
1142         candle("AnalysisGroup.wxs".as_ref());
1143
1144         if target.contains("windows-gnu") {
1145             candle("GccGroup.wxs".as_ref());
1146         }
1147
1148         t!(t!(File::create(exe.join("LICENSE.rtf"))).write_all(rtf.as_bytes()));
1149         install(&etc.join("gfx/banner.bmp"), &exe, 0o644);
1150         install(&etc.join("gfx/dialogbg.bmp"), &exe, 0o644);
1151
1152         let filename = format!("{}-{}.msi", pkgname(build, "rust"), target);
1153         let mut cmd = Command::new(&light);
1154         cmd.arg("-nologo")
1155            .arg("-ext").arg("WixUIExtension")
1156            .arg("-ext").arg("WixUtilExtension")
1157            .arg("-out").arg(exe.join(&filename))
1158            .arg("rust.wixobj")
1159            .arg("ui.wixobj")
1160            .arg("rustwelcomedlg.wixobj")
1161            .arg("RustcGroup.wixobj")
1162            .arg("DocsGroup.wixobj")
1163            .arg("CargoGroup.wixobj")
1164            .arg("StdGroup.wixobj")
1165            .arg("RlsGroup.wixobj")
1166            .arg("AnalysisGroup.wixobj")
1167            .current_dir(&exe);
1168
1169         if target.contains("windows-gnu") {
1170            cmd.arg("GccGroup.wixobj");
1171         }
1172         // ICE57 wrongly complains about the shortcuts
1173         cmd.arg("-sice:ICE57");
1174
1175         build.run(&mut cmd);
1176
1177         t!(fs::rename(exe.join(&filename), distdir(build).join(&filename)));
1178     }
1179 }
1180
1181 fn add_env(build: &Build, cmd: &mut Command, target: &str) {
1182     let mut parts = channel::CFG_RELEASE_NUM.split('.');
1183     cmd.env("CFG_RELEASE_INFO", build.rust_version())
1184        .env("CFG_RELEASE_NUM", channel::CFG_RELEASE_NUM)
1185        .env("CFG_RELEASE", build.rust_release())
1186        .env("CFG_PRERELEASE_VERSION", channel::CFG_PRERELEASE_VERSION)
1187        .env("CFG_VER_MAJOR", parts.next().unwrap())
1188        .env("CFG_VER_MINOR", parts.next().unwrap())
1189        .env("CFG_VER_PATCH", parts.next().unwrap())
1190        .env("CFG_VER_BUILD", "0") // just needed to build
1191        .env("CFG_PACKAGE_VERS", build.rust_package_vers())
1192        .env("CFG_PACKAGE_NAME", pkgname(build, "rust"))
1193        .env("CFG_BUILD", target)
1194        .env("CFG_CHANNEL", &build.config.channel);
1195
1196     if target.contains("windows-gnu") {
1197        cmd.env("CFG_MINGW", "1")
1198           .env("CFG_ABI", "GNU");
1199     } else {
1200        cmd.env("CFG_MINGW", "0")
1201           .env("CFG_ABI", "MSVC");
1202     }
1203
1204     if target.contains("x86_64") {
1205        cmd.env("CFG_PLATFORM", "x64");
1206     } else {
1207        cmd.env("CFG_PLATFORM", "x86");
1208     }
1209 }
1210
1211 pub fn hash_and_sign(build: &Build) {
1212     let compiler = Compiler::new(0, &build.config.build);
1213     let mut cmd = build.tool_cmd(&compiler, "build-manifest");
1214     let sign = build.config.dist_sign_folder.as_ref().unwrap_or_else(|| {
1215         panic!("\n\nfailed to specify `dist.sign-folder` in `config.toml`\n\n")
1216     });
1217     let addr = build.config.dist_upload_addr.as_ref().unwrap_or_else(|| {
1218         panic!("\n\nfailed to specify `dist.upload-addr` in `config.toml`\n\n")
1219     });
1220     let file = build.config.dist_gpg_password_file.as_ref().unwrap_or_else(|| {
1221         panic!("\n\nfailed to specify `dist.gpg-password-file` in `config.toml`\n\n")
1222     });
1223     let mut pass = String::new();
1224     t!(t!(File::open(&file)).read_to_string(&mut pass));
1225
1226     let today = output(Command::new("date").arg("+%Y-%m-%d"));
1227
1228     cmd.arg(sign);
1229     cmd.arg(distdir(build));
1230     cmd.arg(today.trim());
1231     cmd.arg(build.rust_package_vers());
1232     cmd.arg(build.package_vers(&build.release_num("cargo")));
1233     cmd.arg(build.package_vers(&build.release_num("rls")));
1234     cmd.arg(addr);
1235
1236     t!(fs::create_dir_all(distdir(build)));
1237
1238     let mut child = t!(cmd.stdin(Stdio::piped()).spawn());
1239     t!(child.stdin.take().unwrap().write_all(pass.as_bytes()));
1240     let status = t!(child.wait());
1241     assert!(status.success());
1242 }