Move BuildConfig and dependencies into new module
authorDirkjan Ochtman <dirkjan@ochtman.nl>
Sat, 14 Apr 2018 09:55:26 +0000 (11:55 +0200)
committerDirkjan Ochtman <dirkjan@ochtman.nl>
Thu, 3 May 2018 19:54:48 +0000 (21:54 +0200)
src/cargo/core/compiler/build_config.rs [new file with mode: 0644]
src/cargo/core/compiler/mod.rs

diff --git a/src/cargo/core/compiler/build_config.rs b/src/cargo/core/compiler/build_config.rs
new file mode 100644 (file)
index 0000000..61e5ceb
--- /dev/null
@@ -0,0 +1,314 @@
+use std::collections::HashMap;
+use std::path::{Path, PathBuf};
+use util::{CargoResult, CargoResultExt, Config, Rustc};
+use super::BuildOutput;
+
+/// Configuration information for a rustc build.
+pub struct BuildConfig {
+    pub rustc: Rustc,
+    /// Build information for the host arch
+    pub host: TargetConfig,
+    /// The target arch triple, defaults to host arch
+    pub requested_target: Option<String>,
+    /// Build information for the target
+    pub target: TargetConfig,
+    /// How many rustc jobs to run in parallel
+    pub jobs: u32,
+    /// Whether we are building for release
+    pub release: bool,
+    /// In what mode we are compiling
+    pub mode: CompileMode,
+    /// Whether to print std output in json format (for machine reading)
+    pub message_format: MessageFormat,
+}
+
+impl BuildConfig {
+    /// Parse all config files to learn about build configuration. Currently
+    /// configured options are:
+    ///
+    /// * build.jobs
+    /// * build.target
+    /// * target.$target.ar
+    /// * target.$target.linker
+    /// * target.$target.libfoo.metadata
+    pub fn new(
+        config: &Config,
+        jobs: Option<u32>,
+        requested_target: &Option<String>,
+        rustc_info_cache: Option<PathBuf>,
+        mode: CompileMode,
+    ) -> CargoResult<BuildConfig> {
+        let requested_target = match requested_target {
+            &Some(ref target) if target.ends_with(".json") => {
+                let path = Path::new(target)
+                    .canonicalize()
+                    .chain_err(|| format_err!("Target path {:?} is not a valid file", target))?;
+                Some(path.into_os_string()
+                    .into_string()
+                    .map_err(|_| format_err!("Target path is not valid unicode"))?)
+            }
+            other => other.clone(),
+        };
+        if let Some(ref s) = requested_target {
+            if s.trim().is_empty() {
+                bail!("target was empty")
+            }
+        }
+        let cfg_target = config.get_string("build.target")?.map(|s| s.val);
+        let target = requested_target.clone().or(cfg_target);
+
+        if jobs == Some(0) {
+            bail!("jobs must be at least 1")
+        }
+        if jobs.is_some() && config.jobserver_from_env().is_some() {
+            config.shell().warn(
+                "a `-j` argument was passed to Cargo but Cargo is \
+                 also configured with an external jobserver in \
+                 its environment, ignoring the `-j` parameter",
+            )?;
+        }
+        let cfg_jobs = match config.get_i64("build.jobs")? {
+            Some(v) => {
+                if v.val <= 0 {
+                    bail!(
+                        "build.jobs must be positive, but found {} in {}",
+                        v.val,
+                        v.definition
+                    )
+                } else if v.val >= i64::from(u32::max_value()) {
+                    bail!(
+                        "build.jobs is too large: found {} in {}",
+                        v.val,
+                        v.definition
+                    )
+                } else {
+                    Some(v.val as u32)
+                }
+            }
+            None => None,
+        };
+        let jobs = jobs.or(cfg_jobs).unwrap_or(::num_cpus::get() as u32);
+        let rustc = config.rustc(rustc_info_cache)?;
+        let host_config = TargetConfig::new(config, &rustc.host)?;
+        let target_config = match target.as_ref() {
+            Some(triple) => TargetConfig::new(config, triple)?,
+            None => host_config.clone(),
+        };
+        Ok(BuildConfig {
+            rustc,
+            requested_target: target,
+            jobs,
+            host: host_config,
+            target: target_config,
+            release: false,
+            mode,
+            message_format: MessageFormat::Human,
+        })
+    }
+
+    /// The host arch triple
+    ///
+    /// e.g. x86_64-unknown-linux-gnu, would be
+    ///  - machine: x86_64
+    ///  - hardware-platform: unknown
+    ///  - operating system: linux-gnu
+    pub fn host_triple(&self) -> &str {
+        &self.rustc.host
+    }
+
+    pub fn target_triple(&self) -> &str {
+        self.requested_target
+            .as_ref()
+            .map(|s| s.as_str())
+            .unwrap_or(self.host_triple())
+    }
+
+    pub fn json_messages(&self) -> bool {
+        self.message_format == MessageFormat::Json
+    }
+
+    pub fn test(&self) -> bool {
+        self.mode == CompileMode::Test || self.mode == CompileMode::Bench
+    }
+}
+
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+pub enum MessageFormat {
+    Human,
+    Json,
+}
+
+/// The general "mode" of what to do.
+/// This is used for two purposes.  The commands themselves pass this in to
+/// `compile_ws` to tell it the general execution strategy.  This influences
+/// the default targets selected.  The other use is in the `Unit` struct
+/// to indicate what is being done with a specific target.
+#[derive(Clone, Copy, PartialEq, Debug, Eq, Hash)]
+pub enum CompileMode {
+    /// A target being built for a test.
+    Test,
+    /// Building a target with `rustc` (lib or bin).
+    Build,
+    /// Building a target with `rustc` to emit `rmeta` metadata only. If
+    /// `test` is true, then it is also compiled with `--test` to check it like
+    /// a test.
+    Check { test: bool },
+    /// Used to indicate benchmarks should be built.  This is not used in
+    /// `Target` because it is essentially the same as `Test` (indicating
+    /// `--test` should be passed to rustc) and by using `Test` instead it
+    /// allows some de-duping of Units to occur.
+    Bench,
+    /// A target that will be documented with `rustdoc`.
+    /// If `deps` is true, then it will also document all dependencies.
+    Doc { deps: bool },
+    /// A target that will be tested with `rustdoc`.
+    Doctest,
+    /// A marker for Units that represent the execution of a `build.rs`
+    /// script.
+    RunCustomBuild,
+}
+
+impl CompileMode {
+    /// Returns true if the unit is being checked.
+    pub fn is_check(&self) -> bool {
+        match *self {
+            CompileMode::Check { .. } => true,
+            _ => false,
+        }
+    }
+
+    /// Returns true if this is a doc or doctest. Be careful using this.
+    /// Although both run rustdoc, the dependencies for those two modes are
+    /// very different.
+    pub fn is_doc(&self) -> bool {
+        match *self {
+            CompileMode::Doc { .. } | CompileMode::Doctest => true,
+            _ => false,
+        }
+    }
+
+    /// Returns true if this is any type of test (test, benchmark, doctest, or
+    /// check-test).
+    pub fn is_any_test(&self) -> bool {
+        match *self {
+            CompileMode::Test
+            | CompileMode::Bench
+            | CompileMode::Check { test: true }
+            | CompileMode::Doctest => true,
+            _ => false,
+        }
+    }
+
+    /// Returns true if this is the *execution* of a `build.rs` script.
+    pub fn is_run_custom_build(&self) -> bool {
+        *self == CompileMode::RunCustomBuild
+    }
+
+    /// List of all modes (currently used by `cargo clean -p` for computing
+    /// all possible outputs).
+    pub fn all_modes() -> &'static [CompileMode] {
+        static ALL: [CompileMode; 9] = [
+            CompileMode::Test,
+            CompileMode::Build,
+            CompileMode::Check { test: true },
+            CompileMode::Check { test: false },
+            CompileMode::Bench,
+            CompileMode::Doc { deps: true },
+            CompileMode::Doc { deps: false },
+            CompileMode::Doctest,
+            CompileMode::RunCustomBuild,
+        ];
+        &ALL
+    }
+}
+
+/// Information required to build for a target
+#[derive(Clone, Default)]
+pub struct TargetConfig {
+    /// The path of archiver (lib builder) for this target.
+    pub ar: Option<PathBuf>,
+    /// The path of the linker for this target.
+    pub linker: Option<PathBuf>,
+    /// Special build options for any necessary input files (filename -> options)
+    pub overrides: HashMap<String, BuildOutput>,
+}
+
+impl TargetConfig {
+    pub fn new(config: &Config, triple: &str) -> CargoResult<TargetConfig> {
+        let key = format!("target.{}", triple);
+        let mut ret = TargetConfig {
+            ar: config.get_path(&format!("{}.ar", key))?.map(|v| v.val),
+            linker: config.get_path(&format!("{}.linker", key))?.map(|v| v.val),
+            overrides: HashMap::new(),
+        };
+        let table = match config.get_table(&key)? {
+            Some(table) => table.val,
+            None => return Ok(ret),
+        };
+        for (lib_name, value) in table {
+            match lib_name.as_str() {
+                "ar" | "linker" | "runner" | "rustflags" => continue,
+                _ => {}
+            }
+
+            let mut output = BuildOutput {
+                library_paths: Vec::new(),
+                library_links: Vec::new(),
+                cfgs: Vec::new(),
+                env: Vec::new(),
+                metadata: Vec::new(),
+                rerun_if_changed: Vec::new(),
+                rerun_if_env_changed: Vec::new(),
+                warnings: Vec::new(),
+            };
+            // We require deterministic order of evaluation, so we must sort the pairs by key first.
+            let mut pairs = Vec::new();
+            for (k, value) in value.table(&lib_name)?.0 {
+                pairs.push((k, value));
+            }
+            pairs.sort_by_key(|p| p.0);
+            for (k, value) in pairs {
+                let key = format!("{}.{}", key, k);
+                match &k[..] {
+                    "rustc-flags" => {
+                        let (flags, definition) = value.string(k)?;
+                        let whence = format!("in `{}` (in {})", key, definition.display());
+                        let (paths, links) = BuildOutput::parse_rustc_flags(flags, &whence)?;
+                        output.library_paths.extend(paths);
+                        output.library_links.extend(links);
+                    }
+                    "rustc-link-lib" => {
+                        let list = value.list(k)?;
+                        output
+                            .library_links
+                            .extend(list.iter().map(|v| v.0.clone()));
+                    }
+                    "rustc-link-search" => {
+                        let list = value.list(k)?;
+                        output
+                            .library_paths
+                            .extend(list.iter().map(|v| PathBuf::from(&v.0)));
+                    }
+                    "rustc-cfg" => {
+                        let list = value.list(k)?;
+                        output.cfgs.extend(list.iter().map(|v| v.0.clone()));
+                    }
+                    "rustc-env" => for (name, val) in value.table(k)?.0 {
+                        let val = val.string(name)?.0;
+                        output.env.push((name.clone(), val.to_string()));
+                    },
+                    "warning" | "rerun-if-changed" | "rerun-if-env-changed" => {
+                        bail!("`{}` is not supported in build script overrides", k);
+                    }
+                    _ => {
+                        let val = value.string(k)?.0;
+                        output.metadata.push((k.clone(), val.to_string()));
+                    }
+                }
+            }
+            ret.overrides.insert(lib_name, output);
+        }
+
+        Ok(ret)
+    }
+}
index 498e594cd800daa9e0322d96a8fe9fff4c844aaa..f81965b05e719158a93beec22ef6bbc950194d2d 100644 (file)
@@ -1,4 +1,3 @@
-use std::collections::HashMap;
 use std::env;
 use std::ffi::{OsStr, OsString};
 use std::fs;
@@ -14,7 +13,7 @@ use core::shell::ColorChoice;
 use core::{Feature, PackageId, Target};
 use util::errors::{CargoResult, CargoResultExt, Internal};
 use util::paths;
-use util::{self, machine_message, Config, Freshness, ProcessBuilder, Rustc};
+use util::{self, machine_message, Freshness, ProcessBuilder};
 use util::{internal, join_paths, profile};
 
 use self::job::{Job, Work};
@@ -23,11 +22,13 @@ use self::job_queue::JobQueue;
 use self::output_depinfo::output_depinfo;
 
 pub use self::build_context::{BuildContext, FileFlavor, TargetInfo};
+pub use self::build_config::{BuildConfig, CompileMode, MessageFormat, TargetConfig};
 pub use self::compilation::Compilation;
 pub use self::context::{Context, Unit};
 pub use self::custom_build::{BuildMap, BuildOutput, BuildScripts};
 pub use self::layout::is_bad_artifact_name;
 
+mod build_config;
 mod build_context;
 mod compilation;
 mod context;
@@ -47,316 +48,6 @@ pub enum Kind {
     Target,
 }
 
-/// Configuration information for a rustc build.
-pub struct BuildConfig {
-    pub rustc: Rustc,
-    /// Build information for the host arch
-    pub host: TargetConfig,
-    /// The target arch triple, defaults to host arch
-    pub requested_target: Option<String>,
-    /// Build information for the target
-    pub target: TargetConfig,
-    /// How many rustc jobs to run in parallel
-    pub jobs: u32,
-    /// Whether we are building for release
-    pub release: bool,
-    /// In what mode we are compiling
-    pub mode: CompileMode,
-    /// Whether to print std output in json format (for machine reading)
-    pub message_format: MessageFormat,
-}
-
-impl BuildConfig {
-    /// Parse all config files to learn about build configuration. Currently
-    /// configured options are:
-    ///
-    /// * build.jobs
-    /// * build.target
-    /// * target.$target.ar
-    /// * target.$target.linker
-    /// * target.$target.libfoo.metadata
-    pub fn new(
-        config: &Config,
-        jobs: Option<u32>,
-        requested_target: &Option<String>,
-        rustc_info_cache: Option<PathBuf>,
-        mode: CompileMode,
-    ) -> CargoResult<BuildConfig> {
-        let requested_target = match requested_target {
-            &Some(ref target) if target.ends_with(".json") => {
-                let path = Path::new(target)
-                    .canonicalize()
-                    .chain_err(|| format_err!("Target path {:?} is not a valid file", target))?;
-                Some(path.into_os_string()
-                    .into_string()
-                    .map_err(|_| format_err!("Target path is not valid unicode"))?)
-            }
-            other => other.clone(),
-        };
-        if let Some(ref s) = requested_target {
-            if s.trim().is_empty() {
-                bail!("target was empty")
-            }
-        }
-        let cfg_target = config.get_string("build.target")?.map(|s| s.val);
-        let target = requested_target.clone().or(cfg_target);
-
-        if jobs == Some(0) {
-            bail!("jobs must be at least 1")
-        }
-        if jobs.is_some() && config.jobserver_from_env().is_some() {
-            config.shell().warn(
-                "a `-j` argument was passed to Cargo but Cargo is \
-                 also configured with an external jobserver in \
-                 its environment, ignoring the `-j` parameter",
-            )?;
-        }
-        let cfg_jobs = match config.get_i64("build.jobs")? {
-            Some(v) => {
-                if v.val <= 0 {
-                    bail!(
-                        "build.jobs must be positive, but found {} in {}",
-                        v.val,
-                        v.definition
-                    )
-                } else if v.val >= i64::from(u32::max_value()) {
-                    bail!(
-                        "build.jobs is too large: found {} in {}",
-                        v.val,
-                        v.definition
-                    )
-                } else {
-                    Some(v.val as u32)
-                }
-            }
-            None => None,
-        };
-        let jobs = jobs.or(cfg_jobs).unwrap_or(::num_cpus::get() as u32);
-        let rustc = config.rustc(rustc_info_cache)?;
-        let host_config = TargetConfig::new(config, &rustc.host)?;
-        let target_config = match target.as_ref() {
-            Some(triple) => TargetConfig::new(config, triple)?,
-            None => host_config.clone(),
-        };
-        Ok(BuildConfig {
-            rustc,
-            requested_target: target,
-            jobs,
-            host: host_config,
-            target: target_config,
-            release: false,
-            mode,
-            message_format: MessageFormat::Human,
-        })
-    }
-
-    /// The host arch triple
-    ///
-    /// e.g. x86_64-unknown-linux-gnu, would be
-    ///  - machine: x86_64
-    ///  - hardware-platform: unknown
-    ///  - operating system: linux-gnu
-    pub fn host_triple(&self) -> &str {
-        &self.rustc.host
-    }
-
-    pub fn target_triple(&self) -> &str {
-        self.requested_target
-            .as_ref()
-            .map(|s| s.as_str())
-            .unwrap_or(self.host_triple())
-    }
-
-    pub fn json_messages(&self) -> bool {
-        self.message_format == MessageFormat::Json
-    }
-
-    pub fn test(&self) -> bool {
-        self.mode == CompileMode::Test || self.mode == CompileMode::Bench
-    }
-}
-
-#[derive(Clone, Copy, Debug, PartialEq, Eq)]
-pub enum MessageFormat {
-    Human,
-    Json,
-}
-
-/// The general "mode" of what to do.
-/// This is used for two purposes.  The commands themselves pass this in to
-/// `compile_ws` to tell it the general execution strategy.  This influences
-/// the default targets selected.  The other use is in the `Unit` struct
-/// to indicate what is being done with a specific target.
-#[derive(Clone, Copy, PartialEq, Debug, Eq, Hash)]
-pub enum CompileMode {
-    /// A target being built for a test.
-    Test,
-    /// Building a target with `rustc` (lib or bin).
-    Build,
-    /// Building a target with `rustc` to emit `rmeta` metadata only. If
-    /// `test` is true, then it is also compiled with `--test` to check it like
-    /// a test.
-    Check { test: bool },
-    /// Used to indicate benchmarks should be built.  This is not used in
-    /// `Target` because it is essentially the same as `Test` (indicating
-    /// `--test` should be passed to rustc) and by using `Test` instead it
-    /// allows some de-duping of Units to occur.
-    Bench,
-    /// A target that will be documented with `rustdoc`.
-    /// If `deps` is true, then it will also document all dependencies.
-    Doc { deps: bool },
-    /// A target that will be tested with `rustdoc`.
-    Doctest,
-    /// A marker for Units that represent the execution of a `build.rs`
-    /// script.
-    RunCustomBuild,
-}
-
-impl CompileMode {
-    /// Returns true if the unit is being checked.
-    pub fn is_check(&self) -> bool {
-        match *self {
-            CompileMode::Check { .. } => true,
-            _ => false,
-        }
-    }
-
-    /// Returns true if this is a doc or doctest. Be careful using this.
-    /// Although both run rustdoc, the dependencies for those two modes are
-    /// very different.
-    pub fn is_doc(&self) -> bool {
-        match *self {
-            CompileMode::Doc { .. } | CompileMode::Doctest => true,
-            _ => false,
-        }
-    }
-
-    /// Returns true if this is any type of test (test, benchmark, doctest, or
-    /// check-test).
-    pub fn is_any_test(&self) -> bool {
-        match *self {
-            CompileMode::Test
-            | CompileMode::Bench
-            | CompileMode::Check { test: true }
-            | CompileMode::Doctest => true,
-            _ => false,
-        }
-    }
-
-    /// Returns true if this is the *execution* of a `build.rs` script.
-    pub fn is_run_custom_build(&self) -> bool {
-        *self == CompileMode::RunCustomBuild
-    }
-
-    /// List of all modes (currently used by `cargo clean -p` for computing
-    /// all possible outputs).
-    pub fn all_modes() -> &'static [CompileMode] {
-        static ALL: [CompileMode; 9] = [
-            CompileMode::Test,
-            CompileMode::Build,
-            CompileMode::Check { test: true },
-            CompileMode::Check { test: false },
-            CompileMode::Bench,
-            CompileMode::Doc { deps: true },
-            CompileMode::Doc { deps: false },
-            CompileMode::Doctest,
-            CompileMode::RunCustomBuild,
-        ];
-        &ALL
-    }
-}
-
-/// Information required to build for a target
-#[derive(Clone, Default)]
-pub struct TargetConfig {
-    /// The path of archiver (lib builder) for this target.
-    pub ar: Option<PathBuf>,
-    /// The path of the linker for this target.
-    pub linker: Option<PathBuf>,
-    /// Special build options for any necessary input files (filename -> options)
-    pub overrides: HashMap<String, BuildOutput>,
-}
-
-impl TargetConfig {
-    pub fn new(config: &Config, triple: &str) -> CargoResult<TargetConfig> {
-        let key = format!("target.{}", triple);
-        let mut ret = TargetConfig {
-            ar: config.get_path(&format!("{}.ar", key))?.map(|v| v.val),
-            linker: config.get_path(&format!("{}.linker", key))?.map(|v| v.val),
-            overrides: HashMap::new(),
-        };
-        let table = match config.get_table(&key)? {
-            Some(table) => table.val,
-            None => return Ok(ret),
-        };
-        for (lib_name, value) in table {
-            match lib_name.as_str() {
-                "ar" | "linker" | "runner" | "rustflags" => continue,
-                _ => {}
-            }
-
-            let mut output = BuildOutput {
-                library_paths: Vec::new(),
-                library_links: Vec::new(),
-                cfgs: Vec::new(),
-                env: Vec::new(),
-                metadata: Vec::new(),
-                rerun_if_changed: Vec::new(),
-                rerun_if_env_changed: Vec::new(),
-                warnings: Vec::new(),
-            };
-            // We require deterministic order of evaluation, so we must sort the pairs by key first.
-            let mut pairs = Vec::new();
-            for (k, value) in value.table(&lib_name)?.0 {
-                pairs.push((k, value));
-            }
-            pairs.sort_by_key(|p| p.0);
-            for (k, value) in pairs {
-                let key = format!("{}.{}", key, k);
-                match &k[..] {
-                    "rustc-flags" => {
-                        let (flags, definition) = value.string(k)?;
-                        let whence = format!("in `{}` (in {})", key, definition.display());
-                        let (paths, links) = BuildOutput::parse_rustc_flags(flags, &whence)?;
-                        output.library_paths.extend(paths);
-                        output.library_links.extend(links);
-                    }
-                    "rustc-link-lib" => {
-                        let list = value.list(k)?;
-                        output
-                            .library_links
-                            .extend(list.iter().map(|v| v.0.clone()));
-                    }
-                    "rustc-link-search" => {
-                        let list = value.list(k)?;
-                        output
-                            .library_paths
-                            .extend(list.iter().map(|v| PathBuf::from(&v.0)));
-                    }
-                    "rustc-cfg" => {
-                        let list = value.list(k)?;
-                        output.cfgs.extend(list.iter().map(|v| v.0.clone()));
-                    }
-                    "rustc-env" => for (name, val) in value.table(k)?.0 {
-                        let val = val.string(name)?.0;
-                        output.env.push((name.clone(), val.to_string()));
-                    },
-                    "warning" | "rerun-if-changed" | "rerun-if-env-changed" => {
-                        bail!("`{}` is not supported in build script overrides", k);
-                    }
-                    _ => {
-                        let val = value.string(k)?.0;
-                        output.metadata.push((k.clone(), val.to_string()));
-                    }
-                }
-            }
-            ret.overrides.insert(lib_name, output);
-        }
-
-        Ok(ret)
-    }
-}
-
 /// A glorified callback for executing calls to rustc. Rather than calling rustc
 /// directly, we'll use an Executor, giving clients an opportunity to intercept
 /// the build calls.