Utilize interning to allow Copy/Clone steps

This commit is contained in:
Mark Simulacrum 2017-07-13 18:48:44 -06:00
parent e7b1a60ad7
commit 528646e127
17 changed files with 1014 additions and 708 deletions

9
src/Cargo.lock generated
View File

@ -134,10 +134,11 @@ dependencies = [
"filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)",
"getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"toml 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -155,8 +156,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
name = "build-manifest" name = "build-manifest"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
"toml 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
] ]

View File

@ -40,3 +40,4 @@ serde = "1.0.8"
serde_derive = "1.0.8" serde_derive = "1.0.8"
serde_json = "1.0.2" serde_json = "1.0.2"
toml = "0.4" toml = "0.4"
lazy_static = "0.2"

View File

@ -8,20 +8,21 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
use serde::{Serialize, Deserialize}; use std::fmt::Debug;
use std::hash::Hash;
use std::cell::RefCell; use std::cell::RefCell;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::process::Command; use std::process::Command;
use std::fs; use std::fs;
use std::ops::Deref; use std::ops::Deref;
use std::any::{TypeId, Any};
use compile; use compile;
use install; use install;
use dist; use dist;
use util::{exe, libdir, add_lib_path}; use util::{exe, libdir, add_lib_path};
use {Build, Mode}; use {Build, Mode};
use cache::{Cache, Key}; use cache::{INTERNER, Interned, Cache};
use check; use check;
use flags::Subcommand; use flags::Subcommand;
use doc; use doc;
@ -34,7 +35,7 @@ pub struct Builder<'a> {
pub top_stage: u32, pub top_stage: u32,
pub kind: Kind, pub kind: Kind,
cache: Cache, cache: Cache,
stack: RefCell<Vec<Key>>, stack: RefCell<Vec<(TypeId, Box<Any>)>>,
} }
impl<'a> Deref for Builder<'a> { impl<'a> Deref for Builder<'a> {
@ -45,19 +46,10 @@ impl<'a> Deref for Builder<'a> {
} }
} }
pub trait Step<'a>: Serialize + Sized { pub trait Step: 'static + Clone + Debug + PartialEq + Eq + Hash {
/// The output type of this step. This is used in a few places to return a
/// `PathBuf` when directories are created or to return a `Compiler` once /// `PathBuf` when directories are created or to return a `Compiler` once
/// it's been assembled. /// it's been assembled.
/// type Output: Clone;
/// When possible, this should be used instead of implicitly creating files
/// in a prearranged directory that will later be used by the build system.
/// It's not always practical, however, since it makes avoiding rebuilds
/// somewhat harder.
type Output: Serialize + Deserialize<'a> + 'a;
/// This type, but with a 'static bound. Used for caching the step.
type Id: 'static;
const DEFAULT: bool = false; const DEFAULT: bool = false;
@ -72,13 +64,13 @@ pub trait Step<'a>: Serialize + Sized {
/// Primary function to execute this rule. Can call `builder.ensure(...)` /// Primary function to execute this rule. Can call `builder.ensure(...)`
/// with other steps to run those. /// with other steps to run those.
fn run(self, builder: &'a Builder) -> Self::Output; fn run(self, builder: &Builder) -> Self::Output;
/// When bootstrap is passed a set of paths, this controls whether this rule /// When bootstrap is passed a set of paths, this controls whether this rule
/// will execute. However, it does not get called in a "default" context /// will execute. However, it does not get called in a "default" context
/// when we are not passed any paths; in that case, make_run is called /// when we are not passed any paths; in that case, make_run is called
/// directly. /// directly.
fn should_run(_builder: &'a Builder, _path: &Path) -> bool { false } fn should_run(_builder: &Builder, _path: &Path) -> bool { false }
/// Build up a "root" rule, either as a default rule or from a path passed /// Build up a "root" rule, either as a default rule or from a path passed
/// to us. /// to us.
@ -87,10 +79,10 @@ pub trait Step<'a>: Serialize + Sized {
/// passed. When `./x.py build` is run, for example, this rule could get /// passed. When `./x.py build` is run, for example, this rule could get
/// called if it is in the correct list below with a path of `None`. /// called if it is in the correct list below with a path of `None`.
fn make_run( fn make_run(
_builder: &'a Builder, _builder: &Builder,
_path: Option<&Path>, _path: Option<&Path>,
_host: &'a str, _host: Interned<String>,
_target: &'a str, _target: Interned<String>,
) { unimplemented!() } ) { unimplemented!() }
} }
@ -176,26 +168,27 @@ impl<'a> Builder<'a> {
/// not take `Compiler` since all `Compiler` instances are meant to be /// not take `Compiler` since all `Compiler` instances are meant to be
/// obtained through this function, since it ensures that they are valid /// obtained through this function, since it ensures that they are valid
/// (i.e., built and assembled). /// (i.e., built and assembled).
pub fn compiler(&'a self, stage: u32, host: &'a str) -> Compiler<'a> { pub fn compiler(&self, stage: u32, host: Interned<String>) -> Compiler {
self.ensure(compile::Assemble { target_compiler: Compiler { stage, host } }) self.ensure(compile::Assemble { target_compiler: Compiler { stage, host } })
} }
pub fn sysroot(&self, compiler: Compiler<'a>) -> PathBuf { pub fn sysroot(&self, compiler: Compiler) -> Interned<PathBuf> {
self.ensure(compile::Sysroot { compiler }) self.ensure(compile::Sysroot { compiler })
} }
/// Returns the libdir where the standard library and other artifacts are /// Returns the libdir where the standard library and other artifacts are
/// found for a compiler's sysroot. /// found for a compiler's sysroot.
pub fn sysroot_libdir(&self, compiler: Compiler<'a>, target: &'a str) -> PathBuf { pub fn sysroot_libdir(
#[derive(Serialize)] &self, compiler: Compiler, target: Interned<String>
struct Libdir<'a> { ) -> Interned<PathBuf> {
compiler: Compiler<'a>, #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
target: &'a str, struct Libdir {
compiler: Compiler,
target: Interned<String>,
} }
impl<'a> Step<'a> for Libdir<'a> { impl Step for Libdir {
type Id = Libdir<'static>; type Output = Interned<PathBuf>;
type Output = PathBuf; fn run(self, builder: &Builder) -> Interned<PathBuf> {
fn run(self, builder: &Builder) -> PathBuf {
let compiler = self.compiler; let compiler = self.compiler;
let lib = if compiler.stage >= 2 && builder.build.config.libdir_relative.is_some() { let lib = if compiler.stage >= 2 && builder.build.config.libdir_relative.is_some() {
builder.build.config.libdir_relative.clone().unwrap() builder.build.config.libdir_relative.clone().unwrap()
@ -206,7 +199,7 @@ impl<'a> Builder<'a> {
.join("rustlib").join(self.target).join("lib"); .join("rustlib").join(self.target).join("lib");
let _ = fs::remove_dir_all(&sysroot); let _ = fs::remove_dir_all(&sysroot);
t!(fs::create_dir_all(&sysroot)); t!(fs::create_dir_all(&sysroot));
sysroot INTERNER.intern_path(sysroot)
} }
} }
self.ensure(Libdir { compiler, target }) self.ensure(Libdir { compiler, target })
@ -221,7 +214,7 @@ impl<'a> Builder<'a> {
if compiler.is_snapshot(self) { if compiler.is_snapshot(self) {
self.build.rustc_snapshot_libdir() self.build.rustc_snapshot_libdir()
} else { } else {
self.sysroot(compiler).join(libdir(compiler.host)) self.sysroot(compiler).join(libdir(&compiler.host))
} }
} }
@ -243,7 +236,7 @@ impl<'a> Builder<'a> {
if compiler.is_snapshot(self) { if compiler.is_snapshot(self) {
self.initial_rustc.clone() self.initial_rustc.clone()
} else { } else {
self.sysroot(compiler).join("bin").join(exe("rustc", compiler.host)) self.sysroot(compiler).join("bin").join(exe("rustc", &compiler.host))
} }
} }
@ -251,7 +244,7 @@ impl<'a> Builder<'a> {
pub fn rustdoc(&self, compiler: Compiler) -> PathBuf { pub fn rustdoc(&self, compiler: Compiler) -> PathBuf {
let mut rustdoc = self.rustc(compiler); let mut rustdoc = self.rustc(compiler);
rustdoc.pop(); rustdoc.pop();
rustdoc.push(exe("rustdoc", compiler.host)); rustdoc.push(exe("rustdoc", &compiler.host));
rustdoc rustdoc
} }
@ -265,7 +258,7 @@ impl<'a> Builder<'a> {
pub fn cargo(&self, pub fn cargo(&self,
compiler: Compiler, compiler: Compiler,
mode: Mode, mode: Mode,
target: &str, target: Interned<String>,
cmd: &str) -> Command { cmd: &str) -> Command {
let mut cargo = Command::new(&self.initial_cargo); let mut cargo = Command::new(&self.initial_cargo);
let out_dir = self.stage_out(compiler, mode); let out_dir = self.stage_out(compiler, mode);
@ -427,7 +420,7 @@ impl<'a> Builder<'a> {
cargo cargo
} }
fn maybe_run<S: Step<'a>>(&'a self, path: Option<&Path>) { fn maybe_run<S: Step>(&self, path: Option<&Path>) {
let build = self.build; let build = self.build;
let hosts = if S::ONLY_BUILD_TARGETS || S::ONLY_BUILD { let hosts = if S::ONLY_BUILD_TARGETS || S::ONLY_BUILD {
&build.config.host[..1] &build.config.host[..1]
@ -459,7 +452,7 @@ impl<'a> Builder<'a> {
for host in hosts { for host in hosts {
for target in targets { for target in targets {
S::make_run(self, path, host, target); S::make_run(self, path, *host, *target);
} }
} }
} }
@ -467,33 +460,37 @@ impl<'a> Builder<'a> {
/// Ensure that a given step is built, returning it's output. This will /// Ensure that a given step is built, returning it's output. This will
/// cache the step, so it is safe (and good!) to call this as often as /// cache the step, so it is safe (and good!) to call this as often as
/// needed to ensure that all dependencies are built. /// needed to ensure that all dependencies are built.
pub fn ensure<S: Step<'a>>(&'a self, step: S) -> S::Output { pub fn ensure<S: Step>(&'a self, step: S) -> S::Output {
let key = Cache::to_key(&step); let type_id = TypeId::of::<S>();
{ {
let mut stack = self.stack.borrow_mut(); let mut stack = self.stack.borrow_mut();
if stack.contains(&key) { for &(stack_type_id, ref stack_step) in stack.iter() {
if !(type_id == stack_type_id && step == *stack_step.downcast_ref().unwrap()) {
continue
}
let mut out = String::new(); let mut out = String::new();
out += &format!("\n\nCycle in build detected when adding {:?}\n", key); out += &format!("\n\nCycle in build detected when adding {:?}\n", step);
for el in stack.iter().rev() { for el in stack.iter().rev() {
out += &format!("\t{:?}\n", el); out += &format!("\t{:?}\n", el);
} }
panic!(out); panic!(out);
} }
if let Some(out) = self.cache.get::<S::Output>(&key) { if let Some(out) = self.cache.get(&step) {
self.build.verbose(&format!("{}c {:?}", " ".repeat(stack.len()), key)); self.build.verbose(&format!("{}c {:?}", " ".repeat(stack.len()), step));
return out; return out;
} }
self.build.verbose(&format!("{}> {:?}", " ".repeat(stack.len()), key)); self.build.verbose(&format!("{}> {:?}", " ".repeat(stack.len()), step));
stack.push(key.clone()); stack.push((type_id, Box::new(step.clone())));
} }
let out = step.run(self); let out = step.clone().run(self);
{ {
let mut stack = self.stack.borrow_mut(); let mut stack = self.stack.borrow_mut();
assert_eq!(stack.pop().as_ref(), Some(&key)); let (cur_type_id, cur_step) = stack.pop().expect("step stack empty");
assert_eq!((cur_type_id, cur_step.downcast_ref()), (type_id, Some(&step)));
} }
self.build.verbose(&format!("{}< {:?}", " ".repeat(self.stack.borrow().len()), key)); self.build.verbose(&format!("{}< {:?}", " ".repeat(self.stack.borrow().len()), step));
self.cache.put(key.clone(), &out); self.cache.put(step, out.clone());
self.cache.get::<S::Output>(&key).unwrap() out
} }
} }

View File

@ -8,15 +8,250 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
use serde_json; use serde::Deserialize;
use serde::{Serialize, Deserialize}; use serde::de::{self, Deserializer, Visitor};
use std::any::TypeId;
use std::any::{Any, TypeId};
use std::borrow::Borrow;
use std::cell::RefCell;
use std::collections::HashMap;
use std::convert::AsRef;
use std::ffi::OsStr;
use std::fmt;
use std::hash::{Hash, Hasher};
use std::marker::PhantomData;
use std::mem;
use std::ops::Deref;
use std::path::{Path, PathBuf};
use std::sync::Mutex;
use builder::Step; use builder::Step;
use std::fmt; pub struct Interned<T>(usize, PhantomData<*const T>);
use std::mem;
use std::collections::HashMap; impl<'de> Deserialize<'de> for Interned<String> {
use std::cell::RefCell; fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where D: Deserializer<'de>
{
struct StrVisitor;
impl<'de> Visitor<'de> for StrVisitor {
type Value = &'de str;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a str")
}
fn visit_borrowed_str<E>(self, value: &'de str) -> Result<&'de str, E>
where E: de::Error
{
Ok(value)
}
}
Ok(INTERNER.intern_str(deserializer.deserialize_str(StrVisitor)?))
}
}
impl Default for Interned<String> {
fn default() -> Self {
INTERNER.intern_string(String::default())
}
}
impl Default for Interned<PathBuf> {
fn default() -> Self {
INTERNER.intern_path(PathBuf::default())
}
}
impl<T> Copy for Interned<T> {}
impl<T> Clone for Interned<T> {
fn clone(&self) -> Interned<T> {
*self
}
}
impl<T> PartialEq for Interned<T> {
fn eq(&self, other: &Self) -> bool {
self.0 == other.0
}
}
impl<T> Eq for Interned<T> {}
impl PartialEq<str> for Interned<String> {
fn eq(&self, other: &str) -> bool {
*self == other
}
}
impl<'a> PartialEq<&'a str> for Interned<String> {
fn eq(&self, other: &&str) -> bool {
**self == **other
}
}
impl<'a, T> PartialEq<&'a Interned<T>> for Interned<T> {
fn eq(&self, other: &&Self) -> bool {
self.0 == other.0
}
}
impl<'a, T> PartialEq<Interned<T>> for &'a Interned<T> {
fn eq(&self, other: &Interned<T>) -> bool {
self.0 == other.0
}
}
unsafe impl<T> Send for Interned<T> {}
unsafe impl<T> Sync for Interned<T> {}
impl fmt::Display for Interned<String> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let s: &str = &*self;
f.write_str(s)
}
}
impl fmt::Debug for Interned<String> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let s: &str = &*self;
f.write_fmt(format_args!("{:?}", s))
}
}
impl fmt::Debug for Interned<PathBuf> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let s: &Path = &*self;
f.write_fmt(format_args!("{:?}", s))
}
}
impl Hash for Interned<String> {
fn hash<H: Hasher>(&self, state: &mut H) {
let l = INTERNER.strs.lock().unwrap();
l.get(*self).hash(state)
}
}
impl Hash for Interned<PathBuf> {
fn hash<H: Hasher>(&self, state: &mut H) {
let l = INTERNER.paths.lock().unwrap();
l.get(*self).hash(state)
}
}
impl Deref for Interned<String> {
type Target = str;
fn deref(&self) -> &'static str {
let l = INTERNER.strs.lock().unwrap();
unsafe { mem::transmute::<&str, &'static str>(l.get(*self)) }
}
}
impl Deref for Interned<PathBuf> {
type Target = Path;
fn deref(&self) -> &'static Path {
let l = INTERNER.paths.lock().unwrap();
unsafe { mem::transmute::<&Path, &'static Path>(l.get(*self)) }
}
}
impl AsRef<Path> for Interned<PathBuf> {
fn as_ref(&self) -> &'static Path {
let l = INTERNER.paths.lock().unwrap();
unsafe { mem::transmute::<&Path, &'static Path>(l.get(*self)) }
}
}
impl AsRef<Path> for Interned<String> {
fn as_ref(&self) -> &'static Path {
let l = INTERNER.strs.lock().unwrap();
unsafe { mem::transmute::<&Path, &'static Path>(l.get(*self).as_ref()) }
}
}
impl AsRef<OsStr> for Interned<PathBuf> {
fn as_ref(&self) -> &'static OsStr {
let l = INTERNER.paths.lock().unwrap();
unsafe { mem::transmute::<&OsStr, &'static OsStr>(l.get(*self).as_ref()) }
}
}
impl AsRef<OsStr> for Interned<String> {
fn as_ref(&self) -> &'static OsStr {
let l = INTERNER.strs.lock().unwrap();
unsafe { mem::transmute::<&OsStr, &'static OsStr>(l.get(*self).as_ref()) }
}
}
struct TyIntern<T> {
items: Vec<T>,
set: HashMap<T, Interned<T>>,
}
impl<T: Hash + Clone + Eq> TyIntern<T> {
fn new() -> TyIntern<T> {
TyIntern {
items: Vec::new(),
set: HashMap::new(),
}
}
fn intern_borrow<B>(&mut self, item: &B) -> Interned<T>
where
B: Eq + Hash + ToOwned<Owned=T> + ?Sized,
T: Borrow<B>,
{
if let Some(i) = self.set.get(&item) {
return *i;
}
let item = item.to_owned();
let interned = Interned(self.items.len(), PhantomData::<*const T>);
self.set.insert(item.clone(), interned);
self.items.push(item);
interned
}
fn intern(&mut self, item: T) -> Interned<T> {
if let Some(i) = self.set.get(&item) {
return *i;
}
let interned = Interned(self.items.len(), PhantomData::<*const T>);
self.set.insert(item.clone(), interned);
self.items.push(item);
interned
}
fn get(&self, i: Interned<T>) -> &T {
&self.items[i.0]
}
}
pub struct Interner {
strs: Mutex<TyIntern<String>>,
paths: Mutex<TyIntern<PathBuf>>,
}
impl Interner {
fn new() -> Interner {
Interner {
strs: Mutex::new(TyIntern::new()),
paths: Mutex::new(TyIntern::new()),
}
}
pub fn intern_str(&self, s: &str) -> Interned<String> {
self.strs.lock().unwrap().intern_borrow(s)
}
pub fn intern_string(&self, s: String) -> Interned<String> {
self.strs.lock().unwrap().intern(s)
}
pub fn intern_path(&self, s: PathBuf) -> Interned<PathBuf> {
self.paths.lock().unwrap().intern(s)
}
}
lazy_static! {
pub static ref INTERNER: Interner = Interner::new();
}
/// This is essentially a HashMap which allows storing any type in its input and /// This is essentially a HashMap which allows storing any type in its input and
/// any type in its output. It is a write-once cache; values are never evicted, /// any type in its output. It is a write-once cache; values are never evicted,
@ -25,68 +260,37 @@ use std::cell::RefCell;
// //
// FIXME: This type does not permit retrieving &Path from a PathBuf, primarily // FIXME: This type does not permit retrieving &Path from a PathBuf, primarily
// due to a lack of any obvious way to ensure that this is safe, but also not // due to a lack of any obvious way to ensure that this is safe, but also not
// penalize other cases (e.g., deserializing u32 -> &u32, which is non-optimal).
#[derive(Debug)] #[derive(Debug)]
pub struct Cache(RefCell<HashMap<Key, Box<str>>>); pub struct Cache(
RefCell<HashMap<
fn to_json<T: Serialize>(element: &T) -> String { TypeId,
t!(serde_json::to_string(element)) Box<Any>, // actually a HashMap<Step, Interned<Step::Output>>
} >>
);
fn from_json<'a, O: Deserialize<'a>>(data: &'a str) -> O {
t!(serde_json::from_str(data))
}
#[derive(Clone, PartialEq, Eq, Hash)]
pub struct Key(TypeId, String);
impl fmt::Debug for Key {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.write_str(&format!("{:?}; ", self.0))?;
fmt.write_str(&self.1)
}
}
impl Cache { impl Cache {
pub fn new() -> Cache { pub fn new() -> Cache {
Cache(RefCell::new(HashMap::new())) Cache(RefCell::new(HashMap::new()))
} }
pub fn to_key<'a, K: Step<'a>>(key: &K) -> Key { pub fn put<S: Step>(&self, step: S, value: S::Output) {
Key(TypeId::of::<K::Id>(), to_json(key))
}
/// Puts a value into the cache. Will panic if called more than once with
/// the same key.
///
/// Returns the internal key utilized, as an opaque structure, useful only
/// for debugging.
pub fn put<V>(&self, key: Key, value: &V)
where
V: Serialize,
{
let mut cache = self.0.borrow_mut(); let mut cache = self.0.borrow_mut();
let value = to_json(value); let type_id = TypeId::of::<S>();
assert!(!cache.contains_key(&key), "processing {:?} a second time", key); let stepcache = cache.entry(type_id)
// Store a boxed str so that it's location in memory never changes and .or_insert_with(|| Box::new(HashMap::<S, S::Output>::new()))
// it's safe for us to return references to it (so long as they live as .downcast_mut::<HashMap<S, S::Output>>()
// long as us). .expect("invalid type mapped");
cache.insert(key, value.into_boxed_str()); assert!(!stepcache.contains_key(&step), "processing {:?} a second time", step);
stepcache.insert(step, value);
} }
pub fn get<'a, V>(&'a self, key: &Key) -> Option<V> pub fn get<S: Step>(&self, step: &S) -> Option<S::Output> {
where let mut cache = self.0.borrow_mut();
V: Deserialize<'a> + 'a, let type_id = TypeId::of::<S>();
{ let stepcache = cache.entry(type_id)
let cache = self.0.borrow(); .or_insert_with(|| Box::new(HashMap::<S, S::Output>::new()))
cache.get(key).map(|v| { .downcast_mut::<HashMap<S, S::Output>>()
// Change the lifetime. This borrow is valid for as long as self lives; .expect("invalid type mapped");
// the data we're accessing will live as long as us and will be in a stepcache.get(step).cloned()
// stable location, since we use Box<str>.
let v = unsafe {
mem::transmute::<&str, &'a str>(v)
};
from_json(v)
})
} }
} }

View File

@ -38,6 +38,7 @@ use gcc;
use Build; use Build;
use config::Target; use config::Target;
use cache::Interned;
pub fn find(build: &mut Build) { pub fn find(build: &mut Build) {
// For all targets we're going to need a C compiler for building some shims // For all targets we're going to need a C compiler for building some shims
@ -50,11 +51,11 @@ pub fn find(build: &mut Build) {
cfg.cargo_metadata(false).opt_level(0).debug(false) cfg.cargo_metadata(false).opt_level(0).debug(false)
.target(target).host(&build.build); .target(target).host(&build.build);
let config = build.config.target_config.get(target); let config = build.config.target_config.get(&target);
if let Some(cc) = config.and_then(|c| c.cc.as_ref()) { if let Some(cc) = config.and_then(|c| c.cc.as_ref()) {
cfg.compiler(cc); cfg.compiler(cc);
} else { } else {
set_compiler(&mut cfg, "gcc", target, config, build); set_compiler(&mut cfg, "gcc", *target, config, build);
} }
let compiler = cfg.get_compiler(); let compiler = cfg.get_compiler();
@ -63,7 +64,7 @@ pub fn find(build: &mut Build) {
if let Some(ref ar) = ar { if let Some(ref ar) = ar {
build.verbose(&format!("AR_{} = {:?}", target, ar)); build.verbose(&format!("AR_{} = {:?}", target, ar));
} }
build.cc.insert(target.to_string(), (compiler, ar)); build.cc.insert(*target, (compiler, ar));
} }
// For all host triples we need to find a C++ compiler as well // For all host triples we need to find a C++ compiler as well
@ -78,20 +79,20 @@ pub fn find(build: &mut Build) {
if let Some(cxx) = config.and_then(|c| c.cxx.as_ref()) { if let Some(cxx) = config.and_then(|c| c.cxx.as_ref()) {
cfg.compiler(cxx); cfg.compiler(cxx);
} else { } else {
set_compiler(&mut cfg, "g++", host, config, build); set_compiler(&mut cfg, "g++", *host, config, build);
} }
let compiler = cfg.get_compiler(); let compiler = cfg.get_compiler();
build.verbose(&format!("CXX_{} = {:?}", host, compiler.path())); build.verbose(&format!("CXX_{} = {:?}", host, compiler.path()));
build.cxx.insert(host.to_string(), compiler); build.cxx.insert(*host, compiler);
} }
} }
fn set_compiler(cfg: &mut gcc::Config, fn set_compiler(cfg: &mut gcc::Config,
gnu_compiler: &str, gnu_compiler: &str,
target: &str, target: Interned<String>,
config: Option<&Target>, config: Option<&Target>,
build: &Build) { build: &Build) {
match target { match &*target {
// When compiling for android we may have the NDK configured in the // When compiling for android we may have the NDK configured in the
// config.toml in which case we look there. Otherwise the default // config.toml in which case we look there. Otherwise the default
// compiler already takes into account the triple in question. // compiler already takes into account the triple in question.

View File

@ -33,11 +33,12 @@ use compile;
use native; use native;
use builder::{Kind, Builder, Compiler, Step}; use builder::{Kind, Builder, Compiler, Step};
use tool::{self, Tool}; use tool::{self, Tool};
use cache::{INTERNER, Interned};
const ADB_TEST_DIR: &str = "/data/tmp/work"; const ADB_TEST_DIR: &str = "/data/tmp/work";
/// The two modes of the test runner; tests or benchmarks. /// The two modes of the test runner; tests or benchmarks.
#[derive(Serialize, Copy, Clone)] #[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)]
pub enum TestKind { pub enum TestKind {
/// Run `cargo test` /// Run `cargo test`
Test, Test,
@ -93,13 +94,12 @@ fn try_run_quiet(build: &Build, cmd: &mut Command) {
// .host(true) // .host(true)
// .run(move |s| check::linkcheck(build, s.target)); // .run(move |s| check::linkcheck(build, s.target));
#[derive(Serialize)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct Linkcheck<'a> { pub struct Linkcheck {
host: &'a str, host: Interned<String>,
} }
impl<'a> Step<'a> for Linkcheck<'a> { impl Step for Linkcheck {
type Id = Linkcheck<'static>;
type Output = (); type Output = ();
const ONLY_HOSTS: bool = true; const ONLY_HOSTS: bool = true;
const DEFAULT: bool = true; const DEFAULT: bool = true;
@ -125,7 +125,12 @@ impl<'a> Step<'a> for Linkcheck<'a> {
path.ends_with("src/tools/linkchecker") path.ends_with("src/tools/linkchecker")
} }
fn make_run(builder: &Builder, path: Option<&Path>, host: &str, _target: &str) { fn make_run(
builder: &Builder,
path: Option<&Path>,
host: Interned<String>,
_target: Interned<String>,
) {
if path.is_some() { if path.is_some() {
builder.ensure(Linkcheck { host }); builder.ensure(Linkcheck { host });
} else { } else {
@ -142,14 +147,13 @@ impl<'a> Step<'a> for Linkcheck<'a> {
// .host(true) // .host(true)
// .run(move |s| check::cargotest(build, s.stage, s.target)); // .run(move |s| check::cargotest(build, s.stage, s.target));
#[derive(Serialize)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct Cargotest<'a> { pub struct Cargotest {
stage: u32, stage: u32,
host: &'a str, host: Interned<String>,
} }
impl<'a> Step<'a> for Cargotest<'a> { impl Step for Cargotest {
type Id = Cargotest<'static>;
type Output = (); type Output = ();
const ONLY_HOSTS: bool = true; const ONLY_HOSTS: bool = true;
@ -157,7 +161,12 @@ impl<'a> Step<'a> for Cargotest<'a> {
path.ends_with("src/tools/cargotest") path.ends_with("src/tools/cargotest")
} }
fn make_run(builder: &Builder, _path: Option<&Path>, host: &str, _target: &str) { fn make_run(
builder: &Builder,
_path: Option<&Path>,
host: Interned<String>,
_target: Interned<String>,
) {
builder.ensure(Cargotest { builder.ensure(Cargotest {
stage: builder.top_stage, stage: builder.top_stage,
host: host, host: host,
@ -193,14 +202,13 @@ impl<'a> Step<'a> for Cargotest<'a> {
// .host(true) // .host(true)
// .run(move |s| check::cargo(build, s.stage, s.target)); // .run(move |s| check::cargo(build, s.stage, s.target));
#[derive(Serialize)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct Cargo<'a> { pub struct Cargo {
stage: u32, stage: u32,
host: &'a str, host: Interned<String>,
} }
impl<'a> Step<'a> for Cargo<'a> { impl Step for Cargo {
type Id = Cargo<'static>;
type Output = (); type Output = ();
const ONLY_HOSTS: bool = true; const ONLY_HOSTS: bool = true;
@ -208,7 +216,12 @@ impl<'a> Step<'a> for Cargo<'a> {
path.ends_with("src/tools/cargo") path.ends_with("src/tools/cargo")
} }
fn make_run(builder: &Builder, _path: Option<&Path>, _host: &str, target: &str) { fn make_run(
builder: &Builder,
_path: Option<&Path>,
_host: Interned<String>,
target: Interned<String>,
) {
builder.ensure(Cargotest { builder.ensure(Cargotest {
stage: builder.top_stage, stage: builder.top_stage,
host: target, host: target,
@ -304,13 +317,12 @@ fn path_for_cargo(build: &Build, compiler: &Compiler) -> OsString {
// .only_build(true) // .only_build(true)
// .run(move |s| check::tidy(build, s.target)); // .run(move |s| check::tidy(build, s.target));
#[derive(Serialize)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct Tidy<'a> { pub struct Tidy {
host: &'a str, host: Interned<String>,
} }
impl<'a> Step<'a> for Tidy<'a> { impl Step for Tidy {
type Id = Tidy<'static>;
type Output = (); type Output = ();
const DEFAULT: bool = true; const DEFAULT: bool = true;
const ONLY_HOSTS: bool = true; const ONLY_HOSTS: bool = true;
@ -342,14 +354,19 @@ impl<'a> Step<'a> for Tidy<'a> {
path.ends_with("src/tools/tidy") path.ends_with("src/tools/tidy")
} }
fn make_run(builder: &Builder, _path: Option<&Path>, _host: &str, _target: &str) { fn make_run(
builder: &Builder,
_path: Option<&Path>,
_host: Interned<String>,
_target: Interned<String>,
) {
builder.ensure(Tidy { builder.ensure(Tidy {
host: &builder.build.build, host: builder.build.build,
}); });
} }
} }
fn testdir(build: &Build, host: &str) -> PathBuf { fn testdir(build: &Build, host: Interned<String>) -> PathBuf {
build.out.join(host).join("test") build.out.join(host).join("test")
} }
@ -451,15 +468,15 @@ fn testdir(build: &Build, host: &str) -> PathBuf {
// "pretty", "run-fail-fulldeps"); // "pretty", "run-fail-fulldeps");
// } // }
#[derive(Serialize)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct Compiletest<'a> { pub struct Compiletest {
compiler: Compiler<'a>, compiler: Compiler,
target: &'a str, target: Interned<String>,
mode: &'a str, mode: &'static str,
suite: &'a str, suite: &'static str,
} }
#[derive(Copy, Clone, Debug, PartialEq)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
struct Test { struct Test {
path: &'static str, path: &'static str,
mode: &'static str, mode: &'static str,
@ -512,8 +529,7 @@ static COMPILETESTS: &[Test] = &[
Test { path: "src/test/debuginfo-gdb", mode: "debuginfo-gdb", suite: "debuginfo" }, Test { path: "src/test/debuginfo-gdb", mode: "debuginfo-gdb", suite: "debuginfo" },
]; ];
impl<'a> Step<'a> for Compiletest<'a> { impl Step for Compiletest {
type Id = Compiletest<'static>;
type Output = (); type Output = ();
const DEFAULT: bool = true; const DEFAULT: bool = true;
@ -526,7 +542,12 @@ impl<'a> Step<'a> for Compiletest<'a> {
}) })
} }
fn make_run(builder: &Builder, path: Option<&Path>, host: &str, target: &str) { fn make_run(
builder: &Builder,
path: Option<&Path>,
host: Interned<String>,
target: Interned<String>,
) {
let compiler = builder.compiler(builder.top_stage, host); let compiler = builder.compiler(builder.top_stage, host);
let test = path.map(|path| { let test = path.map(|path| {
@ -591,12 +612,12 @@ impl<'a> Step<'a> for Compiletest<'a> {
builder.ensure(Compiletest { builder.ensure(Compiletest {
mode: "debuginfo-lldb", mode: "debuginfo-lldb",
..self ..self
}) });
} else { } else {
builder.ensure(Compiletest { builder.ensure(Compiletest {
mode: "debuginfo-gdb", mode: "debuginfo-gdb",
..self ..self
}) });
}; };
} }
@ -606,7 +627,7 @@ impl<'a> Step<'a> for Compiletest<'a> {
} }
builder.ensure(dist::DebuggerScripts { builder.ensure(dist::DebuggerScripts {
sysroot: &builder.sysroot(compiler), sysroot: builder.sysroot(compiler),
target: target target: target
}); });
@ -630,7 +651,7 @@ impl<'a> Step<'a> for Compiletest<'a> {
let _folder = build.fold_output(|| format!("test_{}", suite)); let _folder = build.fold_output(|| format!("test_{}", suite));
println!("Check compiletest suite={} mode={} ({} -> {})", println!("Check compiletest suite={} mode={} ({} -> {})",
suite, mode, compiler.host, target); suite, mode, &compiler.host, target);
let mut cmd = builder.tool_cmd(Tool::Compiletest); let mut cmd = builder.tool_cmd(Tool::Compiletest);
// compiletest currently has... a lot of arguments, so let's just pass all // compiletest currently has... a lot of arguments, so let's just pass all
@ -645,8 +666,8 @@ impl<'a> Step<'a> for Compiletest<'a> {
cmd.arg("--stage-id").arg(format!("stage{}-{}", compiler.stage, target)); cmd.arg("--stage-id").arg(format!("stage{}-{}", compiler.stage, target));
cmd.arg("--mode").arg(mode); cmd.arg("--mode").arg(mode);
cmd.arg("--target").arg(target); cmd.arg("--target").arg(target);
cmd.arg("--host").arg(compiler.host); cmd.arg("--host").arg(&*compiler.host);
cmd.arg("--llvm-filecheck").arg(build.llvm_filecheck(&build.build)); cmd.arg("--llvm-filecheck").arg(build.llvm_filecheck(build.build));
if let Some(ref nodejs) = build.config.nodejs { if let Some(ref nodejs) = build.config.nodejs {
cmd.arg("--nodejs").arg(nodejs); cmd.arg("--nodejs").arg(nodejs);
@ -664,7 +685,7 @@ impl<'a> Step<'a> for Compiletest<'a> {
hostflags.extend(flags.clone()); hostflags.extend(flags.clone());
cmd.arg("--host-rustcflags").arg(hostflags.join(" ")); cmd.arg("--host-rustcflags").arg(hostflags.join(" "));
let mut targetflags = build.rustc_flags(&target); let mut targetflags = build.rustc_flags(target);
targetflags.extend(flags); targetflags.extend(flags);
targetflags.push(format!("-Lnative={}", targetflags.push(format!("-Lnative={}",
build.test_helpers_out(target).display())); build.test_helpers_out(target).display()));
@ -735,7 +756,7 @@ impl<'a> Step<'a> for Compiletest<'a> {
// Note that if we encounter `PATH` we make sure to append to our own `PATH` // Note that if we encounter `PATH` we make sure to append to our own `PATH`
// rather than stomp over it. // rather than stomp over it.
if target.contains("msvc") { if target.contains("msvc") {
for &(ref k, ref v) in build.cc[target].0.env() { for &(ref k, ref v) in build.cc[&target].0.env() {
if k != "PATH" { if k != "PATH" {
cmd.env(k, v); cmd.env(k, v);
} }
@ -769,9 +790,9 @@ impl<'a> Step<'a> for Compiletest<'a> {
} }
} }
#[derive(Serialize)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct Docs<'a> { pub struct Docs {
compiler: Compiler<'a>, compiler: Compiler,
} }
// rules.test("check-docs", "src/doc") // rules.test("check-docs", "src/doc")
@ -779,8 +800,7 @@ pub struct Docs<'a> {
// .default(true) // .default(true)
// .host(true) // .host(true)
// .run(move |s| check::docs(build, &s.compiler())); // .run(move |s| check::docs(build, &s.compiler()));
impl<'a> Step<'a> for Docs<'a> { impl Step for Docs {
type Id = Docs<'static>;
type Output = (); type Output = ();
const DEFAULT: bool = true; const DEFAULT: bool = true;
const ONLY_HOSTS: bool = true; const ONLY_HOSTS: bool = true;
@ -789,7 +809,12 @@ impl<'a> Step<'a> for Docs<'a> {
path.ends_with("src/doc") path.ends_with("src/doc")
} }
fn make_run(builder: &Builder, _path: Option<&Path>, host: &str, _target: &str) { fn make_run(
builder: &Builder,
_path: Option<&Path>,
host: Interned<String>,
_target: Interned<String>,
) {
builder.ensure(Docs { builder.ensure(Docs {
compiler: builder.compiler(builder.top_stage, host), compiler: builder.compiler(builder.top_stage, host),
}); });
@ -840,13 +865,12 @@ impl<'a> Step<'a> for Docs<'a> {
// .host(true) // .host(true)
// .run(move |s| check::error_index(build, &s.compiler())); // .run(move |s| check::error_index(build, &s.compiler()));
#[derive(Serialize)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct ErrorIndex<'a> { pub struct ErrorIndex {
compiler: Compiler<'a>, compiler: Compiler,
} }
impl<'a> Step<'a> for ErrorIndex<'a> { impl Step for ErrorIndex {
type Id = ErrorIndex<'static>;
type Output = (); type Output = ();
const DEFAULT: bool = true; const DEFAULT: bool = true;
const ONLY_HOSTS: bool = true; const ONLY_HOSTS: bool = true;
@ -855,7 +879,12 @@ impl<'a> Step<'a> for ErrorIndex<'a> {
path.ends_with("src/tools/error_index_generator") path.ends_with("src/tools/error_index_generator")
} }
fn make_run(builder: &Builder, _path: Option<&Path>, host: &str, _target: &str) { fn make_run(
builder: &Builder,
_path: Option<&Path>,
host: Interned<String>,
_target: Interned<String>,
) {
builder.ensure(ErrorIndex { builder.ensure(ErrorIndex {
compiler: builder.compiler(builder.top_stage, host), compiler: builder.compiler(builder.top_stage, host),
}); });
@ -933,16 +962,15 @@ fn markdown_test(builder: &Builder, compiler: Compiler, markdown: &Path) {
// .host(true) // .host(true)
// .run(move |s| check::krate(build, &s.compiler(), s.target, // .run(move |s| check::krate(build, &s.compiler(), s.target,
// Mode::Librustc, TestKind::Test, None)); // Mode::Librustc, TestKind::Test, None));
#[derive(Serialize)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct KrateLibrustc<'a> { pub struct KrateLibrustc {
compiler: Compiler<'a>, compiler: Compiler,
target: &'a str, target: Interned<String>,
test_kind: TestKind, test_kind: TestKind,
krate: Option<&'a str>, krate: Option<Interned<String>>,
} }
impl<'a> Step<'a> for KrateLibrustc<'a> { impl Step for KrateLibrustc {
type Id = KrateLibrustc<'static>;
type Output = (); type Output = ();
const DEFAULT: bool = true; const DEFAULT: bool = true;
const ONLY_HOSTS: bool = true; const ONLY_HOSTS: bool = true;
@ -953,10 +981,15 @@ impl<'a> Step<'a> for KrateLibrustc<'a> {
}) })
} }
fn make_run(builder: &Builder, path: Option<&Path>, host: &str, target: &str) { fn make_run(
builder: &Builder,
path: Option<&Path>,
host: Interned<String>,
target: Interned<String>,
) {
let compiler = builder.compiler(builder.top_stage, host); let compiler = builder.compiler(builder.top_stage, host);
let run = |name: Option<&str>| { let run = |name: Option<Interned<String>>| {
let test_kind = if builder.kind == Kind::Test { let test_kind = if builder.kind == Kind::Test {
TestKind::Test TestKind::Test
} else if builder.kind == Kind::Bench { } else if builder.kind == Kind::Bench {
@ -1043,17 +1076,16 @@ impl<'a> Step<'a> for KrateLibrustc<'a> {
// .run(move |s| check::krate(build, &s.compiler(), s.target, // .run(move |s| check::krate(build, &s.compiler(), s.target,
// Mode::Libtest, TestKind::Test, None)); // Mode::Libtest, TestKind::Test, None));
#[derive(Serialize)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct Krate<'a> { pub struct Krate {
compiler: Compiler<'a>, compiler: Compiler,
target: &'a str, target: Interned<String>,
mode: Mode, mode: Mode,
test_kind: TestKind, test_kind: TestKind,
krate: Option<&'a str>, krate: Option<Interned<String>>,
} }
impl<'a> Step<'a> for Krate<'a> { impl Step for Krate {
type Id = Krate<'static>;
type Output = (); type Output = ();
const DEFAULT: bool = true; const DEFAULT: bool = true;
@ -1066,10 +1098,15 @@ impl<'a> Step<'a> for Krate<'a> {
}) })
} }
fn make_run(builder: &Builder, path: Option<&Path>, host: &str, target: &str) { fn make_run(
builder: &Builder,
path: Option<&Path>,
host: Interned<String>,
target: Interned<String>,
) {
let compiler = builder.compiler(builder.top_stage, host); let compiler = builder.compiler(builder.top_stage, host);
let run = |mode: Mode, name: Option<&str>| { let run = |mode: Mode, name: Option<Interned<String>>| {
let test_kind = if builder.kind == Kind::Test { let test_kind = if builder.kind == Kind::Test {
TestKind::Test TestKind::Test
} else if builder.kind == Kind::Bench { } else if builder.kind == Kind::Bench {
@ -1134,11 +1171,12 @@ impl<'a> Step<'a> for Krate<'a> {
} }
_ => panic!("can only test libraries"), _ => panic!("can only test libraries"),
}; };
let root = INTERNER.intern_string(String::from(root));
let _folder = build.fold_output(|| { let _folder = build.fold_output(|| {
format!("{}_stage{}-{}", test_kind.subcommand(), compiler.stage, name) format!("{}_stage{}-{}", test_kind.subcommand(), compiler.stage, name)
}); });
println!("{} {} stage{} ({} -> {})", test_kind, name, compiler.stage, println!("{} {} stage{} ({} -> {})", test_kind, name, compiler.stage,
compiler.host, target); &compiler.host, target);
// If we're not doing a full bootstrap but we're testing a stage2 version of // If we're not doing a full bootstrap but we're testing a stage2 version of
// libstd, then what we're actually testing is the libstd produced in // libstd, then what we're actually testing is the libstd produced in
@ -1180,12 +1218,12 @@ impl<'a> Step<'a> for Krate<'a> {
// target during the bootstrap and it's just meant to be a // target during the bootstrap and it's just meant to be a
// helper crate, not tested. If it leaks through then it ends up // helper crate, not tested. If it leaks through then it ends up
// messing with various mtime calculations and such. // messing with various mtime calculations and such.
if !name.contains("jemalloc") && name != "build_helper" { if !name.contains("jemalloc") && *name != *"build_helper" {
cargo.arg("-p").arg(&format!("{}:0.0.0", name)); cargo.arg("-p").arg(&format!("{}:0.0.0", name));
} }
for dep in build.crates[name].deps.iter() { for dep in build.crates[&name].deps.iter() {
if visited.insert(dep) { if visited.insert(dep) {
next.push(dep); next.push(*dep);
} }
} }
} }
@ -1198,7 +1236,7 @@ impl<'a> Step<'a> for Krate<'a> {
// Note that to run the compiler we need to run with the *host* libraries, // Note that to run the compiler we need to run with the *host* libraries,
// but our wrapper scripts arrange for that to be the case anyway. // but our wrapper scripts arrange for that to be the case anyway.
let mut dylib_path = dylib_path(); let mut dylib_path = dylib_path();
dylib_path.insert(0, builder.sysroot_libdir(compiler, target)); dylib_path.insert(0, PathBuf::from(&*builder.sysroot_libdir(compiler, target)));
cargo.env(dylib_path_var(), env::join_paths(&dylib_path).unwrap()); cargo.env(dylib_path_var(), env::join_paths(&dylib_path).unwrap());
if target.contains("emscripten") || build.remote_tested(target) { if target.contains("emscripten") || build.remote_tested(target) {
@ -1228,7 +1266,7 @@ impl<'a> Step<'a> for Krate<'a> {
fn krate_emscripten(build: &Build, fn krate_emscripten(build: &Build,
compiler: Compiler, compiler: Compiler,
target: &str, target: Interned<String>,
mode: Mode) { mode: Mode) {
let out_dir = build.cargo_out(compiler, mode, target); let out_dir = build.cargo_out(compiler, mode, target);
let tests = find_tests(&out_dir.join("deps"), target); let tests = find_tests(&out_dir.join("deps"), target);
@ -1247,7 +1285,7 @@ fn krate_emscripten(build: &Build,
fn krate_remote(builder: &Builder, fn krate_remote(builder: &Builder,
compiler: Compiler, compiler: Compiler,
target: &str, target: Interned<String>,
mode: Mode) { mode: Mode) {
let build = builder.build; let build = builder.build;
let out_dir = build.cargo_out(compiler, mode, target); let out_dir = build.cargo_out(compiler, mode, target);
@ -1266,7 +1304,7 @@ fn krate_remote(builder: &Builder,
} }
} }
fn find_tests(dir: &Path, target: &str) -> Vec<PathBuf> { fn find_tests(dir: &Path, target: Interned<String>) -> Vec<PathBuf> {
let mut dst = Vec::new(); let mut dst = Vec::new();
for e in t!(dir.read_dir()).map(|e| t!(e)) { for e in t!(dir.read_dir()).map(|e| t!(e)) {
let file_type = t!(e.file_type()); let file_type = t!(e.file_type());
@ -1313,14 +1351,13 @@ fn find_tests(dir: &Path, target: &str) -> Vec<PathBuf> {
/// QEMU we have to build our own tools so we've got conditional dependencies /// QEMU we have to build our own tools so we've got conditional dependencies
/// on those programs as well. Note that the remote test client is built for /// on those programs as well. Note that the remote test client is built for
/// the build target (us) and the server is built for the target. /// the build target (us) and the server is built for the target.
#[derive(Serialize)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct RemoteCopyLibs<'a> { pub struct RemoteCopyLibs {
compiler: Compiler<'a>, compiler: Compiler,
target: &'a str, target: Interned<String>,
} }
impl<'a> Step<'a> for RemoteCopyLibs<'a> { impl Step for RemoteCopyLibs {
type Id = RemoteCopyLibs<'static>;
type Output = (); type Output = ();
fn run(self, builder: &Builder) { fn run(self, builder: &Builder) {
@ -1368,18 +1405,17 @@ impl<'a> Step<'a> for RemoteCopyLibs<'a> {
// .dep(|s| s.name("dist-src")) // .dep(|s| s.name("dist-src"))
// .run(move |_| check::distcheck(build)); // .run(move |_| check::distcheck(build));
#[derive(Serialize)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct Distcheck; pub struct Distcheck;
impl<'a> Step<'a> for Distcheck { impl Step for Distcheck {
type Id = Distcheck;
type Output = (); type Output = ();
/// Run "distcheck", a 'make check' from a tarball /// Run "distcheck", a 'make check' from a tarball
fn run(self, builder: &Builder) { fn run(self, builder: &Builder) {
let build = builder.build; let build = builder.build;
if build.build != "x86_64-unknown-linux-gnu" { if *build.build != *"x86_64-unknown-linux-gnu" {
return return
} }
if !build.config.host.iter().any(|s| s == "x86_64-unknown-linux-gnu") { if !build.config.host.iter().any(|s| s == "x86_64-unknown-linux-gnu") {
@ -1436,11 +1472,10 @@ impl<'a> Step<'a> for Distcheck {
// .only_build(true) // .only_build(true)
// .run(move |_| check::bootstrap(build)); // .run(move |_| check::bootstrap(build));
#[derive(Serialize)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct Bootstrap; pub struct Bootstrap;
impl<'a> Step<'a> for Bootstrap { impl Step for Bootstrap {
type Id = Bootstrap;
type Output = (); type Output = ();
const DEFAULT: bool = true; const DEFAULT: bool = true;
const ONLY_HOSTS: bool = true; const ONLY_HOSTS: bool = true;
@ -1466,7 +1501,12 @@ impl<'a> Step<'a> for Bootstrap {
path.ends_with("src/bootstrap") path.ends_with("src/bootstrap")
} }
fn make_run(builder: &Builder, _path: Option<&Path>, _host: &str, _target: &str) { fn make_run(
builder: &Builder,
_path: Option<&Path>,
_host: Interned<String>,
_target: Interned<String>,
) {
builder.ensure(Bootstrap); builder.ensure(Bootstrap);
} }
} }

View File

@ -32,6 +32,7 @@ use util::{exe, libdir, is_dylib, copy};
use {Build, Compiler, Mode}; use {Build, Compiler, Mode};
use native; use native;
use cache::{INTERNER, Interned};
use builder::{Step, Builder}; use builder::{Step, Builder};
// //
@ -140,14 +141,13 @@ use builder::{Step, Builder};
// .dep(move |s| s.name("rustc").host(&build.build).target(s.host)) // .dep(move |s| s.name("rustc").host(&build.build).target(s.host))
// .run(move |s| compile::std(build, s.target, &s.compiler())); // .run(move |s| compile::std(build, s.target, &s.compiler()));
// } // }
#[derive(Serialize)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct Std<'a> { pub struct Std {
pub target: &'a str, pub target: Interned<String>,
pub compiler: Compiler<'a>, pub compiler: Compiler,
} }
impl<'a> Step<'a> for Std<'a> { impl Step for Std {
type Id = Std<'static>;
type Output = (); type Output = ();
const DEFAULT: bool = true; const DEFAULT: bool = true;
@ -158,11 +158,16 @@ impl<'a> Step<'a> for Std<'a> {
}) })
} }
fn make_run(builder: &Builder, _path: Option<&Path>, host: &str, target: &str) { fn make_run(
builder: &Builder,
_path: Option<&Path>,
host: Interned<String>,
target: Interned<String>,
) {
builder.ensure(Std { builder.ensure(Std {
compiler: builder.compiler(builder.top_stage, host), compiler: builder.compiler(builder.top_stage, host),
target, target,
}) });
} }
/// Build the standard library. /// Build the standard library.
@ -178,7 +183,7 @@ impl<'a> Step<'a> for Std<'a> {
builder.ensure(StartupObjects { compiler, target }); builder.ensure(StartupObjects { compiler, target });
if build.force_use_stage1(compiler, target) { if build.force_use_stage1(compiler, target) {
let from = builder.compiler(1, &build.build); let from = builder.compiler(1, build.build);
builder.ensure(Std { builder.ensure(Std {
compiler: from, compiler: from,
target: target, target: target,
@ -194,7 +199,7 @@ impl<'a> Step<'a> for Std<'a> {
let _folder = build.fold_output(|| format!("stage{}-std", compiler.stage)); let _folder = build.fold_output(|| format!("stage{}-std", compiler.stage));
println!("Building stage{} std artifacts ({} -> {})", compiler.stage, println!("Building stage{} std artifacts ({} -> {})", compiler.stage,
compiler.host, target); &compiler.host, target);
let out_dir = build.cargo_out(compiler, Mode::Libstd, target); let out_dir = build.cargo_out(compiler, Mode::Libstd, target);
build.clear_if_dirty(&out_dir, &builder.rustc(compiler)); build.clear_if_dirty(&out_dir, &builder.rustc(compiler));
@ -229,7 +234,7 @@ impl<'a> Step<'a> for Std<'a> {
.arg("--manifest-path") .arg("--manifest-path")
.arg(build.src.join("src/libstd/Cargo.toml")); .arg(build.src.join("src/libstd/Cargo.toml"));
if let Some(target) = build.config.target_config.get(target) { if let Some(target) = build.config.target_config.get(&target) {
if let Some(ref jemalloc) = target.jemalloc { if let Some(ref jemalloc) = target.jemalloc {
cargo.env("JEMALLOC_OVERRIDE", jemalloc); cargo.env("JEMALLOC_OVERRIDE", jemalloc);
} }
@ -245,7 +250,7 @@ impl<'a> Step<'a> for Std<'a> {
&libstd_stamp(build, compiler, target)); &libstd_stamp(build, compiler, target));
builder.ensure(StdLink { builder.ensure(StdLink {
compiler: builder.compiler(compiler.stage, &build.build), compiler: builder.compiler(compiler.stage, build.build),
target_compiler: compiler, target_compiler: compiler,
target: target, target: target,
}); });
@ -261,15 +266,14 @@ impl<'a> Step<'a> for Std<'a> {
// .dep(|s| s.name("startup-objects")) // .dep(|s| s.name("startup-objects"))
// .dep(|s| s.name("create-sysroot").target(s.host)); // .dep(|s| s.name("create-sysroot").target(s.host));
#[derive(Serialize)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
struct StdLink<'a> { struct StdLink {
pub compiler: Compiler<'a>, pub compiler: Compiler,
pub target_compiler: Compiler<'a>, pub target_compiler: Compiler,
pub target: &'a str, pub target: Interned<String>,
} }
impl<'a> Step<'a> for StdLink<'a> { impl Step for StdLink {
type Id = StdLink<'static>;
type Output = (); type Output = ();
/// Link all libstd rlibs/dylibs into the sysroot location. /// Link all libstd rlibs/dylibs into the sysroot location.
@ -288,7 +292,7 @@ impl<'a> Step<'a> for StdLink<'a> {
println!("Copying stage{} std from stage{} ({} -> {} / {})", println!("Copying stage{} std from stage{} ({} -> {} / {})",
target_compiler.stage, target_compiler.stage,
compiler.stage, compiler.stage,
compiler.host, &compiler.host,
target_compiler.host, target_compiler.host,
target); target);
let libdir = builder.sysroot_libdir(target_compiler, target); let libdir = builder.sysroot_libdir(target_compiler, target);
@ -310,7 +314,7 @@ impl<'a> Step<'a> for StdLink<'a> {
/// Copies the crt(1,i,n).o startup objects /// Copies the crt(1,i,n).o startup objects
/// ///
/// Only required for musl targets that statically link to libc /// Only required for musl targets that statically link to libc
fn copy_musl_third_party_objects(build: &Build, target: &str, into: &Path) { fn copy_musl_third_party_objects(build: &Build, target: Interned<String>, into: &Path) {
for &obj in &["crt1.o", "crti.o", "crtn.o"] { for &obj in &["crt1.o", "crti.o", "crtn.o"] {
copy(&build.musl_root(target).unwrap().join("lib").join(obj), &into.join(obj)); copy(&build.musl_root(target).unwrap().join("lib").join(obj), &into.join(obj));
} }
@ -332,25 +336,29 @@ fn copy_apple_sanitizer_dylibs(native_dir: &Path, platform: &str, into: &Path) {
// .dep(|s| s.name("create-sysroot").target(s.host)) // .dep(|s| s.name("create-sysroot").target(s.host))
// .run(move |s| compile::build_startup_objects(build, &s.compiler(), s.target)); // .run(move |s| compile::build_startup_objects(build, &s.compiler(), s.target));
#[derive(Serialize)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct StartupObjects<'a> { pub struct StartupObjects {
pub compiler: Compiler<'a>, pub compiler: Compiler,
pub target: &'a str, pub target: Interned<String>,
} }
impl<'a> Step<'a> for StartupObjects<'a> { impl Step for StartupObjects {
type Id = StartupObjects<'static>;
type Output = (); type Output = ();
fn should_run(_builder: &Builder, path: &Path) -> bool { fn should_run(_builder: &Builder, path: &Path) -> bool {
path.ends_with("src/rtstartup") path.ends_with("src/rtstartup")
} }
fn make_run(builder: &Builder, _path: Option<&Path>, host: &str, target: &str) { fn make_run(
builder: &Builder,
_path: Option<&Path>,
host: Interned<String>,
target: Interned<String>,
) {
builder.ensure(StartupObjects { builder.ensure(StartupObjects {
compiler: builder.compiler(builder.top_stage, host), compiler: builder.compiler(builder.top_stage, host),
target, target,
}) });
} }
/// Build and prepare startup objects like rsbegin.o and rsend.o /// Build and prepare startup objects like rsbegin.o and rsend.o
@ -399,14 +407,13 @@ impl<'a> Step<'a> for StartupObjects<'a> {
// .dep(|s| s.name("libstd-link")) // .dep(|s| s.name("libstd-link"))
// .run(move |s| compile::test(build, s.target, &s.compiler())); // .run(move |s| compile::test(build, s.target, &s.compiler()));
// } // }
#[derive(Serialize)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct Test<'a> { pub struct Test {
pub compiler: Compiler<'a>, pub compiler: Compiler,
pub target: &'a str, pub target: Interned<String>,
} }
impl<'a> Step<'a> for Test<'a> { impl Step for Test {
type Id = Test<'static>;
type Output = (); type Output = ();
const DEFAULT: bool = true; const DEFAULT: bool = true;
@ -417,11 +424,16 @@ impl<'a> Step<'a> for Test<'a> {
}) })
} }
fn make_run(builder: &Builder, _path: Option<&Path>, host: &str, target: &str) { fn make_run(
builder: &Builder,
_path: Option<&Path>,
host: Interned<String>,
target: Interned<String>,
) {
builder.ensure(Test { builder.ensure(Test {
compiler: builder.compiler(builder.top_stage, host), compiler: builder.compiler(builder.top_stage, host),
target, target,
}) });
} }
/// Build libtest. /// Build libtest.
@ -438,12 +450,12 @@ impl<'a> Step<'a> for Test<'a> {
if build.force_use_stage1(compiler, target) { if build.force_use_stage1(compiler, target) {
builder.ensure(Test { builder.ensure(Test {
compiler: builder.compiler(1, &build.build), compiler: builder.compiler(1, build.build),
target: target, target: target,
}); });
println!("Uplifting stage1 test ({} -> {})", &build.build, target); println!("Uplifting stage1 test ({} -> {})", &build.build, target);
builder.ensure(TestLink { builder.ensure(TestLink {
compiler: builder.compiler(1, &build.build), compiler: builder.compiler(1, build.build),
target_compiler: compiler, target_compiler: compiler,
target: target, target: target,
}); });
@ -452,7 +464,7 @@ impl<'a> Step<'a> for Test<'a> {
let _folder = build.fold_output(|| format!("stage{}-test", compiler.stage)); let _folder = build.fold_output(|| format!("stage{}-test", compiler.stage));
println!("Building stage{} test artifacts ({} -> {})", compiler.stage, println!("Building stage{} test artifacts ({} -> {})", compiler.stage,
compiler.host, target); &compiler.host, target);
let out_dir = build.cargo_out(compiler, Mode::Libtest, target); let out_dir = build.cargo_out(compiler, Mode::Libtest, target);
build.clear_if_dirty(&out_dir, &libstd_stamp(build, compiler, target)); build.clear_if_dirty(&out_dir, &libstd_stamp(build, compiler, target));
let mut cargo = builder.cargo(compiler, Mode::Libtest, target, "build"); let mut cargo = builder.cargo(compiler, Mode::Libtest, target, "build");
@ -466,7 +478,7 @@ impl<'a> Step<'a> for Test<'a> {
&libtest_stamp(build, compiler, target)); &libtest_stamp(build, compiler, target));
builder.ensure(TestLink { builder.ensure(TestLink {
compiler: builder.compiler(compiler.stage, &build.build), compiler: builder.compiler(compiler.stage, build.build),
target_compiler: compiler, target_compiler: compiler,
target: target, target: target,
}); });
@ -481,15 +493,14 @@ impl<'a> Step<'a> for Test<'a> {
// compile::test_link) // compile::test_link)
// .dep(|s| s.name("libstd-link")); // .dep(|s| s.name("libstd-link"));
#[derive(Serialize)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct TestLink<'a> { pub struct TestLink {
pub compiler: Compiler<'a>, pub compiler: Compiler,
pub target_compiler: Compiler<'a>, pub target_compiler: Compiler,
pub target: &'a str, pub target: Interned<String>,
} }
impl<'a> Step<'a> for TestLink<'a> { impl Step for TestLink {
type Id = TestLink<'static>;
type Output = (); type Output = ();
/// Same as `std_link`, only for libtest /// Same as `std_link`, only for libtest
@ -501,7 +512,7 @@ impl<'a> Step<'a> for TestLink<'a> {
println!("Copying stage{} test from stage{} ({} -> {} / {})", println!("Copying stage{} test from stage{} ({} -> {} / {})",
target_compiler.stage, target_compiler.stage,
compiler.stage, compiler.stage,
compiler.host, &compiler.host,
target_compiler.host, target_compiler.host,
target); target);
add_to_sysroot(&builder.sysroot_libdir(target_compiler, target), add_to_sysroot(&builder.sysroot_libdir(target_compiler, target),
@ -517,14 +528,13 @@ impl<'a> Step<'a> for TestLink<'a> {
// .run(move |s| compile::rustc(build, s.target, &s.compiler())); // .run(move |s| compile::rustc(build, s.target, &s.compiler()));
// } // }
#[derive(Serialize)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct Rustc<'a> { pub struct Rustc {
pub compiler: Compiler<'a>, pub compiler: Compiler,
pub target: &'a str, pub target: Interned<String>,
} }
impl<'a> Step<'a> for Rustc<'a> { impl Step for Rustc {
type Id = Rustc<'static>;
type Output = (); type Output = ();
const ONLY_HOSTS: bool = true; const ONLY_HOSTS: bool = true;
const DEFAULT: bool = true; const DEFAULT: bool = true;
@ -536,11 +546,16 @@ impl<'a> Step<'a> for Rustc<'a> {
}) })
} }
fn make_run(builder: &Builder, _path: Option<&Path>, host: &str, target: &str) { fn make_run(
builder: &Builder,
_path: Option<&Path>,
host: Interned<String>,
target: Interned<String>,
) {
builder.ensure(Rustc { builder.ensure(Rustc {
compiler: builder.compiler(builder.top_stage, host), compiler: builder.compiler(builder.top_stage, host),
target, target,
}) });
} }
/// Build the compiler. /// Build the compiler.
@ -561,12 +576,12 @@ impl<'a> Step<'a> for Rustc<'a> {
if build.force_use_stage1(compiler, target) { if build.force_use_stage1(compiler, target) {
builder.ensure(Rustc { builder.ensure(Rustc {
compiler: builder.compiler(1, &build.build), compiler: builder.compiler(1, build.build),
target: target, target: target,
}); });
println!("Uplifting stage1 rustc ({} -> {})", &build.build, target); println!("Uplifting stage1 rustc ({} -> {})", &build.build, target);
builder.ensure(RustcLink { builder.ensure(RustcLink {
compiler: builder.compiler(1, &build.build), compiler: builder.compiler(1, build.build),
target_compiler: compiler, target_compiler: compiler,
target, target,
}); });
@ -575,13 +590,13 @@ impl<'a> Step<'a> for Rustc<'a> {
// Ensure that build scripts have a std to link against. // Ensure that build scripts have a std to link against.
builder.ensure(Std { builder.ensure(Std {
compiler: builder.compiler(self.compiler.stage, &build.build), compiler: builder.compiler(self.compiler.stage, build.build),
target: &build.build, target: build.build,
}); });
let _folder = build.fold_output(|| format!("stage{}-rustc", compiler.stage)); let _folder = build.fold_output(|| format!("stage{}-rustc", compiler.stage));
println!("Building stage{} compiler artifacts ({} -> {})", println!("Building stage{} compiler artifacts ({} -> {})",
compiler.stage, compiler.host, target); compiler.stage, &compiler.host, target);
let out_dir = build.cargo_out(compiler, Mode::Librustc, target); let out_dir = build.cargo_out(compiler, Mode::Librustc, target);
build.clear_if_dirty(&out_dir, &libtest_stamp(build, compiler, target)); build.clear_if_dirty(&out_dir, &libtest_stamp(build, compiler, target));
@ -627,7 +642,7 @@ impl<'a> Step<'a> for Rustc<'a> {
cargo.env("LLVM_RUSTLLVM", "1"); cargo.env("LLVM_RUSTLLVM", "1");
} }
cargo.env("LLVM_CONFIG", build.llvm_config(target)); cargo.env("LLVM_CONFIG", build.llvm_config(target));
let target_config = build.config.target_config.get(target); let target_config = build.config.target_config.get(&target);
if let Some(s) = target_config.and_then(|c| c.llvm_config.as_ref()) { if let Some(s) = target_config.and_then(|c| c.llvm_config.as_ref()) {
cargo.env("CFG_LLVM_ROOT", s); cargo.env("CFG_LLVM_ROOT", s);
} }
@ -653,7 +668,7 @@ impl<'a> Step<'a> for Rustc<'a> {
&librustc_stamp(build, compiler, target)); &librustc_stamp(build, compiler, target));
builder.ensure(RustcLink { builder.ensure(RustcLink {
compiler: builder.compiler(compiler.stage, &build.build), compiler: builder.compiler(compiler.stage, build.build),
target_compiler: compiler, target_compiler: compiler,
target, target,
}); });
@ -666,15 +681,14 @@ impl<'a> Step<'a> for Rustc<'a> {
// "build-crate-rustc-main", // "build-crate-rustc-main",
// compile::rustc_link) // compile::rustc_link)
// .dep(|s| s.name("libtest-link")); // .dep(|s| s.name("libtest-link"));
#[derive(Serialize)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
struct RustcLink<'a> { struct RustcLink {
pub compiler: Compiler<'a>, pub compiler: Compiler,
pub target_compiler: Compiler<'a>, pub target_compiler: Compiler,
pub target: &'a str, pub target: Interned<String>,
} }
impl<'a> Step<'a> for RustcLink<'a> { impl Step for RustcLink {
type Id = RustcLink<'static>;
type Output = (); type Output = ();
/// Same as `std_link`, only for librustc /// Same as `std_link`, only for librustc
@ -686,7 +700,7 @@ impl<'a> Step<'a> for RustcLink<'a> {
println!("Copying stage{} rustc from stage{} ({} -> {} / {})", println!("Copying stage{} rustc from stage{} ({} -> {} / {})",
target_compiler.stage, target_compiler.stage,
compiler.stage, compiler.stage,
compiler.host, &compiler.host,
target_compiler.host, target_compiler.host,
target); target);
add_to_sysroot(&builder.sysroot_libdir(target_compiler, target), add_to_sysroot(&builder.sysroot_libdir(target_compiler, target),
@ -696,19 +710,19 @@ impl<'a> Step<'a> for RustcLink<'a> {
/// Cargo's output path for the standard library in a given stage, compiled /// Cargo's output path for the standard library in a given stage, compiled
/// by a particular compiler for the specified target. /// by a particular compiler for the specified target.
pub fn libstd_stamp(build: &Build, compiler: Compiler, target: &str) -> PathBuf { pub fn libstd_stamp(build: &Build, compiler: Compiler, target: Interned<String>) -> PathBuf {
build.cargo_out(compiler, Mode::Libstd, target).join(".libstd.stamp") build.cargo_out(compiler, Mode::Libstd, target).join(".libstd.stamp")
} }
/// Cargo's output path for libtest in a given stage, compiled by a particular /// Cargo's output path for libtest in a given stage, compiled by a particular
/// compiler for the specified target. /// compiler for the specified target.
pub fn libtest_stamp(build: &Build, compiler: Compiler, target: &str) -> PathBuf { pub fn libtest_stamp(build: &Build, compiler: Compiler, target: Interned<String>) -> PathBuf {
build.cargo_out(compiler, Mode::Libtest, target).join(".libtest.stamp") build.cargo_out(compiler, Mode::Libtest, target).join(".libtest.stamp")
} }
/// Cargo's output path for librustc in a given stage, compiled by a particular /// Cargo's output path for librustc in a given stage, compiled by a particular
/// compiler for the specified target. /// compiler for the specified target.
pub fn librustc_stamp(build: &Build, compiler: Compiler, target: &str) -> PathBuf { pub fn librustc_stamp(build: &Build, compiler: Compiler, target: Interned<String>) -> PathBuf {
build.cargo_out(compiler, Mode::Librustc, target).join(".librustc.stamp") build.cargo_out(compiler, Mode::Librustc, target).join(".librustc.stamp")
} }
@ -721,14 +735,13 @@ fn compiler_file(compiler: &Path, file: &str) -> PathBuf {
// rules.build("create-sysroot", "path/to/nowhere") // rules.build("create-sysroot", "path/to/nowhere")
// .run(move |s| compile::create_sysroot(build, &s.compiler())); // .run(move |s| compile::create_sysroot(build, &s.compiler()));
#[derive(Serialize)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct Sysroot<'a> { pub struct Sysroot {
pub compiler: Compiler<'a>, pub compiler: Compiler,
} }
impl<'a> Step<'a> for Sysroot<'a> { impl Step for Sysroot {
type Id = Sysroot<'static>; type Output = Interned<PathBuf>;
type Output = PathBuf;
/// Returns the sysroot for the `compiler` specified that *this build system /// Returns the sysroot for the `compiler` specified that *this build system
/// generates*. /// generates*.
@ -736,17 +749,17 @@ impl<'a> Step<'a> for Sysroot<'a> {
/// That is, the sysroot for the stage0 compiler is not what the compiler /// That is, the sysroot for the stage0 compiler is not what the compiler
/// thinks it is by default, but it's the same as the default for stages /// thinks it is by default, but it's the same as the default for stages
/// 1-3. /// 1-3.
fn run(self, builder: &Builder) -> PathBuf { fn run(self, builder: &Builder) -> Interned<PathBuf> {
let build = builder.build; let build = builder.build;
let compiler = self.compiler; let compiler = self.compiler;
let sysroot = if compiler.stage == 0 { let sysroot = if compiler.stage == 0 {
build.out.join(compiler.host).join("stage0-sysroot") build.out.join(&compiler.host).join("stage0-sysroot")
} else { } else {
build.out.join(compiler.host).join(format!("stage{}", compiler.stage)) build.out.join(&compiler.host).join(format!("stage{}", compiler.stage))
}; };
let _ = fs::remove_dir_all(&sysroot); let _ = fs::remove_dir_all(&sysroot);
t!(fs::create_dir_all(&sysroot)); t!(fs::create_dir_all(&sysroot));
sysroot INTERNER.intern_path(sysroot)
} }
} }
@ -764,25 +777,24 @@ impl<'a> Step<'a> for Sysroot<'a> {
// }) // })
// .run(move |s| compile::assemble_rustc(build, s.stage, s.target)); // .run(move |s| compile::assemble_rustc(build, s.stage, s.target));
#[derive(Serialize)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct Assemble<'a> { pub struct Assemble {
/// The compiler which we will produce in this step. Assemble itself will /// The compiler which we will produce in this step. Assemble itself will
/// take care of ensuring that the necessary prerequisites to do so exist, /// take care of ensuring that the necessary prerequisites to do so exist,
/// that is, this target can be a stage2 compiler and Assemble will build /// that is, this target can be a stage2 compiler and Assemble will build
/// previous stages for you. /// previous stages for you.
pub target_compiler: Compiler<'a>, pub target_compiler: Compiler,
} }
impl<'a> Step<'a> for Assemble<'a> { impl Step for Assemble {
type Id = Assemble<'static>; type Output = Compiler;
type Output = Compiler<'a>;
/// Prepare a new compiler from the artifacts in `stage` /// Prepare a new compiler from the artifacts in `stage`
/// ///
/// This will assemble a compiler in `build/$host/stage$stage`. The compiler /// This will assemble a compiler in `build/$host/stage$stage`. The compiler
/// must have been previously produced by the `stage - 1` build.build /// must have been previously produced by the `stage - 1` build.build
/// compiler. /// compiler.
fn run(self, builder: &Builder) -> Compiler<'a> { fn run(self, builder: &Builder) -> Compiler {
let build = builder.build; let build = builder.build;
let target_compiler = self.target_compiler; let target_compiler = self.target_compiler;
@ -799,21 +811,14 @@ impl<'a> Step<'a> for Assemble<'a> {
// compiler for the host platform for this because it doesn't have // compiler for the host platform for this because it doesn't have
// the libraries we need. FIXME: Perhaps we should download those // the libraries we need. FIXME: Perhaps we should download those
// libraries? It would make builds faster... // libraries? It would make builds faster...
builder.ensure(Assemble { // FIXME: It may be faster if we build just a stage 1
target_compiler: Compiler { // compiler and then use that to bootstrap this compiler
// FIXME: It may be faster if we build just a stage 1 // forward.
// compiler and then use that to bootstrap this compiler builder.compiler(target_compiler.stage - 1, build.build)
// forward.
stage: target_compiler.stage - 1,
host: &build.build
},
})
} else { } else {
// Build the compiler we'll use to build the stage requested. This // Build the compiler we'll use to build the stage requested. This
// may build more than one compiler (going down to stage 0). // may build more than one compiler (going down to stage 0).
builder.ensure(Assemble { builder.compiler(target_compiler.stage - 1, target_compiler.host)
target_compiler: target_compiler.with_stage(target_compiler.stage - 1),
})
}; };
// Build the libraries for this compiler to link to (i.e., the libraries // Build the libraries for this compiler to link to (i.e., the libraries
@ -829,7 +834,7 @@ impl<'a> Step<'a> for Assemble<'a> {
// Link in all dylibs to the libdir // Link in all dylibs to the libdir
let sysroot = builder.sysroot(target_compiler); let sysroot = builder.sysroot(target_compiler);
let sysroot_libdir = sysroot.join(libdir(host)); let sysroot_libdir = sysroot.join(libdir(&*host));
t!(fs::create_dir_all(&sysroot_libdir)); t!(fs::create_dir_all(&sysroot_libdir));
let src_libdir = builder.sysroot_libdir(build_compiler, host); 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 t!(fs::read_dir(&src_libdir)).map(|f| t!(f)) {
@ -842,7 +847,7 @@ impl<'a> Step<'a> for Assemble<'a> {
let out_dir = build.cargo_out(build_compiler, Mode::Librustc, host); let out_dir = build.cargo_out(build_compiler, Mode::Librustc, host);
// Link the compiler binary itself into place // Link the compiler binary itself into place
let rustc = out_dir.join(exe("rustc", host)); let rustc = out_dir.join(exe("rustc", &*host));
let bindir = sysroot.join("bin"); let bindir = sysroot.join("bin");
t!(fs::create_dir_all(&bindir)); t!(fs::create_dir_all(&bindir));
let compiler = builder.rustc(target_compiler); let compiler = builder.rustc(target_compiler);
@ -850,7 +855,7 @@ impl<'a> Step<'a> for Assemble<'a> {
copy(&rustc, &compiler); copy(&rustc, &compiler);
// See if rustdoc exists to link it into place // See if rustdoc exists to link it into place
let rustdoc = exe("rustdoc", host); let rustdoc = exe("rustdoc", &*host);
let rustdoc_src = out_dir.join(&rustdoc); let rustdoc_src = out_dir.join(&rustdoc);
let rustdoc_dst = bindir.join(&rustdoc); let rustdoc_dst = bindir.join(&rustdoc);
if fs::metadata(&rustdoc_src).is_ok() { if fs::metadata(&rustdoc_src).is_ok() {

View File

@ -23,6 +23,7 @@ use std::process;
use num_cpus; use num_cpus;
use toml; use toml;
use util::{exe, push_exe_path}; use util::{exe, push_exe_path};
use cache::{INTERNER, Interned};
/// Global configuration for the entire build and/or bootstrap. /// Global configuration for the entire build and/or bootstrap.
/// ///
@ -45,7 +46,7 @@ pub struct Config {
pub docs: bool, pub docs: bool,
pub locked_deps: bool, pub locked_deps: bool,
pub vendor: bool, pub vendor: bool,
pub target_config: HashMap<String, Target>, pub target_config: HashMap<Interned<String>, Target>,
pub full_bootstrap: bool, pub full_bootstrap: bool,
pub extended: bool, pub extended: bool,
pub sanitizers: bool, pub sanitizers: bool,
@ -77,9 +78,9 @@ pub struct Config {
pub rust_debuginfo_tests: bool, pub rust_debuginfo_tests: bool,
pub rust_dist_src: bool, pub rust_dist_src: bool,
pub build: String, pub build: Interned<String>,
pub host: Vec<String>, pub host: Vec<Interned<String>>,
pub target: Vec<String>, pub target: Vec<Interned<String>>,
pub local_rebuild: bool, pub local_rebuild: bool,
// dist misc // dist misc
@ -282,7 +283,7 @@ impl Config {
config.docs = true; config.docs = true;
config.rust_rpath = true; config.rust_rpath = true;
config.rust_codegen_units = 1; config.rust_codegen_units = 1;
config.build = build.to_string(); config.build = INTERNER.intern_str(build);
config.channel = "dev".to_string(); config.channel = "dev".to_string();
config.codegen_tests = true; config.codegen_tests = true;
config.rust_dist_src = true; config.rust_dist_src = true;
@ -302,16 +303,19 @@ impl Config {
}).unwrap_or_else(|| TomlConfig::default()); }).unwrap_or_else(|| TomlConfig::default());
let build = toml.build.clone().unwrap_or(Build::default()); let build = toml.build.clone().unwrap_or(Build::default());
set(&mut config.build, build.build.clone()); set(&mut config.build, build.build.clone().map(|x| INTERNER.intern_string(x)));
config.host.push(config.build.clone()); config.host.push(config.build.clone());
for host in build.host.iter() { for host in build.host.iter() {
if !config.host.contains(host) { let host = INTERNER.intern_str(host);
config.host.push(host.clone()); if !config.host.contains(&host) {
config.host.push(host);
} }
} }
for target in config.host.iter().chain(&build.target) { for target in config.host.iter().cloned()
if !config.target.contains(target) { .chain(build.target.iter().map(|s| INTERNER.intern_str(s)))
config.target.push(target.clone()); {
if !config.target.contains(&target) {
config.target.push(target);
} }
} }
config.nodejs = build.nodejs.map(PathBuf::from); config.nodejs = build.nodejs.map(PathBuf::from);
@ -404,7 +408,7 @@ impl Config {
target.musl_root = cfg.musl_root.clone().map(PathBuf::from); target.musl_root = cfg.musl_root.clone().map(PathBuf::from);
target.qemu_rootfs = cfg.qemu_rootfs.clone().map(PathBuf::from); target.qemu_rootfs = cfg.qemu_rootfs.clone().map(PathBuf::from);
config.target_config.insert(triple.clone(), target); config.target_config.insert(INTERNER.intern_string(triple.clone()), target);
} }
} }
@ -506,13 +510,13 @@ impl Config {
} }
match key { match key {
"CFG_BUILD" if value.len() > 0 => self.build = value.to_string(), "CFG_BUILD" if value.len() > 0 => self.build = INTERNER.intern_str(value),
"CFG_HOST" if value.len() > 0 => { "CFG_HOST" if value.len() > 0 => {
self.host.extend(value.split(" ").map(|s| s.to_string())); self.host.extend(value.split(" ").map(|s| INTERNER.intern_str(s)));
} }
"CFG_TARGET" if value.len() > 0 => { "CFG_TARGET" if value.len() > 0 => {
self.target.extend(value.split(" ").map(|s| s.to_string())); self.target.extend(value.split(" ").map(|s| INTERNER.intern_str(s)));
} }
"CFG_EXPERIMENTAL_TARGETS" if value.len() > 0 => { "CFG_EXPERIMENTAL_TARGETS" if value.len() > 0 => {
self.llvm_experimental_targets = Some(value.to_string()); self.llvm_experimental_targets = Some(value.to_string());
@ -521,33 +525,28 @@ impl Config {
self.musl_root = Some(parse_configure_path(value)); self.musl_root = Some(parse_configure_path(value));
} }
"CFG_MUSL_ROOT_X86_64" if value.len() > 0 => { "CFG_MUSL_ROOT_X86_64" if value.len() > 0 => {
let target = "x86_64-unknown-linux-musl".to_string(); let target = INTERNER.intern_str("x86_64-unknown-linux-musl");
let target = self.target_config.entry(target) let target = self.target_config.entry(target).or_insert(Target::default());
.or_insert(Target::default());
target.musl_root = Some(parse_configure_path(value)); target.musl_root = Some(parse_configure_path(value));
} }
"CFG_MUSL_ROOT_I686" if value.len() > 0 => { "CFG_MUSL_ROOT_I686" if value.len() > 0 => {
let target = "i686-unknown-linux-musl".to_string(); let target = INTERNER.intern_str("i686-unknown-linux-musl");
let target = self.target_config.entry(target) let target = self.target_config.entry(target).or_insert(Target::default());
.or_insert(Target::default());
target.musl_root = Some(parse_configure_path(value)); target.musl_root = Some(parse_configure_path(value));
} }
"CFG_MUSL_ROOT_ARM" if value.len() > 0 => { "CFG_MUSL_ROOT_ARM" if value.len() > 0 => {
let target = "arm-unknown-linux-musleabi".to_string(); let target = INTERNER.intern_str("arm-unknown-linux-musleabi");
let target = self.target_config.entry(target) let target = self.target_config.entry(target).or_insert(Target::default());
.or_insert(Target::default());
target.musl_root = Some(parse_configure_path(value)); target.musl_root = Some(parse_configure_path(value));
} }
"CFG_MUSL_ROOT_ARMHF" if value.len() > 0 => { "CFG_MUSL_ROOT_ARMHF" if value.len() > 0 => {
let target = "arm-unknown-linux-musleabihf".to_string(); let target = INTERNER.intern_str("arm-unknown-linux-musleabihf");
let target = self.target_config.entry(target) let target = self.target_config.entry(target).or_insert(Target::default());
.or_insert(Target::default());
target.musl_root = Some(parse_configure_path(value)); target.musl_root = Some(parse_configure_path(value));
} }
"CFG_MUSL_ROOT_ARMV7" if value.len() > 0 => { "CFG_MUSL_ROOT_ARMV7" if value.len() > 0 => {
let target = "armv7-unknown-linux-musleabihf".to_string(); let target = INTERNER.intern_str("armv7-unknown-linux-musleabihf");
let target = self.target_config.entry(target) let target = self.target_config.entry(target).or_insert(Target::default());
.or_insert(Target::default());
target.musl_root = Some(parse_configure_path(value)); target.musl_root = Some(parse_configure_path(value));
} }
"CFG_DEFAULT_AR" if value.len() > 0 => { "CFG_DEFAULT_AR" if value.len() > 0 => {
@ -595,33 +594,28 @@ impl Config {
target.jemalloc = Some(parse_configure_path(value).join("libjemalloc_pic.a")); target.jemalloc = Some(parse_configure_path(value).join("libjemalloc_pic.a"));
} }
"CFG_ARM_LINUX_ANDROIDEABI_NDK" if value.len() > 0 => { "CFG_ARM_LINUX_ANDROIDEABI_NDK" if value.len() > 0 => {
let target = "arm-linux-androideabi".to_string(); let target = INTERNER.intern_str("arm-linux-androideabi");
let target = self.target_config.entry(target) let target = self.target_config.entry(target).or_insert(Target::default());
.or_insert(Target::default());
target.ndk = Some(parse_configure_path(value)); target.ndk = Some(parse_configure_path(value));
} }
"CFG_ARMV7_LINUX_ANDROIDEABI_NDK" if value.len() > 0 => { "CFG_ARMV7_LINUX_ANDROIDEABI_NDK" if value.len() > 0 => {
let target = "armv7-linux-androideabi".to_string(); let target = INTERNER.intern_str("armv7-linux-androideabi");
let target = self.target_config.entry(target) let target = self.target_config.entry(target).or_insert(Target::default());
.or_insert(Target::default());
target.ndk = Some(parse_configure_path(value)); target.ndk = Some(parse_configure_path(value));
} }
"CFG_I686_LINUX_ANDROID_NDK" if value.len() > 0 => { "CFG_I686_LINUX_ANDROID_NDK" if value.len() > 0 => {
let target = "i686-linux-android".to_string(); let target = INTERNER.intern_str("i686-linux-android");
let target = self.target_config.entry(target) let target = self.target_config.entry(target).or_insert(Target::default());
.or_insert(Target::default());
target.ndk = Some(parse_configure_path(value)); target.ndk = Some(parse_configure_path(value));
} }
"CFG_AARCH64_LINUX_ANDROID_NDK" if value.len() > 0 => { "CFG_AARCH64_LINUX_ANDROID_NDK" if value.len() > 0 => {
let target = "aarch64-linux-android".to_string(); let target = INTERNER.intern_str("aarch64-linux-android");
let target = self.target_config.entry(target) let target = self.target_config.entry(target).or_insert(Target::default());
.or_insert(Target::default());
target.ndk = Some(parse_configure_path(value)); target.ndk = Some(parse_configure_path(value));
} }
"CFG_X86_64_LINUX_ANDROID_NDK" if value.len() > 0 => { "CFG_X86_64_LINUX_ANDROID_NDK" if value.len() > 0 => {
let target = "x86_64-linux-android".to_string(); let target = INTERNER.intern_str("x86_64-linux-android");
let target = self.target_config.entry(target) let target = self.target_config.entry(target).or_insert(Target::default());
.or_insert(Target::default());
target.ndk = Some(parse_configure_path(value)); target.ndk = Some(parse_configure_path(value));
} }
"CFG_LOCAL_RUST_ROOT" if value.len() > 0 => { "CFG_LOCAL_RUST_ROOT" if value.len() > 0 => {
@ -645,9 +639,8 @@ impl Config {
.collect(); .collect();
} }
"CFG_QEMU_ARMHF_ROOTFS" if value.len() > 0 => { "CFG_QEMU_ARMHF_ROOTFS" if value.len() > 0 => {
let target = "arm-unknown-linux-gnueabihf".to_string(); let target = INTERNER.intern_str("arm-unknown-linux-gnueabihf");
let target = self.target_config.entry(target) let target = self.target_config.entry(target).or_insert(Target::default());
.or_insert(Target::default());
target.qemu_rootfs = Some(parse_configure_path(value)); target.qemu_rootfs = Some(parse_configure_path(value));
} }
_ => {} _ => {}

View File

@ -40,6 +40,7 @@ use util::{cp_r, libdir, is_dylib, cp_filtered, copy, exe};
use builder::{Builder, Step}; use builder::{Builder, Step};
use compile; use compile;
use tool::{self, Tool}; use tool::{self, Tool};
use cache::{INTERNER, Interned};
pub fn pkgname(build: &Build, component: &str) -> String { pub fn pkgname(build: &Build, component: &str) -> String {
if component == "cargo" { if component == "cargo" {
@ -71,14 +72,13 @@ fn rust_installer(builder: &Builder) -> Command {
// .dep(move |s| tool_rust_installer(build, s)) // .dep(move |s| tool_rust_installer(build, s))
// .run(move |s| dist::docs(build, s.stage, s.target)); // .run(move |s| dist::docs(build, s.stage, s.target));
#[derive(Serialize)] #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Docs<'a> { pub struct Docs {
pub stage: u32, pub stage: u32,
pub target: &'a str, pub target: Interned<String>,
} }
impl<'a> Step<'a> for Docs<'a> { impl Step for Docs {
type Id = Docs<'static>;
type Output = Option<PathBuf>; type Output = Option<PathBuf>;
const DEFAULT: bool = true; const DEFAULT: bool = true;
const ONLY_BUILD_TARGETS: bool = true; const ONLY_BUILD_TARGETS: bool = true;
@ -87,7 +87,9 @@ impl<'a> Step<'a> for Docs<'a> {
path.ends_with("src/doc") path.ends_with("src/doc")
} }
fn make_run(builder: &Builder, _path: Option<&Path>, _host: &str, target: &str) { fn make_run(
builder: &Builder, _path: Option<&Path>, _host: Interned<String>, target: Interned<String>,
) {
builder.ensure(Docs { builder.ensure(Docs {
stage: builder.top_stage, stage: builder.top_stage,
target: target, target: target,
@ -165,7 +167,9 @@ fn find_files(files: &[&str], path: &[PathBuf]) -> Vec<PathBuf> {
found found
} }
fn make_win_dist(rust_root: &Path, plat_root: &Path, target_triple: &str, build: &Build) { fn make_win_dist(
rust_root: &Path, plat_root: &Path, target_triple: Interned<String>, build: &Build
) {
//Ask gcc where it keeps its stuff //Ask gcc where it keeps its stuff
let mut cmd = Command::new(build.cc(target_triple)); let mut cmd = Command::new(build.cc(target_triple));
cmd.arg("-print-search-dirs"); cmd.arg("-print-search-dirs");
@ -282,13 +286,12 @@ fn make_win_dist(rust_root: &Path, plat_root: &Path, target_triple: &str, build:
// } // }
// }); // });
#[derive(Serialize)] #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Mingw<'a> { pub struct Mingw {
target: &'a str, target: Interned<String>,
} }
impl<'a> Step<'a> for Mingw<'a> { impl Step for Mingw {
type Id = Mingw<'static>;
type Output = Option<PathBuf>; type Output = Option<PathBuf>;
const DEFAULT: bool = true; const DEFAULT: bool = true;
const ONLY_BUILD_TARGETS: bool = true; const ONLY_BUILD_TARGETS: bool = true;
@ -297,7 +300,9 @@ impl<'a> Step<'a> for Mingw<'a> {
false false
} }
fn make_run(builder: &Builder, _path: Option<&Path>, _host: &str, target: &str) { fn make_run(
builder: &Builder, _path: Option<&Path>, _host: Interned<String>, target: Interned<String>
) {
builder.ensure(Mingw { target }); builder.ensure(Mingw { target });
} }
@ -350,14 +355,13 @@ impl<'a> Step<'a> for Mingw<'a> {
// .dep(move |s| tool_rust_installer(build, s)) // .dep(move |s| tool_rust_installer(build, s))
// .run(move |s| dist::rustc(build, s.stage, s.target)); // .run(move |s| dist::rustc(build, s.stage, s.target));
#[derive(Serialize)] #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Rustc<'a> { pub struct Rustc {
pub stage: u32, pub stage: u32,
pub target: &'a str, pub target: Interned<String>,
} }
impl<'a> Step<'a> for Rustc<'a> { impl Step for Rustc {
type Id = Rustc<'static>;
type Output = PathBuf; type Output = PathBuf;
const DEFAULT: bool = true; const DEFAULT: bool = true;
const ONLY_HOSTS: bool = true; const ONLY_HOSTS: bool = true;
@ -367,7 +371,9 @@ impl<'a> Step<'a> for Rustc<'a> {
path.ends_with("src/librustc") path.ends_with("src/librustc")
} }
fn make_run(builder: &Builder, _path: Option<&Path>, _host: &str, target: &str) { fn make_run(
builder: &Builder, _path: Option<&Path>, _host: Interned<String>, target: Interned<String>
) {
builder.ensure(Rustc { builder.ensure(Rustc {
stage: builder.top_stage, stage: builder.top_stage,
target: target, target: target,
@ -381,7 +387,7 @@ impl<'a> Step<'a> for Rustc<'a> {
let target = self.target; let target = self.target;
let compiler = builder.ensure(compile::Assemble { let compiler = builder.ensure(compile::Assemble {
target_compiler: builder.compiler(stage, &build.build), target_compiler: builder.compiler(stage, build.build),
}); });
println!("Dist rustc stage{} ({})", stage, target); println!("Dist rustc stage{} ({})", stage, target);
@ -444,10 +450,12 @@ impl<'a> Step<'a> for Rustc<'a> {
return distdir(build).join(format!("{}-{}.tar.gz", name, target)); return distdir(build).join(format!("{}-{}.tar.gz", name, target));
fn prepare_image(builder: &Builder, compiler: Compiler, target: &str, image: &Path) { fn prepare_image(
builder: &Builder, compiler: Compiler, target: Interned<String>, image: &Path
) {
let build = builder.build; let build = builder.build;
let src = builder.sysroot(compiler); let src = builder.sysroot(compiler);
let libdir = libdir(target); let libdir = libdir(&target);
// Copy rustc/rustdoc binaries // Copy rustc/rustdoc binaries
t!(fs::create_dir_all(image.join("bin"))); t!(fs::create_dir_all(image.join("bin")));
@ -471,7 +479,7 @@ impl<'a> Step<'a> for Rustc<'a> {
// Debugger scripts // Debugger scripts
builder.ensure(DebuggerScripts { builder.ensure(DebuggerScripts {
sysroot: &image, sysroot: INTERNER.intern_path(image.to_owned()),
target: target, target: target,
}); });
@ -491,23 +499,24 @@ impl<'a> Step<'a> for Rustc<'a> {
// .run(move |s| dist::debugger_scripts(build, &builder.sysroot(&s.compiler()), // .run(move |s| dist::debugger_scripts(build, &builder.sysroot(&s.compiler()),
// s.target)); // s.target));
#[derive(Serialize)] #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct DebuggerScripts<'a> { pub struct DebuggerScripts {
pub sysroot: &'a Path, pub sysroot: Interned<PathBuf>,
pub target: &'a str, pub target: Interned<String>,
} }
impl<'a> Step<'a> for DebuggerScripts<'a> { impl Step for DebuggerScripts {
type Id = DebuggerScripts<'static>;
type Output = (); type Output = ();
fn should_run(_builder: &Builder, path: &Path) -> bool { fn should_run(_builder: &Builder, path: &Path) -> bool {
path.ends_with("src/etc/lldb_batchmode.py") path.ends_with("src/etc/lldb_batchmode.py")
} }
fn make_run(builder: &Builder, _path: Option<&Path>, host: &str, target: &str) { fn make_run(
builder: &Builder, _path: Option<&Path>, host: Interned<String>, target: Interned<String>
) {
builder.ensure(DebuggerScripts { builder.ensure(DebuggerScripts {
sysroot: &builder.sysroot(builder.compiler(builder.top_stage, host)), sysroot: builder.sysroot(builder.compiler(builder.top_stage, host)),
target: target, target: target,
}); });
} }
@ -564,14 +573,13 @@ impl<'a> Step<'a> for DebuggerScripts<'a> {
// .dep(move |s| tool_rust_installer(build, s)) // .dep(move |s| tool_rust_installer(build, s))
// .run(move |s| dist::std(build, &s.compiler(), s.target)); // .run(move |s| dist::std(build, &s.compiler(), s.target));
#[derive(Serialize)] #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Std<'a> { pub struct Std {
pub compiler: Compiler<'a>, pub compiler: Compiler,
pub target: &'a str, pub target: Interned<String>,
} }
impl<'a> Step<'a> for Std<'a> { impl Step for Std {
type Id = Std<'static>;
type Output = Option<PathBuf>; type Output = Option<PathBuf>;
const DEFAULT: bool = true; const DEFAULT: bool = true;
const ONLY_BUILD_TARGETS: bool = true; const ONLY_BUILD_TARGETS: bool = true;
@ -580,7 +588,9 @@ impl<'a> Step<'a> for Std<'a> {
path.ends_with("src/libstd") path.ends_with("src/libstd")
} }
fn make_run(builder: &Builder, _path: Option<&Path>, host: &str, target: &str) { fn make_run(
builder: &Builder, _path: Option<&Path>, host: Interned<String>, target: Interned<String>
) {
builder.ensure(Std { builder.ensure(Std {
compiler: builder.compiler(builder.top_stage, host), compiler: builder.compiler(builder.top_stage, host),
target: target, target: target,
@ -592,7 +602,7 @@ impl<'a> Step<'a> for Std<'a> {
let compiler = self.compiler; let compiler = self.compiler;
let target = self.target; let target = self.target;
println!("Dist std stage{} ({} -> {})", compiler.stage, compiler.host, println!("Dist std stage{} ({} -> {})", compiler.stage, &compiler.host,
target); target);
// The only true set of target libraries came from the build triple, so // The only true set of target libraries came from the build triple, so
@ -617,7 +627,7 @@ impl<'a> Step<'a> for Std<'a> {
let dst = image.join("lib/rustlib").join(target); let dst = image.join("lib/rustlib").join(target);
t!(fs::create_dir_all(&dst)); t!(fs::create_dir_all(&dst));
let mut src = builder.sysroot_libdir(compiler, target); let mut src = builder.sysroot_libdir(compiler, target).to_path_buf();
src.pop(); // Remove the trailing /lib folder from the sysroot_libdir src.pop(); // Remove the trailing /lib folder from the sysroot_libdir
cp_r(&src, &dst); cp_r(&src, &dst);
@ -645,14 +655,13 @@ impl<'a> Step<'a> for Std<'a> {
// .dep(move |s| tool_rust_installer(build, s)) // .dep(move |s| tool_rust_installer(build, s))
// .run(move |s| dist::analysis(build, &s.compiler(), s.target)); // .run(move |s| dist::analysis(build, &s.compiler(), s.target));
#[derive(Serialize)] #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Analysis<'a> { pub struct Analysis {
pub compiler: Compiler<'a>, pub compiler: Compiler,
pub target: &'a str, pub target: Interned<String>,
} }
impl<'a> Step<'a> for Analysis<'a> { impl Step for Analysis {
type Id = Analysis<'static>;
type Output = Option<PathBuf>; type Output = Option<PathBuf>;
const DEFAULT: bool = true; const DEFAULT: bool = true;
const ONLY_BUILD_TARGETS: bool = true; const ONLY_BUILD_TARGETS: bool = true;
@ -661,7 +670,12 @@ impl<'a> Step<'a> for Analysis<'a> {
path.ends_with("analysis") path.ends_with("analysis")
} }
fn make_run(builder: &Builder, path: Option<&Path>, host: &str, target: &str) { fn make_run(
builder: &Builder,
path: Option<&Path>,
host: Interned<String>,
target: Interned<String>
) {
if path.is_none() && !builder.build.config.extended { if path.is_none() && !builder.build.config.extended {
return; return;
} }
@ -679,7 +693,7 @@ impl<'a> Step<'a> for Analysis<'a> {
assert!(build.config.extended); assert!(build.config.extended);
println!("Dist analysis"); println!("Dist analysis");
if compiler.host != build.build { if &compiler.host != build.build {
println!("\tskipping, not a build host"); println!("\tskipping, not a build host");
return None; return None;
} }
@ -769,11 +783,10 @@ fn copy_src_dirs(build: &Build, src_dirs: &[&str], exclude_dirs: &[&str], dst_di
// .dep(move |s| tool_rust_installer(build, s)) // .dep(move |s| tool_rust_installer(build, s))
// .run(move |_| dist::rust_src(build)); // .run(move |_| dist::rust_src(build));
#[derive(Serialize)] #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Src; pub struct Src;
impl<'a> Step<'a> for Src { impl Step for Src {
type Id = Src;
/// The output path of the src installer tarball /// The output path of the src installer tarball
type Output = PathBuf; type Output = PathBuf;
const DEFAULT: bool = true; const DEFAULT: bool = true;
@ -785,7 +798,9 @@ impl<'a> Step<'a> for Src {
path.ends_with("src") path.ends_with("src")
} }
fn make_run(builder: &Builder, _path: Option<&Path>, _host: &str, _target: &str) { fn make_run(
builder: &Builder, _path: Option<&Path>, _host: Interned<String>, _target: Interned<String>
) {
builder.ensure(Src); builder.ensure(Src);
} }
@ -867,11 +882,10 @@ const CARGO_VENDOR_VERSION: &str = "0.1.4";
// .dep(move |s| tool_rust_installer(build, s)) // .dep(move |s| tool_rust_installer(build, s))
// .run(move |_| dist::plain_source_tarball(build)); // .run(move |_| dist::plain_source_tarball(build));
#[derive(Serialize)] #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct PlainSourceTarball; pub struct PlainSourceTarball;
impl<'a> Step<'a> for PlainSourceTarball { impl Step for PlainSourceTarball {
type Id = PlainSourceTarball;
/// Produces the location of the tarball generated /// Produces the location of the tarball generated
type Output = PathBuf; type Output = PathBuf;
const DEFAULT: bool = true; const DEFAULT: bool = true;
@ -883,7 +897,9 @@ impl<'a> Step<'a> for PlainSourceTarball {
path.ends_with("src") path.ends_with("src")
} }
fn make_run(builder: &Builder, path: Option<&Path>, _host: &str, _target: &str) { fn make_run(
builder: &Builder, path: Option<&Path>, _host: Interned<String>, _target: Interned<String>
) {
if path.is_none() && !builder.build.config.rust_dist_src { if path.is_none() && !builder.build.config.rust_dist_src {
return; return;
} }
@ -1019,14 +1035,13 @@ fn write_file(path: &Path, data: &[u8]) {
// .dep(move |s| tool_rust_installer(build, s)) // .dep(move |s| tool_rust_installer(build, s))
// .run(move |s| dist::cargo(build, s.stage, s.target)); // .run(move |s| dist::cargo(build, s.stage, s.target));
#[derive(Serialize)] #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Cargo<'a> { pub struct Cargo {
pub stage: u32, pub stage: u32,
pub target: &'a str, pub target: Interned<String>,
} }
impl<'a> Step<'a> for Cargo<'a> { impl Step for Cargo {
type Id = Cargo<'static>;
type Output = PathBuf; type Output = PathBuf;
const ONLY_BUILD_TARGETS: bool = true; const ONLY_BUILD_TARGETS: bool = true;
const ONLY_HOSTS: bool = true; const ONLY_HOSTS: bool = true;
@ -1035,7 +1050,9 @@ impl<'a> Step<'a> for Cargo<'a> {
path.ends_with("cargo") path.ends_with("cargo")
} }
fn make_run(builder: &Builder, _path: Option<&Path>, _host: &str, target: &str) { fn make_run(
builder: &Builder, _path: Option<&Path>, _host: Interned<String>, target: Interned<String>
) {
builder.ensure(Cargo { builder.ensure(Cargo {
stage: builder.top_stage, stage: builder.top_stage,
target: target, target: target,
@ -1050,7 +1067,7 @@ impl<'a> Step<'a> for Cargo<'a> {
builder.ensure(tool::Cargo { stage, target }); builder.ensure(tool::Cargo { stage, target });
println!("Dist cargo stage{} ({})", stage, target); println!("Dist cargo stage{} ({})", stage, target);
let compiler = builder.compiler(stage, &build.build); let compiler = builder.compiler(stage, build.build);
let src = build.src.join("src/tools/cargo"); let src = build.src.join("src/tools/cargo");
let etc = src.join("src/etc"); let etc = src.join("src/etc");
@ -1067,7 +1084,7 @@ impl<'a> Step<'a> for Cargo<'a> {
t!(fs::create_dir_all(image.join("share/zsh/site-functions"))); t!(fs::create_dir_all(image.join("share/zsh/site-functions")));
t!(fs::create_dir_all(image.join("etc/bash_completion.d"))); t!(fs::create_dir_all(image.join("etc/bash_completion.d")));
let cargo = build.cargo_out(compiler, Mode::Tool, target) let cargo = build.cargo_out(compiler, Mode::Tool, target)
.join(exe("cargo", target)); .join(exe("cargo", &target));
install(&cargo, &image.join("bin"), 0o755); install(&cargo, &image.join("bin"), 0o755);
for man in t!(etc.join("man").read_dir()) { for man in t!(etc.join("man").read_dir()) {
let man = t!(man); let man = t!(man);
@ -1116,14 +1133,13 @@ impl<'a> Step<'a> for Cargo<'a> {
// .dep(|s| s.name("tool-rls")) // .dep(|s| s.name("tool-rls"))
// .dep(move |s| tool_rust_installer(build, s)) // .dep(move |s| tool_rust_installer(build, s))
// .run(move |s| dist::rls(build, s.stage, s.target)); // .run(move |s| dist::rls(build, s.stage, s.target));
#[derive(Serialize)] #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Rls<'a> { pub struct Rls {
pub stage: u32, pub stage: u32,
pub target: &'a str, pub target: Interned<String>,
} }
impl<'a> Step<'a> for Rls<'a> { impl Step for Rls {
type Id = Rls<'static>;
type Output = PathBuf; type Output = PathBuf;
const ONLY_BUILD_TARGETS: bool = true; const ONLY_BUILD_TARGETS: bool = true;
const ONLY_HOSTS: bool = true; const ONLY_HOSTS: bool = true;
@ -1132,7 +1148,9 @@ impl<'a> Step<'a> for Rls<'a> {
path.ends_with("rls") path.ends_with("rls")
} }
fn make_run(builder: &Builder, _path: Option<&Path>, _host: &str, target: &str) { fn make_run(
builder: &Builder, _path: Option<&Path>, _host: Interned<String>, target: Interned<String>
) {
builder.ensure(Rls { builder.ensure(Rls {
stage: builder.top_stage, stage: builder.top_stage,
target: target, target: target,
@ -1148,7 +1166,7 @@ impl<'a> Step<'a> for Rls<'a> {
builder.ensure(tool::Rls { stage, target }); builder.ensure(tool::Rls { stage, target });
println!("Dist RLS stage{} ({})", stage, target); println!("Dist RLS stage{} ({})", stage, target);
let compiler = builder.compiler(stage, &build.build); let compiler = builder.compiler(stage, build.build);
let src = build.src.join("src/tools/rls"); let src = build.src.join("src/tools/rls");
let release_num = build.release_num("rls"); let release_num = build.release_num("rls");
@ -1162,7 +1180,7 @@ impl<'a> Step<'a> for Rls<'a> {
// Prepare the image directory // Prepare the image directory
let rls = build.cargo_out(compiler, Mode::Tool, target) let rls = build.cargo_out(compiler, Mode::Tool, target)
.join(exe("rls", target)); .join(exe("rls", &target));
install(&rls, &image.join("bin"), 0o755); install(&rls, &image.join("bin"), 0o755);
let doc = image.join("share/doc/rls"); let doc = image.join("share/doc/rls");
install(&src.join("README.md"), &doc, 0o644); install(&src.join("README.md"), &doc, 0o644);
@ -1210,14 +1228,13 @@ impl<'a> Step<'a> for Rls<'a> {
// .dep(move |s| tool_rust_installer(build, s)) // .dep(move |s| tool_rust_installer(build, s))
// .run(move |s| dist::extended(build, s.stage, s.target)); // .run(move |s| dist::extended(build, s.stage, s.target));
#[derive(Serialize)] #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Extended<'a> { pub struct Extended {
stage: u32, stage: u32,
target: &'a str, target: Interned<String>,
} }
impl<'a> Step<'a> for Extended<'a> { impl Step for Extended {
type Id = Extended<'static>;
type Output = (); type Output = ();
const DEFAULT: bool = true; const DEFAULT: bool = true;
const ONLY_BUILD_TARGETS: bool = true; const ONLY_BUILD_TARGETS: bool = true;
@ -1227,7 +1244,9 @@ impl<'a> Step<'a> for Extended<'a> {
path.ends_with("cargo") path.ends_with("cargo")
} }
fn make_run(builder: &Builder, path: Option<&Path>, _host: &str, target: &str) { fn make_run(
builder: &Builder, path: Option<&Path>, _host: Interned<String>, target: Interned<String>
) {
if path.is_none() && !builder.build.config.extended { if path.is_none() && !builder.build.config.extended {
return; return;
} }
@ -1242,7 +1261,7 @@ impl<'a> Step<'a> for Extended<'a> {
let build = builder.build; let build = builder.build;
let stage = self.stage; let stage = self.stage;
let target = self.target; let target = self.target;
let compiler = builder.compiler(stage, &build.build); let compiler = builder.compiler(stage, build.build);
println!("Dist extended stage{} ({})", stage, target); println!("Dist extended stage{} ({})", stage, target);
@ -1583,7 +1602,7 @@ impl<'a> Step<'a> for Extended<'a> {
} }
} }
fn add_env(build: &Build, cmd: &mut Command, target: &str) { fn add_env(build: &Build, cmd: &mut Command, target: Interned<String>) {
let mut parts = channel::CFG_RELEASE_NUM.split('.'); let mut parts = channel::CFG_RELEASE_NUM.split('.');
cmd.env("CFG_RELEASE_INFO", build.rust_version()) cmd.env("CFG_RELEASE_INFO", build.rust_version())
.env("CFG_RELEASE_NUM", channel::CFG_RELEASE_NUM) .env("CFG_RELEASE_NUM", channel::CFG_RELEASE_NUM)
@ -1620,11 +1639,10 @@ fn add_env(build: &Build, cmd: &mut Command, target: &str) {
// .dep(move |s| s.name("tool-build-manifest").target(&build.build).stage(0)) // .dep(move |s| s.name("tool-build-manifest").target(&build.build).stage(0))
// .run(move |_| dist::hash_and_sign(build)); // .run(move |_| dist::hash_and_sign(build));
#[derive(Serialize)] #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct HashSign; pub struct HashSign;
impl<'a> Step<'a> for HashSign { impl Step for HashSign {
type Id = HashSign;
type Output = (); type Output = ();
const ONLY_BUILD_TARGETS: bool = true; const ONLY_BUILD_TARGETS: bool = true;
const ONLY_HOSTS: bool = true; const ONLY_HOSTS: bool = true;
@ -1634,7 +1652,9 @@ impl<'a> Step<'a> for HashSign {
path.ends_with("hash-and-sign") path.ends_with("hash-and-sign")
} }
fn make_run(builder: &Builder, _path: Option<&Path>, _host: &str, _target: &str) { fn make_run(
builder: &Builder, _path: Option<&Path>, _host: Interned<String>, _target: Interned<String>
) {
builder.ensure(HashSign); builder.ensure(HashSign);
} }

View File

@ -20,27 +20,27 @@
use std::fs::{self, File}; use std::fs::{self, File};
use std::io::prelude::*; use std::io::prelude::*;
use std::io; use std::io;
use std::path::Path; use std::path::{PathBuf, Path};
use std::process::Command; use std::process::Command;
use Mode; use Mode;
use util::{cp_r, symlink_dir};
use build_helper::up_to_date; use build_helper::up_to_date;
use util::{cp_r, symlink_dir};
use builder::{Builder, Step}; use builder::{Builder, Step};
use tool::Tool; use tool::Tool;
use compile; use compile;
use cache::{INTERNER, Interned};
macro_rules! book { macro_rules! book {
($($name:ident, $path:expr, $book_name:expr;)+) => { ($($name:ident, $path:expr, $book_name:expr;)+) => {
$( $(
#[derive(Serialize)] #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct $name<'a> { pub struct $name {
target: &'a str, target: Interned<String>,
} }
impl<'a> Step<'a> for $name<'a> { impl Step for $name {
type Id = $name<'static>;
type Output = (); type Output = ();
const DEFAULT: bool = true; const DEFAULT: bool = true;
@ -48,7 +48,12 @@ macro_rules! book {
path.ends_with($path) path.ends_with($path)
} }
fn make_run(builder: &Builder, path: Option<&Path>, _host: &str, target: &str) { fn make_run(
builder: &Builder,
path: Option<&Path>,
_host: Interned<String>,
target: Interned<String>
) {
if path.is_none() && !builder.build.config.docs { if path.is_none() && !builder.build.config.docs {
// Not a default rule if docs are disabled. // Not a default rule if docs are disabled.
return; return;
@ -62,7 +67,7 @@ macro_rules! book {
fn run(self, builder: &Builder) { fn run(self, builder: &Builder) {
builder.ensure(Rustbook { builder.ensure(Rustbook {
target: self.target, target: self.target,
name: $book_name, name: INTERNER.intern_str($book_name),
}) })
} }
} }
@ -93,14 +98,13 @@ book!(
Reference, "src/doc/reference", "reference"; Reference, "src/doc/reference", "reference";
); );
#[derive(Serialize)] #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Rustbook<'a> { pub struct Rustbook {
target: &'a str, target: Interned<String>,
name: &'a str, name: Interned<String>,
} }
impl<'a> Step<'a> for Rustbook<'a> { impl Step for Rustbook {
type Id = Rustbook<'static>;
type Output = (); type Output = ();
/// Invoke `rustbook` for `target` for the doc book `name`. /// Invoke `rustbook` for `target` for the doc book `name`.
@ -112,7 +116,7 @@ impl<'a> Step<'a> for Rustbook<'a> {
builder.ensure(RustbookSrc { builder.ensure(RustbookSrc {
target: self.target, target: self.target,
name: self.name, name: self.name,
src: &src, src: INTERNER.intern_path(src),
}); });
} }
} }
@ -130,13 +134,12 @@ impl<'a> Step<'a> for Rustbook<'a> {
// s.target, // s.target,
// "unstable-book", // "unstable-book",
// &build.md_doc_out(s.target))); // &build.md_doc_out(s.target)));
#[derive(Serialize)] #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct UnstableBook<'a> { pub struct UnstableBook {
target: &'a str, target: Interned<String>,
} }
impl<'a> Step<'a> for UnstableBook<'a> { impl Step for UnstableBook {
type Id = UnstableBook<'static>;
type Output = (); type Output = ();
const DEFAULT: bool = true; const DEFAULT: bool = true;
@ -144,7 +147,9 @@ impl<'a> Step<'a> for UnstableBook<'a> {
path.ends_with("src/doc/unstable-book") path.ends_with("src/doc/unstable-book")
} }
fn make_run(builder: &Builder, path: Option<&Path>, _host: &str, target: &str) { fn make_run(
builder: &Builder, path: Option<&Path>, _host: Interned<String>, target: Interned<String>
) {
if path.is_none() && !builder.build.config.docs { if path.is_none() && !builder.build.config.docs {
// Not a default rule if docs are disabled. // Not a default rule if docs are disabled.
return; return;
@ -161,21 +166,20 @@ impl<'a> Step<'a> for UnstableBook<'a> {
}); });
builder.ensure(RustbookSrc { builder.ensure(RustbookSrc {
target: self.target, target: self.target,
name: "unstable-book", name: INTERNER.intern_str("unstable-book"),
src: &builder.build.md_doc_out(self.target), src: builder.build.md_doc_out(self.target),
}) })
} }
} }
#[derive(Serialize)] #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct RustbookSrc<'a> { pub struct RustbookSrc {
target: &'a str, target: Interned<String>,
name: &'a str, name: Interned<String>,
src: &'a Path, src: Interned<PathBuf>,
} }
impl<'a> Step<'a> for RustbookSrc<'a> { impl Step for RustbookSrc {
type Id = UnstableBook<'static>;
type Output = (); type Output = ();
/// Invoke `rustbook` for `target` for the doc book `name` from the `src` path. /// Invoke `rustbook` for `target` for the doc book `name` from the `src` path.
@ -217,21 +221,22 @@ impl<'a> Step<'a> for RustbookSrc<'a> {
// .default(build.config.docs) // .default(build.config.docs)
// .run(move |s| doc::book(build, s.target, "book")); // .run(move |s| doc::book(build, s.target, "book"));
#[derive(Serialize)] #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct TheBook<'a> { pub struct TheBook {
target: &'a str, target: Interned<String>,
name: &'a str, name: &'static str,
} }
impl<'a> Step<'a> for TheBook<'a> { impl Step for TheBook {
type Id = TheBook<'static>;
type Output = (); type Output = ();
fn should_run(_builder: &Builder, path: &Path) -> bool { fn should_run(_builder: &Builder, path: &Path) -> bool {
path.ends_with("src/doc/book") path.ends_with("src/doc/book")
} }
fn make_run(builder: &Builder, path: Option<&Path>, _host: &str, target: &str) { fn make_run(
builder: &Builder, path: Option<&Path>, _host: Interned<String>, target: Interned<String>
) {
if path.is_none() && !builder.build.config.docs { if path.is_none() && !builder.build.config.docs {
// Not a default rule if docs are disabled. // Not a default rule if docs are disabled.
return; return;
@ -258,13 +263,13 @@ impl<'a> Step<'a> for TheBook<'a> {
// build book first edition // build book first edition
builder.ensure(Rustbook { builder.ensure(Rustbook {
target: target, target: target,
name: &format!("{}/first-edition", name), name: INTERNER.intern_string(format!("{}/first-edition", name)),
}); });
// build book second edition // build book second edition
builder.ensure(Rustbook { builder.ensure(Rustbook {
target: target, target: target,
name: &format!("{}/second-edition", name), name: INTERNER.intern_string(format!("{}/second-edition", name)),
}); });
// build the index page // build the index page
@ -284,11 +289,11 @@ impl<'a> Step<'a> for TheBook<'a> {
} }
} }
fn invoke_rustdoc(builder: &Builder, target: &str, markdown: &str) { fn invoke_rustdoc(builder: &Builder, target: Interned<String>, markdown: &str) {
let build = builder.build; let build = builder.build;
let out = build.doc_out(target); let out = build.doc_out(target);
let compiler = builder.compiler(0, &build.build); let compiler = builder.compiler(0, build.build);
let path = build.src.join("src/doc").join(markdown); let path = build.src.join("src/doc").join(markdown);
@ -340,13 +345,12 @@ fn invoke_rustdoc(builder: &Builder, target: &str, markdown: &str) {
// .default(build.config.docs) // .default(build.config.docs)
// .run(move |s| doc::standalone(build, s.target)); // .run(move |s| doc::standalone(build, s.target));
#[derive(Serialize)] #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Standalone<'a> { pub struct Standalone {
target: &'a str, target: Interned<String>,
} }
impl<'a> Step<'a> for Standalone<'a> { impl Step for Standalone {
type Id = Standalone<'static>;
type Output = (); type Output = ();
const DEFAULT: bool = true; const DEFAULT: bool = true;
@ -354,7 +358,9 @@ impl<'a> Step<'a> for Standalone<'a> {
path.ends_with("src/doc") path.ends_with("src/doc")
} }
fn make_run(builder: &Builder, path: Option<&Path>, _host: &str, target: &str) { fn make_run(
builder: &Builder, path: Option<&Path>, _host: Interned<String>, target: Interned<String>
) {
if path.is_none() && !builder.build.config.docs { if path.is_none() && !builder.build.config.docs {
// Not a default rule if docs are disabled. // Not a default rule if docs are disabled.
return; return;
@ -380,7 +386,7 @@ impl<'a> Step<'a> for Standalone<'a> {
let out = build.doc_out(target); let out = build.doc_out(target);
t!(fs::create_dir_all(&out)); t!(fs::create_dir_all(&out));
let compiler = builder.compiler(0, &build.build); let compiler = builder.compiler(0, build.build);
let favicon = build.src.join("src/doc/favicon.inc"); let favicon = build.src.join("src/doc/favicon.inc");
let footer = build.src.join("src/doc/footer.inc"); let footer = build.src.join("src/doc/footer.inc");
@ -447,14 +453,13 @@ impl<'a> Step<'a> for Standalone<'a> {
// .run(move |s| doc::std(build, s.stage, s.target)); // .run(move |s| doc::std(build, s.stage, s.target));
// } // }
#[derive(Serialize)] #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Std<'a> { pub struct Std {
stage: u32, stage: u32,
target: &'a str, target: Interned<String>,
} }
impl<'a> Step<'a> for Std<'a> { impl Step for Std {
type Id = Std<'static>;
type Output = (); type Output = ();
const DEFAULT: bool = true; const DEFAULT: bool = true;
@ -464,7 +469,9 @@ impl<'a> Step<'a> for Std<'a> {
}) })
} }
fn make_run(builder: &Builder, path: Option<&Path>, _host: &str, target: &str) { fn make_run(
builder: &Builder, path: Option<&Path>, _host: Interned<String>, target: Interned<String>
) {
let run = || { let run = || {
builder.ensure(Std { builder.ensure(Std {
stage: builder.top_stage, stage: builder.top_stage,
@ -496,7 +503,7 @@ impl<'a> Step<'a> for Std<'a> {
println!("Documenting stage{} std ({})", stage, target); println!("Documenting stage{} std ({})", stage, target);
let out = build.doc_out(target); let out = build.doc_out(target);
t!(fs::create_dir_all(&out)); t!(fs::create_dir_all(&out));
let compiler = builder.compiler(stage, &build.build); let compiler = builder.compiler(stage, build.build);
let compiler = if build.force_use_stage1(compiler, target) { let compiler = if build.force_use_stage1(compiler, target) {
builder.compiler(1, compiler.host) builder.compiler(1, compiler.host)
} else { } else {
@ -559,14 +566,13 @@ impl<'a> Step<'a> for Std<'a> {
// .run(move |s| doc::test(build, s.stage, s.target)); // .run(move |s| doc::test(build, s.stage, s.target));
// } // }
#[derive(Serialize)] #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Test<'a> { pub struct Test {
stage: u32, stage: u32,
target: &'a str, target: Interned<String>,
} }
impl<'a> Step<'a> for Test<'a> { impl Step for Test {
type Id = Test<'static>;
type Output = (); type Output = ();
const DEFAULT: bool = true; const DEFAULT: bool = true;
@ -576,7 +582,9 @@ impl<'a> Step<'a> for Test<'a> {
}) })
} }
fn make_run(builder: &Builder, path: Option<&Path>, _host: &str, target: &str) { fn make_run(
builder: &Builder, path: Option<&Path>, _host: Interned<String>, target: Interned<String>
) {
let run = || { let run = || {
builder.ensure(Test { builder.ensure(Test {
stage: builder.top_stage, stage: builder.top_stage,
@ -608,7 +616,7 @@ impl<'a> Step<'a> for Test<'a> {
println!("Documenting stage{} test ({})", stage, target); println!("Documenting stage{} test ({})", stage, target);
let out = build.doc_out(target); let out = build.doc_out(target);
t!(fs::create_dir_all(&out)); t!(fs::create_dir_all(&out));
let compiler = builder.compiler(stage, &build.build); let compiler = builder.compiler(stage, build.build);
let compiler = if build.force_use_stage1(compiler, target) { let compiler = if build.force_use_stage1(compiler, target) {
builder.compiler(1, compiler.host) builder.compiler(1, compiler.host)
} else { } else {
@ -647,14 +655,13 @@ impl<'a> Step<'a> for Test<'a> {
// } // }
// //
#[derive(Serialize)] #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Rustc<'a> { pub struct Rustc {
stage: u32, stage: u32,
target: &'a str, target: Interned<String>,
} }
impl<'a> Step<'a> for Rustc<'a> { impl Step for Rustc {
type Id = Rustc<'static>;
type Output = (); type Output = ();
const DEFAULT: bool = true; const DEFAULT: bool = true;
const ONLY_HOSTS: bool = true; const ONLY_HOSTS: bool = true;
@ -665,7 +672,9 @@ impl<'a> Step<'a> for Rustc<'a> {
}) })
} }
fn make_run(builder: &Builder, path: Option<&Path>, _host: &str, target: &str) { fn make_run(
builder: &Builder, path: Option<&Path>, _host: Interned<String>, target: Interned<String>
) {
let run = || { let run = || {
builder.ensure(Rustc { builder.ensure(Rustc {
stage: builder.top_stage, stage: builder.top_stage,
@ -697,7 +706,7 @@ impl<'a> Step<'a> for Rustc<'a> {
println!("Documenting stage{} compiler ({})", stage, target); println!("Documenting stage{} compiler ({})", stage, target);
let out = build.doc_out(target); let out = build.doc_out(target);
t!(fs::create_dir_all(&out)); t!(fs::create_dir_all(&out));
let compiler = builder.compiler(stage, &build.build); let compiler = builder.compiler(stage, build.build);
let compiler = if build.force_use_stage1(compiler, target) { let compiler = if build.force_use_stage1(compiler, target) {
builder.compiler(1, compiler.host) builder.compiler(1, compiler.host)
} else { } else {
@ -749,13 +758,12 @@ impl<'a> Step<'a> for Rustc<'a> {
// .host(true) // .host(true)
// .run(move |s| doc::error_index(build, s.target)); // .run(move |s| doc::error_index(build, s.target));
#[derive(Serialize)] #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct ErrorIndex<'a> { pub struct ErrorIndex {
target: &'a str, target: Interned<String>,
} }
impl<'a> Step<'a> for ErrorIndex<'a> { impl Step for ErrorIndex {
type Id = ErrorIndex<'static>;
type Output = (); type Output = ();
const DEFAULT: bool = true; const DEFAULT: bool = true;
const ONLY_HOSTS: bool = true; const ONLY_HOSTS: bool = true;
@ -764,7 +772,9 @@ impl<'a> Step<'a> for ErrorIndex<'a> {
path.ends_with("src/tools/error_index_generator") path.ends_with("src/tools/error_index_generator")
} }
fn make_run(builder: &Builder, path: Option<&Path>, _host: &str, target: &str) { fn make_run(
builder: &Builder, path: Option<&Path>, _host: Interned<String>, target: Interned<String>
) {
if path.is_none() && !builder.build.config.docs { if path.is_none() && !builder.build.config.docs {
// Not a default rule if docs are disabled. // Not a default rule if docs are disabled.
return; return;
@ -782,7 +792,7 @@ impl<'a> Step<'a> for ErrorIndex<'a> {
let target = self.target; let target = self.target;
builder.ensure(compile::Rustc { builder.ensure(compile::Rustc {
compiler: builder.compiler(0, &build.build), compiler: builder.compiler(0, build.build),
target, target,
}); });
@ -812,13 +822,12 @@ impl<'a> Step<'a> for ErrorIndex<'a> {
// .host(true) // .host(true)
// .run(move |s| doc::unstable_book_gen(build, s.target)); // .run(move |s| doc::unstable_book_gen(build, s.target));
#[derive(Serialize)] #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct UnstableBookGen<'a> { pub struct UnstableBookGen {
target: &'a str, target: Interned<String>,
} }
impl<'a> Step<'a> for UnstableBookGen<'a> { impl Step for UnstableBookGen {
type Id = UnstableBookGen<'static>;
type Output = (); type Output = ();
const DEFAULT: bool = true; const DEFAULT: bool = true;
const ONLY_HOSTS: bool = true; const ONLY_HOSTS: bool = true;
@ -827,7 +836,9 @@ impl<'a> Step<'a> for UnstableBookGen<'a> {
path.ends_with("src/doc/unstable-book") path.ends_with("src/doc/unstable-book")
} }
fn make_run(builder: &Builder, path: Option<&Path>, _host: &str, target: &str) { fn make_run(
builder: &Builder, path: Option<&Path>, _host: Interned<String>, target: Interned<String>,
) {
if path.is_none() && !builder.build.config.docs { if path.is_none() && !builder.build.config.docs {
// Not a default rule if docs are disabled. // Not a default rule if docs are disabled.
return; return;
@ -843,7 +854,7 @@ impl<'a> Step<'a> for UnstableBookGen<'a> {
let target = self.target; let target = self.target;
builder.ensure(compile::Std { builder.ensure(compile::Std {
compiler: builder.compiler(builder.top_stage, &build.build), compiler: builder.compiler(builder.top_stage, build.build),
target, target,
}); });

View File

@ -24,15 +24,17 @@ use Build;
use config::Config; use config::Config;
use metadata; use metadata;
use cache::{Interned, INTERNER};
/// Deserialized version of all flags for this compile. /// Deserialized version of all flags for this compile.
pub struct Flags { pub struct Flags {
pub verbose: usize, // verbosity level: 0 == not verbose, 1 == verbose, 2 == very verbose pub verbose: usize, // verbosity level: 0 == not verbose, 1 == verbose, 2 == very verbose
pub on_fail: Option<String>, pub on_fail: Option<String>,
pub stage: Option<u32>, pub stage: Option<u32>,
pub keep_stage: Option<u32>, pub keep_stage: Option<u32>,
pub build: String, pub build: Interned<String>,
pub host: Vec<String>, pub host: Vec<Interned<String>>,
pub target: Vec<String>, pub target: Vec<Interned<String>>,
pub config: Option<PathBuf>, pub config: Option<PathBuf>,
pub src: PathBuf, pub src: PathBuf,
pub jobs: Option<u32>, pub jobs: Option<u32>,
@ -320,11 +322,13 @@ Arguments:
stage: stage, stage: stage,
on_fail: matches.opt_str("on-fail"), on_fail: matches.opt_str("on-fail"),
keep_stage: matches.opt_str("keep-stage").map(|j| j.parse().unwrap()), keep_stage: matches.opt_str("keep-stage").map(|j| j.parse().unwrap()),
build: matches.opt_str("build").unwrap_or_else(|| { build: INTERNER.intern_string(matches.opt_str("build").unwrap_or_else(|| {
env::var("BUILD").unwrap() env::var("BUILD").unwrap()
}), })),
host: split(matches.opt_strs("host")), host: split(matches.opt_strs("host"))
target: split(matches.opt_strs("target")), .into_iter().map(|x| INTERNER.intern_string(x)).collect::<Vec<_>>(),
target: split(matches.opt_strs("target"))
.into_iter().map(|x| INTERNER.intern_string(x)).collect::<Vec<_>>(),
config: cfg_file, config: cfg_file,
src: src, src: src,
jobs: matches.opt_str("jobs").map(|j| j.parse().unwrap()), jobs: matches.opt_str("jobs").map(|j| j.parse().unwrap()),

View File

@ -21,37 +21,44 @@ use std::process::Command;
use dist::{self, pkgname, sanitize_sh, tmpdir}; use dist::{self, pkgname, sanitize_sh, tmpdir};
use builder::{Builder, Step}; use builder::{Builder, Step};
use cache::Interned;
pub fn install_docs(builder: &Builder, stage: u32, host: &str) { pub fn install_docs(builder: &Builder, stage: u32, host: Interned<String>) {
install_sh(builder, "docs", "rust-docs", stage, Some(host)); install_sh(builder, "docs", "rust-docs", stage, Some(host));
} }
pub fn install_std(builder: &Builder, stage: u32) { pub fn install_std(builder: &Builder, stage: u32) {
for target in builder.build.config.target.iter() { for target in builder.build.config.target.iter() {
install_sh(builder, "std", "rust-std", stage, Some(target)); install_sh(builder, "std", "rust-std", stage, Some(*target));
} }
} }
pub fn install_cargo(builder: &Builder, stage: u32, host: &str) { pub fn install_cargo(builder: &Builder, stage: u32, host: Interned<String>) {
install_sh(builder, "cargo", "cargo", stage, Some(host)); install_sh(builder, "cargo", "cargo", stage, Some(host));
} }
pub fn install_rls(builder: &Builder, stage: u32, host: &str) { pub fn install_rls(builder: &Builder, stage: u32, host: Interned<String>) {
install_sh(builder, "rls", "rls", stage, Some(host)); install_sh(builder, "rls", "rls", stage, Some(host));
} }
pub fn install_analysis(builder: &Builder, stage: u32, host: &str) { pub fn install_analysis(builder: &Builder, stage: u32, host: Interned<String>) {
install_sh(builder, "analysis", "rust-analysis", stage, Some(host)); install_sh(builder, "analysis", "rust-analysis", stage, Some(host));
} }
pub fn install_src(builder: &Builder, stage: u32) { pub fn install_src(builder: &Builder, stage: u32) {
install_sh(builder, "src", "rust-src", stage, None); install_sh(builder, "src", "rust-src", stage, None);
} }
pub fn install_rustc(builder: &Builder, stage: u32, host: &str) { pub fn install_rustc(builder: &Builder, stage: u32, host: Interned<String>) {
install_sh(builder, "rustc", "rustc", stage, Some(host)); install_sh(builder, "rustc", "rustc", stage, Some(host));
} }
fn install_sh(builder: &Builder, package: &str, name: &str, stage: u32, host: Option<&str>) { fn install_sh(
builder: &Builder,
package: &str,
name: &str,
stage: u32,
host: Option<Interned<String>>
) {
let build = builder.build; let build = builder.build;
println!("Install {} stage{} ({:?})", package, stage, host); println!("Install {} stage{} ({:?})", package, stage, host);
@ -127,15 +134,15 @@ macro_rules! install {
$default_cond:expr, $default_cond:expr,
only_hosts: $only_hosts:expr, only_hosts: $only_hosts:expr,
$run_item:block $(, $c:ident)*;)+) => { $run_item:block $(, $c:ident)*;)+) => {
$(#[derive(Serialize)] $(
pub struct $name<'a> { #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct $name {
pub stage: u32, pub stage: u32,
pub target: &'a str, pub target: Interned<String>,
pub host: &'a str, pub host: Interned<String>,
} }
impl<'a> Step<'a> for $name<'a> { impl Step for $name {
type Id = $name<'static>;
type Output = (); type Output = ();
const DEFAULT: bool = true; const DEFAULT: bool = true;
const ONLY_BUILD_TARGETS: bool = true; const ONLY_BUILD_TARGETS: bool = true;
@ -146,7 +153,12 @@ macro_rules! install {
path.ends_with($path) path.ends_with($path)
} }
fn make_run($builder: &Builder, path: Option<&Path>, host: &str, target: &str) { fn make_run(
$builder: &Builder,
path: Option<&Path>,
host: Interned<String>,
target: Interned<String>,
) {
if path.is_none() && !($default_cond) { if path.is_none() && !($default_cond) {
return; return;
} }

View File

@ -121,6 +121,8 @@
extern crate build_helper; extern crate build_helper;
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
#[macro_use]
extern crate lazy_static;
extern crate serde; extern crate serde;
extern crate serde_json; extern crate serde_json;
extern crate cmake; extern crate cmake;
@ -186,16 +188,17 @@ mod job {
pub use config::Config; pub use config::Config;
pub use flags::{Flags, Subcommand}; pub use flags::{Flags, Subcommand};
use cache::{Interned, INTERNER};
/// A structure representing a Rust compiler. /// A structure representing a Rust compiler.
/// ///
/// Each compiler has a `stage` that it is associated with and a `host` that /// 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 /// corresponds to the platform the compiler runs on. This structure is used as
/// a parameter to many methods below. /// a parameter to many methods below.
#[derive(Serialize, Deserialize, Eq, PartialEq, Clone, Copy, Hash, Debug)] #[derive(Eq, PartialEq, Clone, Copy, Hash, Debug)]
pub struct Compiler<'a> { pub struct Compiler {
stage: u32, stage: u32,
host: &'a str, host: Interned<String>,
} }
/// Global configuration for the build system. /// Global configuration for the build system.
@ -226,9 +229,9 @@ pub struct Build {
verbosity: usize, verbosity: usize,
// Targets for which to build. // Targets for which to build.
build: String, build: Interned<String>,
hosts: Vec<String>, hosts: Vec<Interned<String>>,
targets: Vec<String>, targets: Vec<Interned<String>>,
// Stage 0 (downloaded) compiler and cargo or their local rust equivalents. // Stage 0 (downloaded) compiler and cargo or their local rust equivalents.
initial_rustc: PathBuf, initial_rustc: PathBuf,
@ -240,10 +243,10 @@ pub struct Build {
// Runtime state filled in later on // Runtime state filled in later on
// target -> (cc, ar) // target -> (cc, ar)
cc: HashMap<String, (gcc::Tool, Option<PathBuf>)>, cc: HashMap<Interned<String>, (gcc::Tool, Option<PathBuf>)>,
// host -> (cc, ar) // host -> (cc, ar)
cxx: HashMap<String, gcc::Tool>, cxx: HashMap<Interned<String>, gcc::Tool>,
crates: HashMap<String, Crate>, crates: HashMap<Interned<String>, Crate>,
is_sudo: bool, is_sudo: bool,
ci_env: CiEnv, ci_env: CiEnv,
delayed_failures: Cell<usize>, delayed_failures: Cell<usize>,
@ -251,9 +254,9 @@ pub struct Build {
#[derive(Debug)] #[derive(Debug)]
struct Crate { struct Crate {
name: String, name: Interned<String>,
version: String, version: String,
deps: Vec<String>, deps: Vec<Interned<String>>,
path: PathBuf, path: PathBuf,
doc_step: String, doc_step: String,
build_step: String, build_step: String,
@ -265,7 +268,7 @@ struct Crate {
/// ///
/// These entries currently correspond to the various output directories of the /// These entries currently correspond to the various output directories of the
/// build system, with each mod generating output in a different directory. /// build system, with each mod generating output in a different directory.
#[derive(Serialize, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Hash, Clone, Copy, PartialEq, Eq)]
pub enum Mode { pub enum Mode {
/// Build the standard library, placing output in the "stageN-std" directory. /// Build the standard library, placing output in the "stageN-std" directory.
Libstd, Libstd,
@ -438,7 +441,7 @@ impl Build {
/// Get the directory for incremental by-products when using the /// Get the directory for incremental by-products when using the
/// given compiler. /// given compiler.
fn incremental_dir(&self, compiler: Compiler) -> PathBuf { fn incremental_dir(&self, compiler: Compiler) -> PathBuf {
self.out.join(compiler.host).join(format!("stage{}-incremental", compiler.stage)) self.out.join(&*compiler.host).join(format!("stage{}-incremental", compiler.stage))
} }
/// Returns the root directory for all output generated in a particular /// Returns the root directory for all output generated in a particular
@ -452,7 +455,7 @@ impl Build {
Mode::Tool => "-tools", Mode::Tool => "-tools",
Mode::Librustc => "-rustc", Mode::Librustc => "-rustc",
}; };
self.out.join(compiler.host) self.out.join(&*compiler.host)
.join(format!("stage{}{}", compiler.stage, suffix)) .join(format!("stage{}{}", compiler.stage, suffix))
} }
@ -462,40 +465,40 @@ impl Build {
fn cargo_out(&self, fn cargo_out(&self,
compiler: Compiler, compiler: Compiler,
mode: Mode, mode: Mode,
target: &str) -> PathBuf { target: Interned<String>) -> PathBuf {
self.stage_out(compiler, mode).join(target).join(self.cargo_dir()) self.stage_out(compiler, mode).join(&*target).join(self.cargo_dir())
} }
/// Root output directory for LLVM compiled for `target` /// Root output directory for LLVM compiled for `target`
/// ///
/// Note that if LLVM is configured externally then the directory returned /// Note that if LLVM is configured externally then the directory returned
/// will likely be empty. /// will likely be empty.
fn llvm_out(&self, target: &str) -> PathBuf { fn llvm_out(&self, target: Interned<String>) -> PathBuf {
self.out.join(target).join("llvm") self.out.join(&*target).join("llvm")
} }
/// Output directory for all documentation for a target /// Output directory for all documentation for a target
fn doc_out(&self, target: &str) -> PathBuf { fn doc_out(&self, target: Interned<String>) -> PathBuf {
self.out.join(target).join("doc") self.out.join(&*target).join("doc")
} }
/// Output directory for some generated md crate documentation for a target (temporary) /// Output directory for some generated md crate documentation for a target (temporary)
fn md_doc_out(&self, target: &str) -> PathBuf { fn md_doc_out(&self, target: Interned<String>) -> Interned<PathBuf> {
self.out.join(target).join("md-doc") INTERNER.intern_path(self.out.join(&*target).join("md-doc"))
} }
/// Output directory for all crate documentation for a target (temporary) /// Output directory for all crate documentation for a target (temporary)
/// ///
/// The artifacts here are then copied into `doc_out` above. /// The artifacts here are then copied into `doc_out` above.
fn crate_doc_out(&self, target: &str) -> PathBuf { fn crate_doc_out(&self, target: Interned<String>) -> PathBuf {
self.out.join(target).join("crate-docs") self.out.join(&*target).join("crate-docs")
} }
/// Returns true if no custom `llvm-config` is set for the specified target. /// Returns true if no custom `llvm-config` is set for the specified target.
/// ///
/// If no custom `llvm-config` was specified then Rust's llvm will be used. /// If no custom `llvm-config` was specified then Rust's llvm will be used.
fn is_rust_llvm(&self, target: &str) -> bool { fn is_rust_llvm(&self, target: Interned<String>) -> bool {
match self.config.target_config.get(target) { match self.config.target_config.get(&target) {
Some(ref c) => c.llvm_config.is_none(), Some(ref c) => c.llvm_config.is_none(),
None => true None => true
} }
@ -505,25 +508,25 @@ impl Build {
/// ///
/// If a custom `llvm-config` was specified for target then that's returned /// If a custom `llvm-config` was specified for target then that's returned
/// instead. /// instead.
fn llvm_config(&self, target: &str) -> PathBuf { fn llvm_config(&self, target: Interned<String>) -> PathBuf {
let target_config = self.config.target_config.get(target); let target_config = self.config.target_config.get(&target);
if let Some(s) = target_config.and_then(|c| c.llvm_config.as_ref()) { if let Some(s) = target_config.and_then(|c| c.llvm_config.as_ref()) {
s.clone() s.clone()
} else { } else {
self.llvm_out(&self.config.build).join("bin") self.llvm_out(self.config.build).join("bin")
.join(exe("llvm-config", target)) .join(exe("llvm-config", &*target))
} }
} }
/// Returns the path to `FileCheck` binary for the specified target /// Returns the path to `FileCheck` binary for the specified target
fn llvm_filecheck(&self, target: &str) -> PathBuf { fn llvm_filecheck(&self, target: Interned<String>) -> PathBuf {
let target_config = self.config.target_config.get(target); let target_config = self.config.target_config.get(&target);
if let Some(s) = target_config.and_then(|c| c.llvm_config.as_ref()) { if let Some(s) = target_config.and_then(|c| c.llvm_config.as_ref()) {
let llvm_bindir = output(Command::new(s).arg("--bindir")); let llvm_bindir = output(Command::new(s).arg("--bindir"));
Path::new(llvm_bindir.trim()).join(exe("FileCheck", target)) Path::new(llvm_bindir.trim()).join(exe("FileCheck", &*target))
} else { } else {
let base = self.llvm_out(&self.config.build).join("build"); let base = self.llvm_out(self.config.build).join("build");
let exe = exe("FileCheck", target); let exe = exe("FileCheck", &*target);
if !self.config.ninja && self.config.build.contains("msvc") { if !self.config.ninja && self.config.build.contains("msvc") {
base.join("Release/bin").join(exe) base.join("Release/bin").join(exe)
} else { } else {
@ -533,13 +536,13 @@ impl Build {
} }
/// Directory for libraries built from C/C++ code and shared between stages. /// Directory for libraries built from C/C++ code and shared between stages.
fn native_dir(&self, target: &str) -> PathBuf { fn native_dir(&self, target: Interned<String>) -> PathBuf {
self.out.join(target).join("native") self.out.join(&*target).join("native")
} }
/// Root output directory for rust_test_helpers library compiled for /// Root output directory for rust_test_helpers library compiled for
/// `target` /// `target`
fn test_helpers_out(&self, target: &str) -> PathBuf { fn test_helpers_out(&self, target: Interned<String>) -> PathBuf {
self.native_dir(target).join("rust-test-helpers") self.native_dir(target).join("rust-test-helpers")
} }
@ -606,16 +609,16 @@ impl Build {
} }
/// Returns the path to the C compiler for the target specified. /// Returns the path to the C compiler for the target specified.
fn cc(&self, target: &str) -> &Path { fn cc(&self, target: Interned<String>) -> &Path {
self.cc[target].0.path() self.cc[&target].0.path()
} }
/// Returns a list of flags to pass to the C compiler for the target /// Returns a list of flags to pass to the C compiler for the target
/// specified. /// specified.
fn cflags(&self, target: &str) -> Vec<String> { fn cflags(&self, target: Interned<String>) -> Vec<String> {
// Filter out -O and /O (the optimization flags) that we picked up from // Filter out -O and /O (the optimization flags) that we picked up from
// gcc-rs because the build scripts will determine that for themselves. // gcc-rs because the build scripts will determine that for themselves.
let mut base = self.cc[target].0.args().iter() let mut base = self.cc[&target].0.args().iter()
.map(|s| s.to_string_lossy().into_owned()) .map(|s| s.to_string_lossy().into_owned())
.filter(|s| !s.starts_with("-O") && !s.starts_with("/O")) .filter(|s| !s.starts_with("-O") && !s.starts_with("/O"))
.collect::<Vec<_>>(); .collect::<Vec<_>>();
@ -631,20 +634,20 @@ impl Build {
// Work around an apparently bad MinGW / GCC optimization, // Work around an apparently bad MinGW / GCC optimization,
// See: http://lists.llvm.org/pipermail/cfe-dev/2016-December/051980.html // See: http://lists.llvm.org/pipermail/cfe-dev/2016-December/051980.html
// See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78936 // See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78936
if target == "i686-pc-windows-gnu" { if &*target == "i686-pc-windows-gnu" {
base.push("-fno-omit-frame-pointer".into()); base.push("-fno-omit-frame-pointer".into());
} }
base base
} }
/// Returns the path to the `ar` archive utility for the target specified. /// Returns the path to the `ar` archive utility for the target specified.
fn ar(&self, target: &str) -> Option<&Path> { fn ar(&self, target: Interned<String>) -> Option<&Path> {
self.cc[target].1.as_ref().map(|p| &**p) self.cc[&target].1.as_ref().map(|p| &**p)
} }
/// Returns the path to the C++ compiler for the target specified. /// Returns the path to the C++ compiler for the target specified.
fn cxx(&self, target: &str) -> Result<&Path, String> { fn cxx(&self, target: Interned<String>) -> Result<&Path, String> {
match self.cxx.get(target) { match self.cxx.get(&target) {
Some(p) => Ok(p.path()), Some(p) => Ok(p.path()),
None => Err(format!( None => Err(format!(
"target `{}` is not configured as a host, only as a target", "target `{}` is not configured as a host, only as a target",
@ -653,7 +656,7 @@ impl Build {
} }
/// Returns flags to pass to the compiler to generate code for `target`. /// Returns flags to pass to the compiler to generate code for `target`.
fn rustc_flags(&self, target: &str) -> Vec<String> { fn rustc_flags(&self, target: Interned<String>) -> Vec<String> {
// New flags should be added here with great caution! // New flags should be added here with great caution!
// //
// It's quite unfortunate to **require** flags to generate code for a // It's quite unfortunate to **require** flags to generate code for a
@ -670,8 +673,8 @@ impl Build {
} }
/// Returns the "musl root" for this `target`, if defined /// Returns the "musl root" for this `target`, if defined
fn musl_root(&self, target: &str) -> Option<&Path> { fn musl_root(&self, target: Interned<String>) -> Option<&Path> {
self.config.target_config.get(target) self.config.target_config.get(&target)
.and_then(|t| t.musl_root.as_ref()) .and_then(|t| t.musl_root.as_ref())
.or(self.config.musl_root.as_ref()) .or(self.config.musl_root.as_ref())
.map(|p| &**p) .map(|p| &**p)
@ -679,7 +682,7 @@ impl Build {
/// Returns whether the target will be tested using the `remote-test-client` /// Returns whether the target will be tested using the `remote-test-client`
/// and `remote-test-server` binaries. /// and `remote-test-server` binaries.
fn remote_tested(&self, target: &str) -> bool { fn remote_tested(&self, target: Interned<String>) -> bool {
self.qemu_rootfs(target).is_some() || target.contains("android") || self.qemu_rootfs(target).is_some() || target.contains("android") ||
env::var_os("TEST_DEVICE_ADDR").is_some() env::var_os("TEST_DEVICE_ADDR").is_some()
} }
@ -689,8 +692,8 @@ impl Build {
/// ///
/// If `Some` is returned then that means that tests for this target are /// If `Some` is returned then that means that tests for this target are
/// emulated with QEMU and binaries will need to be shipped to the emulator. /// emulated with QEMU and binaries will need to be shipped to the emulator.
fn qemu_rootfs(&self, target: &str) -> Option<&Path> { fn qemu_rootfs(&self, target: Interned<String>) -> Option<&Path> {
self.config.target_config.get(target) self.config.target_config.get(&target)
.and_then(|t| t.qemu_rootfs.as_ref()) .and_then(|t| t.qemu_rootfs.as_ref())
.map(|p| &**p) .map(|p| &**p)
} }
@ -718,20 +721,20 @@ impl Build {
/// ///
/// When all of these conditions are met the build will lift artifacts from /// When all of these conditions are met the build will lift artifacts from
/// the previous stage forward. /// the previous stage forward.
fn force_use_stage1(&self, compiler: Compiler, target: &str) -> bool { fn force_use_stage1(&self, compiler: Compiler, target: Interned<String>) -> bool {
!self.config.full_bootstrap && !self.config.full_bootstrap &&
compiler.stage >= 2 && compiler.stage >= 2 &&
self.config.host.iter().any(|h| h == target) self.config.host.iter().any(|h| *h == target)
} }
/// Returns the directory that OpenSSL artifacts are compiled into if /// Returns the directory that OpenSSL artifacts are compiled into if
/// configured to do so. /// configured to do so.
fn openssl_dir(&self, target: &str) -> Option<PathBuf> { fn openssl_dir(&self, target: Interned<String>) -> Option<PathBuf> {
// OpenSSL not used on Windows // OpenSSL not used on Windows
if target.contains("windows") { if target.contains("windows") {
None None
} else if self.config.openssl_static { } else if self.config.openssl_static {
Some(self.out.join(target).join("openssl")) Some(self.out.join(&*target).join("openssl"))
} else { } else {
None None
} }
@ -739,7 +742,7 @@ impl Build {
/// Returns the directory that OpenSSL artifacts are installed into if /// Returns the directory that OpenSSL artifacts are installed into if
/// configured as such. /// configured as such.
fn openssl_install_dir(&self, target: &str) -> Option<PathBuf> { fn openssl_install_dir(&self, target: Interned<String>) -> Option<PathBuf> {
self.openssl_dir(target).map(|p| p.join("install")) self.openssl_dir(target).map(|p| p.join("install"))
} }
@ -842,18 +845,19 @@ impl Build {
/// Get a list of crates from a root crate. /// Get a list of crates from a root crate.
/// ///
/// Returns Vec<(crate, path to crate, is_root_crate)> /// Returns Vec<(crate, path to crate, is_root_crate)>
fn crates(&self, root: &str) -> Vec<(&str, &Path)> { fn crates(&self, root: &str) -> Vec<(Interned<String>, &Path)> {
let interned = INTERNER.intern_string(root.to_owned());
let mut ret = Vec::new(); let mut ret = Vec::new();
let mut list = vec![root]; let mut list = vec![interned];
let mut visited = HashSet::new(); let mut visited = HashSet::new();
while let Some(krate) = list.pop() { while let Some(krate) = list.pop() {
let krate = &self.crates[krate]; let krate = &self.crates[&krate];
// If we can't strip prefix, then out-of-tree path // If we can't strip prefix, then out-of-tree path
let path = krate.path.strip_prefix(&self.src).unwrap_or(&krate.path); let path = krate.path.strip_prefix(&self.src).unwrap_or(&krate.path);
ret.push((&*krate.name, path)); ret.push((krate.name, path));
for dep in &krate.deps { for dep in &krate.deps {
if visited.insert(dep) && dep != "build_helper" { if visited.insert(dep) && dep != "build_helper" {
list.push(dep); list.push(*dep);
} }
} }
} }
@ -861,8 +865,8 @@ impl Build {
} }
} }
impl<'a> Compiler<'a> { impl<'a> Compiler {
pub fn with_stage(mut self, stage: u32) -> Compiler<'a> { pub fn with_stage(mut self, stage: u32) -> Compiler {
self.stage = stage; self.stage = stage;
self self
} }

View File

@ -16,6 +16,7 @@ use build_helper::output;
use serde_json; use serde_json;
use {Build, Crate}; use {Build, Crate};
use cache::Interned;
#[derive(Deserialize)] #[derive(Deserialize)]
struct Output { struct Output {
@ -26,7 +27,7 @@ struct Output {
#[derive(Deserialize)] #[derive(Deserialize)]
struct Package { struct Package {
id: String, id: String,
name: String, name: Interned<String>,
version: String, version: String,
source: Option<String>, source: Option<String>,
manifest_path: String, manifest_path: String,
@ -65,10 +66,10 @@ fn build_krate(build: &mut Build, krate: &str) {
let mut id2name = HashMap::new(); let mut id2name = HashMap::new();
for package in output.packages { for package in output.packages {
if package.source.is_none() { if package.source.is_none() {
id2name.insert(package.id, package.name.clone()); id2name.insert(package.id, package.name);
let mut path = PathBuf::from(package.manifest_path); let mut path = PathBuf::from(package.manifest_path);
path.pop(); path.pop();
build.crates.insert(package.name.clone(), Crate { build.crates.insert(package.name, Crate {
build_step: format!("build-crate-{}", package.name), build_step: format!("build-crate-{}", package.name),
doc_step: format!("doc-crate-{}", package.name), doc_step: format!("doc-crate-{}", package.name),
test_step: format!("test-crate-{}", package.name), test_step: format!("test-crate-{}", package.name),
@ -93,7 +94,7 @@ fn build_krate(build: &mut Build, krate: &str) {
Some(dep) => dep, Some(dep) => dep,
None => continue, None => continue,
}; };
krate.deps.push(dep.clone()); krate.deps.push(*dep);
} }
} }
} }

View File

@ -33,6 +33,7 @@ use Build;
use util; use util;
use build_helper::up_to_date; use build_helper::up_to_date;
use builder::{Builder, Step}; use builder::{Builder, Step};
use cache::Interned;
// rules.build("llvm", "src/llvm") // rules.build("llvm", "src/llvm")
// .host(true) // .host(true)
@ -45,13 +46,12 @@ use builder::{Builder, Step};
// }) // })
// .run(move |s| native::llvm(build, s.target)); // .run(move |s| native::llvm(build, s.target));
#[derive(Serialize)] #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Llvm<'a> { pub struct Llvm {
pub target: &'a str, pub target: Interned<String>,
} }
impl<'a> Step<'a> for Llvm<'a> { impl Step for Llvm {
type Id = Llvm<'static>;
type Output = (); type Output = ();
const ONLY_HOSTS: bool = true; const ONLY_HOSTS: bool = true;
@ -61,7 +61,7 @@ impl<'a> Step<'a> for Llvm<'a> {
let target = self.target; let target = self.target;
// If we're using a custom LLVM bail out here, but we can only use a // If we're using a custom LLVM bail out here, but we can only use a
// custom LLVM for the build triple. // custom LLVM for the build triple.
if let Some(config) = build.config.target_config.get(target) { if let Some(config) = build.config.target_config.get(&target) {
if let Some(ref s) = config.llvm_config { if let Some(ref s) = config.llvm_config {
return check_llvm_version(build, s); return check_llvm_version(build, s);
} }
@ -117,7 +117,7 @@ impl<'a> Step<'a> for Llvm<'a> {
let assertions = if build.config.llvm_assertions {"ON"} else {"OFF"}; let assertions = if build.config.llvm_assertions {"ON"} else {"OFF"};
cfg.target(target) cfg.target(&target)
.host(&build.build) .host(&build.build)
.out_dir(&out_dir) .out_dir(&out_dir)
.profile(profile) .profile(profile)
@ -154,11 +154,11 @@ impl<'a> Step<'a> for Llvm<'a> {
// http://llvm.org/docs/HowToCrossCompileLLVM.html // http://llvm.org/docs/HowToCrossCompileLLVM.html
if target != build.build { if target != build.build {
builder.ensure(Llvm { target: &build.build }); builder.ensure(Llvm { target: build.build });
// FIXME: if the llvm root for the build triple is overridden then we // FIXME: if the llvm root for the build triple is overridden then we
// should use llvm-tblgen from there, also should verify that it // should use llvm-tblgen from there, also should verify that it
// actually exists most of the time in normal installs of LLVM. // actually exists most of the time in normal installs of LLVM.
let host = build.llvm_out(&build.build).join("bin/llvm-tblgen"); let host = build.llvm_out(build.build).join("bin/llvm-tblgen");
cfg.define("CMAKE_CROSSCOMPILING", "True") cfg.define("CMAKE_CROSSCOMPILING", "True")
.define("LLVM_TABLEGEN", &host); .define("LLVM_TABLEGEN", &host);
} }
@ -245,20 +245,24 @@ fn check_llvm_version(build: &Build, llvm_config: &Path) {
//rules.build("test-helpers", "src/rt/rust_test_helpers.c") //rules.build("test-helpers", "src/rt/rust_test_helpers.c")
// .run(move |s| native::test_helpers(build, s.target)); // .run(move |s| native::test_helpers(build, s.target));
#[derive(Serialize)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct TestHelpers<'a> { pub struct TestHelpers {
pub target: &'a str, pub target: Interned<String>,
} }
impl<'a> Step<'a> for TestHelpers<'a> { impl Step for TestHelpers {
type Id = TestHelpers<'static>;
type Output = (); type Output = ();
fn should_run(_builder: &Builder, path: &Path) -> bool { fn should_run(_builder: &Builder, path: &Path) -> bool {
path.ends_with("src/rt/rust_test_helpers.c") path.ends_with("src/rt/rust_test_helpers.c")
} }
fn make_run(builder: &Builder, _path: Option<&Path>, _host: &str, target: &str) { fn make_run(
builder: &Builder,
_path: Option<&Path>,
_host: Interned<String>,
target: Interned<String>,
) {
builder.ensure(TestHelpers { target }) builder.ensure(TestHelpers { target })
} }
@ -290,7 +294,7 @@ impl<'a> Step<'a> for TestHelpers<'a> {
cfg.cargo_metadata(false) cfg.cargo_metadata(false)
.out_dir(&dst) .out_dir(&dst)
.target(target) .target(&target)
.host(&build.build) .host(&build.build)
.opt_level(0) .opt_level(0)
.debug(false) .debug(false)
@ -306,13 +310,12 @@ const OPENSSL_SHA256: &'static str =
//rules.build("openssl", "path/to/nowhere") //rules.build("openssl", "path/to/nowhere")
// .run(move |s| native::openssl(build, s.target)); // .run(move |s| native::openssl(build, s.target));
#[derive(Serialize)] #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Openssl<'a> { pub struct Openssl {
pub target: &'a str, pub target: Interned<String>,
} }
impl<'a> Step<'a> for Openssl<'a> { impl Step for Openssl {
type Id = Openssl<'static>;
type Output = (); type Output = ();
fn should_run(_builder: &Builder, _path: &Path) -> bool { fn should_run(_builder: &Builder, _path: &Path) -> bool {
@ -385,7 +388,7 @@ impl<'a> Step<'a> for Openssl<'a> {
configure.arg("no-ssl2"); configure.arg("no-ssl2");
configure.arg("no-ssl3"); configure.arg("no-ssl3");
let os = match target { let os = match &*target {
"aarch64-linux-android" => "linux-aarch64", "aarch64-linux-android" => "linux-aarch64",
"aarch64-unknown-linux-gnu" => "linux-aarch64", "aarch64-unknown-linux-gnu" => "linux-aarch64",
"arm-linux-androideabi" => "android", "arm-linux-androideabi" => "android",

View File

@ -122,14 +122,14 @@ pub fn check(build: &mut Build) {
continue; continue;
} }
cmd_finder.must_have(build.cc(target)); cmd_finder.must_have(build.cc(*target));
if let Some(ar) = build.ar(target) { if let Some(ar) = build.ar(*target) {
cmd_finder.must_have(ar); cmd_finder.must_have(ar);
} }
} }
for host in build.config.host.iter() { for host in build.config.host.iter() {
cmd_finder.must_have(build.cxx(host).unwrap()); cmd_finder.must_have(build.cxx(*host).unwrap());
// The msvc hosts don't use jemalloc, turn it off globally to // The msvc hosts don't use jemalloc, turn it off globally to
// avoid packaging the dummy liballoc_jemalloc on that platform. // avoid packaging the dummy liballoc_jemalloc on that platform.
@ -139,7 +139,7 @@ pub fn check(build: &mut Build) {
} }
// Externally configured LLVM requires FileCheck to exist // Externally configured LLVM requires FileCheck to exist
let filecheck = build.llvm_filecheck(&build.build); let filecheck = build.llvm_filecheck(build.build);
if !filecheck.starts_with(&build.out) && !filecheck.exists() && build.config.codegen_tests { if !filecheck.starts_with(&build.out) && !filecheck.exists() && build.config.codegen_tests {
panic!("FileCheck executable {:?} does not exist", filecheck); panic!("FileCheck executable {:?} does not exist", filecheck);
} }
@ -153,7 +153,7 @@ pub fn check(build: &mut Build) {
// Make sure musl-root is valid if specified // Make sure musl-root is valid if specified
if target.contains("musl") && !target.contains("mips") { if target.contains("musl") && !target.contains("mips") {
match build.musl_root(target) { match build.musl_root(*target) {
Some(root) => { Some(root) => {
if fs::metadata(root.join("lib/libc.a")).is_err() { if fs::metadata(root.join("lib/libc.a")).is_err() {
panic!("couldn't find libc.a in musl dir: {}", panic!("couldn't find libc.a in musl dir: {}",

View File

@ -19,6 +19,7 @@ use util::{exe, add_lib_path};
use compile::{self, libtest_stamp, libstd_stamp, librustc_stamp, Rustc}; use compile::{self, libtest_stamp, libstd_stamp, librustc_stamp, Rustc};
use native; use native;
use channel::GitInfo; use channel::GitInfo;
use cache::Interned;
//// ======================================================================== //// ========================================================================
//// Build tools //// Build tools
@ -44,15 +45,14 @@ use channel::GitInfo;
// .run(move |s| compile::maybe_clean_tools(build, s.stage, s.target, Mode::Libstd)); // .run(move |s| compile::maybe_clean_tools(build, s.stage, s.target, Mode::Libstd));
// //
#[derive(Serialize)] #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct CleanTools<'a> { pub struct CleanTools {
pub stage: u32, pub stage: u32,
pub target: &'a str, pub target: Interned<String>,
pub mode: Mode, pub mode: Mode,
} }
impl<'a> Step<'a> for CleanTools<'a> { impl Step for CleanTools {
type Id = CleanTools<'static>;
type Output = (); type Output = ();
/// Build a tool in `src/tools` /// Build a tool in `src/tools`
@ -65,7 +65,7 @@ impl<'a> Step<'a> for CleanTools<'a> {
let target = self.target; let target = self.target;
let mode = self.mode; let mode = self.mode;
let compiler = builder.compiler(stage, &build.build); let compiler = builder.compiler(stage, build.build);
let stamp = match mode { let stamp = match mode {
Mode::Libstd => libstd_stamp(build, compiler, target), Mode::Libstd => libstd_stamp(build, compiler, target),
@ -78,16 +78,15 @@ impl<'a> Step<'a> for CleanTools<'a> {
} }
} }
#[derive(Serialize)] #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct ToolBuild<'a> { pub struct ToolBuild {
pub stage: u32, pub stage: u32,
pub target: &'a str, pub target: Interned<String>,
pub tool: &'a str, pub tool: &'static str,
pub mode: Mode, pub mode: Mode,
} }
impl<'a> Step<'a> for ToolBuild<'a> { impl Step for ToolBuild {
type Id = ToolBuild<'static>;
type Output = PathBuf; type Output = PathBuf;
/// Build a tool in `src/tools` /// Build a tool in `src/tools`
@ -100,7 +99,7 @@ impl<'a> Step<'a> for ToolBuild<'a> {
let target = self.target; let target = self.target;
let tool = self.tool; let tool = self.tool;
let compiler = builder.compiler(stage, &build.build); let compiler = builder.compiler(stage, build.build);
builder.ensure(CleanTools { stage, target, mode: self.mode }); builder.ensure(CleanTools { stage, target, mode: self.mode });
match self.mode { match self.mode {
Mode::Libstd => builder.ensure(compile::Std { compiler, target }), Mode::Libstd => builder.ensure(compile::Std { compiler, target }),
@ -140,7 +139,7 @@ impl<'a> Step<'a> for ToolBuild<'a> {
} }
build.run(&mut cargo); build.run(&mut cargo);
build.cargo_out(compiler, Mode::Tool, target).join(exe(tool, compiler.host)) build.cargo_out(compiler, Mode::Tool, target).join(exe(tool, &compiler.host))
} }
} }
@ -159,7 +158,7 @@ macro_rules! tool {
$(Tool::$name => $(Tool::$name =>
self.ensure($name { self.ensure($name {
stage: 0, stage: 0,
target: &self.build.build, target: self.build.build,
}), }),
)+ )+
} }
@ -167,21 +166,25 @@ macro_rules! tool {
} }
$( $(
#[derive(Serialize)] #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct $name<'a> { pub struct $name {
pub stage: u32, pub stage: u32,
pub target: &'a str, pub target: Interned<String>,
} }
impl<'a> Step<'a> for $name<'a> { impl Step for $name {
type Id = $name<'static>;
type Output = PathBuf; type Output = PathBuf;
fn should_run(_builder: &Builder, path: &Path) -> bool { fn should_run(_builder: &Builder, path: &Path) -> bool {
path.ends_with($path) path.ends_with($path)
} }
fn make_run(builder: &Builder, _path: Option<&Path>, _host: &str, target: &str) { fn make_run(
builder: &Builder,
_path: Option<&Path>,
_host: Interned<String>,
target: Interned<String>
) {
builder.ensure($name { builder.ensure($name {
stage: builder.top_stage, stage: builder.top_stage,
target, target,
@ -254,21 +257,25 @@ tool!(
RustInstaller, "src/tools/rust-installer", "rust-installer", Mode::Libstd; RustInstaller, "src/tools/rust-installer", "rust-installer", Mode::Libstd;
); );
#[derive(Serialize)] #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct RemoteTestServer<'a> { pub struct RemoteTestServer {
pub stage: u32, pub stage: u32,
pub target: &'a str, pub target: Interned<String>,
} }
impl<'a> Step<'a> for RemoteTestServer<'a> { impl Step for RemoteTestServer {
type Id = RemoteTestServer<'static>;
type Output = PathBuf; type Output = PathBuf;
fn should_run(_builder: &Builder, path: &Path) -> bool { fn should_run(_builder: &Builder, path: &Path) -> bool {
path.ends_with("src/tools/remote-test-server") path.ends_with("src/tools/remote-test-server")
} }
fn make_run(builder: &Builder, _path: Option<&Path>, _host: &str, target: &str) { fn make_run(
builder: &Builder,
_path: Option<&Path>,
_host: Interned<String>,
target: Interned<String>
) {
builder.ensure(RemoteTestServer { builder.ensure(RemoteTestServer {
stage: builder.top_stage, stage: builder.top_stage,
target, target,
@ -299,14 +306,13 @@ impl<'a> Step<'a> for RemoteTestServer<'a> {
// .host(&build.build) // .host(&build.build)
// }) // })
// .run(move |s| compile::tool(build, s.stage, s.target, "cargo")); // .run(move |s| compile::tool(build, s.stage, s.target, "cargo"));
#[derive(Serialize)] #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Cargo<'a> { pub struct Cargo {
pub stage: u32, pub stage: u32,
pub target: &'a str, pub target: Interned<String>,
} }
impl<'a> Step<'a> for Cargo<'a> { impl Step for Cargo {
type Id = Cargo<'static>;
type Output = PathBuf; type Output = PathBuf;
const DEFAULT: bool = true; const DEFAULT: bool = true;
const ONLY_HOSTS: bool = true; const ONLY_HOSTS: bool = true;
@ -315,7 +321,9 @@ impl<'a> Step<'a> for Cargo<'a> {
path.ends_with("src/tools/cargo") path.ends_with("src/tools/cargo")
} }
fn make_run(builder: &Builder, path: Option<&Path>, _host: &str, target: &str) { fn make_run(
builder: &Builder, path: Option<&Path>, _host: Interned<String>, target: Interned<String>
) {
if path.is_none() && !builder.build.config.extended { if path.is_none() && !builder.build.config.extended {
return; return;
} }
@ -332,8 +340,8 @@ impl<'a> Step<'a> for Cargo<'a> {
// Cargo depends on procedural macros, which requires a full host // Cargo depends on procedural macros, which requires a full host
// compiler to be available, so we need to depend on that. // compiler to be available, so we need to depend on that.
builder.ensure(Rustc { builder.ensure(Rustc {
compiler: builder.compiler(builder.top_stage, &builder.build.build), compiler: builder.compiler(builder.top_stage, builder.build.build),
target: &builder.build.build, target: builder.build.build,
}); });
builder.ensure(ToolBuild { builder.ensure(ToolBuild {
stage: self.stage, stage: self.stage,
@ -357,14 +365,13 @@ impl<'a> Step<'a> for Cargo<'a> {
// }) // })
// .run(move |s| compile::tool(build, s.stage, s.target, "rls")); // .run(move |s| compile::tool(build, s.stage, s.target, "rls"));
// //
#[derive(Serialize)] #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Rls<'a> { pub struct Rls {
pub stage: u32, pub stage: u32,
pub target: &'a str, pub target: Interned<String>,
} }
impl<'a> Step<'a> for Rls<'a> { impl Step for Rls {
type Id = Rls<'static>;
type Output = PathBuf; type Output = PathBuf;
const DEFAULT: bool = true; const DEFAULT: bool = true;
const ONLY_HOSTS: bool = true; const ONLY_HOSTS: bool = true;
@ -373,7 +380,9 @@ impl<'a> Step<'a> for Rls<'a> {
path.ends_with("src/tools/rls") path.ends_with("src/tools/rls")
} }
fn make_run(builder: &Builder, path: Option<&Path>, _host: &str, target: &str) { fn make_run(
builder: &Builder, path: Option<&Path>, _host: Interned<String>, target: Interned<String>
) {
if path.is_none() && !builder.build.config.extended { if path.is_none() && !builder.build.config.extended {
return; return;
} }
@ -390,8 +399,8 @@ impl<'a> Step<'a> for Rls<'a> {
// RLS depends on procedural macros, which requires a full host // RLS depends on procedural macros, which requires a full host
// compiler to be available, so we need to depend on that. // compiler to be available, so we need to depend on that.
builder.ensure(Rustc { builder.ensure(Rustc {
compiler: builder.compiler(builder.top_stage, &builder.build.build), compiler: builder.compiler(builder.top_stage, builder.build.build),
target: &builder.build.build, target: builder.build.build,
}); });
builder.ensure(ToolBuild { builder.ensure(ToolBuild {
stage: self.stage, stage: self.stage,
@ -407,7 +416,7 @@ impl<'a> Builder<'a> {
/// `host`. /// `host`.
pub fn tool_cmd(&self, tool: Tool) -> Command { pub fn tool_cmd(&self, tool: Tool) -> Command {
let mut cmd = Command::new(self.tool_exe(tool)); let mut cmd = Command::new(self.tool_exe(tool));
let compiler = self.compiler(0, &self.build.build); let compiler = self.compiler(0, self.build.build);
self.prepare_tool_cmd(compiler, &mut cmd); self.prepare_tool_cmd(compiler, &mut cmd);
cmd cmd
} }
@ -417,10 +426,10 @@ impl<'a> Builder<'a> {
/// Notably this munges the dynamic library lookup path to point to the /// Notably this munges the dynamic library lookup path to point to the
/// right location to run `compiler`. /// right location to run `compiler`.
fn prepare_tool_cmd(&self, compiler: Compiler, cmd: &mut Command) { fn prepare_tool_cmd(&self, compiler: Compiler, cmd: &mut Command) {
let host = compiler.host; let host = &compiler.host;
let mut paths = vec![ let mut paths: Vec<PathBuf> = vec![
self.sysroot_libdir(compiler, compiler.host), PathBuf::from(&self.sysroot_libdir(compiler, compiler.host)),
self.cargo_out(compiler, Mode::Tool, host).join("deps"), self.cargo_out(compiler, Mode::Tool, *host).join("deps"),
]; ];
// On MSVC a tool may invoke a C compiler (e.g. compiletest in run-make // On MSVC a tool may invoke a C compiler (e.g. compiletest in run-make
@ -429,7 +438,7 @@ impl<'a> Builder<'a> {
if compiler.host.contains("msvc") { if compiler.host.contains("msvc") {
let curpaths = env::var_os("PATH").unwrap_or_default(); let curpaths = env::var_os("PATH").unwrap_or_default();
let curpaths = env::split_paths(&curpaths).collect::<Vec<_>>(); let curpaths = env::split_paths(&curpaths).collect::<Vec<_>>();
for &(ref k, ref v) in self.cc[compiler.host].0.env() { for &(ref k, ref v) in self.cc[&compiler.host].0.env() {
if k != "PATH" { if k != "PATH" {
continue continue
} }