]> git.lizzy.rs Git - rust.git/blobdiff - src/bootstrap/config.rs
Update to toml 0.4
[rust.git] / src / bootstrap / config.rs
index 64b2a665e257182aab416b7ce910841a3f8768e7..810a9924765d8b955f3bb2bc856047e842a433a2 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};
 
 /// Global configuration for the entire build and/or bootstrap.
@@ -60,6 +59,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,
 
@@ -80,8 +80,6 @@ pub struct Config {
     pub build: String,
     pub host: Vec<String>,
     pub target: Vec<String>,
-    pub rustc: Option<PathBuf>,
-    pub cargo: Option<PathBuf>,
     pub local_rebuild: bool,
 
     // dist misc
@@ -113,11 +111,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>,
@@ -132,7 +137,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>,
@@ -143,10 +150,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>,
@@ -168,7 +179,9 @@ struct Build {
 }
 
 /// 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>,
@@ -179,7 +192,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>,
@@ -189,11 +204,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>,
@@ -201,7 +219,8 @@ struct Dist {
     src_tarball: Option<bool>,
 }
 
-#[derive(RustcDecodable)]
+#[derive(Deserialize)]
+#[serde(untagged)]
 enum StringOrBool {
     String(String),
     Bool(bool),
@@ -214,7 +233,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>,
@@ -236,7 +257,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>,
@@ -266,27 +289,13 @@ pub fn parse(build: &str, file: Option<PathBuf>) -> Config {
 
         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);
                 }
             }
@@ -305,8 +314,6 @@ pub fn parse(build: &str, file: Option<PathBuf>) -> Config {
                 config.target.push(target.clone());
             }
         }
-        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);
@@ -350,6 +357,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;
         }
 
@@ -407,7 +415,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.
@@ -415,7 +441,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() {
@@ -488,6 +514,9 @@ macro_rules! check {
                 "CFG_TARGET" if value.len() > 0 => {
                     self.target.extend(value.split(" ").map(|s| s.to_string()));
                 }
+                "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));
                 }
@@ -597,8 +626,8 @@ macro_rules! check {
                 }
                 "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);