]> git.lizzy.rs Git - rust.git/blobdiff - src/bootstrap/config.rs
Utilize interning to allow Copy/Clone steps
[rust.git] / src / bootstrap / config.rs
index abad216d89be48c78482ca82fb6d67ee016bf1c6..abb0408c4d24780e9ebf6f18090c2acc7708ccef 100644 (file)
 
 use std::collections::HashMap;
 use std::env;
-use std::fs::File;
+use std::fs::{self, File};
 use std::io::prelude::*;
 use std::path::PathBuf;
 use std::process;
 
 use num_cpus;
-use rustc_serialize::Decodable;
-use toml::{Parser, Decoder, Value};
+use toml;
 use util::{exe, push_exe_path};
+use cache::{INTERNER, Interned};
 
 /// Global configuration for the entire build and/or bootstrap.
 ///
@@ -46,10 +46,11 @@ pub struct Config {
     pub docs: bool,
     pub locked_deps: bool,
     pub vendor: bool,
-    pub target_config: HashMap<String, Target>,
+    pub target_config: HashMap<Interned<String>, Target>,
     pub full_bootstrap: bool,
     pub extended: bool,
     pub sanitizers: bool,
+    pub profiler: bool,
 
     // llvm codegen options
     pub llvm_assertions: bool,
@@ -59,6 +60,7 @@ pub struct Config {
     pub llvm_static_stdcpp: bool,
     pub llvm_link_shared: bool,
     pub llvm_targets: Option<String>,
+    pub llvm_experimental_targets: Option<String>,
     pub llvm_link_jobs: Option<u32>,
     pub llvm_clean_rebuild: bool,
 
@@ -76,11 +78,9 @@ pub struct Config {
     pub rust_debuginfo_tests: bool,
     pub rust_dist_src: bool,
 
-    pub build: String,
-    pub host: Vec<String>,
-    pub target: Vec<String>,
-    pub rustc: Option<PathBuf>,
-    pub cargo: Option<PathBuf>,
+    pub build: Interned<String>,
+    pub host: Vec<Interned<String>>,
+    pub target: Vec<Interned<String>>,
     pub local_rebuild: bool,
 
     // dist misc
@@ -112,11 +112,18 @@ pub struct Config {
     pub python: Option<PathBuf>,
     pub configure_args: Vec<String>,
     pub openssl_static: bool,
+
+
+    // These are either the stage0 downloaded binaries or the locally installed ones.
+    pub initial_cargo: PathBuf,
+    pub initial_rustc: PathBuf,
+
 }
 
 /// Per-target configuration stored in the global configuration structure.
 #[derive(Default)]
 pub struct Target {
+    /// Some(path to llvm-config) if using an external LLVM.
     pub llvm_config: Option<PathBuf>,
     pub jemalloc: Option<PathBuf>,
     pub cc: Option<PathBuf>,
@@ -131,7 +138,9 @@ pub struct Target {
 /// This structure uses `Decodable` to automatically decode a TOML configuration
 /// file into this format, and then this is traversed and written into the above
 /// `Config` structure.
-#[derive(RustcDecodable, Default)]
+#[derive(Deserialize, Default)]
+#[serde(deny_unknown_fields)]
+#[serde(rename_all = "kebab-case")]
 struct TomlConfig {
     build: Option<Build>,
     install: Option<Install>,
@@ -142,10 +151,14 @@ struct TomlConfig {
 }
 
 /// TOML representation of various global build decisions.
-#[derive(RustcDecodable, Default, Clone)]
+#[derive(Deserialize, Default, Clone)]
+#[serde(deny_unknown_fields)]
+#[serde(rename_all = "kebab-case")]
 struct Build {
     build: Option<String>,
+    #[serde(default)]
     host: Vec<String>,
+    #[serde(default)]
     target: Vec<String>,
     cargo: Option<String>,
     rustc: Option<String>,
@@ -162,11 +175,14 @@ struct Build {
     extended: Option<bool>,
     verbose: Option<usize>,
     sanitizers: Option<bool>,
+    profiler: Option<bool>,
     openssl_static: Option<bool>,
 }
 
 /// TOML representation of various global install decisions.
-#[derive(RustcDecodable, Default, Clone)]
+#[derive(Deserialize, Default, Clone)]
+#[serde(deny_unknown_fields)]
+#[serde(rename_all = "kebab-case")]
 struct Install {
     prefix: Option<String>,
     sysconfdir: Option<String>,
@@ -177,7 +193,9 @@ struct Install {
 }
 
 /// TOML representation of how the LLVM build is configured.
-#[derive(RustcDecodable, Default)]
+#[derive(Deserialize, Default)]
+#[serde(deny_unknown_fields)]
+#[serde(rename_all = "kebab-case")]
 struct Llvm {
     ccache: Option<StringOrBool>,
     ninja: Option<bool>,
@@ -187,11 +205,14 @@ struct Llvm {
     version_check: Option<bool>,
     static_libstdcpp: Option<bool>,
     targets: Option<String>,
+    experimental_targets: Option<String>,
     link_jobs: Option<u32>,
     clean_rebuild: Option<bool>,
 }
 
-#[derive(RustcDecodable, Default, Clone)]
+#[derive(Deserialize, Default, Clone)]
+#[serde(deny_unknown_fields)]
+#[serde(rename_all = "kebab-case")]
 struct Dist {
     sign_folder: Option<String>,
     gpg_password_file: Option<String>,
@@ -199,7 +220,8 @@ struct Dist {
     src_tarball: Option<bool>,
 }
 
-#[derive(RustcDecodable)]
+#[derive(Deserialize)]
+#[serde(untagged)]
 enum StringOrBool {
     String(String),
     Bool(bool),
@@ -212,7 +234,9 @@ fn default() -> StringOrBool {
 }
 
 /// TOML representation of how the Rust build is configured.
-#[derive(RustcDecodable, Default)]
+#[derive(Deserialize, Default)]
+#[serde(deny_unknown_fields)]
+#[serde(rename_all = "kebab-case")]
 struct Rust {
     optimize: Option<bool>,
     codegen_units: Option<u32>,
@@ -234,7 +258,9 @@ struct Rust {
 }
 
 /// TOML representation of how each build target is configured.
-#[derive(RustcDecodable, Default)]
+#[derive(Deserialize, Default)]
+#[serde(deny_unknown_fields)]
+#[serde(rename_all = "kebab-case")]
 struct TomlTarget {
     llvm_config: Option<String>,
     jemalloc: Option<String>,
@@ -257,54 +283,41 @@ pub fn parse(build: &str, file: Option<PathBuf>) -> 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;
 
         let toml = file.map(|file| {
             let mut f = t!(File::open(&file));
-            let mut toml = String::new();
-            t!(f.read_to_string(&mut toml));
-            let mut p = Parser::new(&toml);
-            let table = match p.parse() {
-                Some(table) => table,
-                None => {
-                    println!("failed to parse TOML configuration '{}':", file.to_str().unwrap());
-                    for err in p.errors.iter() {
-                        let (loline, locol) = p.to_linecol(err.lo);
-                        let (hiline, hicol) = p.to_linecol(err.hi);
-                        println!("{}:{}-{}:{}: {}", loline, locol, hiline,
-                                 hicol, err.desc);
-                    }
-                    process::exit(2);
-                }
-            };
-            let mut d = Decoder::new(Value::Table(table));
-            match Decodable::decode(&mut d) {
-                Ok(cfg) => cfg,
-                Err(e) => {
-                    println!("failed to decode TOML: {}", e);
+            let mut contents = String::new();
+            t!(f.read_to_string(&mut contents));
+            match toml::from_str(&contents) {
+                Ok(table) => table,
+                Err(err) => {
+                    println!("failed to parse TOML configuration '{}': {}",
+                        file.display(), err);
                     process::exit(2);
                 }
             }
         }).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.rustc = build.rustc.map(PathBuf::from);
-        config.cargo = build.cargo.map(PathBuf::from);
         config.nodejs = build.nodejs.map(PathBuf::from);
         config.gdb = build.gdb.map(PathBuf::from);
         config.python = build.python.map(PathBuf::from);
@@ -318,6 +331,7 @@ pub fn parse(build: &str, file: Option<PathBuf>) -> Config {
         set(&mut config.extended, build.extended);
         set(&mut config.verbose, build.verbose);
         set(&mut config.sanitizers, build.sanitizers);
+        set(&mut config.profiler, build.profiler);
         set(&mut config.openssl_static, build.openssl_static);
 
         if let Some(ref install) = toml.install {
@@ -347,6 +361,7 @@ pub fn parse(build: &str, file: Option<PathBuf>) -> Config {
             set(&mut config.llvm_static_stdcpp, llvm.static_libstdcpp);
             set(&mut config.llvm_clean_rebuild, llvm.clean_rebuild);
             config.llvm_targets = llvm.targets.clone();
+            config.llvm_experimental_targets = llvm.experimental_targets.clone();
             config.llvm_link_jobs = llvm.link_jobs;
         }
 
@@ -393,7 +408,7 @@ pub fn parse(build: &str, file: Option<PathBuf>) -> 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);
             }
         }
 
@@ -404,7 +419,25 @@ pub fn parse(build: &str, file: Option<PathBuf>) -> Config {
             set(&mut config.rust_dist_src, t.src_tarball);
         }
 
-        return config
+        let cwd = t!(env::current_dir());
+        let out = cwd.join("build");
+
+        let stage0_root = out.join(&config.build).join("stage0/bin");
+        config.initial_rustc = match build.rustc {
+            Some(s) => PathBuf::from(s),
+            None => stage0_root.join(exe("rustc", &config.build)),
+        };
+        config.initial_cargo = match build.cargo {
+            Some(s) => PathBuf::from(s),
+            None => stage0_root.join(exe("cargo", &config.build)),
+        };
+
+        // compat with `./configure` while we're still using that
+        if fs::metadata("config.mk").is_ok() {
+            config.update_with_config_mk();
+        }
+
+        config
     }
 
     /// "Temporary" routine to parse `config.mk` into this configuration.
@@ -412,7 +445,7 @@ pub fn parse(build: &str, file: Option<PathBuf>) -> Config {
     /// While we still have `./configure` this implements the ability to decode
     /// that configuration into this. This isn't exactly a full-blown makefile
     /// parser, but hey it gets the job done!
-    pub fn update_with_config_mk(&mut self) {
+    fn update_with_config_mk(&mut self) {
         let mut config = String::new();
         File::open("config.mk").unwrap().read_to_string(&mut config).unwrap();
         for line in config.lines() {
@@ -471,50 +504,49 @@ macro_rules! check {
                 ("FULL_BOOTSTRAP", self.full_bootstrap),
                 ("EXTENDED", self.extended),
                 ("SANITIZERS", self.sanitizers),
+                ("PROFILER", self.profiler),
                 ("DIST_SRC", self.rust_dist_src),
                 ("CARGO_OPENSSL_STATIC", self.openssl_static),
             }
 
             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());
                 }
                 "CFG_MUSL_ROOT" if value.len() > 0 => {
                     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 => {
@@ -562,39 +594,34 @@ macro_rules! check {
                     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 => {
                     let path = parse_configure_path(value);
-                    self.rustc = Some(push_exe_path(path.clone(), &["bin", "rustc"]));
-                    self.cargo = Some(push_exe_path(path, &["bin", "cargo"]));
+                    self.initial_rustc = push_exe_path(path.clone(), &["bin", "rustc"]);
+                    self.initial_cargo = push_exe_path(path, &["bin", "cargo"]);
                 }
                 "CFG_PYTHON" if value.len() > 0 => {
                     let path = parse_configure_path(value);
@@ -612,9 +639,8 @@ macro_rules! check {
                                                .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));
                 }
                 _ => {}