]> git.lizzy.rs Git - rust.git/blob - src/bootstrap/dist.rs
Rollup merge of #42837 - rthomas:29355-error, r=steveklabnik
[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 mut src = build.sysroot_libdir(compiler, target);
409     src.pop(); // Remove the trailing /lib folder from the sysroot_libdir
410     cp_r(&src, &dst);
411
412     let mut cmd = rust_installer(build);
413     cmd.arg("generate")
414        .arg("--product-name=Rust")
415        .arg("--rel-manifest-dir=rustlib")
416        .arg("--success-message=std-is-standing-at-the-ready.")
417        .arg("--image-dir").arg(&image)
418        .arg("--work-dir").arg(&tmpdir(build))
419        .arg("--output-dir").arg(&distdir(build))
420        .arg(format!("--package-name={}-{}", name, target))
421        .arg(format!("--component-name=rust-std-{}", target))
422        .arg("--legacy-manifest-dirs=rustlib,cargo");
423     build.run(&mut cmd);
424     t!(fs::remove_dir_all(&image));
425 }
426
427 /// The path to the complete rustc-src tarball
428 pub fn rust_src_location(build: &Build) -> PathBuf {
429     let plain_name = format!("rustc-{}-src", build.rust_package_vers());
430     distdir(build).join(&format!("{}.tar.gz", plain_name))
431 }
432
433 /// The path to the rust-src component installer
434 pub fn rust_src_installer(build: &Build) -> PathBuf {
435     let name = pkgname(build, "rust-src");
436     distdir(build).join(&format!("{}.tar.gz", name))
437 }
438
439 /// Creates a tarball of save-analysis metadata, if available.
440 pub fn analysis(build: &Build, compiler: &Compiler, target: &str) {
441     assert!(build.config.extended);
442     println!("Dist analysis");
443
444     if compiler.host != build.build {
445         println!("\tskipping, not a build host");
446         return;
447     }
448
449     // Package save-analysis from stage1 if not doing a full bootstrap, as the
450     // stage2 artifacts is simply copied from stage1 in that case.
451     let compiler = if build.force_use_stage1(compiler, target) {
452         Compiler::new(1, compiler.host)
453     } else {
454         compiler.clone()
455     };
456
457     let name = pkgname(build, "rust-analysis");
458     let image = tmpdir(build).join(format!("{}-{}-image", name, target));
459
460     let src = build.stage_out(&compiler, Mode::Libstd).join(target).join("release").join("deps");
461
462     let image_src = src.join("save-analysis");
463     let dst = image.join("lib/rustlib").join(target).join("analysis");
464     t!(fs::create_dir_all(&dst));
465     println!("image_src: {:?}, dst: {:?}", image_src, dst);
466     cp_r(&image_src, &dst);
467
468     let mut cmd = rust_installer(build);
469     cmd.arg("generate")
470        .arg("--product-name=Rust")
471        .arg("--rel-manifest-dir=rustlib")
472        .arg("--success-message=save-analysis-saved.")
473        .arg("--image-dir").arg(&image)
474        .arg("--work-dir").arg(&tmpdir(build))
475        .arg("--output-dir").arg(&distdir(build))
476        .arg(format!("--package-name={}-{}", name, target))
477        .arg(format!("--component-name=rust-analysis-{}", target))
478        .arg("--legacy-manifest-dirs=rustlib,cargo");
479     build.run(&mut cmd);
480     t!(fs::remove_dir_all(&image));
481 }
482
483 fn copy_src_dirs(build: &Build, src_dirs: &[&str], exclude_dirs: &[&str], dst_dir: &Path) {
484     fn filter_fn(exclude_dirs: &[&str], dir: &str, path: &Path) -> bool {
485         let spath = match path.to_str() {
486             Some(path) => path,
487             None => return false,
488         };
489         if spath.ends_with("~") || spath.ends_with(".pyc") {
490             return false
491         }
492         if (spath.contains("llvm/test") || spath.contains("llvm\\test")) &&
493             (spath.ends_with(".ll") ||
494              spath.ends_with(".td") ||
495              spath.ends_with(".s")) {
496             return false
497         }
498
499         let full_path = Path::new(dir).join(path);
500         if exclude_dirs.iter().any(|excl| full_path == Path::new(excl)) {
501             return false;
502         }
503
504         let excludes = [
505             "CVS", "RCS", "SCCS", ".git", ".gitignore", ".gitmodules",
506             ".gitattributes", ".cvsignore", ".svn", ".arch-ids", "{arch}",
507             "=RELEASE-ID", "=meta-update", "=update", ".bzr", ".bzrignore",
508             ".bzrtags", ".hg", ".hgignore", ".hgrags", "_darcs",
509         ];
510         !path.iter()
511              .map(|s| s.to_str().unwrap())
512              .any(|s| excludes.contains(&s))
513     }
514
515     // Copy the directories using our filter
516     for item in src_dirs {
517         let dst = &dst_dir.join(item);
518         t!(fs::create_dir_all(dst));
519         cp_filtered(&build.src.join(item), dst, &|path| filter_fn(exclude_dirs, item, path));
520     }
521 }
522
523 /// Creates the `rust-src` installer component
524 pub fn rust_src(build: &Build) {
525     println!("Dist src");
526
527     let name = pkgname(build, "rust-src");
528     let image = tmpdir(build).join(format!("{}-image", name));
529     let _ = fs::remove_dir_all(&image);
530
531     let dst = image.join("lib/rustlib/src");
532     let dst_src = dst.join("rust");
533     t!(fs::create_dir_all(&dst_src));
534
535     // This is the reduced set of paths which will become the rust-src component
536     // (essentially libstd and all of its path dependencies)
537     let std_src_dirs = [
538         "src/build_helper",
539         "src/liballoc",
540         "src/liballoc_jemalloc",
541         "src/liballoc_system",
542         "src/libbacktrace",
543         "src/libcollections",
544         "src/libcompiler_builtins",
545         "src/libcore",
546         "src/liblibc",
547         "src/libpanic_abort",
548         "src/libpanic_unwind",
549         "src/librand",
550         "src/librustc_asan",
551         "src/librustc_lsan",
552         "src/librustc_msan",
553         "src/librustc_tsan",
554         "src/libstd",
555         "src/libstd_unicode",
556         "src/libunwind",
557         "src/rustc/compiler_builtins_shim",
558         "src/rustc/libc_shim",
559         "src/libtest",
560         "src/libterm",
561         "src/jemalloc",
562         "src/libprofiler_builtins",
563     ];
564     let std_src_dirs_exclude = [
565         "src/compiler-rt/test",
566         "src/jemalloc/test/unit",
567     ];
568
569     copy_src_dirs(build, &std_src_dirs[..], &std_src_dirs_exclude[..], &dst_src);
570
571     // Create source tarball in rust-installer format
572     let mut cmd = rust_installer(build);
573     cmd.arg("generate")
574        .arg("--product-name=Rust")
575        .arg("--rel-manifest-dir=rustlib")
576        .arg("--success-message=Awesome-Source.")
577        .arg("--image-dir").arg(&image)
578        .arg("--work-dir").arg(&tmpdir(build))
579        .arg("--output-dir").arg(&distdir(build))
580        .arg(format!("--package-name={}", name))
581        .arg("--component-name=rust-src")
582        .arg("--legacy-manifest-dirs=rustlib,cargo");
583     build.run(&mut cmd);
584
585     t!(fs::remove_dir_all(&image));
586 }
587
588 const CARGO_VENDOR_VERSION: &str = "0.1.4";
589
590 /// Creates the plain source tarball
591 pub fn plain_source_tarball(build: &Build) {
592     println!("Create plain source tarball");
593
594     // Make sure that the root folder of tarball has the correct name
595     let plain_name = format!("{}-src", pkgname(build, "rustc"));
596     let plain_dst_src = tmpdir(build).join(&plain_name);
597     let _ = fs::remove_dir_all(&plain_dst_src);
598     t!(fs::create_dir_all(&plain_dst_src));
599
600     // This is the set of root paths which will become part of the source package
601     let src_files = [
602         "COPYRIGHT",
603         "LICENSE-APACHE",
604         "LICENSE-MIT",
605         "CONTRIBUTING.md",
606         "README.md",
607         "RELEASES.md",
608         "configure",
609         "x.py",
610     ];
611     let src_dirs = [
612         "man",
613         "src",
614     ];
615
616     copy_src_dirs(build, &src_dirs[..], &[], &plain_dst_src);
617
618     // Copy the files normally
619     for item in &src_files {
620         copy(&build.src.join(item), &plain_dst_src.join(item));
621     }
622
623     // Create the version file
624     write_file(&plain_dst_src.join("version"), build.rust_version().as_bytes());
625
626     // If we're building from git sources, we need to vendor a complete distribution.
627     if build.rust_info.is_git() {
628         // Get cargo-vendor installed, if it isn't already.
629         let mut has_cargo_vendor = false;
630         let mut cmd = Command::new(&build.initial_cargo);
631         for line in output(cmd.arg("install").arg("--list")).lines() {
632             has_cargo_vendor |= line.starts_with("cargo-vendor ");
633         }
634         if !has_cargo_vendor {
635             let mut cmd = Command::new(&build.initial_cargo);
636             cmd.arg("install")
637                .arg("--force")
638                .arg("--debug")
639                .arg("--vers").arg(CARGO_VENDOR_VERSION)
640                .arg("cargo-vendor")
641                .env("RUSTC", &build.initial_rustc);
642             build.run(&mut cmd);
643         }
644
645         // Vendor all Cargo dependencies
646         let mut cmd = Command::new(&build.initial_cargo);
647         cmd.arg("vendor")
648            .current_dir(&plain_dst_src.join("src"));
649         build.run(&mut cmd);
650     }
651
652     // Create plain source tarball
653     let mut tarball = rust_src_location(build);
654     tarball.set_extension(""); // strip .gz
655     tarball.set_extension(""); // strip .tar
656     if let Some(dir) = tarball.parent() {
657         t!(fs::create_dir_all(dir));
658     }
659     let mut cmd = rust_installer(build);
660     cmd.arg("tarball")
661        .arg("--input").arg(&plain_name)
662        .arg("--output").arg(&tarball)
663        .arg("--work-dir=.")
664        .current_dir(tmpdir(build));
665     build.run(&mut cmd);
666 }
667
668 fn install(src: &Path, dstdir: &Path, perms: u32) {
669     let dst = dstdir.join(src.file_name().unwrap());
670     t!(fs::create_dir_all(dstdir));
671     t!(fs::copy(src, &dst));
672     chmod(&dst, perms);
673 }
674
675 #[cfg(unix)]
676 fn chmod(path: &Path, perms: u32) {
677     use std::os::unix::fs::*;
678     t!(fs::set_permissions(path, fs::Permissions::from_mode(perms)));
679 }
680 #[cfg(windows)]
681 fn chmod(_path: &Path, _perms: u32) {}
682
683 // We have to run a few shell scripts, which choke quite a bit on both `\`
684 // characters and on `C:\` paths, so normalize both of them away.
685 pub fn sanitize_sh(path: &Path) -> String {
686     let path = path.to_str().unwrap().replace("\\", "/");
687     return change_drive(&path).unwrap_or(path);
688
689     fn change_drive(s: &str) -> Option<String> {
690         let mut ch = s.chars();
691         let drive = ch.next().unwrap_or('C');
692         if ch.next() != Some(':') {
693             return None
694         }
695         if ch.next() != Some('/') {
696             return None
697         }
698         Some(format!("/{}/{}", drive, &s[drive.len_utf8() + 2..]))
699     }
700 }
701
702 fn write_file(path: &Path, data: &[u8]) {
703     let mut vf = t!(fs::File::create(path));
704     t!(vf.write_all(data));
705 }
706
707 pub fn cargo(build: &Build, stage: u32, target: &str) {
708     println!("Dist cargo stage{} ({})", stage, target);
709     let compiler = Compiler::new(stage, &build.build);
710
711     let src = build.src.join("src/tools/cargo");
712     let etc = src.join("src/etc");
713     let release_num = build.release_num("cargo");
714     let name = pkgname(build, "cargo");
715     let version = build.cargo_info.version(build, &release_num);
716
717     let tmp = tmpdir(build);
718     let image = tmp.join("cargo-image");
719     drop(fs::remove_dir_all(&image));
720     t!(fs::create_dir_all(&image));
721
722     // Prepare the image directory
723     t!(fs::create_dir_all(image.join("share/zsh/site-functions")));
724     t!(fs::create_dir_all(image.join("etc/bash_completion.d")));
725     let cargo = build.cargo_out(&compiler, Mode::Tool, target)
726                      .join(exe("cargo", target));
727     install(&cargo, &image.join("bin"), 0o755);
728     for man in t!(etc.join("man").read_dir()) {
729         let man = t!(man);
730         install(&man.path(), &image.join("share/man/man1"), 0o644);
731     }
732     install(&etc.join("_cargo"), &image.join("share/zsh/site-functions"), 0o644);
733     copy(&etc.join("cargo.bashcomp.sh"),
734          &image.join("etc/bash_completion.d/cargo"));
735     let doc = image.join("share/doc/cargo");
736     install(&src.join("README.md"), &doc, 0o644);
737     install(&src.join("LICENSE-MIT"), &doc, 0o644);
738     install(&src.join("LICENSE-APACHE"), &doc, 0o644);
739     install(&src.join("LICENSE-THIRD-PARTY"), &doc, 0o644);
740
741     // Prepare the overlay
742     let overlay = tmp.join("cargo-overlay");
743     drop(fs::remove_dir_all(&overlay));
744     t!(fs::create_dir_all(&overlay));
745     install(&src.join("README.md"), &overlay, 0o644);
746     install(&src.join("LICENSE-MIT"), &overlay, 0o644);
747     install(&src.join("LICENSE-APACHE"), &overlay, 0o644);
748     install(&src.join("LICENSE-THIRD-PARTY"), &overlay, 0o644);
749     t!(t!(File::create(overlay.join("version"))).write_all(version.as_bytes()));
750
751     // Generate the installer tarball
752     let mut cmd = rust_installer(build);
753     cmd.arg("generate")
754        .arg("--product-name=Rust")
755        .arg("--rel-manifest-dir=rustlib")
756        .arg("--success-message=Rust-is-ready-to-roll.")
757        .arg("--image-dir").arg(&image)
758        .arg("--work-dir").arg(&tmpdir(build))
759        .arg("--output-dir").arg(&distdir(build))
760        .arg("--non-installed-overlay").arg(&overlay)
761        .arg(format!("--package-name={}-{}", name, target))
762        .arg("--component-name=cargo")
763        .arg("--legacy-manifest-dirs=rustlib,cargo");
764     build.run(&mut cmd);
765 }
766
767 pub fn rls(build: &Build, stage: u32, target: &str) {
768     assert!(build.config.extended);
769     println!("Dist RLS stage{} ({})", stage, target);
770     let compiler = Compiler::new(stage, &build.build);
771
772     let src = build.src.join("src/tools/rls");
773     let release_num = build.release_num("rls");
774     let name = pkgname(build, "rls");
775     let version = build.rls_info.version(build, &release_num);
776
777     let tmp = tmpdir(build);
778     let image = tmp.join("rls-image");
779     drop(fs::remove_dir_all(&image));
780     t!(fs::create_dir_all(&image));
781
782     // Prepare the image directory
783     let rls = build.cargo_out(&compiler, Mode::Tool, target)
784                      .join(exe("rls", target));
785     install(&rls, &image.join("bin"), 0o755);
786     let doc = image.join("share/doc/rls");
787     install(&src.join("README.md"), &doc, 0o644);
788     install(&src.join("LICENSE-MIT"), &doc, 0o644);
789     install(&src.join("LICENSE-APACHE"), &doc, 0o644);
790
791     // Prepare the overlay
792     let overlay = tmp.join("rls-overlay");
793     drop(fs::remove_dir_all(&overlay));
794     t!(fs::create_dir_all(&overlay));
795     install(&src.join("README.md"), &overlay, 0o644);
796     install(&src.join("LICENSE-MIT"), &overlay, 0o644);
797     install(&src.join("LICENSE-APACHE"), &overlay, 0o644);
798     t!(t!(File::create(overlay.join("version"))).write_all(version.as_bytes()));
799
800     // Generate the installer tarball
801     let mut cmd = rust_installer(build);
802     cmd.arg("generate")
803        .arg("--product-name=Rust")
804        .arg("--rel-manifest-dir=rustlib")
805        .arg("--success-message=RLS-ready-to-serve.")
806        .arg("--image-dir").arg(&image)
807        .arg("--work-dir").arg(&tmpdir(build))
808        .arg("--output-dir").arg(&distdir(build))
809        .arg("--non-installed-overlay").arg(&overlay)
810        .arg(format!("--package-name={}-{}", name, target))
811        .arg("--component-name=rls")
812        .arg("--legacy-manifest-dirs=rustlib,cargo");
813     build.run(&mut cmd);
814 }
815
816 /// Creates a combined installer for the specified target in the provided stage.
817 pub fn extended(build: &Build, stage: u32, target: &str) {
818     println!("Dist extended stage{} ({})", stage, target);
819
820     let dist = distdir(build);
821     let rustc_installer = dist.join(format!("{}-{}.tar.gz",
822                                             pkgname(build, "rustc"),
823                                             target));
824     let cargo_installer = dist.join(format!("{}-{}.tar.gz",
825                                             pkgname(build, "cargo"),
826                                             target));
827     let rls_installer = dist.join(format!("{}-{}.tar.gz",
828                                           pkgname(build, "rls"),
829                                           target));
830     let analysis_installer = dist.join(format!("{}-{}.tar.gz",
831                                                pkgname(build, "rust-analysis"),
832                                                target));
833     let docs_installer = dist.join(format!("{}-{}.tar.gz",
834                                            pkgname(build, "rust-docs"),
835                                            target));
836     let mingw_installer = dist.join(format!("{}-{}.tar.gz",
837                                             pkgname(build, "rust-mingw"),
838                                             target));
839     let std_installer = dist.join(format!("{}-{}.tar.gz",
840                                           pkgname(build, "rust-std"),
841                                           target));
842
843     let tmp = tmpdir(build);
844     let overlay = tmp.join("extended-overlay");
845     let etc = build.src.join("src/etc/installer");
846     let work = tmp.join("work");
847
848     let _ = fs::remove_dir_all(&overlay);
849     install(&build.src.join("COPYRIGHT"), &overlay, 0o644);
850     install(&build.src.join("LICENSE-APACHE"), &overlay, 0o644);
851     install(&build.src.join("LICENSE-MIT"), &overlay, 0o644);
852     let version = build.rust_version();
853     t!(t!(File::create(overlay.join("version"))).write_all(version.as_bytes()));
854     install(&etc.join("README.md"), &overlay, 0o644);
855
856     // When rust-std package split from rustc, we needed to ensure that during
857     // upgrades rustc was upgraded before rust-std. To avoid rustc clobbering
858     // the std files during uninstall. To do this ensure that rustc comes
859     // before rust-std in the list below.
860     let mut tarballs = vec![rustc_installer, cargo_installer, rls_installer,
861                             analysis_installer, docs_installer, std_installer];
862     if target.contains("pc-windows-gnu") {
863         tarballs.push(mingw_installer);
864     }
865     let mut input_tarballs = tarballs[0].as_os_str().to_owned();
866     for tarball in &tarballs[1..] {
867         input_tarballs.push(",");
868         input_tarballs.push(tarball);
869     }
870
871     let mut cmd = rust_installer(build);
872     cmd.arg("combine")
873        .arg("--product-name=Rust")
874        .arg("--rel-manifest-dir=rustlib")
875        .arg("--success-message=Rust-is-ready-to-roll.")
876        .arg("--work-dir").arg(&work)
877        .arg("--output-dir").arg(&distdir(build))
878        .arg(format!("--package-name={}-{}", pkgname(build, "rust"), target))
879        .arg("--legacy-manifest-dirs=rustlib,cargo")
880        .arg("--input-tarballs").arg(input_tarballs)
881        .arg("--non-installed-overlay").arg(&overlay);
882     build.run(&mut cmd);
883
884     let mut license = String::new();
885     t!(t!(File::open(build.src.join("COPYRIGHT"))).read_to_string(&mut license));
886     license.push_str("\n");
887     t!(t!(File::open(build.src.join("LICENSE-APACHE"))).read_to_string(&mut license));
888     license.push_str("\n");
889     t!(t!(File::open(build.src.join("LICENSE-MIT"))).read_to_string(&mut license));
890
891     let rtf = r"{\rtf1\ansi\deff0{\fonttbl{\f0\fnil\fcharset0 Arial;}}\nowwrap\fs18";
892     let mut rtf = rtf.to_string();
893     rtf.push_str("\n");
894     for line in license.lines() {
895         rtf.push_str(line);
896         rtf.push_str("\\line ");
897     }
898     rtf.push_str("}");
899
900     if target.contains("apple-darwin") {
901         let pkg = tmp.join("pkg");
902         let _ = fs::remove_dir_all(&pkg);
903         t!(fs::create_dir_all(pkg.join("rustc")));
904         t!(fs::create_dir_all(pkg.join("cargo")));
905         t!(fs::create_dir_all(pkg.join("rust-docs")));
906         t!(fs::create_dir_all(pkg.join("rust-std")));
907         t!(fs::create_dir_all(pkg.join("rls")));
908         t!(fs::create_dir_all(pkg.join("rust-analysis")));
909
910         cp_r(&work.join(&format!("{}-{}", pkgname(build, "rustc"), target)),
911              &pkg.join("rustc"));
912         cp_r(&work.join(&format!("{}-{}", pkgname(build, "cargo"), target)),
913              &pkg.join("cargo"));
914         cp_r(&work.join(&format!("{}-{}", pkgname(build, "rust-docs"), target)),
915              &pkg.join("rust-docs"));
916         cp_r(&work.join(&format!("{}-{}", pkgname(build, "rust-std"), target)),
917              &pkg.join("rust-std"));
918         cp_r(&work.join(&format!("{}-{}", pkgname(build, "rls"), target)),
919              &pkg.join("rls"));
920         cp_r(&work.join(&format!("{}-{}", pkgname(build, "rust-analysis"), target)),
921              &pkg.join("rust-analysis"));
922
923         install(&etc.join("pkg/postinstall"), &pkg.join("rustc"), 0o755);
924         install(&etc.join("pkg/postinstall"), &pkg.join("cargo"), 0o755);
925         install(&etc.join("pkg/postinstall"), &pkg.join("rust-docs"), 0o755);
926         install(&etc.join("pkg/postinstall"), &pkg.join("rust-std"), 0o755);
927         install(&etc.join("pkg/postinstall"), &pkg.join("rls"), 0o755);
928         install(&etc.join("pkg/postinstall"), &pkg.join("rust-analysis"), 0o755);
929
930         let pkgbuild = |component: &str| {
931             let mut cmd = Command::new("pkgbuild");
932             cmd.arg("--identifier").arg(format!("org.rust-lang.{}", component))
933                .arg("--scripts").arg(pkg.join(component))
934                .arg("--nopayload")
935                .arg(pkg.join(component).with_extension("pkg"));
936             build.run(&mut cmd);
937         };
938         pkgbuild("rustc");
939         pkgbuild("cargo");
940         pkgbuild("rust-docs");
941         pkgbuild("rust-std");
942         pkgbuild("rls");
943         pkgbuild("rust-analysis");
944
945         // create an 'uninstall' package
946         install(&etc.join("pkg/postinstall"), &pkg.join("uninstall"), 0o755);
947         pkgbuild("uninstall");
948
949         t!(fs::create_dir_all(pkg.join("res")));
950         t!(t!(File::create(pkg.join("res/LICENSE.txt"))).write_all(license.as_bytes()));
951         install(&etc.join("gfx/rust-logo.png"), &pkg.join("res"), 0o644);
952         let mut cmd = Command::new("productbuild");
953         cmd.arg("--distribution").arg(etc.join("pkg/Distribution.xml"))
954            .arg("--resources").arg(pkg.join("res"))
955            .arg(distdir(build).join(format!("{}-{}.pkg",
956                                              pkgname(build, "rust"),
957                                              target)))
958            .arg("--package-path").arg(&pkg);
959         build.run(&mut cmd);
960     }
961
962     if target.contains("windows") {
963         let exe = tmp.join("exe");
964         let _ = fs::remove_dir_all(&exe);
965         t!(fs::create_dir_all(exe.join("rustc")));
966         t!(fs::create_dir_all(exe.join("cargo")));
967         t!(fs::create_dir_all(exe.join("rls")));
968         t!(fs::create_dir_all(exe.join("rust-analysis")));
969         t!(fs::create_dir_all(exe.join("rust-docs")));
970         t!(fs::create_dir_all(exe.join("rust-std")));
971         cp_r(&work.join(&format!("{}-{}", pkgname(build, "rustc"), target))
972                   .join("rustc"),
973              &exe.join("rustc"));
974         cp_r(&work.join(&format!("{}-{}", pkgname(build, "cargo"), target))
975                   .join("cargo"),
976              &exe.join("cargo"));
977         cp_r(&work.join(&format!("{}-{}", pkgname(build, "rust-docs"), target))
978                   .join("rust-docs"),
979              &exe.join("rust-docs"));
980         cp_r(&work.join(&format!("{}-{}", pkgname(build, "rust-std"), target))
981                   .join(format!("rust-std-{}", target)),
982              &exe.join("rust-std"));
983         cp_r(&work.join(&format!("{}-{}", pkgname(build, "rls"), target))
984                   .join("rls"),
985              &exe.join("rls"));
986         cp_r(&work.join(&format!("{}-{}", pkgname(build, "rust-analysis"), target))
987                   .join(format!("rust-analysis-{}", target)),
988              &exe.join("rust-analysis"));
989
990         t!(fs::remove_file(exe.join("rustc/manifest.in")));
991         t!(fs::remove_file(exe.join("cargo/manifest.in")));
992         t!(fs::remove_file(exe.join("rust-docs/manifest.in")));
993         t!(fs::remove_file(exe.join("rust-std/manifest.in")));
994         t!(fs::remove_file(exe.join("rls/manifest.in")));
995         t!(fs::remove_file(exe.join("rust-analysis/manifest.in")));
996
997         if target.contains("windows-gnu") {
998             t!(fs::create_dir_all(exe.join("rust-mingw")));
999             cp_r(&work.join(&format!("{}-{}", pkgname(build, "rust-mingw"), target))
1000                       .join("rust-mingw"),
1001                  &exe.join("rust-mingw"));
1002             t!(fs::remove_file(exe.join("rust-mingw/manifest.in")));
1003         }
1004
1005         install(&etc.join("exe/rust.iss"), &exe, 0o644);
1006         install(&etc.join("exe/modpath.iss"), &exe, 0o644);
1007         install(&etc.join("exe/upgrade.iss"), &exe, 0o644);
1008         install(&etc.join("gfx/rust-logo.ico"), &exe, 0o644);
1009         t!(t!(File::create(exe.join("LICENSE.txt"))).write_all(license.as_bytes()));
1010
1011         // Generate exe installer
1012         let mut cmd = Command::new("iscc");
1013         cmd.arg("rust.iss")
1014            .current_dir(&exe);
1015         if target.contains("windows-gnu") {
1016             cmd.arg("/dMINGW");
1017         }
1018         add_env(build, &mut cmd, target);
1019         build.run(&mut cmd);
1020         install(&exe.join(format!("{}-{}.exe", pkgname(build, "rust"), target)),
1021                 &distdir(build),
1022                 0o755);
1023
1024         // Generate msi installer
1025         let wix = PathBuf::from(env::var_os("WIX").unwrap());
1026         let heat = wix.join("bin/heat.exe");
1027         let candle = wix.join("bin/candle.exe");
1028         let light = wix.join("bin/light.exe");
1029
1030         let heat_flags = ["-nologo", "-gg", "-sfrag", "-srd", "-sreg"];
1031         build.run(Command::new(&heat)
1032                         .current_dir(&exe)
1033                         .arg("dir")
1034                         .arg("rustc")
1035                         .args(&heat_flags)
1036                         .arg("-cg").arg("RustcGroup")
1037                         .arg("-dr").arg("Rustc")
1038                         .arg("-var").arg("var.RustcDir")
1039                         .arg("-out").arg(exe.join("RustcGroup.wxs")));
1040         build.run(Command::new(&heat)
1041                         .current_dir(&exe)
1042                         .arg("dir")
1043                         .arg("rust-docs")
1044                         .args(&heat_flags)
1045                         .arg("-cg").arg("DocsGroup")
1046                         .arg("-dr").arg("Docs")
1047                         .arg("-var").arg("var.DocsDir")
1048                         .arg("-out").arg(exe.join("DocsGroup.wxs"))
1049                         .arg("-t").arg(etc.join("msi/squash-components.xsl")));
1050         build.run(Command::new(&heat)
1051                         .current_dir(&exe)
1052                         .arg("dir")
1053                         .arg("cargo")
1054                         .args(&heat_flags)
1055                         .arg("-cg").arg("CargoGroup")
1056                         .arg("-dr").arg("Cargo")
1057                         .arg("-var").arg("var.CargoDir")
1058                         .arg("-out").arg(exe.join("CargoGroup.wxs"))
1059                         .arg("-t").arg(etc.join("msi/remove-duplicates.xsl")));
1060         build.run(Command::new(&heat)
1061                         .current_dir(&exe)
1062                         .arg("dir")
1063                         .arg("rust-std")
1064                         .args(&heat_flags)
1065                         .arg("-cg").arg("StdGroup")
1066                         .arg("-dr").arg("Std")
1067                         .arg("-var").arg("var.StdDir")
1068                         .arg("-out").arg(exe.join("StdGroup.wxs")));
1069         build.run(Command::new(&heat)
1070                         .current_dir(&exe)
1071                         .arg("dir")
1072                         .arg("rls")
1073                         .args(&heat_flags)
1074                         .arg("-cg").arg("RlsGroup")
1075                         .arg("-dr").arg("Rls")
1076                         .arg("-var").arg("var.RlsDir")
1077                         .arg("-out").arg(exe.join("RlsGroup.wxs"))
1078                         .arg("-t").arg(etc.join("msi/remove-duplicates.xsl")));
1079         build.run(Command::new(&heat)
1080                         .current_dir(&exe)
1081                         .arg("dir")
1082                         .arg("rust-analysis")
1083                         .args(&heat_flags)
1084                         .arg("-cg").arg("AnalysisGroup")
1085                         .arg("-dr").arg("Analysis")
1086                         .arg("-var").arg("var.AnalysisDir")
1087                         .arg("-out").arg(exe.join("AnalysisGroup.wxs"))
1088                         .arg("-t").arg(etc.join("msi/remove-duplicates.xsl")));
1089         if target.contains("windows-gnu") {
1090             build.run(Command::new(&heat)
1091                             .current_dir(&exe)
1092                             .arg("dir")
1093                             .arg("rust-mingw")
1094                             .args(&heat_flags)
1095                             .arg("-cg").arg("GccGroup")
1096                             .arg("-dr").arg("Gcc")
1097                             .arg("-var").arg("var.GccDir")
1098                             .arg("-out").arg(exe.join("GccGroup.wxs")));
1099         }
1100
1101         let candle = |input: &Path| {
1102             let output = exe.join(input.file_stem().unwrap())
1103                             .with_extension("wixobj");
1104             let arch = if target.contains("x86_64") {"x64"} else {"x86"};
1105             let mut cmd = Command::new(&candle);
1106             cmd.current_dir(&exe)
1107                .arg("-nologo")
1108                .arg("-dRustcDir=rustc")
1109                .arg("-dDocsDir=rust-docs")
1110                .arg("-dCargoDir=cargo")
1111                .arg("-dStdDir=rust-std")
1112                .arg("-dRlsDir=rls")
1113                .arg("-dAnalysisDir=rust-analysis")
1114                .arg("-arch").arg(&arch)
1115                .arg("-out").arg(&output)
1116                .arg(&input);
1117             add_env(build, &mut cmd, target);
1118
1119             if target.contains("windows-gnu") {
1120                cmd.arg("-dGccDir=rust-mingw");
1121             }
1122             build.run(&mut cmd);
1123         };
1124         candle(&etc.join("msi/rust.wxs"));
1125         candle(&etc.join("msi/ui.wxs"));
1126         candle(&etc.join("msi/rustwelcomedlg.wxs"));
1127         candle("RustcGroup.wxs".as_ref());
1128         candle("DocsGroup.wxs".as_ref());
1129         candle("CargoGroup.wxs".as_ref());
1130         candle("StdGroup.wxs".as_ref());
1131         candle("RlsGroup.wxs".as_ref());
1132         candle("AnalysisGroup.wxs".as_ref());
1133
1134         if target.contains("windows-gnu") {
1135             candle("GccGroup.wxs".as_ref());
1136         }
1137
1138         t!(t!(File::create(exe.join("LICENSE.rtf"))).write_all(rtf.as_bytes()));
1139         install(&etc.join("gfx/banner.bmp"), &exe, 0o644);
1140         install(&etc.join("gfx/dialogbg.bmp"), &exe, 0o644);
1141
1142         let filename = format!("{}-{}.msi", pkgname(build, "rust"), target);
1143         let mut cmd = Command::new(&light);
1144         cmd.arg("-nologo")
1145            .arg("-ext").arg("WixUIExtension")
1146            .arg("-ext").arg("WixUtilExtension")
1147            .arg("-out").arg(exe.join(&filename))
1148            .arg("rust.wixobj")
1149            .arg("ui.wixobj")
1150            .arg("rustwelcomedlg.wixobj")
1151            .arg("RustcGroup.wixobj")
1152            .arg("DocsGroup.wixobj")
1153            .arg("CargoGroup.wixobj")
1154            .arg("StdGroup.wixobj")
1155            .arg("RlsGroup.wixobj")
1156            .arg("AnalysisGroup.wixobj")
1157            .current_dir(&exe);
1158
1159         if target.contains("windows-gnu") {
1160            cmd.arg("GccGroup.wixobj");
1161         }
1162         // ICE57 wrongly complains about the shortcuts
1163         cmd.arg("-sice:ICE57");
1164
1165         build.run(&mut cmd);
1166
1167         t!(fs::rename(exe.join(&filename), distdir(build).join(&filename)));
1168     }
1169 }
1170
1171 fn add_env(build: &Build, cmd: &mut Command, target: &str) {
1172     let mut parts = channel::CFG_RELEASE_NUM.split('.');
1173     cmd.env("CFG_RELEASE_INFO", build.rust_version())
1174        .env("CFG_RELEASE_NUM", channel::CFG_RELEASE_NUM)
1175        .env("CFG_RELEASE", build.rust_release())
1176        .env("CFG_PRERELEASE_VERSION", channel::CFG_PRERELEASE_VERSION)
1177        .env("CFG_VER_MAJOR", parts.next().unwrap())
1178        .env("CFG_VER_MINOR", parts.next().unwrap())
1179        .env("CFG_VER_PATCH", parts.next().unwrap())
1180        .env("CFG_VER_BUILD", "0") // just needed to build
1181        .env("CFG_PACKAGE_VERS", build.rust_package_vers())
1182        .env("CFG_PACKAGE_NAME", pkgname(build, "rust"))
1183        .env("CFG_BUILD", target)
1184        .env("CFG_CHANNEL", &build.config.channel);
1185
1186     if target.contains("windows-gnu") {
1187        cmd.env("CFG_MINGW", "1")
1188           .env("CFG_ABI", "GNU");
1189     } else {
1190        cmd.env("CFG_MINGW", "0")
1191           .env("CFG_ABI", "MSVC");
1192     }
1193
1194     if target.contains("x86_64") {
1195        cmd.env("CFG_PLATFORM", "x64");
1196     } else {
1197        cmd.env("CFG_PLATFORM", "x86");
1198     }
1199 }
1200
1201 pub fn hash_and_sign(build: &Build) {
1202     let compiler = Compiler::new(0, &build.build);
1203     let mut cmd = build.tool_cmd(&compiler, "build-manifest");
1204     let sign = build.config.dist_sign_folder.as_ref().unwrap_or_else(|| {
1205         panic!("\n\nfailed to specify `dist.sign-folder` in `config.toml`\n\n")
1206     });
1207     let addr = build.config.dist_upload_addr.as_ref().unwrap_or_else(|| {
1208         panic!("\n\nfailed to specify `dist.upload-addr` in `config.toml`\n\n")
1209     });
1210     let file = build.config.dist_gpg_password_file.as_ref().unwrap_or_else(|| {
1211         panic!("\n\nfailed to specify `dist.gpg-password-file` in `config.toml`\n\n")
1212     });
1213     let mut pass = String::new();
1214     t!(t!(File::open(&file)).read_to_string(&mut pass));
1215
1216     let today = output(Command::new("date").arg("+%Y-%m-%d"));
1217
1218     cmd.arg(sign);
1219     cmd.arg(distdir(build));
1220     cmd.arg(today.trim());
1221     cmd.arg(build.rust_package_vers());
1222     cmd.arg(build.package_vers(&build.release_num("cargo")));
1223     cmd.arg(build.package_vers(&build.release_num("rls")));
1224     cmd.arg(addr);
1225
1226     t!(fs::create_dir_all(distdir(build)));
1227
1228     let mut child = t!(cmd.stdin(Stdio::piped()).spawn());
1229     t!(child.stdin.take().unwrap().write_all(pass.as_bytes()));
1230     let status = t!(child.wait());
1231     assert!(status.success());
1232 }