From 528646e1275a90900179b473b204ca3ce19984b5 Mon Sep 17 00:00:00 2001 From: Mark Simulacrum Date: Thu, 13 Jul 2017 18:48:44 -0600 Subject: [PATCH] Utilize interning to allow Copy/Clone steps --- src/Cargo.lock | 9 +- src/bootstrap/Cargo.toml | 1 + src/bootstrap/builder.rs | 99 ++++++------ src/bootstrap/cache.rs | 324 +++++++++++++++++++++++++++++++------- src/bootstrap/cc.rs | 15 +- src/bootstrap/check.rs | 234 +++++++++++++++------------ src/bootstrap/compile.rs | 219 +++++++++++++------------- src/bootstrap/config.rs | 89 +++++------ src/bootstrap/dist.rs | 188 ++++++++++++---------- src/bootstrap/doc.rs | 179 +++++++++++---------- src/bootstrap/flags.rs | 18 ++- src/bootstrap/install.rs | 40 +++-- src/bootstrap/lib.rs | 134 ++++++++-------- src/bootstrap/metadata.rs | 9 +- src/bootstrap/native.rs | 47 +++--- src/bootstrap/sanity.rs | 10 +- src/bootstrap/tool.rs | 107 +++++++------ 17 files changed, 1014 insertions(+), 708 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index 35d77eda951..3f216b0c2f6 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -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)", ] diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml index 00004d71aac..daa2a3d0a0f 100644 --- a/src/bootstrap/Cargo.toml +++ b/src/bootstrap/Cargo.toml @@ -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" diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 72736c76111..f217cd1dd37 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -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>, + stack: RefCell)>>, } 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, + _target: Interned, ) { 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) -> 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 { 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 + ) -> Interned { + #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] + struct Libdir { + compiler: Compiler, + target: Interned, } - 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; + fn run(self, builder: &Builder) -> Interned { 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, 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>(&'a self, path: Option<&Path>) { + fn maybe_run(&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>(&'a self, step: S) -> S::Output { - let key = Cache::to_key(&step); + pub fn ensure(&'a self, step: S) -> S::Output { + let type_id = TypeId::of::(); { 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::(&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::(&key).unwrap() + self.build.verbose(&format!("{}< {:?}", " ".repeat(self.stack.borrow().len()), step)); + self.cache.put(step, out.clone()); + out } } diff --git a/src/bootstrap/cache.rs b/src/bootstrap/cache.rs index 475e3abfd40..e2576673338 100644 --- a/src/bootstrap/cache.rs +++ b/src/bootstrap/cache.rs @@ -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(usize, PhantomData<*const T>); + +impl<'de> Deserialize<'de> for Interned { + fn deserialize(deserializer: D) -> Result + 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(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 { + fn default() -> Self { + INTERNER.intern_string(String::default()) + } +} + +impl Default for Interned { + fn default() -> Self { + INTERNER.intern_path(PathBuf::default()) + } +} + +impl Copy for Interned {} +impl Clone for Interned { + fn clone(&self) -> Interned { + *self + } +} + +impl PartialEq for Interned { + fn eq(&self, other: &Self) -> bool { + self.0 == other.0 + } +} +impl Eq for Interned {} + +impl PartialEq for Interned { + fn eq(&self, other: &str) -> bool { + *self == other + } +} +impl<'a> PartialEq<&'a str> for Interned { + fn eq(&self, other: &&str) -> bool { + **self == **other + } +} +impl<'a, T> PartialEq<&'a Interned> for Interned { + fn eq(&self, other: &&Self) -> bool { + self.0 == other.0 + } +} +impl<'a, T> PartialEq> for &'a Interned { + fn eq(&self, other: &Interned) -> bool { + self.0 == other.0 + } +} + +unsafe impl Send for Interned {} +unsafe impl Sync for Interned {} + +impl fmt::Display for Interned { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let s: &str = &*self; + f.write_str(s) + } +} + +impl fmt::Debug for Interned { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let s: &str = &*self; + f.write_fmt(format_args!("{:?}", s)) + } +} +impl fmt::Debug for Interned { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let s: &Path = &*self; + f.write_fmt(format_args!("{:?}", s)) + } +} + +impl Hash for Interned { + fn hash(&self, state: &mut H) { + let l = INTERNER.strs.lock().unwrap(); + l.get(*self).hash(state) + } +} + +impl Hash for Interned { + fn hash(&self, state: &mut H) { + let l = INTERNER.paths.lock().unwrap(); + l.get(*self).hash(state) + } +} + +impl Deref for Interned { + 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 { + 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 for Interned { + fn as_ref(&self) -> &'static Path { + let l = INTERNER.paths.lock().unwrap(); + unsafe { mem::transmute::<&Path, &'static Path>(l.get(*self)) } + } +} + +impl AsRef for Interned { + 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 for Interned { + 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 for Interned { + 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 { + items: Vec, + set: HashMap>, +} + +impl TyIntern { + fn new() -> TyIntern { + TyIntern { + items: Vec::new(), + set: HashMap::new(), + } + } + + fn intern_borrow(&mut self, item: &B) -> Interned + where + B: Eq + Hash + ToOwned + ?Sized, + T: Borrow, + { + 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 { + 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 { + &self.items[i.0] + } +} + +pub struct Interner { + strs: Mutex>, + paths: Mutex>, +} + +impl Interner { + fn new() -> Interner { + Interner { + strs: Mutex::new(TyIntern::new()), + paths: Mutex::new(TyIntern::new()), + } + } + + pub fn intern_str(&self, s: &str) -> Interned { + self.strs.lock().unwrap().intern_borrow(s) + } + pub fn intern_string(&self, s: String) -> Interned { + self.strs.lock().unwrap().intern(s) + } + + pub fn intern_path(&self, s: PathBuf) -> Interned { + 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>>); - -fn to_json(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, // actually a HashMap> + >> +); 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::(), 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(&self, key: Key, value: &V) - where - V: Serialize, - { + pub fn put(&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::(); + let stepcache = cache.entry(type_id) + .or_insert_with(|| Box::new(HashMap::::new())) + .downcast_mut::>() + .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 - 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. - let v = unsafe { - mem::transmute::<&str, &'a str>(v) - }; - from_json(v) - }) + pub fn get(&self, step: &S) -> Option { + let mut cache = self.0.borrow_mut(); + let type_id = TypeId::of::(); + let stepcache = cache.entry(type_id) + .or_insert_with(|| Box::new(HashMap::::new())) + .downcast_mut::>() + .expect("invalid type mapped"); + stepcache.get(step).cloned() } } diff --git a/src/bootstrap/cc.rs b/src/bootstrap/cc.rs index 7c7161916ee..739904e4f7c 100644 --- a/src/bootstrap/cc.rs +++ b/src/bootstrap/cc.rs @@ -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, 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. diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index 8adfed44f01..d983e54ac08 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -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, } -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, + _target: Interned, + ) { 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, } -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, + _target: Interned, + ) { 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, } -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, + target: Interned, + ) { 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, } -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, + _target: Interned, + ) { builder.ensure(Tidy { - host: &builder.build.build, + host: builder.build.build, }); } } -fn testdir(build: &Build, host: &str) -> PathBuf { +fn testdir(build: &Build, host: Interned) -> 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, + 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, + target: Interned, + ) { 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, + _target: Interned, + ) { 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, + _target: Interned, + ) { 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, test_kind: TestKind, - krate: Option<&'a str>, + krate: Option>, } -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, + target: Interned, + ) { let compiler = builder.compiler(builder.top_stage, host); - let run = |name: Option<&str>| { + let run = |name: Option>| { 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, mode: Mode, test_kind: TestKind, - krate: Option<&'a str>, + krate: Option>, } -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, + target: Interned, + ) { let compiler = builder.compiler(builder.top_stage, host); - let run = |mode: Mode, name: Option<&str>| { + let run = |mode: Mode, name: Option>| { 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, 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, 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 { +fn find_tests(dir: &Path, target: Interned) -> Vec { 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 { /// 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, } -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, + _target: Interned, + ) { builder.ensure(Bootstrap); } } diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index ec08bb9db2b..558ced12cfe 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -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, + 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, + target: Interned, + ) { 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, } -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, 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, } -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, + target: Interned, + ) { 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, } -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, + target: Interned, + ) { 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, } -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, } -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, + target: Interned, + ) { 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, } -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) -> 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) -> 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) -> 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; /// 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 { 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() { diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 810a9924765..abb0408c4d2 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -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, + pub target_config: HashMap, 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, - pub target: Vec, + pub build: Interned, + pub host: Vec>, + pub target: Vec>, 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)); } _ => {} diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index f19536e2f49..e9a2fc7fc1a 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -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, } -impl<'a> Step<'a> for Docs<'a> { - type Id = Docs<'static>; +impl Step for Docs { type Output = Option; 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, target: Interned, + ) { builder.ensure(Docs { stage: builder.top_stage, target: target, @@ -165,7 +167,9 @@ fn find_files(files: &[&str], path: &[PathBuf]) -> Vec { 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, 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, } -impl<'a> Step<'a> for Mingw<'a> { - type Id = Mingw<'static>; +impl Step for Mingw { type Output = Option; 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, target: Interned + ) { 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, } -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, target: Interned + ) { 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, 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, + pub target: Interned, } -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, target: Interned + ) { 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, } -impl<'a> Step<'a> for Std<'a> { - type Id = Std<'static>; +impl Step for Std { type Output = Option; 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, target: Interned + ) { 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, } -impl<'a> Step<'a> for Analysis<'a> { - type Id = Analysis<'static>; +impl Step for Analysis { type Output = Option; 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, + target: Interned + ) { 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, _target: Interned + ) { 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, _target: Interned + ) { 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, } -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, target: Interned + ) { 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, } -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, target: Interned + ) { 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, } -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, target: Interned + ) { 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) { 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, _target: Interned + ) { builder.ensure(HashSign); } diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 56715d284a6..3c3f4bf2be7 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -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, } - 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, + target: Interned + ) { 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, + name: Interned, } -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, } -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, target: Interned + ) { 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, + name: Interned, + src: Interned, } -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, + 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, target: Interned + ) { 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, 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, } -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, target: Interned + ) { 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, } -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, target: Interned + ) { 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, } -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, target: Interned + ) { 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, } -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, target: Interned + ) { 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, } -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, target: Interned + ) { 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, } -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, target: Interned, + ) { 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, }); diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index 30bc8cdef4a..b1ea441795e 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -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, pub stage: Option, pub keep_stage: Option, - pub build: String, - pub host: Vec, - pub target: Vec, + pub build: Interned, + pub host: Vec>, + pub target: Vec>, pub config: Option, pub src: PathBuf, pub jobs: Option, @@ -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::>(), + target: split(matches.opt_strs("target")) + .into_iter().map(|x| INTERNER.intern_string(x)).collect::>(), config: cfg_file, src: src, jobs: matches.opt_str("jobs").map(|j| j.parse().unwrap()), diff --git a/src/bootstrap/install.rs b/src/bootstrap/install.rs index a7d36bfa70c..6b6160f43ca 100644 --- a/src/bootstrap/install.rs +++ b/src/bootstrap/install.rs @@ -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) { 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) { 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) { 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) { 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) { 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> +) { 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, + pub host: Interned, } - 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, + target: Interned, + ) { if path.is_none() && !($default_cond) { return; } diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 68465604db6..472aea783f2 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -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, } /// Global configuration for the build system. @@ -226,9 +229,9 @@ pub struct Build { verbosity: usize, // Targets for which to build. - build: String, - hosts: Vec, - targets: Vec, + build: Interned, + hosts: Vec>, + targets: Vec>, // 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)>, + cc: HashMap, (gcc::Tool, Option)>, // host -> (cc, ar) - cxx: HashMap, - crates: HashMap, + cxx: HashMap, gcc::Tool>, + crates: HashMap, Crate>, is_sudo: bool, ci_env: CiEnv, delayed_failures: Cell, @@ -251,9 +254,9 @@ pub struct Build { #[derive(Debug)] struct Crate { - name: String, + name: Interned, version: String, - deps: Vec, + deps: Vec>, 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) -> 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) -> 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) -> 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) -> Interned { + 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) -> 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) -> 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) -> 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) -> 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) -> 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) -> 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) -> &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 { + fn cflags(&self, target: Interned) -> Vec { // 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::>(); @@ -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) -> 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) -> 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 { + fn rustc_flags(&self, target: Interned) -> Vec { // 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) -> 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) -> 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) -> 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) -> 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 { + fn openssl_dir(&self, target: Interned) -> Option { // 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 { + fn openssl_install_dir(&self, target: Interned) -> Option { 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, &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 } diff --git a/src/bootstrap/metadata.rs b/src/bootstrap/metadata.rs index ca0eed3ae86..2b641cd8484 100644 --- a/src/bootstrap/metadata.rs +++ b/src/bootstrap/metadata.rs @@ -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, version: String, source: Option, 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); } } } diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index d8dc9f76702..c0ec693a17e 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -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, } -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, } -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, + target: Interned, + ) { 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, } -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", diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs index a9c1b023dd4..7063b28f19d 100644 --- a/src/bootstrap/sanity.rs +++ b/src/bootstrap/sanity.rs @@ -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: {}", diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index 27785506eae..00616caf120 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -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, 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, + 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, } - 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, + target: Interned + ) { 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, } -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, + target: Interned + ) { 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, } -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, target: Interned + ) { 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, } -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, target: Interned + ) { 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 = 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::>(); - 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 }