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