Refactor to use a dry-run config instead of cfg(test)
This ensures that each build will support the testing design of "dry running" builds. It's also checked that a dry run build is equivalent step-wise to a "wet" run build; the graphs we generate when running are directly compared node/node and edge/edge, both for order and contents.
This commit is contained in:
parent
b0dbc7c15d
commit
a727447f59
12 changed files with 393 additions and 293 deletions
|
|
@ -413,8 +413,9 @@ impl<'a> Builder<'a> {
|
|||
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]>) {
|
||||
|
|
@ -910,6 +911,7 @@ impl<'a> Builder<'a> {
|
|||
#[cfg(test)]
|
||||
mod __test {
|
||||
use config::Config;
|
||||
use std::thread;
|
||||
use super::*;
|
||||
|
||||
fn configure(host: &[&str], target: &[&str]) -> Config {
|
||||
|
|
@ -917,6 +919,12 @@ mod __test {
|
|||
// 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<_>>();
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ impl Step for Std {
|
|||
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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -102,7 +102,7 @@ impl Step for Rustc {
|
|||
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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -143,7 +143,7 @@ impl Step for Test {
|
|||
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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ use build_helper::{output, mtime, up_to_date};
|
|||
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;
|
||||
|
|
@ -130,7 +130,7 @@ fn copy_musl_third_party_objects(build: &Build,
|
|||
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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -220,13 +220,13 @@ impl Step for StdLink {
|
|||
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 {
|
||||
|
|
@ -237,7 +237,7 @@ impl Step for StdLink {
|
|||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
|
@ -245,7 +245,7 @@ fn copy_apple_sanitizer_dylibs(native_dir: &Path, platform: &str, into: &Path) {
|
|||
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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -301,7 +301,7 @@ impl Step for StartupObjects {
|
|||
.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() {
|
||||
|
|
@ -309,7 +309,7 @@ impl Step for StartupObjects {
|
|||
build.cc(target),
|
||||
target,
|
||||
obj);
|
||||
copy(&src, &sysroot_dir.join(obj));
|
||||
build.copy(&src, &sysroot_dir.join(obj));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -420,7 +420,7 @@ impl Step for TestLink {
|
|||
&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,
|
||||
|
|
@ -575,7 +575,7 @@ impl Step for RustcLink {
|
|||
&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,
|
||||
|
|
@ -690,7 +690,7 @@ impl Step for CodegenBackend {
|
|||
cargo.arg("--features").arg(features),
|
||||
&tmp_stamp,
|
||||
false);
|
||||
if cfg!(test) {
|
||||
if builder.config.dry_run {
|
||||
return;
|
||||
}
|
||||
let mut files = files.into_iter()
|
||||
|
|
@ -736,6 +736,10 @@ fn copy_codegen_backends_to_sysroot(builder: &Builder,
|
|||
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();
|
||||
|
|
@ -751,7 +755,7 @@ fn copy_codegen_backends_to_sysroot(builder: &Builder,
|
|||
backend,
|
||||
&filename[dot..])
|
||||
};
|
||||
copy(&file, &dst.join(target_filename));
|
||||
build.copy(&file, &dst.join(target_filename));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -767,7 +771,7 @@ fn copy_lld_to_sysroot(builder: &Builder,
|
|||
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
|
||||
|
|
@ -936,10 +940,10 @@ impl Step for Assemble {
|
|||
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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -957,7 +961,7 @@ impl Step for Assemble {
|
|||
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
|
||||
}
|
||||
|
|
@ -967,10 +971,10 @@ impl Step for Assemble {
|
|||
///
|
||||
/// 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()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1000,6 +1004,10 @@ fn stderr_isatty() -> bool {
|
|||
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
|
||||
|
|
@ -1141,6 +1149,9 @@ pub fn stream_cargo(
|
|||
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")
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
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;
|
||||
|
|
@ -69,6 +69,7 @@ pub struct Config {
|
|||
pub jobs: Option<u32>,
|
||||
pub cmd: Subcommand,
|
||||
pub incremental: bool,
|
||||
pub dry_run: bool,
|
||||
|
||||
// llvm codegen options
|
||||
pub llvm_enabled: bool,
|
||||
|
|
@ -362,8 +363,15 @@ impl Config {
|
|||
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());
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
|
||||
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};
|
||||
|
||||
|
|
@ -28,7 +28,7 @@ use build_helper::output;
|
|||
|
||||
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;
|
||||
|
|
@ -103,7 +103,7 @@ impl Step for Docs {
|
|||
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")
|
||||
|
|
@ -118,7 +118,7 @@ impl Step for Docs {
|
|||
.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))
|
||||
}
|
||||
|
|
@ -166,7 +166,7 @@ impl Step for RustcDocs {
|
|||
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")
|
||||
|
|
@ -181,7 +181,7 @@ impl Step for RustcDocs {
|
|||
.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))
|
||||
}
|
||||
|
|
@ -292,31 +292,25 @@ fn make_win_dist(
|
|||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -417,7 +411,7 @@ impl Step for Rustc {
|
|||
// 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");
|
||||
|
|
@ -425,9 +419,9 @@ impl Step for Rustc {
|
|||
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
|
||||
|
|
@ -445,7 +439,7 @@ impl Step for Rustc {
|
|||
|
||||
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!
|
||||
|
|
@ -462,8 +456,8 @@ impl Step for Rustc {
|
|||
.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));
|
||||
|
||||
|
|
@ -475,17 +469,17 @@ impl Step for Rustc {
|
|||
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -496,7 +490,7 @@ impl Step for Rustc {
|
|||
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 {
|
||||
|
|
@ -511,7 +505,7 @@ impl Step for Rustc {
|
|||
.join("bin")
|
||||
.join(&exe);
|
||||
t!(fs::create_dir_all(&dst.parent().unwrap()));
|
||||
copy(&src, &dst);
|
||||
build.copy(&src, &dst);
|
||||
}
|
||||
|
||||
// Man pages
|
||||
|
|
@ -521,13 +515,12 @@ impl Step for Rustc {
|
|||
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)]);
|
||||
}
|
||||
|
|
@ -540,7 +533,7 @@ impl Step for Rustc {
|
|||
|
||||
// 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");
|
||||
|
|
@ -578,11 +571,11 @@ impl Step for DebuggerScripts {
|
|||
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");
|
||||
|
|
@ -592,14 +585,14 @@ impl Step for DebuggerScripts {
|
|||
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");
|
||||
|
|
@ -659,7 +652,7 @@ impl Step for Std {
|
|||
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")
|
||||
|
|
@ -678,7 +671,7 @@ impl Step for Std {
|
|||
.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))
|
||||
}
|
||||
}
|
||||
|
|
@ -738,7 +731,7 @@ impl Step for Analysis {
|
|||
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")
|
||||
|
|
@ -752,7 +745,7 @@ impl Step for Analysis {
|
|||
.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))
|
||||
}
|
||||
}
|
||||
|
|
@ -796,7 +789,7 @@ fn copy_src_dirs(build: &Build, src_dirs: &[&str], exclude_dirs: &[&str], dst_di
|
|||
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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -870,7 +863,7 @@ impl Step for Src {
|
|||
|
||||
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
|
||||
|
|
@ -887,7 +880,7 @@ impl Step for Src {
|
|||
.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))
|
||||
}
|
||||
}
|
||||
|
|
@ -943,13 +936,13 @@ impl Step for PlainSourceTarball {
|
|||
|
||||
// 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.
|
||||
|
|
@ -990,7 +983,7 @@ impl Step for PlainSourceTarball {
|
|||
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);
|
||||
|
|
@ -1004,26 +997,6 @@ impl Step for PlainSourceTarball {
|
|||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
|
|
@ -1043,11 +1016,6 @@ 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,
|
||||
|
|
@ -1084,38 +1052,38 @@ impl Step for Cargo {
|
|||
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);
|
||||
|
|
@ -1181,20 +1149,20 @@ impl Step for Rls {
|
|||
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);
|
||||
|
|
@ -1251,7 +1219,7 @@ impl Step for Rustfmt {
|
|||
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 {
|
||||
|
|
@ -1263,21 +1231,21 @@ impl Step for 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);
|
||||
|
|
@ -1355,15 +1323,15 @@ impl Step for Extended {
|
|||
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
|
||||
|
|
@ -1402,11 +1370,11 @@ impl Step for Extended {
|
|||
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();
|
||||
|
|
@ -1463,10 +1431,10 @@ impl Step for Extended {
|
|||
};
|
||||
|
||||
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");
|
||||
|
|
@ -1480,12 +1448,12 @@ impl Step for Extended {
|
|||
}
|
||||
|
||||
// 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"))
|
||||
|
|
@ -1501,7 +1469,7 @@ impl Step for Extended {
|
|||
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" {
|
||||
|
|
@ -1509,7 +1477,7 @@ impl Step for Extended {
|
|||
} 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")));
|
||||
|
|
@ -1526,10 +1494,10 @@ impl Step for Extended {
|
|||
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
|
||||
|
|
@ -1541,7 +1509,7 @@ impl Step for Extended {
|
|||
}
|
||||
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);
|
||||
|
||||
|
|
@ -1666,8 +1634,8 @@ impl Step for Extended {
|
|||
}
|
||||
|
||||
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);
|
||||
|
|
@ -1772,7 +1740,7 @@ impl Step for HashSign {
|
|||
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()));
|
||||
|
|
|
|||
|
|
@ -26,11 +26,12 @@ use std::path::{PathBuf, Path};
|
|||
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;)+) => {
|
||||
|
|
@ -210,12 +211,13 @@ impl Step for RustbookSrc {
|
|||
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")
|
||||
|
|
@ -370,7 +372,7 @@ impl Step for Standalone {
|
|||
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())
|
||||
|
|
@ -394,7 +396,7 @@ impl Step for Standalone {
|
|||
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
|
||||
}
|
||||
|
||||
|
|
@ -479,7 +481,7 @@ impl Step for Std {
|
|||
// 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);
|
||||
|
|
@ -496,7 +498,7 @@ impl Step for Std {
|
|||
}
|
||||
|
||||
build.run(&mut cargo);
|
||||
cp_r(&my_out, &out);
|
||||
build.cp_r(&my_out, &out);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -551,12 +553,12 @@ impl Step for Test {
|
|||
// 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -617,7 +619,7 @@ impl Step for WhitelistedRustc {
|
|||
// 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);
|
||||
|
|
@ -631,7 +633,7 @@ impl Step for WhitelistedRustc {
|
|||
}
|
||||
|
||||
build.run(&mut cargo);
|
||||
cp_r(&my_out, &out);
|
||||
build.cp_r(&my_out, &out);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -693,7 +695,7 @@ impl Step for Rustc {
|
|||
// 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);
|
||||
|
|
@ -806,8 +808,8 @@ impl Step for UnstableBookGen {
|
|||
|
||||
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);
|
||||
|
|
@ -816,7 +818,10 @@ impl Step for UnstableBookGen {
|
|||
}
|
||||
}
|
||||
|
||||
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));
|
||||
|
|
@ -829,5 +834,5 @@ fn symlink_dir_force(src: &Path, dst: &Path) -> io::Result<()> {
|
|||
}
|
||||
}
|
||||
|
||||
symlink_dir(src, dst)
|
||||
symlink_dir(config, src, dst)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@
|
|||
//! 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;
|
||||
|
|
@ -42,6 +41,7 @@ pub struct Flags {
|
|||
pub incremental: bool,
|
||||
pub exclude: Vec<PathBuf>,
|
||||
pub rustc_error_format: Option<String>,
|
||||
pub dry_run: bool,
|
||||
}
|
||||
|
||||
pub enum Subcommand {
|
||||
|
|
@ -112,6 +112,7 @@ To learn more about a subcommand, run `./x.py <subcommand> -h`");
|
|||
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");
|
||||
|
|
@ -365,6 +366,7 @@ Arguments:
|
|||
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()),
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@
|
|||
//! 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]
|
||||
|
|
@ -143,13 +143,15 @@ extern crate libc;
|
|||
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};
|
||||
|
||||
|
|
@ -404,13 +406,36 @@ impl Build {
|
|||
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();
|
||||
|
|
@ -997,8 +1022,168 @@ impl Build {
|
|||
}
|
||||
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 {
|
||||
self.stage = stage;
|
||||
|
|
|
|||
|
|
@ -60,9 +60,6 @@ impl Step for Llvm {
|
|||
|
||||
/// 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;
|
||||
|
|
@ -220,6 +217,11 @@ impl Step for Llvm {
|
|||
// 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()));
|
||||
|
|
@ -339,7 +341,7 @@ impl Step for Lld {
|
|||
|
||||
/// 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;
|
||||
|
|
@ -395,7 +397,7 @@ impl Step for TestHelpers {
|
|||
/// 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;
|
||||
|
|
@ -450,7 +452,7 @@ impl Step for Openssl {
|
|||
}
|
||||
|
||||
fn run(self, builder: &Builder) {
|
||||
if cfg!(test) {
|
||||
if builder.config.dry_run {
|
||||
return;
|
||||
}
|
||||
let build = builder.build;
|
||||
|
|
|
|||
|
|
@ -1042,6 +1042,7 @@ impl Step for DocTest {
|
|||
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()));
|
||||
|
|
@ -1058,7 +1059,13 @@ impl Step for DocTest {
|
|||
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
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ use std::slice::SliceConcatExt;
|
|||
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;
|
||||
|
|
@ -207,7 +207,7 @@ impl Step for ToolBuild {
|
|||
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)
|
||||
}
|
||||
}
|
||||
|
|
@ -443,7 +443,7 @@ impl Step for Rustdoc {
|
|||
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
|
||||
|
|
|
|||
|
|
@ -15,13 +15,13 @@
|
|||
|
||||
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 {
|
||||
|
|
@ -32,102 +32,6 @@ 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 {
|
||||
|
|
@ -214,8 +118,8 @@ impl Drop for TimeIt {
|
|||
|
||||
/// 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);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue