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)",
"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)",
"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)",
"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_derive 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.9 (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)",
]
@ -155,8 +156,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
name = "build-manifest"
version = "0.1.0"
dependencies = [
"serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 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.9 (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_json = "1.0.2"
toml = "0.4"
lazy_static = "0.2"

View File

@ -8,20 +8,21 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use serde::{Serialize, Deserialize};
use std::fmt::Debug;
use std::hash::Hash;
use std::cell::RefCell;
use std::path::{Path, PathBuf};
use std::process::Command;
use std::fs;
use std::ops::Deref;
use std::any::{TypeId, Any};
use compile;
use install;
use dist;
use util::{exe, libdir, add_lib_path};
use {Build, Mode};
use cache::{Cache, Key};
use cache::{INTERNER, Interned, Cache};
use check;
use flags::Subcommand;
use doc;
@ -34,7 +35,7 @@ pub struct Builder<'a> {
pub top_stage: u32,
pub kind: Kind,
cache: Cache,
stack: RefCell<Vec<Key>>,
stack: RefCell<Vec<(TypeId, Box<Any>)>>,
}
impl<'a> Deref for Builder<'a> {
@ -45,19 +46,10 @@ impl<'a> Deref for Builder<'a> {
}
}
pub trait Step<'a>: Serialize + Sized {
/// The output type of this step. This is used in a few places to return a
pub trait Step: 'static + Clone + Debug + PartialEq + Eq + Hash {
/// `PathBuf` when directories are created or to return a `Compiler` once
/// it's been assembled.
///
/// 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;
type Output: Clone;
const DEFAULT: bool = false;
@ -72,13 +64,13 @@ pub trait Step<'a>: Serialize + Sized {
/// Primary function to execute this rule. Can call `builder.ensure(...)`
/// 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
/// 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
/// 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
/// 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
/// called if it is in the correct list below with a path of `None`.
fn make_run(
_builder: &'a Builder,
_builder: &Builder,
_path: Option<&Path>,
_host: &'a str,
_target: &'a str,
_host: Interned<String>,
_target: Interned<String>,
) { unimplemented!() }
}
@ -176,26 +168,27 @@ impl<'a> Builder<'a> {
/// not take `Compiler` since all `Compiler` instances are meant to be
/// obtained through this function, since it ensures that they are valid
/// (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 } })
}
pub fn sysroot(&self, compiler: Compiler<'a>) -> PathBuf {
pub fn sysroot(&self, compiler: Compiler) -> Interned<PathBuf> {
self.ensure(compile::Sysroot { compiler })
}
/// Returns the libdir where the standard library and other artifacts are
/// found for a compiler's sysroot.
pub fn sysroot_libdir(&self, compiler: Compiler<'a>, target: &'a str) -> PathBuf {
#[derive(Serialize)]
struct Libdir<'a> {
compiler: Compiler<'a>,
target: &'a str,
pub fn sysroot_libdir(
&self, compiler: Compiler, target: Interned<String>
) -> Interned<PathBuf> {
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
struct Libdir {
compiler: Compiler,
target: Interned<String>,
}
impl<'a> Step<'a> for Libdir<'a> {
type Id = Libdir<'static>;
type Output = PathBuf;
fn run(self, builder: &Builder) -> PathBuf {
impl Step for Libdir {
type Output = Interned<PathBuf>;
fn run(self, builder: &Builder) -> Interned<PathBuf> {
let compiler = self.compiler;
let lib = if compiler.stage >= 2 && builder.build.config.libdir_relative.is_some() {
builder.build.config.libdir_relative.clone().unwrap()
@ -206,7 +199,7 @@ impl<'a> Builder<'a> {
.join("rustlib").join(self.target).join("lib");
let _ = fs::remove_dir_all(&sysroot);
t!(fs::create_dir_all(&sysroot));
sysroot
INTERNER.intern_path(sysroot)
}
}
self.ensure(Libdir { compiler, target })
@ -221,7 +214,7 @@ impl<'a> Builder<'a> {
if compiler.is_snapshot(self) {
self.build.rustc_snapshot_libdir()
} 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) {
self.initial_rustc.clone()
} 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 {
let mut rustdoc = self.rustc(compiler);
rustdoc.pop();
rustdoc.push(exe("rustdoc", compiler.host));
rustdoc.push(exe("rustdoc", &compiler.host));
rustdoc
}
@ -265,7 +258,7 @@ impl<'a> Builder<'a> {
pub fn cargo(&self,
compiler: Compiler,
mode: Mode,
target: &str,
target: Interned<String>,
cmd: &str) -> Command {
let mut cargo = Command::new(&self.initial_cargo);
let out_dir = self.stage_out(compiler, mode);
@ -427,7 +420,7 @@ impl<'a> Builder<'a> {
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 hosts = if S::ONLY_BUILD_TARGETS || S::ONLY_BUILD {
&build.config.host[..1]
@ -459,7 +452,7 @@ impl<'a> Builder<'a> {
for host in hosts {
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
/// cache the step, so it is safe (and good!) to call this as often as
/// needed to ensure that all dependencies are built.
pub fn ensure<S: Step<'a>>(&'a self, step: S) -> S::Output {
let key = Cache::to_key(&step);
pub fn ensure<S: Step>(&'a self, step: S) -> S::Output {
let type_id = TypeId::of::<S>();
{
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();
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() {
out += &format!("\t{:?}\n", el);
}
panic!(out);
}
if let Some(out) = self.cache.get::<S::Output>(&key) {
self.build.verbose(&format!("{}c {:?}", " ".repeat(stack.len()), key));
if let Some(out) = self.cache.get(&step) {
self.build.verbose(&format!("{}c {:?}", " ".repeat(stack.len()), step));
return out;
}
self.build.verbose(&format!("{}> {:?}", " ".repeat(stack.len()), key));
stack.push(key.clone());
self.build.verbose(&format!("{}> {:?}", " ".repeat(stack.len()), step));
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();
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.cache.put(key.clone(), &out);
self.cache.get::<S::Output>(&key).unwrap()
self.build.verbose(&format!("{}< {:?}", " ".repeat(self.stack.borrow().len()), step));
self.cache.put(step, out.clone());
out
}
}

View File

@ -8,15 +8,250 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use serde_json;
use serde::{Serialize, Deserialize};
use std::any::TypeId;
use serde::Deserialize;
use serde::de::{self, Deserializer, Visitor};
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 std::fmt;
use std::mem;
use std::collections::HashMap;
use std::cell::RefCell;
pub struct Interned<T>(usize, PhantomData<*const T>);
impl<'de> Deserialize<'de> for Interned<String> {
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
/// 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
// 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)]
pub struct Cache(RefCell<HashMap<Key, Box<str>>>);
fn to_json<T: Serialize>(element: &T) -> String {
t!(serde_json::to_string(element))
}
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)
}
}
pub struct Cache(
RefCell<HashMap<
TypeId,
Box<Any>, // actually a HashMap<Step, Interned<Step::Output>>
>>
);
impl Cache {
pub fn new() -> Cache {
Cache(RefCell::new(HashMap::new()))
}
pub fn to_key<'a, K: Step<'a>>(key: &K) -> Key {
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,
{
pub fn put<S: Step>(&self, step: S, value: S::Output) {
let mut cache = self.0.borrow_mut();
let value = to_json(value);
assert!(!cache.contains_key(&key), "processing {:?} a second time", key);
// Store a boxed str so that it's location in memory never changes and
// it's safe for us to return references to it (so long as they live as
// long as us).
cache.insert(key, value.into_boxed_str());
let type_id = TypeId::of::<S>();
let stepcache = cache.entry(type_id)
.or_insert_with(|| Box::new(HashMap::<S, S::Output>::new()))
.downcast_mut::<HashMap<S, S::Output>>()
.expect("invalid type mapped");
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>
where
V: Deserialize<'a> + 'a,
{
let cache = self.0.borrow();
cache.get(key).map(|v| {
// Change the lifetime. This borrow is valid for as long as self lives;
// the data we're accessing will live as long as us and will be in a
// stable location, since we use Box<str>.
let v = unsafe {
mem::transmute::<&str, &'a str>(v)
};
from_json(v)
})
pub fn get<S: Step>(&self, step: &S) -> Option<S::Output> {
let mut cache = self.0.borrow_mut();
let type_id = TypeId::of::<S>();
let stepcache = cache.entry(type_id)
.or_insert_with(|| Box::new(HashMap::<S, S::Output>::new()))
.downcast_mut::<HashMap<S, S::Output>>()
.expect("invalid type mapped");
stepcache.get(step).cloned()
}
}

View File

@ -38,6 +38,7 @@ use gcc;
use Build;
use config::Target;
use cache::Interned;
pub fn find(build: &mut Build) {
// 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)
.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()) {
cfg.compiler(cc);
} else {
set_compiler(&mut cfg, "gcc", target, config, build);
set_compiler(&mut cfg, "gcc", *target, config, build);
}
let compiler = cfg.get_compiler();
@ -63,7 +64,7 @@ pub fn find(build: &mut Build) {
if let Some(ref ar) = 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
@ -78,20 +79,20 @@ pub fn find(build: &mut Build) {
if let Some(cxx) = config.and_then(|c| c.cxx.as_ref()) {
cfg.compiler(cxx);
} else {
set_compiler(&mut cfg, "g++", host, config, build);
set_compiler(&mut cfg, "g++", *host, config, build);
}
let compiler = cfg.get_compiler();
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,
gnu_compiler: &str,
target: &str,
target: Interned<String>,
config: Option<&Target>,
build: &Build) {
match target {
match &*target {
// When compiling for android we may have the NDK configured in the
// config.toml in which case we look there. Otherwise the default
// compiler already takes into account the triple in question.

View File

@ -33,11 +33,12 @@ use compile;
use native;
use builder::{Kind, Builder, Compiler, Step};
use tool::{self, Tool};
use cache::{INTERNER, Interned};
const ADB_TEST_DIR: &str = "/data/tmp/work";
/// The two modes of the test runner; tests or benchmarks.
#[derive(Serialize, Copy, Clone)]
#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)]
pub enum TestKind {
/// Run `cargo test`
Test,
@ -93,13 +94,12 @@ fn try_run_quiet(build: &Build, cmd: &mut Command) {
// .host(true)
// .run(move |s| check::linkcheck(build, s.target));
#[derive(Serialize)]
pub struct Linkcheck<'a> {
host: &'a str,
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct Linkcheck {
host: Interned<String>,
}
impl<'a> Step<'a> for Linkcheck<'a> {
type Id = Linkcheck<'static>;
impl Step for Linkcheck {
type Output = ();
const ONLY_HOSTS: bool = true;
const DEFAULT: bool = true;
@ -125,7 +125,12 @@ impl<'a> Step<'a> for Linkcheck<'a> {
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() {
builder.ensure(Linkcheck { host });
} else {
@ -142,14 +147,13 @@ impl<'a> Step<'a> for Linkcheck<'a> {
// .host(true)
// .run(move |s| check::cargotest(build, s.stage, s.target));
#[derive(Serialize)]
pub struct Cargotest<'a> {
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct Cargotest {
stage: u32,
host: &'a str,
host: Interned<String>,
}
impl<'a> Step<'a> for Cargotest<'a> {
type Id = Cargotest<'static>;
impl Step for Cargotest {
type Output = ();
const ONLY_HOSTS: bool = true;
@ -157,7 +161,12 @@ impl<'a> Step<'a> for Cargotest<'a> {
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 {
stage: builder.top_stage,
host: host,
@ -193,14 +202,13 @@ impl<'a> Step<'a> for Cargotest<'a> {
// .host(true)
// .run(move |s| check::cargo(build, s.stage, s.target));
#[derive(Serialize)]
pub struct Cargo<'a> {
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct Cargo {
stage: u32,
host: &'a str,
host: Interned<String>,
}
impl<'a> Step<'a> for Cargo<'a> {
type Id = Cargo<'static>;
impl Step for Cargo {
type Output = ();
const ONLY_HOSTS: bool = true;
@ -208,7 +216,12 @@ impl<'a> Step<'a> for Cargo<'a> {
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 {
stage: builder.top_stage,
host: target,
@ -304,13 +317,12 @@ fn path_for_cargo(build: &Build, compiler: &Compiler) -> OsString {
// .only_build(true)
// .run(move |s| check::tidy(build, s.target));
#[derive(Serialize)]
pub struct Tidy<'a> {
host: &'a str,
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct Tidy {
host: Interned<String>,
}
impl<'a> Step<'a> for Tidy<'a> {
type Id = Tidy<'static>;
impl Step for Tidy {
type Output = ();
const DEFAULT: bool = true;
const ONLY_HOSTS: bool = true;
@ -342,14 +354,19 @@ impl<'a> Step<'a> for Tidy<'a> {
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 {
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")
}
@ -451,15 +468,15 @@ fn testdir(build: &Build, host: &str) -> PathBuf {
// "pretty", "run-fail-fulldeps");
// }
#[derive(Serialize)]
pub struct Compiletest<'a> {
compiler: Compiler<'a>,
target: &'a str,
mode: &'a str,
suite: &'a str,
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct Compiletest {
compiler: Compiler,
target: Interned<String>,
mode: &'static str,
suite: &'static str,
}
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
struct Test {
path: &'static str,
mode: &'static str,
@ -512,8 +529,7 @@ static COMPILETESTS: &[Test] = &[
Test { path: "src/test/debuginfo-gdb", mode: "debuginfo-gdb", suite: "debuginfo" },
];
impl<'a> Step<'a> for Compiletest<'a> {
type Id = Compiletest<'static>;
impl Step for Compiletest {
type Output = ();
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 test = path.map(|path| {
@ -591,12 +612,12 @@ impl<'a> Step<'a> for Compiletest<'a> {
builder.ensure(Compiletest {
mode: "debuginfo-lldb",
..self
})
});
} else {
builder.ensure(Compiletest {
mode: "debuginfo-gdb",
..self
})
});
};
}
@ -606,7 +627,7 @@ impl<'a> Step<'a> for Compiletest<'a> {
}
builder.ensure(dist::DebuggerScripts {
sysroot: &builder.sysroot(compiler),
sysroot: builder.sysroot(compiler),
target: target
});
@ -630,7 +651,7 @@ impl<'a> Step<'a> for Compiletest<'a> {
let _folder = build.fold_output(|| format!("test_{}", suite));
println!("Check compiletest suite={} mode={} ({} -> {})",
suite, mode, compiler.host, target);
suite, mode, &compiler.host, target);
let mut cmd = builder.tool_cmd(Tool::Compiletest);
// 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("--mode").arg(mode);
cmd.arg("--target").arg(target);
cmd.arg("--host").arg(compiler.host);
cmd.arg("--llvm-filecheck").arg(build.llvm_filecheck(&build.build));
cmd.arg("--host").arg(&*compiler.host);
cmd.arg("--llvm-filecheck").arg(build.llvm_filecheck(build.build));
if let Some(ref nodejs) = build.config.nodejs {
cmd.arg("--nodejs").arg(nodejs);
@ -664,7 +685,7 @@ impl<'a> Step<'a> for Compiletest<'a> {
hostflags.extend(flags.clone());
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.push(format!("-Lnative={}",
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`
// rather than stomp over it.
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" {
cmd.env(k, v);
}
@ -769,9 +790,9 @@ impl<'a> Step<'a> for Compiletest<'a> {
}
}
#[derive(Serialize)]
pub struct Docs<'a> {
compiler: Compiler<'a>,
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct Docs {
compiler: Compiler,
}
// rules.test("check-docs", "src/doc")
@ -779,8 +800,7 @@ pub struct Docs<'a> {
// .default(true)
// .host(true)
// .run(move |s| check::docs(build, &s.compiler()));
impl<'a> Step<'a> for Docs<'a> {
type Id = Docs<'static>;
impl Step for Docs {
type Output = ();
const DEFAULT: bool = true;
const ONLY_HOSTS: bool = true;
@ -789,7 +809,12 @@ impl<'a> Step<'a> for Docs<'a> {
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 {
compiler: builder.compiler(builder.top_stage, host),
});
@ -840,13 +865,12 @@ impl<'a> Step<'a> for Docs<'a> {
// .host(true)
// .run(move |s| check::error_index(build, &s.compiler()));
#[derive(Serialize)]
pub struct ErrorIndex<'a> {
compiler: Compiler<'a>,
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct ErrorIndex {
compiler: Compiler,
}
impl<'a> Step<'a> for ErrorIndex<'a> {
type Id = ErrorIndex<'static>;
impl Step for ErrorIndex {
type Output = ();
const DEFAULT: 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")
}
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 {
compiler: builder.compiler(builder.top_stage, host),
});
@ -933,16 +962,15 @@ fn markdown_test(builder: &Builder, compiler: Compiler, markdown: &Path) {
// .host(true)
// .run(move |s| check::krate(build, &s.compiler(), s.target,
// Mode::Librustc, TestKind::Test, None));
#[derive(Serialize)]
pub struct KrateLibrustc<'a> {
compiler: Compiler<'a>,
target: &'a str,
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct KrateLibrustc {
compiler: Compiler,
target: Interned<String>,
test_kind: TestKind,
krate: Option<&'a str>,
krate: Option<Interned<String>>,
}
impl<'a> Step<'a> for KrateLibrustc<'a> {
type Id = KrateLibrustc<'static>;
impl Step for KrateLibrustc {
type Output = ();
const DEFAULT: 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 run = |name: Option<&str>| {
let run = |name: Option<Interned<String>>| {
let test_kind = if builder.kind == Kind::Test {
TestKind::Test
} 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,
// Mode::Libtest, TestKind::Test, None));
#[derive(Serialize)]
pub struct Krate<'a> {
compiler: Compiler<'a>,
target: &'a str,
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct Krate {
compiler: Compiler,
target: Interned<String>,
mode: Mode,
test_kind: TestKind,
krate: Option<&'a str>,
krate: Option<Interned<String>>,
}
impl<'a> Step<'a> for Krate<'a> {
type Id = Krate<'static>;
impl Step for Krate {
type Output = ();
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 run = |mode: Mode, name: Option<&str>| {
let run = |mode: Mode, name: Option<Interned<String>>| {
let test_kind = if builder.kind == Kind::Test {
TestKind::Test
} else if builder.kind == Kind::Bench {
@ -1134,11 +1171,12 @@ impl<'a> Step<'a> for Krate<'a> {
}
_ => panic!("can only test libraries"),
};
let root = INTERNER.intern_string(String::from(root));
let _folder = build.fold_output(|| {
format!("{}_stage{}-{}", test_kind.subcommand(), compiler.stage, name)
});
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
// 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
// helper crate, not tested. If it leaks through then it ends up
// 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));
}
for dep in build.crates[name].deps.iter() {
for dep in build.crates[&name].deps.iter() {
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,
// but our wrapper scripts arrange for that to be the case anyway.
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());
if target.contains("emscripten") || build.remote_tested(target) {
@ -1228,7 +1266,7 @@ impl<'a> Step<'a> for Krate<'a> {
fn krate_emscripten(build: &Build,
compiler: Compiler,
target: &str,
target: Interned<String>,
mode: Mode) {
let out_dir = build.cargo_out(compiler, mode, target);
let tests = find_tests(&out_dir.join("deps"), target);
@ -1247,7 +1285,7 @@ fn krate_emscripten(build: &Build,
fn krate_remote(builder: &Builder,
compiler: Compiler,
target: &str,
target: Interned<String>,
mode: Mode) {
let build = builder.build;
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();
for e in t!(dir.read_dir()).map(|e| t!(e)) {
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
/// 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.
#[derive(Serialize)]
pub struct RemoteCopyLibs<'a> {
compiler: Compiler<'a>,
target: &'a str,
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct RemoteCopyLibs {
compiler: Compiler,
target: Interned<String>,
}
impl<'a> Step<'a> for RemoteCopyLibs<'a> {
type Id = RemoteCopyLibs<'static>;
impl Step for RemoteCopyLibs {
type Output = ();
fn run(self, builder: &Builder) {
@ -1368,18 +1405,17 @@ impl<'a> Step<'a> for RemoteCopyLibs<'a> {
// .dep(|s| s.name("dist-src"))
// .run(move |_| check::distcheck(build));
#[derive(Serialize)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct Distcheck;
impl<'a> Step<'a> for Distcheck {
type Id = Distcheck;
impl Step for Distcheck {
type Output = ();
/// Run "distcheck", a 'make check' from a tarball
fn run(self, builder: &Builder) {
let build = builder.build;
if build.build != "x86_64-unknown-linux-gnu" {
if *build.build != *"x86_64-unknown-linux-gnu" {
return
}
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)
// .run(move |_| check::bootstrap(build));
#[derive(Serialize)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct Bootstrap;
impl<'a> Step<'a> for Bootstrap {
type Id = Bootstrap;
impl Step for Bootstrap {
type Output = ();
const DEFAULT: bool = true;
const ONLY_HOSTS: bool = true;
@ -1466,7 +1501,12 @@ impl<'a> Step<'a> for 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);
}
}

View File

@ -32,6 +32,7 @@ use util::{exe, libdir, is_dylib, copy};
use {Build, Compiler, Mode};
use native;
use cache::{INTERNER, Interned};
use builder::{Step, Builder};
//
@ -140,14 +141,13 @@ use builder::{Step, Builder};
// .dep(move |s| s.name("rustc").host(&build.build).target(s.host))
// .run(move |s| compile::std(build, s.target, &s.compiler()));
// }
#[derive(Serialize)]
pub struct Std<'a> {
pub target: &'a str,
pub compiler: Compiler<'a>,
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct Std {
pub target: Interned<String>,
pub compiler: Compiler,
}
impl<'a> Step<'a> for Std<'a> {
type Id = Std<'static>;
impl Step for Std {
type Output = ();
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 {
compiler: builder.compiler(builder.top_stage, host),
target,
})
});
}
/// Build the standard library.
@ -178,7 +183,7 @@ impl<'a> Step<'a> for Std<'a> {
builder.ensure(StartupObjects { 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 {
compiler: from,
target: target,
@ -194,7 +199,7 @@ impl<'a> Step<'a> for Std<'a> {
let _folder = build.fold_output(|| format!("stage{}-std", 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);
build.clear_if_dirty(&out_dir, &builder.rustc(compiler));
@ -229,7 +234,7 @@ impl<'a> Step<'a> for Std<'a> {
.arg("--manifest-path")
.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 {
cargo.env("JEMALLOC_OVERRIDE", jemalloc);
}
@ -245,7 +250,7 @@ impl<'a> Step<'a> for Std<'a> {
&libstd_stamp(build, compiler, target));
builder.ensure(StdLink {
compiler: builder.compiler(compiler.stage, &build.build),
compiler: builder.compiler(compiler.stage, build.build),
target_compiler: compiler,
target: target,
});
@ -261,15 +266,14 @@ impl<'a> Step<'a> for Std<'a> {
// .dep(|s| s.name("startup-objects"))
// .dep(|s| s.name("create-sysroot").target(s.host));
#[derive(Serialize)]
struct StdLink<'a> {
pub compiler: Compiler<'a>,
pub target_compiler: Compiler<'a>,
pub target: &'a str,
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
struct StdLink {
pub compiler: Compiler,
pub target_compiler: Compiler,
pub target: Interned<String>,
}
impl<'a> Step<'a> for StdLink<'a> {
type Id = StdLink<'static>;
impl Step for StdLink {
type Output = ();
/// 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{} ({} -> {} / {})",
target_compiler.stage,
compiler.stage,
compiler.host,
&compiler.host,
target_compiler.host,
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
///
/// 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"] {
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))
// .run(move |s| compile::build_startup_objects(build, &s.compiler(), s.target));
#[derive(Serialize)]
pub struct StartupObjects<'a> {
pub compiler: Compiler<'a>,
pub target: &'a str,
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct StartupObjects {
pub compiler: Compiler,
pub target: Interned<String>,
}
impl<'a> Step<'a> for StartupObjects<'a> {
type Id = StartupObjects<'static>;
impl Step for StartupObjects {
type Output = ();
fn should_run(_builder: &Builder, path: &Path) -> bool {
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 {
compiler: builder.compiler(builder.top_stage, host),
target,
})
});
}
/// 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"))
// .run(move |s| compile::test(build, s.target, &s.compiler()));
// }
#[derive(Serialize)]
pub struct Test<'a> {
pub compiler: Compiler<'a>,
pub target: &'a str,
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct Test {
pub compiler: Compiler,
pub target: Interned<String>,
}
impl<'a> Step<'a> for Test<'a> {
type Id = Test<'static>;
impl Step for Test {
type Output = ();
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 {
compiler: builder.compiler(builder.top_stage, host),
target,
})
});
}
/// Build libtest.
@ -438,12 +450,12 @@ impl<'a> Step<'a> for Test<'a> {
if build.force_use_stage1(compiler, target) {
builder.ensure(Test {
compiler: builder.compiler(1, &build.build),
compiler: builder.compiler(1, build.build),
target: target,
});
println!("Uplifting stage1 test ({} -> {})", &build.build, target);
builder.ensure(TestLink {
compiler: builder.compiler(1, &build.build),
compiler: builder.compiler(1, build.build),
target_compiler: compiler,
target: target,
});
@ -452,7 +464,7 @@ impl<'a> Step<'a> for Test<'a> {
let _folder = build.fold_output(|| format!("stage{}-test", 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);
build.clear_if_dirty(&out_dir, &libstd_stamp(build, compiler, target));
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));
builder.ensure(TestLink {
compiler: builder.compiler(compiler.stage, &build.build),
compiler: builder.compiler(compiler.stage, build.build),
target_compiler: compiler,
target: target,
});
@ -481,15 +493,14 @@ impl<'a> Step<'a> for Test<'a> {
// compile::test_link)
// .dep(|s| s.name("libstd-link"));
#[derive(Serialize)]
pub struct TestLink<'a> {
pub compiler: Compiler<'a>,
pub target_compiler: Compiler<'a>,
pub target: &'a str,
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct TestLink {
pub compiler: Compiler,
pub target_compiler: Compiler,
pub target: Interned<String>,
}
impl<'a> Step<'a> for TestLink<'a> {
type Id = TestLink<'static>;
impl Step for TestLink {
type Output = ();
/// Same as `std_link`, only for libtest
@ -501,7 +512,7 @@ impl<'a> Step<'a> for TestLink<'a> {
println!("Copying stage{} test from stage{} ({} -> {} / {})",
target_compiler.stage,
compiler.stage,
compiler.host,
&compiler.host,
target_compiler.host,
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()));
// }
#[derive(Serialize)]
pub struct Rustc<'a> {
pub compiler: Compiler<'a>,
pub target: &'a str,
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct Rustc {
pub compiler: Compiler,
pub target: Interned<String>,
}
impl<'a> Step<'a> for Rustc<'a> {
type Id = Rustc<'static>;
impl Step for Rustc {
type Output = ();
const ONLY_HOSTS: 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 {
compiler: builder.compiler(builder.top_stage, host),
target,
})
});
}
/// Build the compiler.
@ -561,12 +576,12 @@ impl<'a> Step<'a> for Rustc<'a> {
if build.force_use_stage1(compiler, target) {
builder.ensure(Rustc {
compiler: builder.compiler(1, &build.build),
compiler: builder.compiler(1, build.build),
target: target,
});
println!("Uplifting stage1 rustc ({} -> {})", &build.build, target);
builder.ensure(RustcLink {
compiler: builder.compiler(1, &build.build),
compiler: builder.compiler(1, build.build),
target_compiler: compiler,
target,
});
@ -575,13 +590,13 @@ impl<'a> Step<'a> for Rustc<'a> {
// Ensure that build scripts have a std to link against.
builder.ensure(Std {
compiler: builder.compiler(self.compiler.stage, &build.build),
target: &build.build,
compiler: builder.compiler(self.compiler.stage, build.build),
target: build.build,
});
let _folder = build.fold_output(|| format!("stage{}-rustc", compiler.stage));
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);
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_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()) {
cargo.env("CFG_LLVM_ROOT", s);
}
@ -653,7 +668,7 @@ impl<'a> Step<'a> for Rustc<'a> {
&librustc_stamp(build, compiler, target));
builder.ensure(RustcLink {
compiler: builder.compiler(compiler.stage, &build.build),
compiler: builder.compiler(compiler.stage, build.build),
target_compiler: compiler,
target,
});
@ -666,15 +681,14 @@ impl<'a> Step<'a> for Rustc<'a> {
// "build-crate-rustc-main",
// compile::rustc_link)
// .dep(|s| s.name("libtest-link"));
#[derive(Serialize)]
struct RustcLink<'a> {
pub compiler: Compiler<'a>,
pub target_compiler: Compiler<'a>,
pub target: &'a str,
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
struct RustcLink {
pub compiler: Compiler,
pub target_compiler: Compiler,
pub target: Interned<String>,
}
impl<'a> Step<'a> for RustcLink<'a> {
type Id = RustcLink<'static>;
impl Step for RustcLink {
type Output = ();
/// Same as `std_link`, only for librustc
@ -686,7 +700,7 @@ impl<'a> Step<'a> for RustcLink<'a> {
println!("Copying stage{} rustc from stage{} ({} -> {} / {})",
target_compiler.stage,
compiler.stage,
compiler.host,
&compiler.host,
target_compiler.host,
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
/// 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")
}
/// Cargo's output path for libtest in a given stage, compiled by a particular
/// 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")
}
/// Cargo's output path for librustc in a given stage, compiled by a particular
/// 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")
}
@ -721,14 +735,13 @@ fn compiler_file(compiler: &Path, file: &str) -> PathBuf {
// rules.build("create-sysroot", "path/to/nowhere")
// .run(move |s| compile::create_sysroot(build, &s.compiler()));
#[derive(Serialize)]
pub struct Sysroot<'a> {
pub compiler: Compiler<'a>,
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct Sysroot {
pub compiler: Compiler,
}
impl<'a> Step<'a> for Sysroot<'a> {
type Id = Sysroot<'static>;
type Output = PathBuf;
impl Step for Sysroot {
type Output = Interned<PathBuf>;
/// Returns the sysroot for the `compiler` specified that *this build system
/// 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
/// thinks it is by default, but it's the same as the default for stages
/// 1-3.
fn run(self, builder: &Builder) -> PathBuf {
fn run(self, builder: &Builder) -> Interned<PathBuf> {
let build = builder.build;
let compiler = self.compiler;
let sysroot = if compiler.stage == 0 {
build.out.join(compiler.host).join("stage0-sysroot")
build.out.join(&compiler.host).join("stage0-sysroot")
} 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);
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));
#[derive(Serialize)]
pub struct Assemble<'a> {
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct Assemble {
/// The compiler which we will produce in this step. Assemble itself will
/// take care of ensuring that the necessary prerequisites to do so exist,
/// that is, this target can be a stage2 compiler and Assemble will build
/// previous stages for you.
pub target_compiler: Compiler<'a>,
pub target_compiler: Compiler,
}
impl<'a> Step<'a> for Assemble<'a> {
type Id = Assemble<'static>;
type Output = Compiler<'a>;
impl Step for Assemble {
type Output = Compiler;
/// Prepare a new compiler from the artifacts in `stage`
///
/// This will assemble a compiler in `build/$host/stage$stage`. The compiler
/// must have been previously produced by the `stage - 1` build.build
/// compiler.
fn run(self, builder: &Builder) -> Compiler<'a> {
fn run(self, builder: &Builder) -> Compiler {
let build = builder.build;
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
// the libraries we need. FIXME: Perhaps we should download those
// libraries? It would make builds faster...
builder.ensure(Assemble {
target_compiler: Compiler {
// FIXME: It may be faster if we build just a stage 1
// compiler and then use that to bootstrap this compiler
// forward.
stage: target_compiler.stage - 1,
host: &build.build
},
})
// FIXME: It may be faster if we build just a stage 1
// compiler and then use that to bootstrap this compiler
// forward.
builder.compiler(target_compiler.stage - 1, build.build)
} else {
// Build the compiler we'll use to build the stage requested. This
// may build more than one compiler (going down to stage 0).
builder.ensure(Assemble {
target_compiler: target_compiler.with_stage(target_compiler.stage - 1),
})
builder.compiler(target_compiler.stage - 1, target_compiler.host)
};
// 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
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));
let src_libdir = builder.sysroot_libdir(build_compiler, host);
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);
// 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");
t!(fs::create_dir_all(&bindir));
let compiler = builder.rustc(target_compiler);
@ -850,7 +855,7 @@ impl<'a> Step<'a> for Assemble<'a> {
copy(&rustc, &compiler);
// 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_dst = bindir.join(&rustdoc);
if fs::metadata(&rustdoc_src).is_ok() {

View File

@ -23,6 +23,7 @@ use std::process;
use num_cpus;
use toml;
use util::{exe, push_exe_path};
use cache::{INTERNER, Interned};
/// Global configuration for the entire build and/or bootstrap.
///
@ -45,7 +46,7 @@ pub struct Config {
pub docs: bool,
pub locked_deps: bool,
pub vendor: bool,
pub target_config: HashMap<String, Target>,
pub target_config: HashMap<Interned<String>, Target>,
pub full_bootstrap: bool,
pub extended: bool,
pub sanitizers: bool,
@ -77,9 +78,9 @@ pub struct Config {
pub rust_debuginfo_tests: bool,
pub rust_dist_src: bool,
pub build: String,
pub host: Vec<String>,
pub target: Vec<String>,
pub build: Interned<String>,
pub host: Vec<Interned<String>>,
pub target: Vec<Interned<String>>,
pub local_rebuild: bool,
// dist misc
@ -282,7 +283,7 @@ impl Config {
config.docs = true;
config.rust_rpath = true;
config.rust_codegen_units = 1;
config.build = build.to_string();
config.build = INTERNER.intern_str(build);
config.channel = "dev".to_string();
config.codegen_tests = true;
config.rust_dist_src = true;
@ -302,16 +303,19 @@ impl Config {
}).unwrap_or_else(|| TomlConfig::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());
for host in build.host.iter() {
if !config.host.contains(host) {
config.host.push(host.clone());
let host = INTERNER.intern_str(host);
if !config.host.contains(&host) {
config.host.push(host);
}
}
for target in config.host.iter().chain(&build.target) {
if !config.target.contains(target) {
config.target.push(target.clone());
for target in config.host.iter().cloned()
.chain(build.target.iter().map(|s| INTERNER.intern_str(s)))
{
if !config.target.contains(&target) {
config.target.push(target);
}
}
config.nodejs = build.nodejs.map(PathBuf::from);
@ -404,7 +408,7 @@ impl Config {
target.musl_root = cfg.musl_root.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 {
"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 => {
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 => {
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 => {
self.llvm_experimental_targets = Some(value.to_string());
@ -521,33 +525,28 @@ impl Config {
self.musl_root = Some(parse_configure_path(value));
}
"CFG_MUSL_ROOT_X86_64" if value.len() > 0 => {
let target = "x86_64-unknown-linux-musl".to_string();
let target = self.target_config.entry(target)
.or_insert(Target::default());
let target = INTERNER.intern_str("x86_64-unknown-linux-musl");
let target = self.target_config.entry(target).or_insert(Target::default());
target.musl_root = Some(parse_configure_path(value));
}
"CFG_MUSL_ROOT_I686" if value.len() > 0 => {
let target = "i686-unknown-linux-musl".to_string();
let target = self.target_config.entry(target)
.or_insert(Target::default());
let target = INTERNER.intern_str("i686-unknown-linux-musl");
let target = self.target_config.entry(target).or_insert(Target::default());
target.musl_root = Some(parse_configure_path(value));
}
"CFG_MUSL_ROOT_ARM" if value.len() > 0 => {
let target = "arm-unknown-linux-musleabi".to_string();
let target = self.target_config.entry(target)
.or_insert(Target::default());
let target = INTERNER.intern_str("arm-unknown-linux-musleabi");
let target = self.target_config.entry(target).or_insert(Target::default());
target.musl_root = Some(parse_configure_path(value));
}
"CFG_MUSL_ROOT_ARMHF" if value.len() > 0 => {
let target = "arm-unknown-linux-musleabihf".to_string();
let target = self.target_config.entry(target)
.or_insert(Target::default());
let target = INTERNER.intern_str("arm-unknown-linux-musleabihf");
let target = self.target_config.entry(target).or_insert(Target::default());
target.musl_root = Some(parse_configure_path(value));
}
"CFG_MUSL_ROOT_ARMV7" if value.len() > 0 => {
let target = "armv7-unknown-linux-musleabihf".to_string();
let target = self.target_config.entry(target)
.or_insert(Target::default());
let target = INTERNER.intern_str("armv7-unknown-linux-musleabihf");
let target = self.target_config.entry(target).or_insert(Target::default());
target.musl_root = Some(parse_configure_path(value));
}
"CFG_DEFAULT_AR" if value.len() > 0 => {
@ -595,33 +594,28 @@ impl Config {
target.jemalloc = Some(parse_configure_path(value).join("libjemalloc_pic.a"));
}
"CFG_ARM_LINUX_ANDROIDEABI_NDK" if value.len() > 0 => {
let target = "arm-linux-androideabi".to_string();
let target = self.target_config.entry(target)
.or_insert(Target::default());
let target = INTERNER.intern_str("arm-linux-androideabi");
let target = self.target_config.entry(target).or_insert(Target::default());
target.ndk = Some(parse_configure_path(value));
}
"CFG_ARMV7_LINUX_ANDROIDEABI_NDK" if value.len() > 0 => {
let target = "armv7-linux-androideabi".to_string();
let target = self.target_config.entry(target)
.or_insert(Target::default());
let target = INTERNER.intern_str("armv7-linux-androideabi");
let target = self.target_config.entry(target).or_insert(Target::default());
target.ndk = Some(parse_configure_path(value));
}
"CFG_I686_LINUX_ANDROID_NDK" if value.len() > 0 => {
let target = "i686-linux-android".to_string();
let target = self.target_config.entry(target)
.or_insert(Target::default());
let target = INTERNER.intern_str("i686-linux-android");
let target = self.target_config.entry(target).or_insert(Target::default());
target.ndk = Some(parse_configure_path(value));
}
"CFG_AARCH64_LINUX_ANDROID_NDK" if value.len() > 0 => {
let target = "aarch64-linux-android".to_string();
let target = self.target_config.entry(target)
.or_insert(Target::default());
let target = INTERNER.intern_str("aarch64-linux-android");
let target = self.target_config.entry(target).or_insert(Target::default());
target.ndk = Some(parse_configure_path(value));
}
"CFG_X86_64_LINUX_ANDROID_NDK" if value.len() > 0 => {
let target = "x86_64-linux-android".to_string();
let target = self.target_config.entry(target)
.or_insert(Target::default());
let target = INTERNER.intern_str("x86_64-linux-android");
let target = self.target_config.entry(target).or_insert(Target::default());
target.ndk = Some(parse_configure_path(value));
}
"CFG_LOCAL_RUST_ROOT" if value.len() > 0 => {
@ -645,9 +639,8 @@ impl Config {
.collect();
}
"CFG_QEMU_ARMHF_ROOTFS" if value.len() > 0 => {
let target = "arm-unknown-linux-gnueabihf".to_string();
let target = self.target_config.entry(target)
.or_insert(Target::default());
let target = INTERNER.intern_str("arm-unknown-linux-gnueabihf");
let target = self.target_config.entry(target).or_insert(Target::default());
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 compile;
use tool::{self, Tool};
use cache::{INTERNER, Interned};
pub fn pkgname(build: &Build, component: &str) -> String {
if component == "cargo" {
@ -71,14 +72,13 @@ fn rust_installer(builder: &Builder) -> Command {
// .dep(move |s| tool_rust_installer(build, s))
// .run(move |s| dist::docs(build, s.stage, s.target));
#[derive(Serialize)]
pub struct Docs<'a> {
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Docs {
pub stage: u32,
pub target: &'a str,
pub target: Interned<String>,
}
impl<'a> Step<'a> for Docs<'a> {
type Id = Docs<'static>;
impl Step for Docs {
type Output = Option<PathBuf>;
const DEFAULT: bool = true;
const ONLY_BUILD_TARGETS: bool = true;
@ -87,7 +87,9 @@ impl<'a> Step<'a> for Docs<'a> {
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 {
stage: builder.top_stage,
target: target,
@ -165,7 +167,9 @@ fn find_files(files: &[&str], path: &[PathBuf]) -> Vec<PathBuf> {
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
let mut cmd = Command::new(build.cc(target_triple));
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)]
pub struct Mingw<'a> {
target: &'a str,
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Mingw {
target: Interned<String>,
}
impl<'a> Step<'a> for Mingw<'a> {
type Id = Mingw<'static>;
impl Step for Mingw {
type Output = Option<PathBuf>;
const DEFAULT: bool = true;
const ONLY_BUILD_TARGETS: bool = true;
@ -297,7 +300,9 @@ impl<'a> Step<'a> for Mingw<'a> {
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 });
}
@ -350,14 +355,13 @@ impl<'a> Step<'a> for Mingw<'a> {
// .dep(move |s| tool_rust_installer(build, s))
// .run(move |s| dist::rustc(build, s.stage, s.target));
#[derive(Serialize)]
pub struct Rustc<'a> {
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Rustc {
pub stage: u32,
pub target: &'a str,
pub target: Interned<String>,
}
impl<'a> Step<'a> for Rustc<'a> {
type Id = Rustc<'static>;
impl Step for Rustc {
type Output = PathBuf;
const DEFAULT: bool = true;
const ONLY_HOSTS: bool = true;
@ -367,7 +371,9 @@ impl<'a> Step<'a> for Rustc<'a> {
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 {
stage: builder.top_stage,
target: target,
@ -381,7 +387,7 @@ impl<'a> Step<'a> for Rustc<'a> {
let target = self.target;
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);
@ -444,10 +450,12 @@ impl<'a> Step<'a> for Rustc<'a> {
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 src = builder.sysroot(compiler);
let libdir = libdir(target);
let libdir = libdir(&target);
// Copy rustc/rustdoc binaries
t!(fs::create_dir_all(image.join("bin")));
@ -471,7 +479,7 @@ impl<'a> Step<'a> for Rustc<'a> {
// Debugger scripts
builder.ensure(DebuggerScripts {
sysroot: &image,
sysroot: INTERNER.intern_path(image.to_owned()),
target: target,
});
@ -491,23 +499,24 @@ impl<'a> Step<'a> for Rustc<'a> {
// .run(move |s| dist::debugger_scripts(build, &builder.sysroot(&s.compiler()),
// s.target));
#[derive(Serialize)]
pub struct DebuggerScripts<'a> {
pub sysroot: &'a Path,
pub target: &'a str,
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct DebuggerScripts {
pub sysroot: Interned<PathBuf>,
pub target: Interned<String>,
}
impl<'a> Step<'a> for DebuggerScripts<'a> {
type Id = DebuggerScripts<'static>;
impl Step for DebuggerScripts {
type Output = ();
fn should_run(_builder: &Builder, path: &Path) -> bool {
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 {
sysroot: &builder.sysroot(builder.compiler(builder.top_stage, host)),
sysroot: builder.sysroot(builder.compiler(builder.top_stage, host)),
target: target,
});
}
@ -564,14 +573,13 @@ impl<'a> Step<'a> for DebuggerScripts<'a> {
// .dep(move |s| tool_rust_installer(build, s))
// .run(move |s| dist::std(build, &s.compiler(), s.target));
#[derive(Serialize)]
pub struct Std<'a> {
pub compiler: Compiler<'a>,
pub target: &'a str,
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Std {
pub compiler: Compiler,
pub target: Interned<String>,
}
impl<'a> Step<'a> for Std<'a> {
type Id = Std<'static>;
impl Step for Std {
type Output = Option<PathBuf>;
const DEFAULT: bool = true;
const ONLY_BUILD_TARGETS: bool = true;
@ -580,7 +588,9 @@ impl<'a> Step<'a> for Std<'a> {
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 {
compiler: builder.compiler(builder.top_stage, host),
target: target,
@ -592,7 +602,7 @@ impl<'a> Step<'a> for Std<'a> {
let compiler = self.compiler;
let target = self.target;
println!("Dist std stage{} ({} -> {})", compiler.stage, compiler.host,
println!("Dist std stage{} ({} -> {})", compiler.stage, &compiler.host,
target);
// 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);
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
cp_r(&src, &dst);
@ -645,14 +655,13 @@ impl<'a> Step<'a> for Std<'a> {
// .dep(move |s| tool_rust_installer(build, s))
// .run(move |s| dist::analysis(build, &s.compiler(), s.target));
#[derive(Serialize)]
pub struct Analysis<'a> {
pub compiler: Compiler<'a>,
pub target: &'a str,
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Analysis {
pub compiler: Compiler,
pub target: Interned<String>,
}
impl<'a> Step<'a> for Analysis<'a> {
type Id = Analysis<'static>;
impl Step for Analysis {
type Output = Option<PathBuf>;
const DEFAULT: bool = true;
const ONLY_BUILD_TARGETS: bool = true;
@ -661,7 +670,12 @@ impl<'a> Step<'a> for Analysis<'a> {
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 {
return;
}
@ -679,7 +693,7 @@ impl<'a> Step<'a> for Analysis<'a> {
assert!(build.config.extended);
println!("Dist analysis");
if compiler.host != build.build {
if &compiler.host != build.build {
println!("\tskipping, not a build host");
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))
// .run(move |_| dist::rust_src(build));
#[derive(Serialize)]
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Src;
impl<'a> Step<'a> for Src {
type Id = Src;
impl Step for Src {
/// The output path of the src installer tarball
type Output = PathBuf;
const DEFAULT: bool = true;
@ -785,7 +798,9 @@ impl<'a> Step<'a> for 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);
}
@ -867,11 +882,10 @@ const CARGO_VENDOR_VERSION: &str = "0.1.4";
// .dep(move |s| tool_rust_installer(build, s))
// .run(move |_| dist::plain_source_tarball(build));
#[derive(Serialize)]
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct PlainSourceTarball;
impl<'a> Step<'a> for PlainSourceTarball {
type Id = PlainSourceTarball;
impl Step for PlainSourceTarball {
/// Produces the location of the tarball generated
type Output = PathBuf;
const DEFAULT: bool = true;
@ -883,7 +897,9 @@ impl<'a> Step<'a> for PlainSourceTarball {
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 {
return;
}
@ -1019,14 +1035,13 @@ fn write_file(path: &Path, data: &[u8]) {
// .dep(move |s| tool_rust_installer(build, s))
// .run(move |s| dist::cargo(build, s.stage, s.target));
#[derive(Serialize)]
pub struct Cargo<'a> {
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Cargo {
pub stage: u32,
pub target: &'a str,
pub target: Interned<String>,
}
impl<'a> Step<'a> for Cargo<'a> {
type Id = Cargo<'static>;
impl Step for Cargo {
type Output = PathBuf;
const ONLY_BUILD_TARGETS: bool = true;
const ONLY_HOSTS: bool = true;
@ -1035,7 +1050,9 @@ impl<'a> Step<'a> for Cargo<'a> {
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 {
stage: builder.top_stage,
target: target,
@ -1050,7 +1067,7 @@ impl<'a> Step<'a> for Cargo<'a> {
builder.ensure(tool::Cargo { 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 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("etc/bash_completion.d")));
let cargo = build.cargo_out(compiler, Mode::Tool, target)
.join(exe("cargo", target));
.join(exe("cargo", &target));
install(&cargo, &image.join("bin"), 0o755);
for man in t!(etc.join("man").read_dir()) {
let man = t!(man);
@ -1116,14 +1133,13 @@ impl<'a> Step<'a> for Cargo<'a> {
// .dep(|s| s.name("tool-rls"))
// .dep(move |s| tool_rust_installer(build, s))
// .run(move |s| dist::rls(build, s.stage, s.target));
#[derive(Serialize)]
pub struct Rls<'a> {
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Rls {
pub stage: u32,
pub target: &'a str,
pub target: Interned<String>,
}
impl<'a> Step<'a> for Rls<'a> {
type Id = Rls<'static>;
impl Step for Rls {
type Output = PathBuf;
const ONLY_BUILD_TARGETS: bool = true;
const ONLY_HOSTS: bool = true;
@ -1132,7 +1148,9 @@ impl<'a> Step<'a> for Rls<'a> {
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 {
stage: builder.top_stage,
target: target,
@ -1148,7 +1166,7 @@ impl<'a> Step<'a> for Rls<'a> {
builder.ensure(tool::Rls { 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 release_num = build.release_num("rls");
@ -1162,7 +1180,7 @@ impl<'a> Step<'a> for Rls<'a> {
// Prepare the image directory
let rls = build.cargo_out(compiler, Mode::Tool, target)
.join(exe("rls", target));
.join(exe("rls", &target));
install(&rls, &image.join("bin"), 0o755);
let doc = image.join("share/doc/rls");
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))
// .run(move |s| dist::extended(build, s.stage, s.target));
#[derive(Serialize)]
pub struct Extended<'a> {
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Extended {
stage: u32,
target: &'a str,
target: Interned<String>,
}
impl<'a> Step<'a> for Extended<'a> {
type Id = Extended<'static>;
impl Step for Extended {
type Output = ();
const DEFAULT: bool = true;
const ONLY_BUILD_TARGETS: bool = true;
@ -1227,7 +1244,9 @@ impl<'a> Step<'a> for Extended<'a> {
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 {
return;
}
@ -1242,7 +1261,7 @@ impl<'a> Step<'a> for Extended<'a> {
let build = builder.build;
let stage = self.stage;
let target = self.target;
let compiler = builder.compiler(stage, &build.build);
let compiler = builder.compiler(stage, build.build);
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('.');
cmd.env("CFG_RELEASE_INFO", build.rust_version())
.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))
// .run(move |_| dist::hash_and_sign(build));
#[derive(Serialize)]
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct HashSign;
impl<'a> Step<'a> for HashSign {
type Id = HashSign;
impl Step for HashSign {
type Output = ();
const ONLY_BUILD_TARGETS: bool = true;
const ONLY_HOSTS: bool = true;
@ -1634,7 +1652,9 @@ impl<'a> Step<'a> for HashSign {
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);
}

View File

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

View File

@ -24,15 +24,17 @@ use Build;
use config::Config;
use metadata;
use cache::{Interned, INTERNER};
/// Deserialized version of all flags for this compile.
pub struct Flags {
pub verbose: usize, // verbosity level: 0 == not verbose, 1 == verbose, 2 == very verbose
pub on_fail: Option<String>,
pub stage: Option<u32>,
pub keep_stage: Option<u32>,
pub build: String,
pub host: Vec<String>,
pub target: Vec<String>,
pub build: Interned<String>,
pub host: Vec<Interned<String>>,
pub target: Vec<Interned<String>>,
pub config: Option<PathBuf>,
pub src: PathBuf,
pub jobs: Option<u32>,
@ -320,11 +322,13 @@ Arguments:
stage: stage,
on_fail: matches.opt_str("on-fail"),
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()
}),
host: split(matches.opt_strs("host")),
target: split(matches.opt_strs("target")),
})),
host: split(matches.opt_strs("host"))
.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,
src: src,
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 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));
}
pub fn install_std(builder: &Builder, stage: u32) {
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));
}
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));
}
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));
}
pub fn install_src(builder: &Builder, stage: u32) {
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));
}
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;
println!("Install {} stage{} ({:?})", package, stage, host);
@ -127,15 +134,15 @@ macro_rules! install {
$default_cond:expr,
only_hosts: $only_hosts:expr,
$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 target: &'a str,
pub host: &'a str,
pub target: Interned<String>,
pub host: Interned<String>,
}
impl<'a> Step<'a> for $name<'a> {
type Id = $name<'static>;
impl Step for $name {
type Output = ();
const DEFAULT: bool = true;
const ONLY_BUILD_TARGETS: bool = true;
@ -146,7 +153,12 @@ macro_rules! install {
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) {
return;
}

View File

@ -121,6 +121,8 @@
extern crate build_helper;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate lazy_static;
extern crate serde;
extern crate serde_json;
extern crate cmake;
@ -186,16 +188,17 @@ mod job {
pub use config::Config;
pub use flags::{Flags, Subcommand};
use cache::{Interned, INTERNER};
/// A structure representing a Rust compiler.
///
/// Each compiler has a `stage` that it is associated with and a `host` that
/// corresponds to the platform the compiler runs on. This structure is used as
/// a parameter to many methods below.
#[derive(Serialize, Deserialize, Eq, PartialEq, Clone, Copy, Hash, Debug)]
pub struct Compiler<'a> {
#[derive(Eq, PartialEq, Clone, Copy, Hash, Debug)]
pub struct Compiler {
stage: u32,
host: &'a str,
host: Interned<String>,
}
/// Global configuration for the build system.
@ -226,9 +229,9 @@ pub struct Build {
verbosity: usize,
// Targets for which to build.
build: String,
hosts: Vec<String>,
targets: Vec<String>,
build: Interned<String>,
hosts: Vec<Interned<String>>,
targets: Vec<Interned<String>>,
// Stage 0 (downloaded) compiler and cargo or their local rust equivalents.
initial_rustc: PathBuf,
@ -240,10 +243,10 @@ pub struct Build {
// Runtime state filled in later on
// target -> (cc, ar)
cc: HashMap<String, (gcc::Tool, Option<PathBuf>)>,
cc: HashMap<Interned<String>, (gcc::Tool, Option<PathBuf>)>,
// host -> (cc, ar)
cxx: HashMap<String, gcc::Tool>,
crates: HashMap<String, Crate>,
cxx: HashMap<Interned<String>, gcc::Tool>,
crates: HashMap<Interned<String>, Crate>,
is_sudo: bool,
ci_env: CiEnv,
delayed_failures: Cell<usize>,
@ -251,9 +254,9 @@ pub struct Build {
#[derive(Debug)]
struct Crate {
name: String,
name: Interned<String>,
version: String,
deps: Vec<String>,
deps: Vec<Interned<String>>,
path: PathBuf,
doc_step: String,
build_step: String,
@ -265,7 +268,7 @@ struct Crate {
///
/// These entries currently correspond to the various output directories of the
/// 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 {
/// Build the standard library, placing output in the "stageN-std" directory.
Libstd,
@ -438,7 +441,7 @@ impl Build {
/// Get the directory for incremental by-products when using the
/// given compiler.
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
@ -452,7 +455,7 @@ impl Build {
Mode::Tool => "-tools",
Mode::Librustc => "-rustc",
};
self.out.join(compiler.host)
self.out.join(&*compiler.host)
.join(format!("stage{}{}", compiler.stage, suffix))
}
@ -462,40 +465,40 @@ impl Build {
fn cargo_out(&self,
compiler: Compiler,
mode: Mode,
target: &str) -> PathBuf {
self.stage_out(compiler, mode).join(target).join(self.cargo_dir())
target: Interned<String>) -> PathBuf {
self.stage_out(compiler, mode).join(&*target).join(self.cargo_dir())
}
/// Root output directory for LLVM compiled for `target`
///
/// Note that if LLVM is configured externally then the directory returned
/// will likely be empty.
fn llvm_out(&self, target: &str) -> PathBuf {
self.out.join(target).join("llvm")
fn llvm_out(&self, target: Interned<String>) -> PathBuf {
self.out.join(&*target).join("llvm")
}
/// Output directory for all documentation for a target
fn doc_out(&self, target: &str) -> PathBuf {
self.out.join(target).join("doc")
fn doc_out(&self, target: Interned<String>) -> PathBuf {
self.out.join(&*target).join("doc")
}
/// Output directory for some generated md crate documentation for a target (temporary)
fn md_doc_out(&self, target: &str) -> PathBuf {
self.out.join(target).join("md-doc")
fn md_doc_out(&self, target: Interned<String>) -> Interned<PathBuf> {
INTERNER.intern_path(self.out.join(&*target).join("md-doc"))
}
/// Output directory for all crate documentation for a target (temporary)
///
/// The artifacts here are then copied into `doc_out` above.
fn crate_doc_out(&self, target: &str) -> PathBuf {
self.out.join(target).join("crate-docs")
fn crate_doc_out(&self, target: Interned<String>) -> PathBuf {
self.out.join(&*target).join("crate-docs")
}
/// 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.
fn is_rust_llvm(&self, target: &str) -> bool {
match self.config.target_config.get(target) {
fn is_rust_llvm(&self, target: Interned<String>) -> bool {
match self.config.target_config.get(&target) {
Some(ref c) => c.llvm_config.is_none(),
None => true
}
@ -505,25 +508,25 @@ impl Build {
///
/// If a custom `llvm-config` was specified for target then that's returned
/// instead.
fn llvm_config(&self, target: &str) -> PathBuf {
let target_config = self.config.target_config.get(target);
fn llvm_config(&self, target: Interned<String>) -> PathBuf {
let target_config = self.config.target_config.get(&target);
if let Some(s) = target_config.and_then(|c| c.llvm_config.as_ref()) {
s.clone()
} else {
self.llvm_out(&self.config.build).join("bin")
.join(exe("llvm-config", target))
self.llvm_out(self.config.build).join("bin")
.join(exe("llvm-config", &*target))
}
}
/// Returns the path to `FileCheck` binary for the specified target
fn llvm_filecheck(&self, target: &str) -> PathBuf {
let target_config = self.config.target_config.get(target);
fn llvm_filecheck(&self, target: Interned<String>) -> PathBuf {
let target_config = self.config.target_config.get(&target);
if let Some(s) = target_config.and_then(|c| c.llvm_config.as_ref()) {
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 {
let base = self.llvm_out(&self.config.build).join("build");
let exe = exe("FileCheck", target);
let base = self.llvm_out(self.config.build).join("build");
let exe = exe("FileCheck", &*target);
if !self.config.ninja && self.config.build.contains("msvc") {
base.join("Release/bin").join(exe)
} else {
@ -533,13 +536,13 @@ impl Build {
}
/// Directory for libraries built from C/C++ code and shared between stages.
fn native_dir(&self, target: &str) -> PathBuf {
self.out.join(target).join("native")
fn native_dir(&self, target: Interned<String>) -> PathBuf {
self.out.join(&*target).join("native")
}
/// Root output directory for rust_test_helpers library compiled for
/// `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")
}
@ -606,16 +609,16 @@ impl Build {
}
/// Returns the path to the C compiler for the target specified.
fn cc(&self, target: &str) -> &Path {
self.cc[target].0.path()
fn cc(&self, target: Interned<String>) -> &Path {
self.cc[&target].0.path()
}
/// Returns a list of flags to pass to the C compiler for the target
/// 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
// 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())
.filter(|s| !s.starts_with("-O") && !s.starts_with("/O"))
.collect::<Vec<_>>();
@ -631,20 +634,20 @@ impl Build {
// Work around an apparently bad MinGW / GCC optimization,
// See: http://lists.llvm.org/pipermail/cfe-dev/2016-December/051980.html
// 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
}
/// Returns the path to the `ar` archive utility for the target specified.
fn ar(&self, target: &str) -> Option<&Path> {
self.cc[target].1.as_ref().map(|p| &**p)
fn ar(&self, target: Interned<String>) -> Option<&Path> {
self.cc[&target].1.as_ref().map(|p| &**p)
}
/// Returns the path to the C++ compiler for the target specified.
fn cxx(&self, target: &str) -> Result<&Path, String> {
match self.cxx.get(target) {
fn cxx(&self, target: Interned<String>) -> Result<&Path, String> {
match self.cxx.get(&target) {
Some(p) => Ok(p.path()),
None => Err(format!(
"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`.
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!
//
// 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
fn musl_root(&self, target: &str) -> Option<&Path> {
self.config.target_config.get(target)
fn musl_root(&self, target: Interned<String>) -> Option<&Path> {
self.config.target_config.get(&target)
.and_then(|t| t.musl_root.as_ref())
.or(self.config.musl_root.as_ref())
.map(|p| &**p)
@ -679,7 +682,7 @@ impl Build {
/// Returns whether the target will be tested using the `remote-test-client`
/// 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") ||
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
/// emulated with QEMU and binaries will need to be shipped to the emulator.
fn qemu_rootfs(&self, target: &str) -> Option<&Path> {
self.config.target_config.get(target)
fn qemu_rootfs(&self, target: Interned<String>) -> Option<&Path> {
self.config.target_config.get(&target)
.and_then(|t| t.qemu_rootfs.as_ref())
.map(|p| &**p)
}
@ -718,20 +721,20 @@ impl Build {
///
/// When all of these conditions are met the build will lift artifacts from
/// 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 &&
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
/// 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
if target.contains("windows") {
None
} else if self.config.openssl_static {
Some(self.out.join(target).join("openssl"))
Some(self.out.join(&*target).join("openssl"))
} else {
None
}
@ -739,7 +742,7 @@ impl Build {
/// Returns the directory that OpenSSL artifacts are installed into if
/// 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"))
}
@ -842,18 +845,19 @@ impl Build {
/// Get a list of crates from a 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 list = vec![root];
let mut list = vec![interned];
let mut visited = HashSet::new();
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
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 {
if visited.insert(dep) && dep != "build_helper" {
list.push(dep);
list.push(*dep);
}
}
}
@ -861,8 +865,8 @@ impl Build {
}
}
impl<'a> Compiler<'a> {
pub fn with_stage(mut self, stage: u32) -> Compiler<'a> {
impl<'a> Compiler {
pub fn with_stage(mut self, stage: u32) -> Compiler {
self.stage = stage;
self
}

View File

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

View File

@ -33,6 +33,7 @@ use Build;
use util;
use build_helper::up_to_date;
use builder::{Builder, Step};
use cache::Interned;
// rules.build("llvm", "src/llvm")
// .host(true)
@ -45,13 +46,12 @@ use builder::{Builder, Step};
// })
// .run(move |s| native::llvm(build, s.target));
#[derive(Serialize)]
pub struct Llvm<'a> {
pub target: &'a str,
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Llvm {
pub target: Interned<String>,
}
impl<'a> Step<'a> for Llvm<'a> {
type Id = Llvm<'static>;
impl Step for Llvm {
type Output = ();
const ONLY_HOSTS: bool = true;
@ -61,7 +61,7 @@ impl<'a> Step<'a> for Llvm<'a> {
let target = self.target;
// If we're using a custom LLVM bail out here, but we can only use a
// 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 {
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"};
cfg.target(target)
cfg.target(&target)
.host(&build.build)
.out_dir(&out_dir)
.profile(profile)
@ -154,11 +154,11 @@ impl<'a> Step<'a> for Llvm<'a> {
// http://llvm.org/docs/HowToCrossCompileLLVM.html
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
// should use llvm-tblgen from there, also should verify that it
// 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")
.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")
// .run(move |s| native::test_helpers(build, s.target));
#[derive(Serialize)]
pub struct TestHelpers<'a> {
pub target: &'a str,
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct TestHelpers {
pub target: Interned<String>,
}
impl<'a> Step<'a> for TestHelpers<'a> {
type Id = TestHelpers<'static>;
impl Step for TestHelpers {
type Output = ();
fn should_run(_builder: &Builder, path: &Path) -> bool {
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 })
}
@ -290,7 +294,7 @@ impl<'a> Step<'a> for TestHelpers<'a> {
cfg.cargo_metadata(false)
.out_dir(&dst)
.target(target)
.target(&target)
.host(&build.build)
.opt_level(0)
.debug(false)
@ -306,13 +310,12 @@ const OPENSSL_SHA256: &'static str =
//rules.build("openssl", "path/to/nowhere")
// .run(move |s| native::openssl(build, s.target));
#[derive(Serialize)]
pub struct Openssl<'a> {
pub target: &'a str,
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Openssl {
pub target: Interned<String>,
}
impl<'a> Step<'a> for Openssl<'a> {
type Id = Openssl<'static>;
impl Step for Openssl {
type Output = ();
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-ssl3");
let os = match target {
let os = match &*target {
"aarch64-linux-android" => "linux-aarch64",
"aarch64-unknown-linux-gnu" => "linux-aarch64",
"arm-linux-androideabi" => "android",

View File

@ -122,14 +122,14 @@ pub fn check(build: &mut Build) {
continue;
}
cmd_finder.must_have(build.cc(target));
if let Some(ar) = build.ar(target) {
cmd_finder.must_have(build.cc(*target));
if let Some(ar) = build.ar(*target) {
cmd_finder.must_have(ar);
}
}
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
// 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
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 {
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
if target.contains("musl") && !target.contains("mips") {
match build.musl_root(target) {
match build.musl_root(*target) {
Some(root) => {
if fs::metadata(root.join("lib/libc.a")).is_err() {
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 native;
use channel::GitInfo;
use cache::Interned;
//// ========================================================================
//// Build tools
@ -44,15 +45,14 @@ use channel::GitInfo;
// .run(move |s| compile::maybe_clean_tools(build, s.stage, s.target, Mode::Libstd));
//
#[derive(Serialize)]
pub struct CleanTools<'a> {
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct CleanTools {
pub stage: u32,
pub target: &'a str,
pub target: Interned<String>,
pub mode: Mode,
}
impl<'a> Step<'a> for CleanTools<'a> {
type Id = CleanTools<'static>;
impl Step for CleanTools {
type Output = ();
/// Build a tool in `src/tools`
@ -65,7 +65,7 @@ impl<'a> Step<'a> for CleanTools<'a> {
let target = self.target;
let mode = self.mode;
let compiler = builder.compiler(stage, &build.build);
let compiler = builder.compiler(stage, build.build);
let stamp = match mode {
Mode::Libstd => libstd_stamp(build, compiler, target),
@ -78,16 +78,15 @@ impl<'a> Step<'a> for CleanTools<'a> {
}
}
#[derive(Serialize)]
pub struct ToolBuild<'a> {
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct ToolBuild {
pub stage: u32,
pub target: &'a str,
pub tool: &'a str,
pub target: Interned<String>,
pub tool: &'static str,
pub mode: Mode,
}
impl<'a> Step<'a> for ToolBuild<'a> {
type Id = ToolBuild<'static>;
impl Step for ToolBuild {
type Output = PathBuf;
/// Build a tool in `src/tools`
@ -100,7 +99,7 @@ impl<'a> Step<'a> for ToolBuild<'a> {
let target = self.target;
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 });
match self.mode {
Mode::Libstd => builder.ensure(compile::Std { compiler, target }),
@ -140,7 +139,7 @@ impl<'a> Step<'a> for ToolBuild<'a> {
}
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 =>
self.ensure($name {
stage: 0,
target: &self.build.build,
target: self.build.build,
}),
)+
}
@ -167,21 +166,25 @@ macro_rules! tool {
}
$(
#[derive(Serialize)]
pub struct $name<'a> {
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct $name {
pub stage: u32,
pub target: &'a str,
pub target: Interned<String>,
}
impl<'a> Step<'a> for $name<'a> {
type Id = $name<'static>;
impl Step for $name {
type Output = PathBuf;
fn should_run(_builder: &Builder, path: &Path) -> bool {
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 {
stage: builder.top_stage,
target,
@ -254,21 +257,25 @@ tool!(
RustInstaller, "src/tools/rust-installer", "rust-installer", Mode::Libstd;
);
#[derive(Serialize)]
pub struct RemoteTestServer<'a> {
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct RemoteTestServer {
pub stage: u32,
pub target: &'a str,
pub target: Interned<String>,
}
impl<'a> Step<'a> for RemoteTestServer<'a> {
type Id = RemoteTestServer<'static>;
impl Step for RemoteTestServer {
type Output = PathBuf;
fn should_run(_builder: &Builder, path: &Path) -> bool {
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 {
stage: builder.top_stage,
target,
@ -299,14 +306,13 @@ impl<'a> Step<'a> for RemoteTestServer<'a> {
// .host(&build.build)
// })
// .run(move |s| compile::tool(build, s.stage, s.target, "cargo"));
#[derive(Serialize)]
pub struct Cargo<'a> {
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Cargo {
pub stage: u32,
pub target: &'a str,
pub target: Interned<String>,
}
impl<'a> Step<'a> for Cargo<'a> {
type Id = Cargo<'static>;
impl Step for Cargo {
type Output = PathBuf;
const DEFAULT: bool = true;
const ONLY_HOSTS: bool = true;
@ -315,7 +321,9 @@ impl<'a> Step<'a> for Cargo<'a> {
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 {
return;
}
@ -332,8 +340,8 @@ impl<'a> Step<'a> for Cargo<'a> {
// Cargo depends on procedural macros, which requires a full host
// compiler to be available, so we need to depend on that.
builder.ensure(Rustc {
compiler: builder.compiler(builder.top_stage, &builder.build.build),
target: &builder.build.build,
compiler: builder.compiler(builder.top_stage, builder.build.build),
target: builder.build.build,
});
builder.ensure(ToolBuild {
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"));
//
#[derive(Serialize)]
pub struct Rls<'a> {
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Rls {
pub stage: u32,
pub target: &'a str,
pub target: Interned<String>,
}
impl<'a> Step<'a> for Rls<'a> {
type Id = Rls<'static>;
impl Step for Rls {
type Output = PathBuf;
const DEFAULT: bool = true;
const ONLY_HOSTS: bool = true;
@ -373,7 +380,9 @@ impl<'a> Step<'a> for Rls<'a> {
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 {
return;
}
@ -390,8 +399,8 @@ impl<'a> Step<'a> for Rls<'a> {
// RLS depends on procedural macros, which requires a full host
// compiler to be available, so we need to depend on that.
builder.ensure(Rustc {
compiler: builder.compiler(builder.top_stage, &builder.build.build),
target: &builder.build.build,
compiler: builder.compiler(builder.top_stage, builder.build.build),
target: builder.build.build,
});
builder.ensure(ToolBuild {
stage: self.stage,
@ -407,7 +416,7 @@ impl<'a> Builder<'a> {
/// `host`.
pub fn tool_cmd(&self, tool: Tool) -> Command {
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);
cmd
}
@ -417,10 +426,10 @@ impl<'a> Builder<'a> {
/// Notably this munges the dynamic library lookup path to point to the
/// right location to run `compiler`.
fn prepare_tool_cmd(&self, compiler: Compiler, cmd: &mut Command) {
let host = compiler.host;
let mut paths = vec![
self.sysroot_libdir(compiler, compiler.host),
self.cargo_out(compiler, Mode::Tool, host).join("deps"),
let host = &compiler.host;
let mut paths: Vec<PathBuf> = vec![
PathBuf::from(&self.sysroot_libdir(compiler, compiler.host)),
self.cargo_out(compiler, Mode::Tool, *host).join("deps"),
];
// 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") {
let curpaths = env::var_os("PATH").unwrap_or_default();
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" {
continue
}