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