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