Auto merge of #48913 - Mark-Simulacrum:rustbuild-test, r=alexcrichton

Add tests to rustbuild

In order to run tests, we cfg out various parts of rustbuild. Generally
speaking, these are filesystem and process-spawning operations. Then, rustbuild
is run "as normal" and the various steps that where run are retrieved from the
cache and checked against the expected results.

Note that this means that the current implementation primarily tests "what" we
build, but doesn't actually test that what we build *will* build. In other
words, it doesn't do any form of dependency verification for any crate. This is
possible to implement, but is considered future work.

This implementation strives to cfg out as little code as possible; it also does
not currently test anywhere near all of rustbuild. The current tests are also
not checked for "correctness," rather, they simply represent what we do as of
this commit, which may be wrong.

Test cases are drawn from the old implementation of rustbuild, though the
expected results may vary.

r? @alexcrichton
This commit is contained in:
bors
2018-04-04 15:38:10 +00:00
17 changed files with 1211 additions and 470 deletions
+40
View File
@@ -124,6 +124,8 @@ dependencies = [
"lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"petgraph 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
"pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -528,6 +530,11 @@ name = "diff"
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "difference"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "dlmalloc"
version = "0.0.0"
@@ -635,6 +642,11 @@ version = "0.1.0"
name = "find_impls"
version = "0.1.0"
[[package]]
name = "fixedbitset"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "flate2"
version = "1.0.1"
@@ -1162,6 +1174,11 @@ dependencies = [
"vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "ordermap"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "owning_ref"
version = "0.3.3"
@@ -1228,11 +1245,29 @@ dependencies = [
"syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "petgraph"
version = "0.4.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"fixedbitset 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
"ordermap 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "pkg-config"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "pretty_assertions"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "proc-macro2"
version = "0.2.3"
@@ -2683,6 +2718,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum curl-sys 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f46e49c7125131f5afaded06944d6888b55cbdf8eba05dae73c954019b907961"
"checksum derive-new 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6fcb923bab47a948f1b01cec2f758fdebba95c9ebc255458654b2b88efe59d71"
"checksum diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3c2b69f912779fbb121ceb775d74d51e915af17aaebc38d28a592843a2dd0a3a"
"checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198"
"checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab"
"checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0"
"checksum ena 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f8b449f3b18c89d2dbe40548d2ee4fa58ea0a08b761992da6ecb9788e4688834"
@@ -2693,6 +2729,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "934799b6c1de475a012a02dab0ace1ace43789ee4b99bcfbf1a2e3e8ced5de82"
"checksum failure_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c7cdda555bb90c9bb67a3b670a0f42de8e73f5981524123ad8578aafec8ddb8b"
"checksum filetime 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "714653f3e34871534de23771ac7b26e999651a0a228f47beb324dfdf1dd4b10f"
"checksum fixedbitset 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "86d4de0081402f5e88cdac65c8dcdcc73118c1a7a465e2a05f0da05843a8ea33"
"checksum flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9fac2277e84e5e858483756647a9d0aa8d9a2b7cba517fd84325a0aaa69a0909"
"checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3"
"checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
@@ -2748,13 +2785,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum openssl 0.10.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1636c9f1d78af9cbcc50e523bfff4a30274108aad5e86761afd4d31e4e184fa7"
"checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de"
"checksum openssl-sys 0.9.27 (registry+https://github.com/rust-lang/crates.io-index)" = "d6fdc5c4a02e69ce65046f1763a0181107038e02176233acb0b3351d7cc588f9"
"checksum ordermap 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a86ed3f5f244b372d6b1a00b72ef7f8876d0bc6a78a4c9985c53614041512063"
"checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37"
"checksum parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "9fd9d732f2de194336fb02fe11f9eed13d9e76f13f4315b4d88a14ca411750cd"
"checksum parking_lot_core 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "538ef00b7317875071d5e00f603f24d16f0b474c1a5fc0ccb8b454ca72eafa79"
"checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831"
"checksum pest 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0fce5d8b5cc33983fc74f78ad552b5522ab41442c4ca91606e4236eb4b5ceefc"
"checksum pest_derive 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "ab94faafeb93f4c5e3ce81ca0e5a779529a602ad5d09ae6d21996bfb8b6a52bf"
"checksum petgraph 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "8b30dc85588cd02b9b76f5e386535db546d21dc68506cff2abebee0b6445e8e4"
"checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903"
"checksum pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3a029430f0d744bc3d15dd474d591bed2402b645d024583082b9f63bb936dac6"
"checksum proc-macro2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cd07deb3c6d1d9ff827999c7f9b04cdfd66b1b17ae508e14fe47b620f2282ae0"
"checksum proc-macro2 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "388d7ea47318c5ccdeb9ba6312cee7d3f65dd2804be8580a170fce410d50b786"
"checksum pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d6fdf85cda6cadfae5428a54661d431330b312bc767ddbc57adbedc24da66e32"
+4
View File
@@ -42,3 +42,7 @@ serde_json = "1.0.2"
toml = "0.4"
lazy_static = "0.2"
time = "0.1"
petgraph = "0.4.12"
[dev-dependencies]
pretty_assertions = "0.5"
+4 -1
View File
@@ -314,7 +314,7 @@ class RustBuild(object):
self.build_dir = os.path.join(os.getcwd(), "build")
self.clean = False
self.config_toml = ''
self.rust_root = os.path.abspath(os.path.join(__file__, '../../..'))
self.rust_root = ''
self.use_locked_deps = ''
self.use_vendored_sources = ''
self.verbose = False
@@ -710,6 +710,7 @@ def bootstrap(help_triggered):
parser = argparse.ArgumentParser(description='Build rust')
parser.add_argument('--config')
parser.add_argument('--build')
parser.add_argument('--src')
parser.add_argument('--clean', action='store_true')
parser.add_argument('-v', '--verbose', action='count', default=0)
@@ -718,6 +719,7 @@ def bootstrap(help_triggered):
# Configure initial bootstrap
build = RustBuild()
build.rust_root = args.src or os.path.abspath(os.path.join(__file__, '../../..'))
build.verbose = args.verbose
build.clean = args.clean
@@ -788,6 +790,7 @@ def bootstrap(help_triggered):
env["SRC"] = build.rust_root
env["BOOTSTRAP_PARENT_ID"] = str(os.getpid())
env["BOOTSTRAP_PYTHON"] = sys.executable
env["BUILD_DIR"] = build.build_dir
run(args, env=env, verbose=build.verbose)
+536 -10
View File
@@ -19,6 +19,7 @@ use std::ops::Deref;
use std::path::{Path, PathBuf};
use std::process::Command;
use std::time::{Instant, Duration};
use std::collections::HashMap;
use compile;
use install;
@@ -35,6 +36,9 @@ use native;
pub use Compiler;
use petgraph::Graph;
use petgraph::graph::NodeIndex;
pub struct Builder<'a> {
pub build: &'a Build,
pub top_stage: u32,
@@ -42,6 +46,10 @@ pub struct Builder<'a> {
cache: Cache,
stack: RefCell<Vec<Box<Any>>>,
time_spent_on_dependencies: Cell<Duration>,
pub paths: Vec<PathBuf>,
graph_nodes: RefCell<HashMap<String, NodeIndex>>,
graph: RefCell<Graph<String, bool>>,
parent: Cell<Option<NodeIndex>>,
}
impl<'a> Deref for Builder<'a> {
@@ -351,6 +359,10 @@ impl<'a> Builder<'a> {
cache: Cache::new(),
stack: RefCell::new(Vec::new()),
time_spent_on_dependencies: Cell::new(Duration::new(0, 0)),
paths: vec![],
graph_nodes: RefCell::new(HashMap::new()),
graph: RefCell::new(Graph::new()),
parent: Cell::new(None),
};
let builder = &builder;
@@ -367,7 +379,7 @@ impl<'a> Builder<'a> {
Some(help)
}
pub fn run(build: &Build) {
pub fn new(build: &Build) -> Builder {
let (kind, paths) = match build.config.cmd {
Subcommand::Build { ref paths } => (Kind::Build, &paths[..]),
Subcommand::Check { ref paths } => (Kind::Check, &paths[..]),
@@ -379,12 +391,6 @@ impl<'a> Builder<'a> {
Subcommand::Clean { .. } => panic!(),
};
if let Some(path) = paths.get(0) {
if path == Path::new("nonexistent/path/to/trigger/cargo/metadata") {
return;
}
}
let builder = Builder {
build,
top_stage: build.config.stage.unwrap_or(2),
@@ -392,20 +398,33 @@ impl<'a> Builder<'a> {
cache: Cache::new(),
stack: RefCell::new(Vec::new()),
time_spent_on_dependencies: Cell::new(Duration::new(0, 0)),
paths: paths.to_owned(),
graph_nodes: RefCell::new(HashMap::new()),
graph: RefCell::new(Graph::new()),
parent: Cell::new(None),
};
if kind == Kind::Dist {
assert!(!build.config.test_miri, "Do not distribute with miri enabled.\n\
assert!(!builder.config.test_miri, "Do not distribute with miri enabled.\n\
The distributed libraries would include all MIR (increasing binary size).
The distributed MIR would include validation statements.");
}
StepDescription::run(&Builder::get_step_descriptions(builder.kind), &builder, paths);
builder
}
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]>) {
let paths = paths.unwrap_or(&[]);
StepDescription::run(&Builder::get_step_descriptions(Kind::Doc), self, paths);
self.run_step_descriptions(&Builder::get_step_descriptions(Kind::Doc), paths);
}
fn run_step_descriptions(&self, v: &[StepDescription], paths: &[PathBuf]) {
StepDescription::run(v, self, paths);
}
/// Obtain a compiler at a given stage and for a given host. Explicitly does
@@ -828,12 +847,37 @@ impl<'a> Builder<'a> {
if let Some(out) = self.cache.get(&step) {
self.build.verbose(&format!("{}c {:?}", " ".repeat(stack.len()), step));
{
let mut graph = self.graph.borrow_mut();
let parent = self.parent.get();
let us = *self.graph_nodes.borrow_mut()
.entry(format!("{:?}", step))
.or_insert_with(|| graph.add_node(format!("{:?}", step)));
if let Some(parent) = parent {
graph.add_edge(parent, us, false);
}
}
return out;
}
self.build.verbose(&format!("{}> {:?}", " ".repeat(stack.len()), step));
stack.push(Box::new(step.clone()));
}
let prev_parent = self.parent.get();
{
let mut graph = self.graph.borrow_mut();
let parent = self.parent.get();
let us = *self.graph_nodes.borrow_mut()
.entry(format!("{:?}", step))
.or_insert_with(|| graph.add_node(format!("{:?}", step)));
self.parent.set(Some(us));
if let Some(parent) = parent {
graph.add_edge(parent, us, true);
}
}
let (out, dur) = {
let start = Instant::now();
let zero = Duration::new(0, 0);
@@ -844,6 +888,8 @@ impl<'a> Builder<'a> {
(out, dur - deps)
};
self.parent.set(prev_parent);
if self.build.config.print_step_timings && dur > Duration::from_millis(100) {
println!("[TIMING] {:?} -- {}.{:03}",
step,
@@ -861,3 +907,483 @@ impl<'a> Builder<'a> {
out
}
}
#[cfg(test)]
mod __test {
use config::Config;
use std::thread;
use super::*;
fn configure(host: &[&str], target: &[&str]) -> Config {
let mut config = Config::default_opts();
// 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<_>>();
config.targets = config.hosts.clone().into_iter()
.chain(target.iter().map(|s| INTERNER.intern_str(s))).collect::<Vec<_>>();
config
}
fn first<A, B>(v: Vec<(A, B)>) -> Vec<A> {
v.into_iter().map(|(a, _)| a).collect::<Vec<_>>()
}
#[test]
fn dist_baseline() {
let build = Build::new(configure(&[], &[]));
let mut builder = Builder::new(&build);
builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]);
let a = INTERNER.intern_str("A");
assert_eq!(first(builder.cache.all::<dist::Docs>()), &[
dist::Docs { stage: 2, host: a },
]);
assert_eq!(first(builder.cache.all::<dist::Mingw>()), &[
dist::Mingw { host: a },
]);
assert_eq!(first(builder.cache.all::<dist::Rustc>()), &[
dist::Rustc { compiler: Compiler { host: a, stage: 2 } },
]);
assert_eq!(first(builder.cache.all::<dist::Std>()), &[
dist::Std {
compiler: Compiler { host: a, stage: 2 },
target: a,
},
]);
assert_eq!(first(builder.cache.all::<dist::Src>()), &[dist::Src]);
}
#[test]
fn dist_with_targets() {
let build = Build::new(configure(&[], &["B"]));
let mut builder = Builder::new(&build);
builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]);
let a = INTERNER.intern_str("A");
let b = INTERNER.intern_str("B");
assert_eq!(first(builder.cache.all::<dist::Docs>()), &[
dist::Docs { stage: 2, host: a },
dist::Docs { stage: 2, host: b },
]);
assert_eq!(first(builder.cache.all::<dist::Mingw>()), &[
dist::Mingw { host: a },
dist::Mingw { host: b },
]);
assert_eq!(first(builder.cache.all::<dist::Rustc>()), &[
dist::Rustc { compiler: Compiler { host: a, stage: 2 } },
]);
assert_eq!(first(builder.cache.all::<dist::Std>()), &[
dist::Std {
compiler: Compiler { host: a, stage: 2 },
target: a,
},
dist::Std {
compiler: Compiler { host: a, stage: 2 },
target: b,
},
]);
assert_eq!(first(builder.cache.all::<dist::Src>()), &[dist::Src]);
}
#[test]
fn dist_with_hosts() {
let build = Build::new(configure(&["B"], &[]));
let mut builder = Builder::new(&build);
builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]);
let a = INTERNER.intern_str("A");
let b = INTERNER.intern_str("B");
assert_eq!(first(builder.cache.all::<dist::Docs>()), &[
dist::Docs { stage: 2, host: a },
dist::Docs { stage: 2, host: b },
]);
assert_eq!(first(builder.cache.all::<dist::Mingw>()), &[
dist::Mingw { host: a },
dist::Mingw { host: b },
]);
assert_eq!(first(builder.cache.all::<dist::Rustc>()), &[
dist::Rustc { compiler: Compiler { host: a, stage: 2 } },
dist::Rustc { compiler: Compiler { host: b, stage: 2 } },
]);
assert_eq!(first(builder.cache.all::<dist::Std>()), &[
dist::Std {
compiler: Compiler { host: a, stage: 2 },
target: a,
},
dist::Std {
compiler: Compiler { host: a, stage: 2 },
target: b,
},
]);
assert_eq!(first(builder.cache.all::<dist::Src>()), &[dist::Src]);
}
#[test]
fn dist_with_targets_and_hosts() {
let build = Build::new(configure(&["B"], &["C"]));
let mut builder = Builder::new(&build);
builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]);
let a = INTERNER.intern_str("A");
let b = INTERNER.intern_str("B");
let c = INTERNER.intern_str("C");
assert_eq!(first(builder.cache.all::<dist::Docs>()), &[
dist::Docs { stage: 2, host: a },
dist::Docs { stage: 2, host: b },
dist::Docs { stage: 2, host: c },
]);
assert_eq!(first(builder.cache.all::<dist::Mingw>()), &[
dist::Mingw { host: a },
dist::Mingw { host: b },
dist::Mingw { host: c },
]);
assert_eq!(first(builder.cache.all::<dist::Rustc>()), &[
dist::Rustc { compiler: Compiler { host: a, stage: 2 } },
dist::Rustc { compiler: Compiler { host: b, stage: 2 } },
]);
assert_eq!(first(builder.cache.all::<dist::Std>()), &[
dist::Std {
compiler: Compiler { host: a, stage: 2 },
target: a,
},
dist::Std {
compiler: Compiler { host: a, stage: 2 },
target: b,
},
dist::Std {
compiler: Compiler { host: a, stage: 2 },
target: c,
},
]);
assert_eq!(first(builder.cache.all::<dist::Src>()), &[dist::Src]);
}
#[test]
fn dist_with_target_flag() {
let mut config = configure(&["B"], &["C"]);
config.run_host_only = false; // as-if --target=C was passed
let build = Build::new(config);
let mut builder = Builder::new(&build);
builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]);
let a = INTERNER.intern_str("A");
let b = INTERNER.intern_str("B");
let c = INTERNER.intern_str("C");
assert_eq!(first(builder.cache.all::<dist::Docs>()), &[
dist::Docs { stage: 2, host: a },
dist::Docs { stage: 2, host: b },
dist::Docs { stage: 2, host: c },
]);
assert_eq!(first(builder.cache.all::<dist::Mingw>()), &[
dist::Mingw { host: a },
dist::Mingw { host: b },
dist::Mingw { host: c },
]);
assert_eq!(first(builder.cache.all::<dist::Rustc>()), &[]);
assert_eq!(first(builder.cache.all::<dist::Std>()), &[
dist::Std {
compiler: Compiler { host: a, stage: 2 },
target: a,
},
dist::Std {
compiler: Compiler { host: a, stage: 2 },
target: b,
},
dist::Std {
compiler: Compiler { host: a, stage: 2 },
target: c,
},
]);
assert_eq!(first(builder.cache.all::<dist::Src>()), &[]);
}
#[test]
fn dist_with_same_targets_and_hosts() {
let build = Build::new(configure(&["B"], &["B"]));
let mut builder = Builder::new(&build);
builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]);
let a = INTERNER.intern_str("A");
let b = INTERNER.intern_str("B");
assert_eq!(first(builder.cache.all::<dist::Docs>()), &[
dist::Docs { stage: 2, host: a },
dist::Docs { stage: 2, host: b },
]);
assert_eq!(first(builder.cache.all::<dist::Mingw>()), &[
dist::Mingw { host: a },
dist::Mingw { host: b },
]);
assert_eq!(first(builder.cache.all::<dist::Rustc>()), &[
dist::Rustc { compiler: Compiler { host: a, stage: 2 } },
dist::Rustc { compiler: Compiler { host: b, stage: 2 } },
]);
assert_eq!(first(builder.cache.all::<dist::Std>()), &[
dist::Std {
compiler: Compiler { host: a, stage: 2 },
target: a,
},
dist::Std {
compiler: Compiler { host: a, stage: 2 },
target: b,
},
]);
assert_eq!(first(builder.cache.all::<dist::Src>()), &[dist::Src]);
assert_eq!(first(builder.cache.all::<compile::Std>()), &[
compile::Std {
compiler: Compiler { host: a, stage: 0 },
target: a,
},
compile::Std {
compiler: Compiler { host: a, stage: 1 },
target: a,
},
compile::Std {
compiler: Compiler { host: a, stage: 2 },
target: a,
},
compile::Std {
compiler: Compiler { host: a, stage: 1 },
target: b,
},
compile::Std {
compiler: Compiler { host: a, stage: 2 },
target: b,
},
]);
assert_eq!(first(builder.cache.all::<compile::Test>()), &[
compile::Test {
compiler: Compiler { host: a, stage: 0 },
target: a,
},
compile::Test {
compiler: Compiler { host: a, stage: 1 },
target: a,
},
compile::Test {
compiler: Compiler { host: a, stage: 2 },
target: a,
},
compile::Test {
compiler: Compiler { host: a, stage: 1 },
target: b,
},
compile::Test {
compiler: Compiler { host: a, stage: 2 },
target: b,
},
]);
assert_eq!(first(builder.cache.all::<compile::Assemble>()), &[
compile::Assemble {
target_compiler: Compiler { host: a, stage: 0 },
},
compile::Assemble {
target_compiler: Compiler { host: a, stage: 1 },
},
compile::Assemble {
target_compiler: Compiler { host: a, stage: 2 },
},
compile::Assemble {
target_compiler: Compiler { host: b, stage: 2 },
},
]);
}
#[test]
fn build_default() {
let build = Build::new(configure(&["B"], &["C"]));
let mut builder = Builder::new(&build);
builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Build), &[]);
let a = INTERNER.intern_str("A");
let b = INTERNER.intern_str("B");
let c = INTERNER.intern_str("C");
assert!(!builder.cache.all::<compile::Std>().is_empty());
assert!(!builder.cache.all::<compile::Assemble>().is_empty());
assert_eq!(first(builder.cache.all::<compile::Rustc>()), &[
compile::Rustc {
compiler: Compiler { host: a, stage: 0 },
target: a,
},
compile::Rustc {
compiler: Compiler { host: a, stage: 1 },
target: a,
},
compile::Rustc {
compiler: Compiler { host: a, stage: 2 },
target: a,
},
compile::Rustc {
compiler: Compiler { host: b, stage: 2 },
target: a,
},
compile::Rustc {
compiler: Compiler { host: a, stage: 0 },
target: b,
},
compile::Rustc {
compiler: Compiler { host: a, stage: 1 },
target: b,
},
compile::Rustc {
compiler: Compiler { host: a, stage: 2 },
target: b,
},
compile::Rustc {
compiler: Compiler { host: b, stage: 2 },
target: b,
},
]);
assert_eq!(first(builder.cache.all::<compile::Test>()), &[
compile::Test {
compiler: Compiler { host: a, stage: 0 },
target: a,
},
compile::Test {
compiler: Compiler { host: a, stage: 1 },
target: a,
},
compile::Test {
compiler: Compiler { host: a, stage: 2 },
target: a,
},
compile::Test {
compiler: Compiler { host: b, stage: 2 },
target: a,
},
compile::Test {
compiler: Compiler { host: a, stage: 0 },
target: b,
},
compile::Test {
compiler: Compiler { host: a, stage: 1 },
target: b,
},
compile::Test {
compiler: Compiler { host: a, stage: 2 },
target: b,
},
compile::Test {
compiler: Compiler { host: b, stage: 2 },
target: b,
},
compile::Test {
compiler: Compiler { host: a, stage: 2 },
target: c,
},
compile::Test {
compiler: Compiler { host: b, stage: 2 },
target: c,
},
]);
}
#[test]
fn build_with_target_flag() {
let mut config = configure(&["B"], &["C"]);
config.run_host_only = false;
let build = Build::new(config);
let mut builder = Builder::new(&build);
builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Build), &[]);
let a = INTERNER.intern_str("A");
let b = INTERNER.intern_str("B");
let c = INTERNER.intern_str("C");
assert!(!builder.cache.all::<compile::Std>().is_empty());
assert_eq!(first(builder.cache.all::<compile::Assemble>()), &[
compile::Assemble {
target_compiler: Compiler { host: a, stage: 0 },
},
compile::Assemble {
target_compiler: Compiler { host: a, stage: 1 },
},
compile::Assemble {
target_compiler: Compiler { host: b, stage: 1 },
},
compile::Assemble {
target_compiler: Compiler { host: a, stage: 2 },
},
compile::Assemble {
target_compiler: Compiler { host: b, stage: 2 },
},
]);
assert_eq!(first(builder.cache.all::<compile::Rustc>()), &[
compile::Rustc {
compiler: Compiler { host: a, stage: 0 },
target: a,
},
compile::Rustc {
compiler: Compiler { host: a, stage: 1 },
target: a,
},
compile::Rustc {
compiler: Compiler { host: a, stage: 0 },
target: b,
},
compile::Rustc {
compiler: Compiler { host: a, stage: 1 },
target: b,
},
]);
assert_eq!(first(builder.cache.all::<compile::Test>()), &[
compile::Test {
compiler: Compiler { host: a, stage: 0 },
target: a,
},
compile::Test {
compiler: Compiler { host: a, stage: 1 },
target: a,
},
compile::Test {
compiler: Compiler { host: a, stage: 2 },
target: a,
},
compile::Test {
compiler: Compiler { host: b, stage: 2 },
target: a,
},
compile::Test {
compiler: Compiler { host: a, stage: 0 },
target: b,
},
compile::Test {
compiler: Compiler { host: a, stage: 1 },
target: b,
},
compile::Test {
compiler: Compiler { host: a, stage: 2 },
target: b,
},
compile::Test {
compiler: Compiler { host: b, stage: 2 },
target: b,
},
compile::Test {
compiler: Compiler { host: a, stage: 2 },
target: c,
},
compile::Test {
compiler: Compiler { host: b, stage: 2 },
target: c,
},
]);
}
}
+26
View File
@@ -21,6 +21,7 @@ use std::mem;
use std::ops::Deref;
use std::path::{Path, PathBuf};
use std::sync::Mutex;
use std::cmp::{PartialOrd, Ord, Ordering};
use builder::Step;
@@ -154,6 +155,19 @@ impl AsRef<OsStr> for Interned<String> {
}
}
impl PartialOrd<Interned<String>> for Interned<String> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
let l = INTERNER.strs.lock().unwrap();
l.get(*self).partial_cmp(l.get(*other))
}
}
impl Ord for Interned<String> {
fn cmp(&self, other: &Self) -> Ordering {
let l = INTERNER.strs.lock().unwrap();
l.get(*self).cmp(l.get(*other))
}
}
struct TyIntern<T> {
items: Vec<T>,
@@ -264,4 +278,16 @@ impl Cache {
.expect("invalid type mapped");
stepcache.get(step).cloned()
}
#[cfg(test)]
pub fn all<S: Ord + Copy + Step>(&mut self) -> Vec<(S, S::Output)> {
let cache = self.0.get_mut();
let type_id = TypeId::of::<S>();
let mut v = cache.remove(&type_id)
.map(|b| b.downcast::<HashMap<S, S::Output>>().expect("correct type"))
.map(|m| m.into_iter().collect::<Vec<_>>())
.unwrap_or_default();
v.sort_by_key(|&(a, _)| a);
v
}
}
+3 -3
View File
@@ -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));
}
}
+57 -43
View File
@@ -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;
@@ -38,7 +38,7 @@ use tool;
use cache::{INTERNER, Interned};
use builder::{Step, RunConfig, ShouldRun, Builder};
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[derive(Debug, PartialOrd, Ord, Copy, Clone, PartialEq, Eq, Hash)]
pub struct Std {
pub target: Interned<String>,
pub compiler: Compiler,
@@ -77,7 +77,7 @@ impl Step for Std {
compiler: from,
target,
});
println!("Uplifting stage1 std ({} -> {})", from.host, target);
builder.info(&format!("Uplifting stage1 std ({} -> {})", from.host, target));
// Even if we're not building std this stage, the new sysroot must
// still contain the musl startup objects.
@@ -105,8 +105,8 @@ impl Step for Std {
std_cargo(builder, &compiler, target, &mut cargo);
let _folder = build.fold_output(|| format!("stage{}-std", compiler.stage));
println!("Building stage{} std artifacts ({} -> {})", compiler.stage,
&compiler.host, target);
build.info(&format!("Building stage{} std artifacts ({} -> {})", compiler.stage,
&compiler.host, target));
run_cargo(build,
&mut cargo,
&libstd_stamp(build, compiler, target),
@@ -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));
}
}
@@ -213,20 +213,20 @@ impl Step for StdLink {
let compiler = self.compiler;
let target_compiler = self.target_compiler;
let target = self.target;
println!("Copying stage{} std from stage{} ({} -> {} / {})",
build.info(&format!("Copying stage{} std from stage{} ({} -> {} / {})",
target_compiler.stage,
compiler.stage,
&compiler.host,
target_compiler.host,
target);
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,15 +309,15 @@ impl Step for StartupObjects {
build.cc(target),
target,
obj);
copy(&src, &sysroot_dir.join(obj));
build.copy(&src, &sysroot_dir.join(obj));
}
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[derive(Debug, PartialOrd, Ord, Copy, Clone, PartialEq, Eq, Hash)]
pub struct Test {
pub compiler: Compiler,
pub target: Interned<String>,
pub compiler: Compiler,
}
impl Step for Test {
@@ -352,7 +352,7 @@ impl Step for Test {
compiler: builder.compiler(1, build.build),
target,
});
println!("Uplifting stage1 test ({} -> {})", &build.build, target);
build.info(&format!("Uplifting stage1 test ({} -> {})", &build.build, target));
builder.ensure(TestLink {
compiler: builder.compiler(1, build.build),
target_compiler: compiler,
@@ -367,8 +367,8 @@ impl Step for Test {
test_cargo(build, &compiler, target, &mut cargo);
let _folder = build.fold_output(|| format!("stage{}-test", compiler.stage));
println!("Building stage{} test artifacts ({} -> {})", compiler.stage,
&compiler.host, target);
build.info(&format!("Building stage{} test artifacts ({} -> {})", compiler.stage,
&compiler.host, target));
run_cargo(build,
&mut cargo,
&libtest_stamp(build, compiler, target),
@@ -414,13 +414,13 @@ impl Step for TestLink {
let compiler = self.compiler;
let target_compiler = self.target_compiler;
let target = self.target;
println!("Copying stage{} test from stage{} ({} -> {} / {})",
build.info(&format!("Copying stage{} test from stage{} ({} -> {} / {})",
target_compiler.stage,
compiler.stage,
&compiler.host,
target_compiler.host,
target);
add_to_sysroot(&builder.sysroot_libdir(target_compiler, target),
target));
add_to_sysroot(&build, &builder.sysroot_libdir(target_compiler, target),
&libtest_stamp(build, compiler, target));
builder.ensure(tool::CleanTools {
compiler: target_compiler,
@@ -430,10 +430,10 @@ impl Step for TestLink {
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[derive(Debug, PartialOrd, Ord, Copy, Clone, PartialEq, Eq, Hash)]
pub struct Rustc {
pub compiler: Compiler,
pub target: Interned<String>,
pub compiler: Compiler,
}
impl Step for Rustc {
@@ -469,7 +469,7 @@ impl Step for Rustc {
compiler: builder.compiler(1, build.build),
target,
});
println!("Uplifting stage1 rustc ({} -> {})", &build.build, target);
build.info(&format!("Uplifting stage1 rustc ({} -> {})", &build.build, target));
builder.ensure(RustcLink {
compiler: builder.compiler(1, build.build),
target_compiler: compiler,
@@ -491,8 +491,8 @@ impl Step for Rustc {
rustc_cargo(build, &mut cargo);
let _folder = build.fold_output(|| format!("stage{}-rustc", compiler.stage));
println!("Building stage{} compiler artifacts ({} -> {})",
compiler.stage, &compiler.host, target);
build.info(&format!("Building stage{} compiler artifacts ({} -> {})",
compiler.stage, &compiler.host, target));
run_cargo(build,
&mut cargo,
&librustc_stamp(build, compiler, target),
@@ -569,13 +569,13 @@ impl Step for RustcLink {
let compiler = self.compiler;
let target_compiler = self.target_compiler;
let target = self.target;
println!("Copying stage{} rustc from stage{} ({} -> {} / {})",
build.info(&format!("Copying stage{} rustc from stage{} ({} -> {} / {})",
target_compiler.stage,
compiler.stage,
&compiler.host,
target_compiler.host,
target);
add_to_sysroot(&builder.sysroot_libdir(target_compiler, target),
target));
add_to_sysroot(&build, &builder.sysroot_libdir(target_compiler, target),
&librustc_stamp(build, compiler, target));
builder.ensure(tool::CleanTools {
compiler: target_compiler,
@@ -648,8 +648,8 @@ impl Step for CodegenBackend {
features.push_str(" emscripten");
}
println!("Building stage{} codegen artifacts ({} -> {}, {})",
compiler.stage, &compiler.host, target, self.backend);
build.info(&format!("Building stage{} codegen artifacts ({} -> {}, {})",
compiler.stage, &compiler.host, target, self.backend));
// Pass down configuration from the LLVM build into the build of
// librustc_llvm and librustc_trans.
@@ -690,6 +690,9 @@ impl Step for CodegenBackend {
cargo.arg("--features").arg(features),
&tmp_stamp,
false);
if builder.config.dry_run {
return;
}
let mut files = files.into_iter()
.filter(|f| {
let filename = f.file_name().unwrap().to_str().unwrap();
@@ -733,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();
@@ -748,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));
}
}
@@ -764,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
@@ -836,7 +843,7 @@ impl Step for Sysroot {
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[derive(Debug, Copy, PartialOrd, Ord, Clone, PartialEq, Eq, Hash)]
pub struct Assemble {
/// The compiler which we will produce in this step. Assemble itself will
/// take care of ensuring that the necessary prerequisites to do so exist,
@@ -926,17 +933,17 @@ impl Step for Assemble {
let stage = target_compiler.stage;
let host = target_compiler.host;
println!("Assembling stage{} compiler ({})", stage, host);
build.info(&format!("Assembling stage{} compiler ({})", stage, host));
// Link in all dylibs to the libdir
let sysroot = builder.sysroot(target_compiler);
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));
}
}
@@ -954,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
}
@@ -964,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()));
}
}
@@ -997,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
@@ -1138,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")
@@ -1172,7 +1186,7 @@ pub fn stream_cargo(
// Make sure Cargo actually succeeded after we read all of its stdout.
let status = t!(child.wait());
if !status.success() {
println!("command did not execute successfully: {:?}\n\
eprintln!("command did not execute successfully: {:?}\n\
expected success, got: {}",
cargo,
status);
+35 -28
View File
@@ -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,
@@ -143,6 +144,7 @@ pub struct Config {
// These are either the stage0 downloaded binaries or the locally installed ones.
pub initial_cargo: PathBuf,
pub initial_rustc: PathBuf,
pub out: PathBuf,
}
/// Per-target configuration stored in the global configuration structure.
@@ -317,11 +319,8 @@ struct TomlTarget {
}
impl Config {
pub fn parse(args: &[String]) -> Config {
let flags = Flags::parse(&args);
let file = flags.config.clone();
pub fn default_opts() -> Config {
let mut config = Config::default();
config.exclude = flags.exclude;
config.llvm_enabled = true;
config.llvm_optimize = true;
config.llvm_version_check = true;
@@ -341,15 +340,38 @@ impl Config {
config.rust_codegen_backends = vec![INTERNER.intern_str("llvm")];
config.rust_codegen_backends_dir = "codegen-backends".to_owned();
// set by bootstrap.py
config.src = env::var_os("SRC").map(PathBuf::from).expect("'SRC' to be set");
config.build = INTERNER.intern_str(&env::var("BUILD").expect("'BUILD' to be set"));
config.out = env::var_os("BUILD_DIR").map(PathBuf::from).expect("'BUILD_DIR' set");
let stage0_root = config.out.join(&config.build).join("stage0/bin");
config.initial_rustc = stage0_root.join(exe("rustc", &config.build));
config.initial_cargo = stage0_root.join(exe("cargo", &config.build));
config
}
pub fn parse(args: &[String]) -> Config {
let flags = Flags::parse(&args);
let file = flags.config.clone();
let mut config = Config::default_opts();
config.exclude = flags.exclude;
config.rustc_error_format = flags.rustc_error_format;
config.on_fail = flags.on_fail;
config.stage = flags.stage;
config.src = flags.src;
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());
@@ -368,12 +390,7 @@ impl Config {
}).unwrap_or_else(|| TomlConfig::default());
let build = toml.build.clone().unwrap_or(Build::default());
set(&mut config.build, build.build.clone().map(|x| INTERNER.intern_string(x)));
set(&mut config.build, flags.build);
if config.build.is_empty() {
// set by bootstrap.py
config.build = INTERNER.intern_str(&env::var("BUILD").unwrap());
}
// set by bootstrap.py
config.hosts.push(config.build.clone());
for host in build.host.iter() {
let host = INTERNER.intern_str(host);
@@ -514,13 +531,13 @@ impl Config {
let mut target = Target::default();
if let Some(ref s) = cfg.llvm_config {
target.llvm_config = Some(env::current_dir().unwrap().join(s));
target.llvm_config = Some(config.src.join(s));
}
if let Some(ref s) = cfg.jemalloc {
target.jemalloc = Some(env::current_dir().unwrap().join(s));
target.jemalloc = Some(config.src.join(s));
}
if let Some(ref s) = cfg.android_ndk {
target.ndk = Some(env::current_dir().unwrap().join(s));
target.ndk = Some(config.src.join(s));
}
target.cc = cfg.cc.clone().map(PathBuf::from);
target.cxx = cfg.cxx.clone().map(PathBuf::from);
@@ -541,22 +558,12 @@ impl Config {
set(&mut config.rust_dist_src, t.src_tarball);
}
let cwd = t!(env::current_dir());
let out = cwd.join("build");
let stage0_root = out.join(&config.build).join("stage0/bin");
config.initial_rustc = match build.rustc {
Some(s) => PathBuf::from(s),
None => stage0_root.join(exe("rustc", &config.build)),
};
config.initial_cargo = match build.cargo {
Some(s) => PathBuf::from(s),
None => stage0_root.join(exe("cargo", &config.build)),
};
// Now that we've reached the end of our configuration, infer the
// default values for all options that we haven't otherwise stored yet.
set(&mut config.initial_rustc, build.rustc.map(PathBuf::from));
set(&mut config.initial_rustc, build.cargo.map(PathBuf::from));
let default = false;
config.llvm_assertions = llvm_assertions.unwrap_or(default);
+141 -168
View File
@@ -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;
@@ -61,7 +61,7 @@ fn rust_installer(builder: &Builder) -> Command {
builder.tool_cmd(Tool::RustInstaller)
}
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
#[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Docs {
pub stage: u32,
pub host: Interned<String>,
@@ -89,9 +89,9 @@ impl Step for Docs {
let name = pkgname(build, "rust-docs");
println!("Dist docs ({})", host);
build.info(&format!("Dist docs ({})", host));
if !build.config.docs {
println!("\tskipping - docs disabled");
build.info(&format!("\tskipping - docs disabled"));
return distdir(build).join(format!("{}-{}.tar.gz", name, host));
}
@@ -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))
}
@@ -152,9 +152,9 @@ impl Step for RustcDocs {
let name = pkgname(build, "rustc-docs");
println!("Dist compiler docs ({})", host);
build.info(&format!("Dist compiler docs ({})", host));
if !build.config.compiler_docs {
println!("\tskipping - compiler docs disabled");
build.info(&format!("\tskipping - compiler docs disabled"));
return 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,37 +292,31 @@ 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);
}
}
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
#[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Mingw {
host: Interned<String>,
pub host: Interned<String>,
}
impl Step for Mingw {
@@ -349,7 +343,7 @@ impl Step for Mingw {
return None;
}
println!("Dist mingw ({})", host);
build.info(&format!("Dist mingw ({})", host));
let name = pkgname(build, "rust-mingw");
let image = tmpdir(build).join(format!("{}-{}-image", name, host));
let _ = fs::remove_dir_all(&image);
@@ -378,7 +372,7 @@ impl Step for Mingw {
}
}
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
#[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Rustc {
pub compiler: Compiler,
}
@@ -404,7 +398,7 @@ impl Step for Rustc {
let compiler = self.compiler;
let host = self.compiler.host;
println!("Dist rustc stage{} ({})", compiler.stage, compiler.host);
build.info(&format!("Dist rustc stage{} ({})", compiler.stage, compiler.host));
let name = pkgname(build, "rustc");
let image = tmpdir(build).join(format!("{}-{}-image", name, host));
let _ = fs::remove_dir_all(&image);
@@ -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");
@@ -607,7 +600,7 @@ impl Step for DebuggerScripts {
}
}
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
#[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Std {
pub compiler: Compiler,
pub target: Interned<String>,
@@ -634,12 +627,12 @@ impl Step for Std {
let target = self.target;
let name = pkgname(build, "rust-std");
println!("Dist std stage{} ({} -> {})", compiler.stage, &compiler.host, target);
build.info(&format!("Dist std stage{} ({} -> {})", compiler.stage, &compiler.host, target));
// The only true set of target libraries came from the build triple, so
// let's reduce redundant work by only producing archives from that host.
if compiler.host != build.build {
println!("\tskipping, not a build host");
build.info(&format!("\tskipping, not a build host"));
return distdir(build).join(format!("{}-{}.tar.gz", name, target));
}
@@ -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))
}
}
@@ -711,11 +704,11 @@ impl Step for Analysis {
let compiler = self.compiler;
let target = self.target;
assert!(build.config.extended);
println!("Dist analysis");
build.info(&format!("Dist analysis"));
let name = pkgname(build, "rust-analysis");
if &compiler.host != build.build {
println!("\tskipping, not a build host");
build.info(&format!("\tskipping, not a build host"));
return distdir(build).join(format!("{}-{}.tar.gz", name, target));
}
@@ -737,8 +730,8 @@ impl Step for Analysis {
let image_src = src.join("save-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.info(&format!("image_src: {:?}, dst: {:?}", 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,11 +789,11 @@ 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));
}
}
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
#[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Src;
impl Step for Src {
@@ -820,7 +813,7 @@ impl Step for Src {
/// Creates the `rust-src` installer component
fn run(self, builder: &Builder) -> PathBuf {
let build = builder.build;
println!("Dist src");
build.info(&format!("Dist src"));
let name = pkgname(build, "rust-src");
let image = tmpdir(build).join(format!("{}-image", name));
@@ -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,14 +880,14 @@ 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))
}
}
const CARGO_VENDOR_VERSION: &str = "0.1.4";
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
#[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
pub struct PlainSourceTarball;
impl Step for PlainSourceTarball {
@@ -915,7 +908,7 @@ impl Step for PlainSourceTarball {
/// Creates the plain source tarball
fn run(self, builder: &Builder) -> PathBuf {
let build = builder.build;
println!("Create plain source tarball");
build.info(&format!("Create plain source tarball"));
// Make sure that the root folder of tarball has the correct name
let plain_name = format!("{}-src", pkgname(build, "rustc"));
@@ -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,9 +983,9 @@ 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");
build.info(&format!("running installer"));
let mut cmd = rust_installer(builder);
cmd.arg("tarball")
.arg("--input").arg(&plain_name)
@@ -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,12 +1016,7 @@ 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, Copy, Clone, Hash, PartialEq, Eq)]
#[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Cargo {
pub stage: u32,
pub target: Interned<String>,
@@ -1074,7 +1042,7 @@ impl Step for Cargo {
let stage = self.stage;
let target = self.target;
println!("Dist cargo stage{} ({})", stage, target);
build.info(&format!("Dist cargo stage{} ({})", stage, target));
let src = build.src.join("src/tools/cargo");
let etc = src.join("src/etc");
let release_num = build.release_num("cargo");
@@ -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);
@@ -1135,7 +1103,7 @@ impl Step for Cargo {
}
}
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
#[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Rls {
pub stage: u32,
pub target: Interned<String>,
@@ -1162,7 +1130,7 @@ impl Step for Rls {
let target = self.target;
assert!(build.config.extended);
println!("Dist RLS stage{} ({})", stage, target);
build.info(&format!("Dist RLS stage{} ({})", stage, target));
let src = build.src.join("src/tools/rls");
let release_num = build.release_num("rls");
let name = pkgname(build, "rls");
@@ -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);
@@ -1216,7 +1184,7 @@ impl Step for Rls {
}
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
#[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Rustfmt {
pub stage: u32,
pub target: Interned<String>,
@@ -1242,7 +1210,7 @@ impl Step for Rustfmt {
let stage = self.stage;
let target = self.target;
println!("Dist Rustfmt stage{} ({})", stage, target);
build.info(&format!("Dist Rustfmt stage{} ({})", stage, target));
let src = build.src.join("src/tools/rustfmt");
let release_num = build.release_num("rustfmt");
let name = pkgname(build, "rustfmt");
@@ -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);
@@ -1298,7 +1266,7 @@ impl Step for Rustfmt {
}
}
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
#[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Extended {
stage: u32,
host: Interned<String>,
@@ -1329,7 +1297,7 @@ impl Step for Extended {
let stage = self.stage;
let target = self.target;
println!("Dist extended stage{} ({})", stage, target);
build.info(&format!("Dist extended stage{} ({})", stage, target));
let rustc_installer = builder.ensure(Rustc {
compiler: builder.compiler(stage, target),
@@ -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,10 +1477,10 @@ 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")));
build.remove(&exe.join(name).join("manifest.in"));
};
prepare("rustc");
prepare("cargo");
@@ -1526,11 +1494,11 @@ 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);
t!(t!(File::create(exe.join("LICENSE.txt"))).write_all(license.as_bytes()));
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);
build.create(&exe.join("LICENSE.txt"), &license);
// Generate exe installer
let mut cmd = Command::new("iscc");
@@ -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);
@@ -1665,9 +1633,9 @@ impl Step for Extended {
candle("GccGroup.wxs".as_ref());
}
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.create(&exe.join("LICENSE.rtf"), &rtf);
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);
@@ -1697,7 +1665,9 @@ impl Step for Extended {
build.run(&mut cmd);
t!(fs::rename(exe.join(&filename), distdir(build).join(&filename)));
if !build.config.dry_run {
t!(fs::rename(exe.join(&filename), distdir(build).join(&filename)));
}
}
}
}
@@ -1731,7 +1701,7 @@ fn add_env(build: &Build, cmd: &mut Command, target: Interned<String>) {
}
}
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
#[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
pub struct HashSign;
impl Step for HashSign {
@@ -1749,6 +1719,9 @@ impl Step for HashSign {
fn run(self, builder: &Builder) {
let build = builder.build;
let mut cmd = builder.tool_cmd(Tool::BuildManifest);
if build.config.dry_run {
return;
}
let sign = build.config.dist_sign_folder.as_ref().unwrap_or_else(|| {
panic!("\n\nfailed to specify `dist.sign-folder` in `config.toml`\n\n")
});
@@ -1772,7 +1745,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()));
+32 -27
View File
@@ -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;)+) => {
@@ -168,7 +169,7 @@ impl Step for CargoBook {
let out = out.join(name);
println!("Cargo Book ({}) - {}", target, name);
build.info(&format!("Cargo Book ({}) - {}", target, name));
let _ = fs::remove_dir_all(&out);
@@ -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);
build.info(&format!("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")
@@ -281,11 +283,11 @@ impl Step for TheBook {
// build the index page
let index = format!("{}/index.md", name);
println!("Documenting book index ({})", target);
build.info(&format!("Documenting book index ({})", target));
invoke_rustdoc(builder, compiler, target, &index);
// build the redirect pages
println!("Documenting book redirect pages ({})", target);
build.info(&format!("Documenting book redirect pages ({})", target));
for file in t!(fs::read_dir(build.src.join("src/doc/book/redirects"))) {
let file = t!(file);
let path = file.path();
@@ -358,7 +360,7 @@ impl Step for Standalone {
let build = builder.build;
let target = self.target;
let compiler = self.compiler;
println!("Documenting standalone ({})", target);
build.info(&format!("Documenting standalone ({})", target));
let out = build.doc_out(target);
t!(fs::create_dir_all(&out));
@@ -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
}
@@ -449,7 +451,7 @@ impl Step for Std {
let build = builder.build;
let stage = self.stage;
let target = self.target;
println!("Documenting stage{} std ({})", stage, target);
build.info(&format!("Documenting stage{} std ({})", stage, target));
let out = build.doc_out(target);
t!(fs::create_dir_all(&out));
let compiler = builder.compiler(stage, build.build);
@@ -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);
}
}
@@ -530,7 +532,7 @@ impl Step for Test {
let build = builder.build;
let stage = self.stage;
let target = self.target;
println!("Documenting stage{} test ({})", stage, target);
build.info(&format!("Documenting stage{} test ({})", stage, target));
let out = build.doc_out(target);
t!(fs::create_dir_all(&out));
let compiler = builder.compiler(stage, build.build);
@@ -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);
}
}
@@ -596,7 +598,7 @@ impl Step for WhitelistedRustc {
let build = builder.build;
let stage = self.stage;
let target = self.target;
println!("Documenting stage{} whitelisted compiler ({})", stage, target);
build.info(&format!("Documenting stage{} whitelisted compiler ({})", stage, target));
let out = build.doc_out(target);
t!(fs::create_dir_all(&out));
let compiler = builder.compiler(stage, build.build);
@@ -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);
}
}
@@ -668,7 +670,7 @@ impl Step for Rustc {
let build = builder.build;
let stage = self.stage;
let target = self.target;
println!("Documenting stage{} compiler ({})", stage, target);
build.info(&format!("Documenting stage{} compiler ({})", stage, target));
let out = build.compiler_doc_out(target);
t!(fs::create_dir_all(&out));
let compiler = builder.compiler(stage, build.build);
@@ -680,7 +682,7 @@ impl Step for Rustc {
};
if !build.config.compiler_docs {
println!("\tskipping - compiler docs disabled");
build.info(&format!("\tskipping - compiler docs disabled"));
return;
}
@@ -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);
@@ -759,7 +761,7 @@ impl Step for ErrorIndex {
let build = builder.build;
let target = self.target;
println!("Documenting error index ({})", target);
build.info(&format!("Documenting error index ({})", target));
let out = build.doc_out(target);
t!(fs::create_dir_all(&out));
let mut index = builder.tool_cmd(Tool::ErrorIndex);
@@ -804,10 +806,10 @@ impl Step for UnstableBookGen {
target,
});
println!("Generating unstable book md files ({})", target);
build.info(&format!("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)
}
+3 -9
View File
@@ -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;
@@ -33,17 +32,16 @@ pub struct Flags {
pub on_fail: Option<String>,
pub stage: Option<u32>,
pub keep_stage: Option<u32>,
pub build: Option<Interned<String>>,
pub host: Vec<Interned<String>>,
pub target: Vec<Interned<String>>,
pub config: Option<PathBuf>,
pub src: PathBuf,
pub jobs: Option<u32>,
pub cmd: Subcommand,
pub incremental: bool,
pub exclude: Vec<PathBuf>,
pub rustc_error_format: Option<String>,
pub dry_run: bool,
}
pub enum Subcommand {
@@ -114,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");
@@ -278,10 +277,6 @@ Arguments:
_ => { }
};
// Get any optional paths which occur after the subcommand
let cwd = t!(env::current_dir());
let src = matches.opt_str("src").map(PathBuf::from)
.or_else(|| env::var_os("SRC").map(PathBuf::from))
.unwrap_or(cwd.clone());
let paths = matches.free[1..].iter().map(|p| p.into()).collect::<Vec<PathBuf>>();
let cfg_file = matches.opt_str("config").map(PathBuf::from).or_else(|| {
@@ -371,10 +366,10 @@ 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()),
build: matches.opt_str("build").map(|s| INTERNER.intern_string(s)),
host: split(matches.opt_strs("host"))
.into_iter().map(|x| INTERNER.intern_string(x)).collect::<Vec<_>>(),
target: split(matches.opt_strs("target"))
@@ -385,7 +380,6 @@ Arguments:
incremental: matches.opt_present("incremental"),
exclude: split(matches.opt_strs("exclude"))
.into_iter().map(|p| p.into()).collect::<Vec<_>>(),
src,
}
}
}
+4 -3
View File
@@ -63,7 +63,7 @@ fn install_sh(
host: Option<Interned<String>>
) {
let build = builder.build;
println!("Install {} stage{} ({:?})", package, stage, host);
build.info(&format!("Install {} stage{} ({:?})", package, stage, host));
let prefix_default = PathBuf::from("/usr/local");
let sysconfdir_default = PathBuf::from("/etc");
@@ -212,7 +212,7 @@ install!((self, builder, _config),
Self::should_install(builder) {
install_rls(builder, self.stage, self.target);
} else {
println!("skipping Install RLS stage{} ({})", self.stage, self.target);
builder.info(&format!("skipping Install RLS stage{} ({})", self.stage, self.target));
}
};
Rustfmt, "rustfmt", Self::should_build(_config), only_hosts: true, {
@@ -220,7 +220,8 @@ install!((self, builder, _config),
Self::should_install(builder) {
install_rustfmt(builder, self.stage, self.target);
} else {
println!("skipping Install Rustfmt stage{} ({})", self.stage, self.target);
builder.info(
&format!("skipping Install Rustfmt stage{} ({})", self.stage, self.target));
}
};
Analysis, "analysis", Self::should_build(_config), only_hosts: false, {
+231 -25
View File
@@ -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]
@@ -131,6 +131,11 @@ extern crate getopts;
extern crate num_cpus;
extern crate toml;
extern crate time;
extern crate petgraph;
#[cfg(test)]
#[macro_use]
extern crate pretty_assertions;
#[cfg(unix)]
extern crate libc;
@@ -138,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};
@@ -198,7 +205,7 @@ use toolstate::ToolState;
/// Each compiler has a `stage` that it is associated with and a `host` that
/// corresponds to the platform the compiler runs on. This structure is used as
/// a parameter to many methods below.
#[derive(Eq, PartialEq, Clone, Copy, Hash, Debug)]
#[derive(Eq, PartialOrd, Ord, PartialEq, Clone, Copy, Hash, Debug)]
pub struct Compiler {
stage: u32,
host: Interned<String>,
@@ -309,9 +316,8 @@ impl Build {
///
/// By default all build output will be placed in the current directory.
pub fn new(config: Config) -> Build {
let cwd = t!(env::current_dir());
let src = config.src.clone();
let out = cwd.join("build");
let out = config.out.clone();
let is_sudo = match env::var_os("SUDO_USER") {
Some(sudo_user) => {
@@ -327,7 +333,7 @@ impl Build {
let rls_info = channel::GitInfo::new(&config, &src.join("src/tools/rls"));
let rustfmt_info = channel::GitInfo::new(&config, &src.join("src/tools/rustfmt"));
Build {
let mut build = Build {
initial_rustc: config.initial_rustc.clone(),
initial_cargo: config.initial_cargo.clone(),
local_rebuild: config.local_rebuild,
@@ -358,7 +364,30 @@ impl Build {
delayed_failures: RefCell::new(Vec::new()),
prerelease_version: Cell::new(None),
tool_artifacts: Default::default(),
};
build.verbose("finding compilers");
cc_detect::find(&mut build);
build.verbose("running sanity check");
sanity::check(&mut build);
// If local-rust is the same major.minor as the current version, then force a
// local-rebuild
let local_version_verbose = output(
Command::new(&build.initial_rustc).arg("--version").arg("--verbose"));
let local_release = local_version_verbose
.lines().filter(|x| x.starts_with("release:"))
.next().unwrap().trim_left_matches("release:").trim();
let my_version = channel::CFG_RELEASE_NUM;
if local_release.split('.').take(2).eq(my_version.split('.').take(2)) {
build.verbose(&format!("auto-detected local-rebuild {}", local_release));
build.local_rebuild = true;
}
build.verbose("learning about cargo");
metadata::build(&mut build);
build
}
pub fn build_triple(&self) -> &[Interned<String>] {
@@ -377,25 +406,28 @@ impl Build {
return clean::clean(self, all);
}
self.verbose("finding compilers");
cc_detect::find(self);
self.verbose("running sanity check");
sanity::check(self);
// If local-rust is the same major.minor as the current version, then force a local-rebuild
let local_version_verbose = output(
Command::new(&self.initial_rustc).arg("--version").arg("--verbose"));
let local_release = local_version_verbose
.lines().filter(|x| x.starts_with("release:"))
.next().unwrap().trim_left_matches("release:").trim();
let my_version = channel::CFG_RELEASE_NUM;
if local_release.split('.').take(2).eq(my_version.split('.').take(2)) {
self.verbose(&format!("auto-detected local-rebuild {}", local_release));
self.local_rebuild = true;
{
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;
}
}
}
self.verbose("learning about cargo");
metadata::build(self);
builder::Builder::run(&self);
if !self.config.dry_run {
{
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);
builder.execute_cli();
} 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();
@@ -586,12 +618,14 @@ impl Build {
/// Runs a command, printing out nice contextual information if it fails.
fn run(&self, cmd: &mut Command) {
if self.config.dry_run { return; }
self.verbose(&format!("running: {:?}", cmd));
run_silent(cmd)
}
/// Runs a command, printing out nice contextual information if it fails.
fn run_quiet(&self, cmd: &mut Command) {
if self.config.dry_run { return; }
self.verbose(&format!("running: {:?}", cmd));
run_suppressed(cmd)
}
@@ -600,6 +634,7 @@ impl Build {
/// Exits if the command failed to execute at all, otherwise returns its
/// `status.success()`.
fn try_run(&self, cmd: &mut Command) -> bool {
if self.config.dry_run { return true; }
self.verbose(&format!("running: {:?}", cmd));
try_run_silent(cmd)
}
@@ -608,6 +643,7 @@ impl Build {
/// Exits if the command failed to execute at all, otherwise returns its
/// `status.success()`.
fn try_run_quiet(&self, cmd: &mut Command) -> bool {
if self.config.dry_run { return true; }
self.verbose(&format!("running: {:?}", cmd));
try_run_suppressed(cmd)
}
@@ -623,6 +659,11 @@ impl Build {
}
}
fn info(&self, msg: &str) {
if self.config.dry_run { return; }
println!("{}", msg);
}
/// Returns the number of parallel jobs that have been configured for this
/// build.
fn jobs(&self) -> u32 {
@@ -930,7 +971,7 @@ impl Build {
pub fn fold_output<D, F>(&self, name: F) -> Option<OutputFolder>
where D: Into<String>, F: FnOnce() -> D
{
if self.ci_env == CiEnv::Travis {
if !self.config.dry_run && self.ci_env == CiEnv::Travis {
Some(OutputFolder::new(name().into()))
} else {
None
@@ -978,8 +1019,173 @@ 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()
}
fn remove(&self, f: &Path) {
if self.config.dry_run { return; }
fs::remove_file(f).unwrap_or_else(|_| panic!("failed to remove {:?}", f));
}
}
#[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;
+26 -8
View File
@@ -106,8 +106,8 @@ impl Step for Llvm {
let _folder = build.fold_output(|| "llvm");
let descriptor = if emscripten { "Emscripten " } else { "" };
println!("Building {}LLVM for {}", descriptor, target);
let _time = util::timeit();
build.info(&format!("Building {}LLVM for {}", descriptor, target));
let _time = util::timeit(&build);
t!(fs::create_dir_all(&out_dir));
// http://llvm.org/docs/CMake.html
@@ -217,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()));
@@ -230,6 +235,10 @@ fn check_llvm_version(build: &Build, llvm_config: &Path) {
return
}
if build.config.dry_run {
return;
}
let mut cmd = Command::new(llvm_config);
let version = output(cmd.arg("--version"));
let mut parts = version.split('.').take(2)
@@ -336,6 +345,9 @@ impl Step for Lld {
/// Compile LLVM for `target`.
fn run(self, builder: &Builder) -> PathBuf {
if builder.config.dry_run {
return PathBuf::from("lld-out-dir-test-gen");
}
let target = self.target;
let build = builder.build;
@@ -351,8 +363,8 @@ impl Step for Lld {
}
let _folder = build.fold_output(|| "lld");
println!("Building LLD for {}", target);
let _time = util::timeit();
build.info(&format!("Building LLD for {}", target));
let _time = util::timeit(&build);
t!(fs::create_dir_all(&out_dir));
let mut cfg = cmake::Config::new(build.src.join("src/tools/lld"));
@@ -389,6 +401,9 @@ 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 builder.config.dry_run {
return;
}
let build = builder.build;
let target = self.target;
let dst = build.test_helpers_out(target);
@@ -398,7 +413,7 @@ impl Step for TestHelpers {
}
let _folder = build.fold_output(|| "build_test_helpers");
println!("Building test helpers");
build.info(&format!("Building test helpers"));
t!(fs::create_dir_all(&dst));
let mut cfg = cc::Build::new();
@@ -441,6 +456,9 @@ impl Step for Openssl {
}
fn run(self, builder: &Builder) {
if builder.config.dry_run {
return;
}
let build = builder.build;
let target = self.target;
let out = match build.openssl_dir(target) {
@@ -591,11 +609,11 @@ impl Step for Openssl {
configure.arg("no-asm");
}
configure.current_dir(&obj);
println!("Configuring openssl for {}", target);
build.info(&format!("Configuring openssl for {}", target));
build.run_quiet(&mut configure);
println!("Building openssl for {}", target);
build.info(&format!("Building openssl for {}", target));
build.run_quiet(Command::new("make").arg("-j1").current_dir(&obj));
println!("Installing openssl for {}", target);
build.info(&format!("Installing openssl for {}", target));
build.run_quiet(Command::new("make").arg("install").arg("-j1").current_dir(&obj));
let mut f = t!(File::create(&stamp));
+48 -33
View File
@@ -109,11 +109,11 @@ impl Step for Linkcheck {
let build = builder.build;
let host = self.host;
println!("Linkcheck ({})", host);
build.info(&format!("Linkcheck ({})", host));
builder.default_doc(None);
let _time = util::timeit();
let _time = util::timeit(&build);
try_run(build, builder.tool_cmd(Tool::Linkchecker)
.arg(build.out.join(host).join("doc")));
}
@@ -164,7 +164,7 @@ impl Step for Cargotest {
let out_dir = build.out.join("ct");
t!(fs::create_dir_all(&out_dir));
let _time = util::timeit();
let _time = util::timeit(&build);
let mut cmd = builder.tool_cmd(Tool::CargoTest);
try_run(build, cmd.arg(&build.initial_cargo)
.arg(&out_dir)
@@ -509,7 +509,7 @@ impl Step for RustdocJS {
});
builder.run(&mut command);
} else {
println!("No nodejs found, skipping \"src/test/rustdoc-js\" tests");
builder.info(&format!("No nodejs found, skipping \"src/test/rustdoc-js\" tests"));
}
}
}
@@ -541,7 +541,7 @@ impl Step for Tidy {
}
let _folder = build.fold_output(|| "tidy");
println!("tidy check");
builder.info(&format!("tidy check"));
try_run(build, &mut cmd);
}
@@ -926,15 +926,17 @@ impl Step for Compiletest {
target: build.config.build,
emscripten: false,
});
let llvm_version = output(Command::new(&llvm_config).arg("--version"));
cmd.arg("--llvm-version").arg(llvm_version);
if !build.config.dry_run {
let llvm_version = output(Command::new(&llvm_config).arg("--version"));
cmd.arg("--llvm-version").arg(llvm_version);
}
if !build.is_rust_llvm(target) {
cmd.arg("--system-llvm");
}
// Only pass correct values for these flags for the `run-make` suite as it
// requires that a C++ compiler was configured which isn't always the case.
if suite == "run-make-fulldeps" {
if !build.config.dry_run && suite == "run-make-fulldeps" {
let llvm_components = output(Command::new(&llvm_config).arg("--components"));
let llvm_cxxflags = output(Command::new(&llvm_config).arg("--cxxflags"));
cmd.arg("--cc").arg(build.cc(target))
@@ -948,7 +950,8 @@ impl Step for Compiletest {
}
}
if suite == "run-make-fulldeps" && !build.config.llvm_enabled {
println!("Ignoring run-make test suite as they generally don't work without LLVM");
builder.info(
&format!("Ignoring run-make test suite as they generally don't work without LLVM"));
return;
}
@@ -1002,9 +1005,9 @@ impl Step for Compiletest {
build.ci_env.force_coloring_in_ci(&mut cmd);
let _folder = build.fold_output(|| format!("test_{}", suite));
println!("Check compiletest suite={} mode={} ({} -> {})",
suite, mode, &compiler.host, target);
let _time = util::timeit();
builder.info(&format!("Check compiletest suite={} mode={} ({} -> {})",
suite, mode, &compiler.host, target));
let _time = util::timeit(&build);
try_run(build, &mut cmd);
}
}
@@ -1039,9 +1042,10 @@ impl Step for DocTest {
// Do a breadth-first traversal of the `src/doc` directory and just run
// tests for all files that end in `*.md`
let mut stack = vec![build.src.join(self.path)];
let _time = util::timeit();
let _time = util::timeit(&build);
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 +1062,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
@@ -1160,8 +1170,8 @@ impl Step for ErrorIndex {
let _folder = build.fold_output(|| "test_error_index");
println!("Testing error-index stage{}", compiler.stage);
let _time = util::timeit();
build.info(&format!("Testing error-index stage{}", compiler.stage));
let _time = util::timeit(&build);
build.run(&mut tool);
markdown_test(builder, compiler, &output);
}
@@ -1169,14 +1179,18 @@ impl Step for ErrorIndex {
fn markdown_test(builder: &Builder, compiler: Compiler, markdown: &Path) -> bool {
let build = builder.build;
let mut file = t!(File::open(markdown));
let mut contents = String::new();
t!(file.read_to_string(&mut contents));
if !contents.contains("```") {
return true;
match File::open(markdown) {
Ok(mut file) => {
let mut contents = String::new();
t!(file.read_to_string(&mut contents));
if !contents.contains("```") {
return true;
}
}
Err(_) => {},
}
println!("doc tests for: {}", markdown.display());
build.info(&format!("doc tests for: {}", markdown.display()));
let mut cmd = builder.rustdoc_cmd(compiler.host);
build.add_rust_test_threads(&mut cmd);
cmd.arg("--test");
@@ -1446,8 +1460,8 @@ impl Step for Crate {
// The javascript shim implements the syscall interface so that test
// output can be correctly reported.
if !build.config.wasm_syscall {
println!("Libstd was built without `wasm_syscall` feature enabled: \
test output may not be visible.");
build.info(&format!("Libstd was built without `wasm_syscall` feature enabled: \
test output may not be visible."));
}
// On the wasm32-unknown-unknown target we're using LTO which is
@@ -1469,9 +1483,9 @@ impl Step for Crate {
let _folder = build.fold_output(|| {
format!("{}_stage{}-{}", test_kind.subcommand(), compiler.stage, krate)
});
println!("{} {} stage{} ({} -> {})", test_kind, krate, compiler.stage,
&compiler.host, target);
let _time = util::timeit();
build.info(&format!("{} {} stage{} ({} -> {})", test_kind, krate, compiler.stage,
&compiler.host, target));
let _time = util::timeit(&build);
try_run(build, &mut cargo);
}
}
@@ -1536,9 +1550,9 @@ impl Step for CrateRustdoc {
let _folder = build.fold_output(|| {
format!("{}_stage{}-rustdoc", test_kind.subcommand(), compiler.stage)
});
println!("{} rustdoc stage{} ({} -> {})", test_kind, compiler.stage,
&compiler.host, target);
let _time = util::timeit();
build.info(&format!("{} rustdoc stage{} ({} -> {})", test_kind, compiler.stage,
&compiler.host, target));
let _time = util::timeit(&build);
try_run(build, &mut cargo);
}
@@ -1585,7 +1599,7 @@ impl Step for RemoteCopyLibs {
builder.ensure(compile::Test { compiler, target });
println!("REMOTE copy libs to emulator ({})", target);
build.info(&format!("REMOTE copy libs to emulator ({})", target));
t!(fs::create_dir_all(build.out.join("tmp")));
let server = builder.ensure(tool::RemoteTestServer { compiler, target });
@@ -1633,7 +1647,7 @@ impl Step for Distcheck {
fn run(self, builder: &Builder) {
let build = builder.build;
println!("Distcheck");
build.info(&format!("Distcheck"));
let dir = build.out.join("tmp").join("distcheck");
let _ = fs::remove_dir_all(&dir);
t!(fs::create_dir_all(&dir));
@@ -1657,7 +1671,7 @@ impl Step for Distcheck {
.current_dir(&dir));
// Now make sure that rust-src has all of libstd's dependencies
println!("Distcheck rust-src");
build.info(&format!("Distcheck rust-src"));
let dir = build.out.join("tmp").join("distcheck-src");
let _ = fs::remove_dir_all(&dir);
t!(fs::create_dir_all(&dir));
@@ -1692,6 +1706,7 @@ impl Step for Bootstrap {
let mut cmd = Command::new(&build.initial_cargo);
cmd.arg("test")
.current_dir(build.src.join("src/bootstrap"))
.env("RUSTFLAGS", "-Cdebuginfo=2")
.env("CARGO_TARGET_DIR", build.out.join("bootstrap"))
.env("RUSTC_BOOTSTRAP", "1")
.env("RUSTC", &build.initial_rustc);
+6 -5
View File
@@ -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;
@@ -116,7 +116,7 @@ impl Step for ToolBuild {
cargo.arg("--features").arg(self.extra_features.join(" "));
let _folder = build.fold_output(|| format!("stage{}-{}", compiler.stage, tool));
println!("Building stage{} tool {} ({})", compiler.stage, tool, target);
build.info(&format!("Building stage{} tool {} ({})", compiler.stage, tool, target));
let mut duplicates = Vec::new();
let is_expected = compile::stream_cargo(build, &mut cargo, &mut |msg| {
// Only care about big things like the RLS/Cargo for now
@@ -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)
}
}
@@ -427,7 +427,8 @@ impl Step for Rustdoc {
.env("RUSTC_DEBUGINFO_LINES", builder.config.rust_debuginfo_lines.to_string());
let _folder = build.fold_output(|| format!("stage{}-rustdoc", target_compiler.stage));
println!("Building rustdoc for stage{} ({})", target_compiler.stage, target_compiler.host);
build.info(&format!("Building rustdoc for stage{} ({})",
target_compiler.stage, target_compiler.host));
build.run(&mut cargo);
// Cargo adds a number of paths to the dylib search path on windows, which results in
@@ -443,7 +444,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 -107
View File
@@ -15,13 +15,14 @@
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;
use Build;
/// Returns the `name` as the filename of a static library for `target`.
pub fn staticlib(name: &str, target: &str) -> String {
@@ -32,102 +33,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 {
@@ -196,25 +101,28 @@ pub fn push_exe_path(mut buf: PathBuf, components: &[&str]) -> PathBuf {
buf
}
pub struct TimeIt(Instant);
pub struct TimeIt(bool, Instant);
/// Returns an RAII structure that prints out how long it took to drop.
pub fn timeit() -> TimeIt {
TimeIt(Instant::now())
pub fn timeit(build: &Build) -> TimeIt {
TimeIt(build.config.dry_run, Instant::now())
}
impl Drop for TimeIt {
fn drop(&mut self) {
let time = self.0.elapsed();
println!("\tfinished in {}.{:03}",
time.as_secs(),
time.subsec_nanos() / 1_000_000);
let time = self.1.elapsed();
if !self.0 {
println!("\tfinished in {}.{:03}",
time.as_secs(),
time.subsec_nanos() / 1_000_000);
}
}
}
/// Symlinks two directories, using junctions on Windows and normal symlinks on
/// Unix.
pub fn symlink_dir(src: &Path, dest: &Path) -> io::Result<()> {
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);