builder
}
- pub fn execute_cli(&self) {
+ pub fn execute_cli(&self) -> Graph<String, bool> {
self.run_step_descriptions(&Builder::get_step_descriptions(self.kind), &self.paths);
+ self.graph.borrow().clone()
}
pub fn default_doc(&self, paths: Option<&[PathBuf]>) {
#[cfg(test)]
mod __test {
use config::Config;
+ use std::thread;
use super::*;
fn configure(host: &[&str], target: &[&str]) -> Config {
// don't save toolstates
config.save_toolstates = None;
config.run_host_only = true;
+ config.dry_run = true;
+ // try to avoid spurious failures in dist where we create/delete each others file
+ let dir = config.out.join("tmp-rustbuild-tests")
+ .join(&thread::current().name().unwrap_or("unknown").replace(":", "-"));
+ t!(fs::create_dir_all(&dir));
+ config.out = dir;
config.build = INTERNER.intern_str("A");
config.hosts = vec![config.build].clone().into_iter()
.chain(host.iter().map(|s| INTERNER.intern_str(s))).collect::<Vec<_>>();
true);
let libdir = builder.sysroot_libdir(compiler, target);
- add_to_sysroot(&libdir, &libstd_stamp(build, compiler, target));
+ add_to_sysroot(&build, &libdir, &libstd_stamp(build, compiler, target));
}
}
true);
let libdir = builder.sysroot_libdir(compiler, target);
- add_to_sysroot(&libdir, &librustc_stamp(build, compiler, target));
+ add_to_sysroot(&build, &libdir, &librustc_stamp(build, compiler, target));
}
}
true);
let libdir = builder.sysroot_libdir(compiler, target);
- add_to_sysroot(&libdir, &libtest_stamp(build, compiler, target));
+ add_to_sysroot(&build, &libdir, &libtest_stamp(build, compiler, target));
}
}
use filetime::FileTime;
use serde_json;
-use util::{exe, libdir, is_dylib, copy, read_stamp_file, CiEnv};
+use util::{exe, libdir, is_dylib, CiEnv};
use {Build, Compiler, Mode};
use native;
use tool;
target: Interned<String>,
into: &Path) {
for &obj in &["crt1.o", "crti.o", "crtn.o"] {
- copy(&build.musl_root(target).unwrap().join("lib").join(obj), &into.join(obj));
+ build.copy(&build.musl_root(target).unwrap().join("lib").join(obj), &into.join(obj));
}
}
target_compiler.host,
target);
let libdir = builder.sysroot_libdir(target_compiler, target);
- add_to_sysroot(&libdir, &libstd_stamp(build, compiler, target));
+ add_to_sysroot(&build, &libdir, &libstd_stamp(build, compiler, target));
if build.config.sanitizers && compiler.stage != 0 && target == "x86_64-apple-darwin" {
// The sanitizers are only built in stage1 or above, so the dylibs will
// be missing in stage0 and causes panic. See the `std()` function above
// for reason why the sanitizers are not built in stage0.
- copy_apple_sanitizer_dylibs(&build.native_dir(target), "osx", &libdir);
+ copy_apple_sanitizer_dylibs(&build, &build.native_dir(target), "osx", &libdir);
}
builder.ensure(tool::CleanTools {
}
}
-fn copy_apple_sanitizer_dylibs(native_dir: &Path, platform: &str, into: &Path) {
+fn copy_apple_sanitizer_dylibs(build: &Build, native_dir: &Path, platform: &str, into: &Path) {
for &sanitizer in &["asan", "tsan"] {
let filename = format!("libclang_rt.{}_{}_dynamic.dylib", sanitizer, platform);
let mut src_path = native_dir.join(sanitizer);
src_path.push("lib");
src_path.push("darwin");
src_path.push(&filename);
- copy(&src_path, &into.join(filename));
+ build.copy(&src_path, &into.join(filename));
}
}
.arg(src_file));
}
- copy(dst_file, &sysroot_dir.join(file.to_string() + ".o"));
+ build.copy(dst_file, &sysroot_dir.join(file.to_string() + ".o"));
}
for obj in ["crt2.o", "dllcrt2.o"].iter() {
build.cc(target),
target,
obj);
- copy(&src, &sysroot_dir.join(obj));
+ build.copy(&src, &sysroot_dir.join(obj));
}
}
}
&compiler.host,
target_compiler.host,
target);
- add_to_sysroot(&builder.sysroot_libdir(target_compiler, target),
+ add_to_sysroot(&build, &builder.sysroot_libdir(target_compiler, target),
&libtest_stamp(build, compiler, target));
builder.ensure(tool::CleanTools {
compiler: target_compiler,
&compiler.host,
target_compiler.host,
target);
- add_to_sysroot(&builder.sysroot_libdir(target_compiler, target),
+ add_to_sysroot(&build, &builder.sysroot_libdir(target_compiler, target),
&librustc_stamp(build, compiler, target));
builder.ensure(tool::CleanTools {
compiler: target_compiler,
cargo.arg("--features").arg(features),
&tmp_stamp,
false);
- if cfg!(test) {
+ if builder.config.dry_run {
return;
}
let mut files = files.into_iter()
let dst = builder.sysroot_codegen_backends(target_compiler);
t!(fs::create_dir_all(&dst));
+ if builder.config.dry_run {
+ return;
+ }
+
for backend in builder.config.rust_codegen_backends.iter() {
let stamp = codegen_backend_stamp(build, compiler, target, *backend);
let mut dylib = String::new();
backend,
&filename[dot..])
};
- copy(&file, &dst.join(target_filename));
+ build.copy(&file, &dst.join(target_filename));
}
}
t!(fs::create_dir_all(&dst));
let exe = exe("lld", &target);
- copy(&lld_install_root.join("bin").join(&exe), &dst.join(&exe));
+ builder.copy(&lld_install_root.join("bin").join(&exe), &dst.join(&exe));
}
/// Cargo's output path for the standard library in a given stage, compiled
let sysroot_libdir = sysroot.join(libdir(&*host));
t!(fs::create_dir_all(&sysroot_libdir));
let src_libdir = builder.sysroot_libdir(build_compiler, host);
- for f in t!(fs::read_dir(&src_libdir)).map(|f| t!(f)) {
+ for f in builder.read_dir(&src_libdir) {
let filename = f.file_name().into_string().unwrap();
if is_dylib(&filename) {
- copy(&f.path(), &sysroot_libdir.join(&filename));
+ builder.copy(&f.path(), &sysroot_libdir.join(&filename));
}
}
t!(fs::create_dir_all(&bindir));
let compiler = builder.rustc(target_compiler);
let _ = fs::remove_file(&compiler);
- copy(&rustc, &compiler);
+ builder.copy(&rustc, &compiler);
target_compiler
}
///
/// For a particular stage this will link the file listed in `stamp` into the
/// `sysroot_dst` provided.
-pub fn add_to_sysroot(sysroot_dst: &Path, stamp: &Path) {
+pub fn add_to_sysroot(build: &Build, sysroot_dst: &Path, stamp: &Path) {
t!(fs::create_dir_all(&sysroot_dst));
- for path in read_stamp_file(stamp) {
- copy(&path, &sysroot_dst.join(path.file_name().unwrap()));
+ for path in build.read_stamp_file(stamp) {
+ build.copy(&path, &sysroot_dst.join(path.file_name().unwrap()));
}
}
pub fn run_cargo(build: &Build, cargo: &mut Command, stamp: &Path, is_check: bool)
-> Vec<PathBuf>
{
+ if build.config.dry_run {
+ return Vec::new();
+ }
+
// `target_root_dir` looks like $dir/$target/release
let target_root_dir = stamp.parent().unwrap();
// `target_deps_dir` looks like $dir/$target/release/deps
cargo: &mut Command,
cb: &mut FnMut(CargoMessage),
) -> bool {
+ if build.config.dry_run {
+ return true;
+ }
// Instruct Cargo to give us json messages on stdout, critically leaving
// stderr as piped so we can get those pretty colors.
cargo.arg("--message-format").arg("json")
use std::collections::{HashMap, HashSet};
use std::env;
-use std::fs::File;
+use std::fs::{self, File};
use std::io::prelude::*;
use std::path::{Path, PathBuf};
use std::process;
pub jobs: Option<u32>,
pub cmd: Subcommand,
pub incremental: bool,
+ pub dry_run: bool,
// llvm codegen options
pub llvm_enabled: bool,
config.jobs = flags.jobs;
config.cmd = flags.cmd;
config.incremental = flags.incremental;
+ config.dry_run = flags.dry_run;
config.keep_stage = flags.keep_stage;
+ if config.dry_run {
+ let dir = config.out.join("tmp-dry-run");
+ t!(fs::create_dir_all(&dir));
+ config.out = dir;
+ }
+
// If --target was specified but --host wasn't specified, don't run any host-only tests.
config.run_host_only = !(flags.host.is_empty() && !flags.target.is_empty());
use std::env;
use std::fs::{self, File};
-use std::io::{self, Read, Write};
+use std::io::{Read, Write};
use std::path::{PathBuf, Path};
use std::process::{Command, Stdio};
use {Build, Compiler, Mode};
use channel;
-use util::{cp_r, libdir, is_dylib, cp_filtered, copy, replace_in_file, exe};
+use util::{libdir, is_dylib, exe};
use builder::{Builder, RunConfig, ShouldRun, Step};
use compile;
use native;
let dst = image.join("share/doc/rust/html");
t!(fs::create_dir_all(&dst));
let src = build.doc_out(host);
- cp_r(&src, &dst);
+ build.cp_r(&src, &dst);
let mut cmd = rust_installer(builder);
cmd.arg("generate")
.arg("--legacy-manifest-dirs=rustlib,cargo")
.arg("--bulk-dirs=share/doc/rust/html");
build.run(&mut cmd);
- t!(fs::remove_dir_all(&image));
+ build.remove_dir(&image);
distdir(build).join(format!("{}-{}.tar.gz", name, host))
}
let dst = image.join("share/doc/rust/html");
t!(fs::create_dir_all(&dst));
let src = build.compiler_doc_out(host);
- cp_r(&src, &dst);
+ build.cp_r(&src, &dst);
let mut cmd = rust_installer(builder);
cmd.arg("generate")
.arg("--legacy-manifest-dirs=rustlib,cargo")
.arg("--bulk-dirs=share/doc/rust/html");
build.run(&mut cmd);
- t!(fs::remove_dir_all(&image));
+ build.remove_dir(&image);
distdir(build).join(format!("{}-{}.tar.gz", name, host))
}
let rustc_dlls = find_files(&rustc_dlls, &bin_path);
let target_libs = find_files(&target_libs, &lib_path);
- fn copy_to_folder(src: &Path, dest_folder: &Path) {
- let file_name = src.file_name().unwrap();
- let dest = dest_folder.join(file_name);
- copy(src, &dest);
- }
-
- //Copy runtime dlls next to rustc.exe
+ // Copy runtime dlls next to rustc.exe
let dist_bin_dir = rust_root.join("bin/");
fs::create_dir_all(&dist_bin_dir).expect("creating dist_bin_dir failed");
for src in rustc_dlls {
- copy_to_folder(&src, &dist_bin_dir);
+ build.copy_to_folder(&src, &dist_bin_dir);
}
//Copy platform tools to platform-specific bin directory
let target_bin_dir = plat_root.join("lib").join("rustlib").join(target_triple).join("bin");
fs::create_dir_all(&target_bin_dir).expect("creating target_bin_dir failed");
for src in target_tools {
- copy_to_folder(&src, &target_bin_dir);
+ build.copy_to_folder(&src, &target_bin_dir);
}
//Copy platform libs to platform-specific lib directory
let target_lib_dir = plat_root.join("lib").join("rustlib").join(target_triple).join("lib");
fs::create_dir_all(&target_lib_dir).expect("creating target_lib_dir failed");
for src in target_libs {
- copy_to_folder(&src, &target_lib_dir);
+ build.copy_to_folder(&src, &target_lib_dir);
}
}
// Prepare the overlay which is part of the tarball but won't actually be
// installed
let cp = |file: &str| {
- install(&build.src.join(file), &overlay, 0o644);
+ build.install(&build.src.join(file), &overlay, 0o644);
};
cp("COPYRIGHT");
cp("LICENSE-APACHE");
cp("README.md");
// tiny morsel of metadata is used by rust-packaging
let version = build.rust_version();
- t!(t!(File::create(overlay.join("version"))).write_all(version.as_bytes()));
+ build.create(&overlay.join("version"), &version);
if let Some(sha) = build.rust_sha() {
- t!(t!(File::create(overlay.join("git-commit-hash"))).write_all(sha.as_bytes()));
+ build.create(&overlay.join("git-commit-hash"), &sha);
}
// On MinGW we've got a few runtime DLL dependencies that we need to
let dst = image.join("share/doc");
t!(fs::create_dir_all(&dst));
- cp_r(&build.src.join("src/etc/third-party"), &dst);
+ build.cp_r(&build.src.join("src/etc/third-party"), &dst);
}
// Finally, wrap everything up in a nice tarball!
.arg("--component-name=rustc")
.arg("--legacy-manifest-dirs=rustlib,cargo");
build.run(&mut cmd);
- t!(fs::remove_dir_all(&image));
- t!(fs::remove_dir_all(&overlay));
+ build.remove_dir(&image);
+ build.remove_dir(&overlay);
return distdir(build).join(format!("{}-{}.tar.gz", name, host));
// Copy rustc/rustdoc binaries
t!(fs::create_dir_all(image.join("bin")));
- cp_r(&src.join("bin"), &image.join("bin"));
+ build.cp_r(&src.join("bin"), &image.join("bin"));
- install(&builder.rustdoc(compiler.host), &image.join("bin"), 0o755);
+ build.install(&builder.rustdoc(compiler.host), &image.join("bin"), 0o755);
// Copy runtime DLLs needed by the compiler
if libdir != "bin" {
- for entry in t!(src.join(libdir).read_dir()).map(|e| t!(e)) {
+ for entry in build.read_dir(&src.join(libdir)) {
let name = entry.file_name();
if let Some(s) = name.to_str() {
if is_dylib(s) {
- install(&entry.path(), &image.join(libdir), 0o644);
+ build.install(&entry.path(), &image.join(libdir), 0o644);
}
}
}
let backends_rel = backends_src.strip_prefix(&src).unwrap();
let backends_dst = image.join(&backends_rel);
t!(fs::create_dir_all(&backends_dst));
- cp_r(&backends_src, &backends_dst);
+ build.cp_r(&backends_src, &backends_dst);
// Copy over lld if it's there
if builder.config.lld_enabled {
.join("bin")
.join(&exe);
t!(fs::create_dir_all(&dst.parent().unwrap()));
- copy(&src, &dst);
+ build.copy(&src, &dst);
}
// Man pages
let month_year = t!(time::strftime("%B %Y", &time::now()));
// don't use our `bootstrap::util::{copy, cp_r}`, because those try
// to hardlink, and we don't want to edit the source templates
- for entry_result in t!(fs::read_dir(man_src)) {
- let file_entry = t!(entry_result);
+ for file_entry in build.read_dir(&man_src) {
let page_src = file_entry.path();
let page_dst = man_dst.join(file_entry.file_name());
t!(fs::copy(&page_src, &page_dst));
// template in month/year and version number
- replace_in_file(&page_dst,
+ build.replace_in_file(&page_dst,
&[("<INSERT DATE HERE>", &month_year),
("<INSERT VERSION HERE>", channel::CFG_RELEASE_NUM)]);
}
// Misc license info
let cp = |file: &str| {
- install(&build.src.join(file), &image.join("share/doc/rust"), 0o644);
+ build.install(&build.src.join(file), &image.join("share/doc/rust"), 0o644);
};
cp("COPYRIGHT");
cp("LICENSE-APACHE");
let dst = sysroot.join("lib/rustlib/etc");
t!(fs::create_dir_all(&dst));
let cp_debugger_script = |file: &str| {
- install(&build.src.join("src/etc/").join(file), &dst, 0o644);
+ build.install(&build.src.join("src/etc/").join(file), &dst, 0o644);
};
if host.contains("windows-msvc") {
// windbg debugger scripts
- install(&build.src.join("src/etc/rust-windbg.cmd"), &sysroot.join("bin"),
+ build.install(&build.src.join("src/etc/rust-windbg.cmd"), &sysroot.join("bin"),
0o755);
cp_debugger_script("natvis/intrinsic.natvis");
cp_debugger_script("debugger_pretty_printers_common.py");
// gdb debugger scripts
- install(&build.src.join("src/etc/rust-gdb"), &sysroot.join("bin"),
+ build.install(&build.src.join("src/etc/rust-gdb"), &sysroot.join("bin"),
0o755);
cp_debugger_script("gdb_load_rust_pretty_printers.py");
cp_debugger_script("gdb_rust_pretty_printing.py");
// lldb debugger scripts
- install(&build.src.join("src/etc/rust-lldb"), &sysroot.join("bin"),
+ build.install(&build.src.join("src/etc/rust-lldb"), &sysroot.join("bin"),
0o755);
cp_debugger_script("lldb_rust_formatters.py");
t!(fs::create_dir_all(&dst));
let mut src = builder.sysroot_libdir(compiler, target).to_path_buf();
src.pop(); // Remove the trailing /lib folder from the sysroot_libdir
- cp_filtered(&src, &dst, &|path| {
+ build.cp_filtered(&src, &dst, &|path| {
let name = path.file_name().and_then(|s| s.to_str());
name != Some(build.config.rust_codegen_backends_dir.as_str()) &&
name != Some("bin")
.arg(format!("--component-name=rust-std-{}", target))
.arg("--legacy-manifest-dirs=rustlib,cargo");
build.run(&mut cmd);
- t!(fs::remove_dir_all(&image));
+ build.remove_dir(&image);
distdir(build).join(format!("{}-{}.tar.gz", name, target))
}
}
let dst = image.join("lib/rustlib").join(target).join("analysis");
t!(fs::create_dir_all(&dst));
println!("image_src: {:?}, dst: {:?}", image_src, dst);
- cp_r(&image_src, &dst);
+ build.cp_r(&image_src, &dst);
let mut cmd = rust_installer(builder);
cmd.arg("generate")
.arg(format!("--component-name=rust-analysis-{}", target))
.arg("--legacy-manifest-dirs=rustlib,cargo");
build.run(&mut cmd);
- t!(fs::remove_dir_all(&image));
+ build.remove_dir(&image);
distdir(build).join(format!("{}-{}.tar.gz", name, target))
}
}
for item in src_dirs {
let dst = &dst_dir.join(item);
t!(fs::create_dir_all(dst));
- cp_filtered(&build.src.join(item), dst, &|path| filter_fn(exclude_dirs, item, path));
+ build.cp_filtered(&build.src.join(item), dst, &|path| filter_fn(exclude_dirs, item, path));
}
}
copy_src_dirs(build, &std_src_dirs[..], &std_src_dirs_exclude[..], &dst_src);
for file in src_files.iter() {
- copy(&build.src.join(file), &dst_src.join(file));
+ build.copy(&build.src.join(file), &dst_src.join(file));
}
// Create source tarball in rust-installer format
.arg("--legacy-manifest-dirs=rustlib,cargo");
build.run(&mut cmd);
- t!(fs::remove_dir_all(&image));
+ build.remove_dir(&image);
distdir(build).join(&format!("{}.tar.gz", name))
}
}
// Copy the files normally
for item in &src_files {
- copy(&build.src.join(item), &plain_dst_src.join(item));
+ build.copy(&build.src.join(item), &plain_dst_src.join(item));
}
// Create the version file
- write_file(&plain_dst_src.join("version"), build.rust_version().as_bytes());
+ build.create(&plain_dst_src.join("version"), &build.rust_version());
if let Some(sha) = build.rust_sha() {
- write_file(&plain_dst_src.join("git-commit-hash"), sha.as_bytes());
+ build.create(&plain_dst_src.join("git-commit-hash"), &sha);
}
// If we're building from git sources, we need to vendor a complete distribution.
tarball.set_extension(""); // strip .gz
tarball.set_extension(""); // strip .tar
if let Some(dir) = tarball.parent() {
- t!(fs::create_dir_all(dir));
+ build.create_dir(&dir);
}
println!("running installer");
let mut cmd = rust_installer(builder);
}
}
-fn install(src: &Path, dstdir: &Path, perms: u32) {
- let dst = dstdir.join(src.file_name().unwrap());
- t!(fs::create_dir_all(dstdir));
- drop(fs::remove_file(&dst));
- {
- let mut s = t!(fs::File::open(&src));
- let mut d = t!(fs::File::create(&dst));
- io::copy(&mut s, &mut d).expect("failed to copy");
- }
- chmod(&dst, perms);
-}
-
-#[cfg(unix)]
-fn chmod(path: &Path, perms: u32) {
- use std::os::unix::fs::*;
- t!(fs::set_permissions(path, fs::Permissions::from_mode(perms)));
-}
-#[cfg(windows)]
-fn chmod(_path: &Path, _perms: u32) {}
-
// We have to run a few shell scripts, which choke quite a bit on both `\`
// characters and on `C:\` paths, so normalize both of them away.
pub fn sanitize_sh(path: &Path) -> String {
}
}
-fn write_file(path: &Path, data: &[u8]) {
- let mut vf = t!(fs::File::create(path));
- t!(vf.write_all(data));
-}
-
#[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Cargo {
pub stage: u32,
let tmp = tmpdir(build);
let image = tmp.join("cargo-image");
drop(fs::remove_dir_all(&image));
- t!(fs::create_dir_all(&image));
+ build.create_dir(&image);
// Prepare the image directory
- t!(fs::create_dir_all(image.join("share/zsh/site-functions")));
- t!(fs::create_dir_all(image.join("etc/bash_completion.d")));
+ build.create_dir(&image.join("share/zsh/site-functions"));
+ build.create_dir(&image.join("etc/bash_completion.d"));
let cargo = builder.ensure(tool::Cargo {
compiler: builder.compiler(stage, build.build),
target
});
- install(&cargo, &image.join("bin"), 0o755);
+ build.install(&cargo, &image.join("bin"), 0o755);
for man in t!(etc.join("man").read_dir()) {
let man = t!(man);
- install(&man.path(), &image.join("share/man/man1"), 0o644);
+ build.install(&man.path(), &image.join("share/man/man1"), 0o644);
}
- install(&etc.join("_cargo"), &image.join("share/zsh/site-functions"), 0o644);
- copy(&etc.join("cargo.bashcomp.sh"),
+ build.install(&etc.join("_cargo"), &image.join("share/zsh/site-functions"), 0o644);
+ build.copy(&etc.join("cargo.bashcomp.sh"),
&image.join("etc/bash_completion.d/cargo"));
let doc = image.join("share/doc/cargo");
- install(&src.join("README.md"), &doc, 0o644);
- install(&src.join("LICENSE-MIT"), &doc, 0o644);
- install(&src.join("LICENSE-APACHE"), &doc, 0o644);
- install(&src.join("LICENSE-THIRD-PARTY"), &doc, 0o644);
+ build.install(&src.join("README.md"), &doc, 0o644);
+ build.install(&src.join("LICENSE-MIT"), &doc, 0o644);
+ build.install(&src.join("LICENSE-APACHE"), &doc, 0o644);
+ build.install(&src.join("LICENSE-THIRD-PARTY"), &doc, 0o644);
// Prepare the overlay
let overlay = tmp.join("cargo-overlay");
drop(fs::remove_dir_all(&overlay));
- t!(fs::create_dir_all(&overlay));
- install(&src.join("README.md"), &overlay, 0o644);
- install(&src.join("LICENSE-MIT"), &overlay, 0o644);
- install(&src.join("LICENSE-APACHE"), &overlay, 0o644);
- install(&src.join("LICENSE-THIRD-PARTY"), &overlay, 0o644);
- t!(t!(File::create(overlay.join("version"))).write_all(version.as_bytes()));
+ build.create_dir(&overlay);
+ build.install(&src.join("README.md"), &overlay, 0o644);
+ build.install(&src.join("LICENSE-MIT"), &overlay, 0o644);
+ build.install(&src.join("LICENSE-APACHE"), &overlay, 0o644);
+ build.install(&src.join("LICENSE-THIRD-PARTY"), &overlay, 0o644);
+ build.create(&overlay.join("version"), &version);
// Generate the installer tarball
let mut cmd = rust_installer(builder);
target, extra_features: Vec::new()
}).or_else(|| { println!("Unable to build RLS, skipping dist"); None })?;
- install(&rls, &image.join("bin"), 0o755);
+ build.install(&rls, &image.join("bin"), 0o755);
let doc = image.join("share/doc/rls");
- install(&src.join("README.md"), &doc, 0o644);
- install(&src.join("LICENSE-MIT"), &doc, 0o644);
- install(&src.join("LICENSE-APACHE"), &doc, 0o644);
+ build.install(&src.join("README.md"), &doc, 0o644);
+ build.install(&src.join("LICENSE-MIT"), &doc, 0o644);
+ build.install(&src.join("LICENSE-APACHE"), &doc, 0o644);
// Prepare the overlay
let overlay = tmp.join("rls-overlay");
drop(fs::remove_dir_all(&overlay));
t!(fs::create_dir_all(&overlay));
- install(&src.join("README.md"), &overlay, 0o644);
- install(&src.join("LICENSE-MIT"), &overlay, 0o644);
- install(&src.join("LICENSE-APACHE"), &overlay, 0o644);
- t!(t!(File::create(overlay.join("version"))).write_all(version.as_bytes()));
+ build.install(&src.join("README.md"), &overlay, 0o644);
+ build.install(&src.join("LICENSE-MIT"), &overlay, 0o644);
+ build.install(&src.join("LICENSE-APACHE"), &overlay, 0o644);
+ build.create(&overlay.join("version"), &version);
// Generate the installer tarball
let mut cmd = rust_installer(builder);
let tmp = tmpdir(build);
let image = tmp.join("rustfmt-image");
drop(fs::remove_dir_all(&image));
- t!(fs::create_dir_all(&image));
+ build.create_dir(&image);
// Prepare the image directory
let rustfmt = builder.ensure(tool::Rustfmt {
target, extra_features: Vec::new()
}).or_else(|| { println!("Unable to build Cargofmt, skipping dist"); None })?;
- install(&rustfmt, &image.join("bin"), 0o755);
- install(&cargofmt, &image.join("bin"), 0o755);
+ build.install(&rustfmt, &image.join("bin"), 0o755);
+ build.install(&cargofmt, &image.join("bin"), 0o755);
let doc = image.join("share/doc/rustfmt");
- install(&src.join("README.md"), &doc, 0o644);
- install(&src.join("LICENSE-MIT"), &doc, 0o644);
- install(&src.join("LICENSE-APACHE"), &doc, 0o644);
+ build.install(&src.join("README.md"), &doc, 0o644);
+ build.install(&src.join("LICENSE-MIT"), &doc, 0o644);
+ build.install(&src.join("LICENSE-APACHE"), &doc, 0o644);
// Prepare the overlay
let overlay = tmp.join("rustfmt-overlay");
drop(fs::remove_dir_all(&overlay));
- t!(fs::create_dir_all(&overlay));
- install(&src.join("README.md"), &overlay, 0o644);
- install(&src.join("LICENSE-MIT"), &overlay, 0o644);
- install(&src.join("LICENSE-APACHE"), &overlay, 0o644);
- t!(t!(File::create(overlay.join("version"))).write_all(version.as_bytes()));
+ build.create_dir(&overlay);
+ build.install(&src.join("README.md"), &overlay, 0o644);
+ build.install(&src.join("LICENSE-MIT"), &overlay, 0o644);
+ build.install(&src.join("LICENSE-APACHE"), &overlay, 0o644);
+ build.create(&overlay.join("version"), &version);
// Generate the installer tarball
let mut cmd = rust_installer(builder);
let work = tmp.join("work");
let _ = fs::remove_dir_all(&overlay);
- install(&build.src.join("COPYRIGHT"), &overlay, 0o644);
- install(&build.src.join("LICENSE-APACHE"), &overlay, 0o644);
- install(&build.src.join("LICENSE-MIT"), &overlay, 0o644);
+ build.install(&build.src.join("COPYRIGHT"), &overlay, 0o644);
+ build.install(&build.src.join("LICENSE-APACHE"), &overlay, 0o644);
+ build.install(&build.src.join("LICENSE-MIT"), &overlay, 0o644);
let version = build.rust_version();
- t!(t!(File::create(overlay.join("version"))).write_all(version.as_bytes()));
+ build.create(&overlay.join("version"), &version);
if let Some(sha) = build.rust_sha() {
- t!(t!(File::create(overlay.join("git-commit-hash"))).write_all(sha.as_bytes()));
+ build.create(&overlay.join("git-commit-hash"), &sha);
}
- install(&etc.join("README.md"), &overlay, 0o644);
+ build.install(&etc.join("README.md"), &overlay, 0o644);
// When rust-std package split from rustc, we needed to ensure that during
// upgrades rustc was upgraded before rust-std. To avoid rustc clobbering
build.run(&mut cmd);
let mut license = String::new();
- t!(t!(File::open(build.src.join("COPYRIGHT"))).read_to_string(&mut license));
+ license += &build.read(&build.src.join("COPYRIGHT"));
+ license += &build.read(&build.src.join("LICENSE-APACHE"));
+ license += &build.read(&build.src.join("LICENSE-MIT"));
license.push_str("\n");
- t!(t!(File::open(build.src.join("LICENSE-APACHE"))).read_to_string(&mut license));
license.push_str("\n");
- t!(t!(File::open(build.src.join("LICENSE-MIT"))).read_to_string(&mut license));
let rtf = r"{\rtf1\ansi\deff0{\fonttbl{\f0\fnil\fcharset0 Arial;}}\nowwrap\fs18";
let mut rtf = rtf.to_string();
};
let prepare = |name: &str| {
- t!(fs::create_dir_all(pkg.join(name)));
- cp_r(&work.join(&format!("{}-{}", pkgname(build, name), target)),
+ build.create_dir(&pkg.join(name));
+ build.cp_r(&work.join(&format!("{}-{}", pkgname(build, name), target)),
&pkg.join(name));
- install(&etc.join("pkg/postinstall"), &pkg.join(name), 0o755);
+ build.install(&etc.join("pkg/postinstall"), &pkg.join(name), 0o755);
pkgbuild(name);
};
prepare("rustc");
}
// create an 'uninstall' package
- install(&etc.join("pkg/postinstall"), &pkg.join("uninstall"), 0o755);
+ build.install(&etc.join("pkg/postinstall"), &pkg.join("uninstall"), 0o755);
pkgbuild("uninstall");
- t!(fs::create_dir_all(pkg.join("res")));
- t!(t!(File::create(pkg.join("res/LICENSE.txt"))).write_all(license.as_bytes()));
- install(&etc.join("gfx/rust-logo.png"), &pkg.join("res"), 0o644);
+ build.create_dir(&pkg.join("res"));
+ build.create(&pkg.join("res/LICENSE.txt"), &license);
+ build.install(&etc.join("gfx/rust-logo.png"), &pkg.join("res"), 0o644);
let mut cmd = Command::new("productbuild");
cmd.arg("--distribution").arg(xform(&etc.join("pkg/Distribution.xml")))
.arg("--resources").arg(pkg.join("res"))
let _ = fs::remove_dir_all(&exe);
let prepare = |name: &str| {
- t!(fs::create_dir_all(exe.join(name)));
+ build.create_dir(&exe.join(name));
let dir = if name == "rust-std" || name == "rust-analysis" {
format!("{}-{}", name, target)
} else if name == "rls" {
} else {
name.to_string()
};
- cp_r(&work.join(&format!("{}-{}", pkgname(build, name), target))
+ build.cp_r(&work.join(&format!("{}-{}", pkgname(build, name), target))
.join(dir),
&exe.join(name));
t!(fs::remove_file(exe.join(name).join("manifest.in")));
prepare("rust-mingw");
}
- install(&xform(&etc.join("exe/rust.iss")), &exe, 0o644);
- install(&etc.join("exe/modpath.iss"), &exe, 0o644);
- install(&etc.join("exe/upgrade.iss"), &exe, 0o644);
- install(&etc.join("gfx/rust-logo.ico"), &exe, 0o644);
+ build.install(&xform(&etc.join("exe/rust.iss")), &exe, 0o644);
+ build.install(&etc.join("exe/modpath.iss"), &exe, 0o644);
+ build.install(&etc.join("exe/upgrade.iss"), &exe, 0o644);
+ build.install(&etc.join("gfx/rust-logo.ico"), &exe, 0o644);
t!(t!(File::create(exe.join("LICENSE.txt"))).write_all(license.as_bytes()));
// Generate exe installer
}
add_env(build, &mut cmd, target);
build.run(&mut cmd);
- install(&exe.join(format!("{}-{}.exe", pkgname(build, "rust"), target)),
+ build.install(&exe.join(format!("{}-{}.exe", pkgname(build, "rust"), target)),
&distdir(build),
0o755);
}
t!(t!(File::create(exe.join("LICENSE.rtf"))).write_all(rtf.as_bytes()));
- install(&etc.join("gfx/banner.bmp"), &exe, 0o644);
- install(&etc.join("gfx/dialogbg.bmp"), &exe, 0o644);
+ build.install(&etc.join("gfx/banner.bmp"), &exe, 0o644);
+ build.install(&etc.join("gfx/dialogbg.bmp"), &exe, 0o644);
let filename = format!("{}-{}.msi", pkgname(build, "rust"), target);
let mut cmd = Command::new(&light);
cmd.arg(build.package_vers(&build.release_num("rustfmt")));
cmd.arg(addr);
- t!(fs::create_dir_all(distdir(build)));
+ build.create_dir(&distdir(build));
let mut child = t!(cmd.stdin(Stdio::piped()).spawn());
t!(child.stdin.take().unwrap().write_all(pass.as_bytes()));
use {Build, Mode};
use build_helper::up_to_date;
-use util::{cp_r, symlink_dir};
+use util::symlink_dir;
use builder::{Builder, Compiler, RunConfig, ShouldRun, Step};
use tool::Tool;
use compile;
use cache::{INTERNER, Interned};
+use config::Config;
macro_rules! book {
($($name:ident, $path:expr, $book_name:expr;)+) => {
let src = src.join(name);
let index = out.join("index.html");
let rustbook = builder.tool_exe(Tool::Rustbook);
+ let mut rustbook_cmd = builder.tool_cmd(Tool::Rustbook);
if up_to_date(&src, &index) && up_to_date(&rustbook, &index) {
return
}
println!("Rustbook ({}) - {}", target, name);
let _ = fs::remove_dir_all(&out);
- build.run(builder.tool_cmd(Tool::Rustbook)
+ build.run(rustbook_cmd
.arg("build")
.arg(&src)
.arg("-d")
let version_input = build.src.join("src/doc/version_info.html.template");
let version_info = out.join("version_info.html");
- if !up_to_date(&version_input, &version_info) {
+ if !build.config.dry_run && !up_to_date(&version_input, &version_info) {
let mut info = String::new();
t!(t!(File::open(&version_input)).read_to_string(&mut info));
let info = info.replace("VERSION", &build.rust_release())
up_to_date(&favicon, &html) &&
up_to_date(&full_toc, &html) &&
up_to_date(&version_info, &html) &&
- up_to_date(&rustdoc, &html) {
+ (build.config.dry_run || up_to_date(&rustdoc, &html)) {
continue
}
// will also directly handle merging.
let my_out = build.crate_doc_out(target);
build.clear_if_dirty(&my_out, &rustdoc);
- t!(symlink_dir_force(&my_out, &out_dir));
+ t!(symlink_dir_force(&build.config, &my_out, &out_dir));
let mut cargo = builder.cargo(compiler, Mode::Libstd, target, "doc");
compile::std_cargo(builder, &compiler, target, &mut cargo);
}
build.run(&mut cargo);
- cp_r(&my_out, &out);
+ build.cp_r(&my_out, &out);
}
}
// See docs in std above for why we symlink
let my_out = build.crate_doc_out(target);
build.clear_if_dirty(&my_out, &rustdoc);
- t!(symlink_dir_force(&my_out, &out_dir));
+ t!(symlink_dir_force(&builder.config, &my_out, &out_dir));
let mut cargo = builder.cargo(compiler, Mode::Libtest, target, "doc");
compile::test_cargo(build, &compiler, target, &mut cargo);
build.run(&mut cargo);
- cp_r(&my_out, &out);
+ build.cp_r(&my_out, &out);
}
}
// See docs in std above for why we symlink
let my_out = build.crate_doc_out(target);
build.clear_if_dirty(&my_out, &rustdoc);
- t!(symlink_dir_force(&my_out, &out_dir));
+ t!(symlink_dir_force(&builder.config, &my_out, &out_dir));
let mut cargo = builder.cargo(compiler, Mode::Librustc, target, "doc");
compile::rustc_cargo(build, &mut cargo);
}
build.run(&mut cargo);
- cp_r(&my_out, &out);
+ build.cp_r(&my_out, &out);
}
}
// We do not symlink to the same shared folder that already contains std library
// documentation from previous steps as we do not want to include that.
build.clear_if_dirty(&out, &rustdoc);
- t!(symlink_dir_force(&out, &out_dir));
+ t!(symlink_dir_force(&builder.config, &out, &out_dir));
let mut cargo = builder.cargo(compiler, Mode::Librustc, target, "doc");
compile::rustc_cargo(build, &mut cargo);
println!("Generating unstable book md files ({})", target);
let out = build.md_doc_out(target).join("unstable-book");
- t!(fs::create_dir_all(&out));
- t!(fs::remove_dir_all(&out));
+ build.create_dir(&out);
+ build.remove_dir(&out);
let mut cmd = builder.tool_cmd(Tool::UnstableBookGen);
cmd.arg(build.src.join("src"));
cmd.arg(out);
}
}
-fn symlink_dir_force(src: &Path, dst: &Path) -> io::Result<()> {
+fn symlink_dir_force(config: &Config, src: &Path, dst: &Path) -> io::Result<()> {
+ if config.dry_run {
+ return Ok(());
+ }
if let Ok(m) = fs::symlink_metadata(dst) {
if m.file_type().is_dir() {
try!(fs::remove_dir_all(dst));
}
}
- symlink_dir(src, dst)
+ symlink_dir(config, src, dst)
}
//! This module implements the command-line parsing of the build system which
//! has various flags to configure how it's run.
-use std::env;
use std::fs;
use std::path::PathBuf;
use std::process;
pub incremental: bool,
pub exclude: Vec<PathBuf>,
pub rustc_error_format: Option<String>,
+ pub dry_run: bool,
}
pub enum Subcommand {
opts.optmulti("", "target", "target targets to build", "TARGET");
opts.optmulti("", "exclude", "build paths to exclude", "PATH");
opts.optopt("", "on-fail", "command to run on failure", "CMD");
+ opts.optflag("", "dry-run", "dry run; don't build anything");
opts.optopt("", "stage", "stage to build", "N");
opts.optopt("", "keep-stage", "stage to keep without recompiling", "N");
opts.optopt("", "src", "path to the root of the rust checkout", "DIR");
Flags {
verbose: matches.opt_count("verbose"),
stage,
+ dry_run: matches.opt_present("dry-run"),
on_fail: matches.opt_str("on-fail"),
rustc_error_format: matches.opt_str("error-format"),
keep_stage: matches.opt_str("keep-stage").map(|j| j.parse().unwrap()),
//! also check out the `src/bootstrap/README.md` file for more information.
#![deny(warnings)]
-#![feature(core_intrinsics)]
+#![feature(conservative_impl_trait, fs_read_write, core_intrinsics)]
#![feature(slice_concat_ext)]
#[macro_use]
use std::cell::{RefCell, Cell};
use std::collections::{HashSet, HashMap};
use std::env;
-use std::fs::{self, File};
-use std::io::Read;
+use std::fs::{self, OpenOptions, File};
+use std::io::{self, Seek, SeekFrom, Write, Read};
use std::path::{PathBuf, Path};
use std::process::{self, Command};
use std::slice;
+use std::str;
use build_helper::{run_silent, run_suppressed, try_run_silent, try_run_suppressed, output, mtime};
+use filetime::FileTime;
use util::{exe, libdir, OutputFolder, CiEnv};
return clean::clean(self, all);
}
- let builder = builder::Builder::new(&self);
- if let Some(path) = builder.paths.get(0) {
- if path == Path::new("nonexistent/path/to/trigger/cargo/metadata") {
- return;
+ {
+ let builder = builder::Builder::new(&self);
+ if let Some(path) = builder.paths.get(0) {
+ if path == Path::new("nonexistent/path/to/trigger/cargo/metadata") {
+ return;
+ }
}
}
- builder.execute_cli();
+
+ if !self.config.dry_run {
+ let dry_graph = {
+ self.config.dry_run = true;
+ let builder = builder::Builder::new(&self);
+ builder.execute_cli()
+ };
+ self.config.dry_run = false;
+ let builder = builder::Builder::new(&self);
+ let act_graph = builder.execute_cli();
+ assert_eq!(dry_graph.raw_nodes().iter().map(|i| &i.weight).collect::<Vec<_>>(),
+ act_graph.raw_nodes().iter().map(|i| &i.weight).collect::<Vec<_>>());
+ assert_eq!(dry_graph.raw_edges()
+ .iter().map(|i| (&dry_graph[i.source()], &dry_graph[i.target()], &i.weight))
+ .collect::<Vec<_>>(),
+ act_graph.raw_edges()
+ .iter().map(|i| (&act_graph[i.source()], &act_graph[i.target()], &i.weight))
+ .collect::<Vec<_>>());
+ } else {
+ let builder = builder::Builder::new(&self);
+ let _ = builder.execute_cli();
+ }
// Check for postponed failures from `test --no-fail-fast`.
let failures = self.delayed_failures.borrow();
}
ret
}
+
+ fn read_stamp_file(&self, stamp: &Path) -> Vec<PathBuf> {
+ if self.config.dry_run {
+ return Vec::new();
+ }
+
+ let mut paths = Vec::new();
+ let mut contents = Vec::new();
+ t!(t!(File::open(stamp)).read_to_end(&mut contents));
+ // This is the method we use for extracting paths from the stamp file passed to us. See
+ // run_cargo for more information (in compile.rs).
+ for part in contents.split(|b| *b == 0) {
+ if part.is_empty() {
+ continue
+ }
+ let path = PathBuf::from(t!(str::from_utf8(part)));
+ paths.push(path);
+ }
+ paths
+ }
+
+ /// Copies a file from `src` to `dst`
+ pub fn copy(&self, src: &Path, dst: &Path) {
+ if self.config.dry_run { return; }
+ let _ = fs::remove_file(&dst);
+ // Attempt to "easy copy" by creating a hard link (symlinks don't work on
+ // windows), but if that fails just fall back to a slow `copy` operation.
+ if let Ok(()) = fs::hard_link(src, dst) {
+ return
+ }
+ if let Err(e) = fs::copy(src, dst) {
+ panic!("failed to copy `{}` to `{}`: {}", src.display(),
+ dst.display(), e)
+ }
+ let metadata = t!(src.metadata());
+ t!(fs::set_permissions(dst, metadata.permissions()));
+ let atime = FileTime::from_last_access_time(&metadata);
+ let mtime = FileTime::from_last_modification_time(&metadata);
+ t!(filetime::set_file_times(dst, atime, mtime));
+ }
+
+ /// Search-and-replaces within a file. (Not maximally efficiently: allocates a
+ /// new string for each replacement.)
+ pub fn replace_in_file(&self, path: &Path, replacements: &[(&str, &str)]) {
+ if self.config.dry_run { return; }
+ let mut contents = String::new();
+ let mut file = t!(OpenOptions::new().read(true).write(true).open(path));
+ t!(file.read_to_string(&mut contents));
+ for &(target, replacement) in replacements {
+ contents = contents.replace(target, replacement);
+ }
+ t!(file.seek(SeekFrom::Start(0)));
+ t!(file.set_len(0));
+ t!(file.write_all(contents.as_bytes()));
+ }
+
+ /// Copies the `src` directory recursively to `dst`. Both are assumed to exist
+ /// when this function is called.
+ pub fn cp_r(&self, src: &Path, dst: &Path) {
+ if self.config.dry_run { return; }
+ for f in t!(fs::read_dir(src)) {
+ let f = t!(f);
+ let path = f.path();
+ let name = path.file_name().unwrap();
+ let dst = dst.join(name);
+ if t!(f.file_type()).is_dir() {
+ t!(fs::create_dir_all(&dst));
+ self.cp_r(&path, &dst);
+ } else {
+ let _ = fs::remove_file(&dst);
+ self.copy(&path, &dst);
+ }
+ }
+ }
+
+ /// Copies the `src` directory recursively to `dst`. Both are assumed to exist
+ /// when this function is called. Unwanted files or directories can be skipped
+ /// by returning `false` from the filter function.
+ pub fn cp_filtered(&self, src: &Path, dst: &Path, filter: &Fn(&Path) -> bool) {
+ // Immediately recurse with an empty relative path
+ self.recurse_(src, dst, Path::new(""), filter)
+ }
+
+ // Inner function does the actual work
+ fn recurse_(&self, src: &Path, dst: &Path, relative: &Path, filter: &Fn(&Path) -> bool) {
+ for f in self.read_dir(src) {
+ let path = f.path();
+ let name = path.file_name().unwrap();
+ let dst = dst.join(name);
+ let relative = relative.join(name);
+ // Only copy file or directory if the filter function returns true
+ if filter(&relative) {
+ if t!(f.file_type()).is_dir() {
+ let _ = fs::remove_dir_all(&dst);
+ self.create_dir(&dst);
+ self.recurse_(&path, &dst, &relative, filter);
+ } else {
+ let _ = fs::remove_file(&dst);
+ self.copy(&path, &dst);
+ }
+ }
+ }
+ }
+
+ fn copy_to_folder(&self, src: &Path, dest_folder: &Path) {
+ let file_name = src.file_name().unwrap();
+ let dest = dest_folder.join(file_name);
+ self.copy(src, &dest);
+ }
+
+ fn install(&self, src: &Path, dstdir: &Path, perms: u32) {
+ if self.config.dry_run { return; }
+ let dst = dstdir.join(src.file_name().unwrap());
+ t!(fs::create_dir_all(dstdir));
+ drop(fs::remove_file(&dst));
+ {
+ let mut s = t!(fs::File::open(&src));
+ let mut d = t!(fs::File::create(&dst));
+ io::copy(&mut s, &mut d).expect("failed to copy");
+ }
+ chmod(&dst, perms);
+ }
+
+ fn create(&self, path: &Path, s: &str) {
+ if self.config.dry_run { return; }
+ t!(fs::write(path, s));
+ }
+
+ fn read(&self, path: &Path) -> String {
+ if self.config.dry_run { return String::new(); }
+ t!(fs::read_string(path))
+ }
+
+ fn create_dir(&self, dir: &Path) {
+ if self.config.dry_run { return; }
+ t!(fs::create_dir_all(dir))
+ }
+
+ fn remove_dir(&self, dir: &Path) {
+ if self.config.dry_run { return; }
+ t!(fs::remove_dir_all(dir))
+ }
+
+ fn read_dir(&self, dir: &Path) -> impl Iterator<Item=fs::DirEntry> {
+ let iter = match fs::read_dir(dir) {
+ Ok(v) => v,
+ Err(_) if self.config.dry_run => return vec![].into_iter(),
+ Err(err) => panic!("could not read dir {:?}: {:?}", dir, err),
+ };
+ iter.map(|e| t!(e)).collect::<Vec<_>>().into_iter()
+ }
+}
+
+#[cfg(unix)]
+fn chmod(path: &Path, perms: u32) {
+ use std::os::unix::fs::*;
+ t!(fs::set_permissions(path, fs::Permissions::from_mode(perms)));
}
+#[cfg(windows)]
+fn chmod(_path: &Path, _perms: u32) {}
+
impl<'a> Compiler {
pub fn with_stage(mut self, stage: u32) -> Compiler {
/// Compile LLVM for `target`.
fn run(self, builder: &Builder) -> PathBuf {
- if cfg!(test) {
- return PathBuf::from("llvm-config-test-generated");
- }
let build = builder.build;
let target = self.target;
let emscripten = self.emscripten;
// libraries here, e.g. we just want a few components and a few
// tools. Figure out how to filter them down and only build the right
// tools and libs on all platforms.
+
+ if builder.config.dry_run {
+ return build_llvm_config;
+ }
+
cfg.build();
t!(t!(File::create(&done_stamp)).write_all(rebuild_trigger_contents.as_bytes()));
/// Compile LLVM for `target`.
fn run(self, builder: &Builder) -> PathBuf {
- if cfg!(test) {
+ if builder.config.dry_run {
return PathBuf::from("lld-out-dir-test-gen");
}
let target = self.target;
/// Compiles the `rust_test_helpers.c` library which we used in various
/// `run-pass` test suites for ABI testing.
fn run(self, builder: &Builder) {
- if cfg!(test) {
+ if builder.config.dry_run {
return;
}
let build = builder.build;
}
fn run(self, builder: &Builder) {
- if cfg!(test) {
+ if builder.config.dry_run {
return;
}
let build = builder.build;
let _time = util::timeit();
let _folder = build.fold_output(|| format!("test_{}", self.name));
+ let mut files = Vec::new();
while let Some(p) = stack.pop() {
if p.is_dir() {
stack.extend(t!(p.read_dir()).map(|p| t!(p).path()));
continue;
}
- let test_result = markdown_test(builder, compiler, &p);
+ files.push(p);
+ }
+
+ files.sort();
+
+ for file in files {
+ let test_result = markdown_test(builder, compiler, &file);
if self.is_ext_doc {
let toolstate = if test_result {
ToolState::TestPass
use Mode;
use Compiler;
use builder::{Step, RunConfig, ShouldRun, Builder};
-use util::{copy, exe, add_lib_path};
+use util::{exe, add_lib_path};
use compile::{self, libtest_stamp, libstd_stamp, librustc_stamp};
use native;
use channel::GitInfo;
let cargo_out = build.cargo_out(compiler, Mode::Tool, target)
.join(exe(tool, &compiler.host));
let bin = build.tools_dir(compiler).join(exe(tool, &compiler.host));
- copy(&cargo_out, &bin);
+ build.copy(&cargo_out, &bin);
Some(bin)
}
}
t!(fs::create_dir_all(&bindir));
let bin_rustdoc = bindir.join(exe("rustdoc", &*target_compiler.host));
let _ = fs::remove_file(&bin_rustdoc);
- copy(&tool_rustdoc, &bin_rustdoc);
+ build.copy(&tool_rustdoc, &bin_rustdoc);
bin_rustdoc
} else {
tool_rustdoc
use std::env;
use std::str;
-use std::fs::{self, File, OpenOptions};
-use std::io::{self, Read, Write, Seek, SeekFrom};
+use std::fs;
+use std::io::{self, Write};
use std::path::{Path, PathBuf};
use std::process::Command;
use std::time::{SystemTime, Instant};
-use filetime::{self, FileTime};
+use config::Config;
/// Returns the `name` as the filename of a static library for `target`.
pub fn staticlib(name: &str, target: &str) -> String {
}
}
-/// Copies a file from `src` to `dst`
-pub fn copy(src: &Path, dst: &Path) {
- let _ = fs::remove_file(&dst);
- // Attempt to "easy copy" by creating a hard link (symlinks don't work on
- // windows), but if that fails just fall back to a slow `copy` operation.
- if let Ok(()) = fs::hard_link(src, dst) {
- return
- }
- if let Err(e) = fs::copy(src, dst) {
- panic!("failed to copy `{}` to `{}`: {}", src.display(),
- dst.display(), e)
- }
- let metadata = t!(src.metadata());
- t!(fs::set_permissions(dst, metadata.permissions()));
- let atime = FileTime::from_last_access_time(&metadata);
- let mtime = FileTime::from_last_modification_time(&metadata);
- t!(filetime::set_file_times(dst, atime, mtime));
-}
-
-/// Search-and-replaces within a file. (Not maximally efficiently: allocates a
-/// new string for each replacement.)
-pub fn replace_in_file(path: &Path, replacements: &[(&str, &str)]) {
- let mut contents = String::new();
- let mut file = t!(OpenOptions::new().read(true).write(true).open(path));
- t!(file.read_to_string(&mut contents));
- for &(target, replacement) in replacements {
- contents = contents.replace(target, replacement);
- }
- t!(file.seek(SeekFrom::Start(0)));
- t!(file.set_len(0));
- t!(file.write_all(contents.as_bytes()));
-}
-
-pub fn read_stamp_file(stamp: &Path) -> Vec<PathBuf> {
- let mut paths = Vec::new();
- let mut contents = Vec::new();
- t!(t!(File::open(stamp)).read_to_end(&mut contents));
- // This is the method we use for extracting paths from the stamp file passed to us. See
- // run_cargo for more information (in compile.rs).
- for part in contents.split(|b| *b == 0) {
- if part.is_empty() {
- continue
- }
- let path = PathBuf::from(t!(str::from_utf8(part)));
- paths.push(path);
- }
- paths
-}
-
-/// Copies the `src` directory recursively to `dst`. Both are assumed to exist
-/// when this function is called.
-pub fn cp_r(src: &Path, dst: &Path) {
- for f in t!(fs::read_dir(src)) {
- let f = t!(f);
- let path = f.path();
- let name = path.file_name().unwrap();
- let dst = dst.join(name);
- if t!(f.file_type()).is_dir() {
- t!(fs::create_dir_all(&dst));
- cp_r(&path, &dst);
- } else {
- let _ = fs::remove_file(&dst);
- copy(&path, &dst);
- }
- }
-}
-
-/// Copies the `src` directory recursively to `dst`. Both are assumed to exist
-/// when this function is called. Unwanted files or directories can be skipped
-/// by returning `false` from the filter function.
-pub fn cp_filtered(src: &Path, dst: &Path, filter: &Fn(&Path) -> bool) {
- // Inner function does the actual work
- fn recurse(src: &Path, dst: &Path, relative: &Path, filter: &Fn(&Path) -> bool) {
- for f in t!(fs::read_dir(src)) {
- let f = t!(f);
- let path = f.path();
- let name = path.file_name().unwrap();
- let dst = dst.join(name);
- let relative = relative.join(name);
- // Only copy file or directory if the filter function returns true
- if filter(&relative) {
- if t!(f.file_type()).is_dir() {
- let _ = fs::remove_dir_all(&dst);
- t!(fs::create_dir(&dst));
- recurse(&path, &dst, &relative, filter);
- } else {
- let _ = fs::remove_file(&dst);
- copy(&path, &dst);
- }
- }
- }
- }
- // Immediately recurse with an empty relative path
- recurse(src, dst, Path::new(""), filter)
-}
-
/// Given an executable called `name`, return the filename for the
/// executable for a particular target.
pub fn exe(name: &str, target: &str) -> String {
/// Symlinks two directories, using junctions on Windows and normal symlinks on
/// Unix.
-pub fn symlink_dir(src: &Path, dest: &Path) -> io::Result<()> {
- if cfg!(test) { return Ok(()); }
+pub fn symlink_dir(config: &Config, src: &Path, dest: &Path) -> io::Result<()> {
+ if config.dry_run { return Ok(()); }
let _ = fs::remove_dir(dest);
return symlink_dir_inner(src, dest);