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