Split Context into two types
authorDirkjan Ochtman <dirkjan@ochtman.nl>
Sat, 28 Apr 2018 15:20:27 +0000 (17:20 +0200)
committerDirkjan Ochtman <dirkjan@ochtman.nl>
Wed, 2 May 2018 08:02:17 +0000 (10:02 +0200)
src/cargo/core/compiler/compilation.rs
src/cargo/core/compiler/context/compilation_files.rs
src/cargo/core/compiler/context/mod.rs
src/cargo/core/compiler/context/unit_dependencies.rs
src/cargo/core/compiler/custom_build.rs
src/cargo/core/compiler/fingerprint.rs
src/cargo/core/compiler/job_queue.rs
src/cargo/core/compiler/mod.rs
src/cargo/core/compiler/output_depinfo.rs
src/cargo/ops/cargo_clean.rs
src/cargo/ops/cargo_compile.rs

index 71bddf20faee015fe79e8fac49a8b63984c4b2ad..ece186c9dc13441d24333ec2d342ace60b85f1b4 100644 (file)
@@ -175,7 +175,7 @@ impl<'cfg> Compilation<'cfg> {
         // When adding new environment variables depending on
         // crate properties which might require rebuild upon change
         // consider adding the corresponding properties to the hash
-        // in Context::target_metadata()
+        // in BuildContext::target_metadata()
         cmd.env("CARGO_MANIFEST_DIR", pkg.root())
             .env("CARGO_PKG_VERSION_MAJOR", &pkg.version().major.to_string())
             .env("CARGO_PKG_VERSION_MINOR", &pkg.version().minor.to_string())
index 9fcacb33614f3f52b8c1c5b347af4f60bd46370c..cf3046eec2d3129ad2c5a04c80539cf6ceb31bdb 100644 (file)
@@ -7,7 +7,7 @@ use std::sync::Arc;
 
 use lazycell::LazyCell;
 
-use super::{Context, FileFlavor, Kind, Layout, Unit};
+use super::{BuildContext, Context, FileFlavor, Kind, Layout, Unit};
 use core::{TargetKind, Workspace};
 use util::{self, CargoResult};
 
@@ -172,10 +172,10 @@ impl<'a, 'cfg: 'a> CompilationFiles<'a, 'cfg> {
     pub(super) fn outputs(
         &self,
         unit: &Unit<'a>,
-        cx: &Context<'a, 'cfg>,
+        bcx: &BuildContext<'a, 'cfg>,
     ) -> CargoResult<Arc<Vec<OutputFile>>> {
         self.outputs[unit]
-            .try_borrow_with(|| self.calc_outputs(unit, cx))
+            .try_borrow_with(|| self.calc_outputs(unit, bcx))
             .map(Arc::clone)
     }
 
@@ -230,15 +230,15 @@ impl<'a, 'cfg: 'a> CompilationFiles<'a, 'cfg> {
     fn calc_outputs(
         &self,
         unit: &Unit<'a>,
-        cx: &Context<'a, 'cfg>,
+        bcx: &BuildContext<'a, 'cfg>,
     ) -> CargoResult<Arc<Vec<OutputFile>>> {
         let out_dir = self.out_dir(unit);
         let file_stem = self.file_stem(unit);
         let link_stem = self.link_stem(unit);
         let info = if unit.target.for_host() {
-            &cx.host_info
+            &bcx.host_info
         } else {
-            &cx.target_info
+            &bcx.target_info
         };
 
         let mut ret = Vec::new();
@@ -268,7 +268,7 @@ impl<'a, 'cfg: 'a> CompilationFiles<'a, 'cfg> {
                         crate_type,
                         flavor,
                         unit.target.kind(),
-                        cx.build_config.target_triple(),
+                        bcx.build_config.target_triple(),
                     )?;
 
                     match file_types {
@@ -324,14 +324,14 @@ impl<'a, 'cfg: 'a> CompilationFiles<'a, 'cfg> {
                      does not support these crate types",
                     unsupported.join(", "),
                     unit.pkg,
-                    cx.build_config.target_triple()
+                    bcx.build_config.target_triple()
                 )
             }
             bail!(
                 "cannot compile `{}` as the target `{}` does not \
                  support any of the output crate types",
                 unit.pkg,
-                cx.build_config.target_triple()
+                bcx.build_config.target_triple()
             );
         }
         info!("Target filenames: {:?}", ret);
@@ -380,10 +380,11 @@ fn compute_metadata<'a, 'cfg>(
     // This environment variable should not be relied on! It's
     // just here for rustbuild. We need a more principled method
     // doing this eventually.
+    let bcx = &cx.bcx;
     let __cargo_default_lib_metadata = env::var("__CARGO_DEFAULT_LIB_METADATA");
     if !(unit.mode.is_any_test() || unit.mode.is_check())
         && (unit.target.is_dylib() || unit.target.is_cdylib()
-            || (unit.target.is_bin() && cx.build_config.target_triple().starts_with("wasm32-")))
+            || (unit.target.is_bin() && bcx.build_config.target_triple().starts_with("wasm32-")))
         && unit.pkg.package_id().source_id().is_path()
         && __cargo_default_lib_metadata.is_err()
     {
@@ -396,7 +397,7 @@ fn compute_metadata<'a, 'cfg>(
     // to pull crates from anywhere w/o worrying about conflicts
     unit.pkg
         .package_id()
-        .stable_hash(cx.ws.root())
+        .stable_hash(bcx.ws.root())
         .hash(&mut hasher);
 
     // Add package properties which map to environment variables
@@ -408,7 +409,7 @@ fn compute_metadata<'a, 'cfg>(
 
     // Also mix in enabled features to our metadata. This'll ensure that
     // when changing feature sets each lib is separately cached.
-    cx.resolve
+    bcx.resolve
         .features_sorted(unit.pkg.package_id())
         .hash(&mut hasher);
 
@@ -427,7 +428,7 @@ fn compute_metadata<'a, 'cfg>(
     // settings like debuginfo and whatnot.
     unit.profile.hash(&mut hasher);
     unit.mode.hash(&mut hasher);
-    if let Some(ref args) = cx.extra_args_for(unit) {
+    if let Some(ref args) = bcx.extra_args_for(unit) {
         args.hash(&mut hasher);
     }
 
@@ -441,7 +442,7 @@ fn compute_metadata<'a, 'cfg>(
     unit.target.name().hash(&mut hasher);
     unit.target.kind().hash(&mut hasher);
 
-    cx.build_config.rustc.verbose_version.hash(&mut hasher);
+    bcx.build_config.rustc.verbose_version.hash(&mut hasher);
 
     // Seed the contents of __CARGO_DEFAULT_LIB_METADATA to the hasher if present.
     // This should be the release channel, to get a different hash for each channel.
index 8992cf719953c5f2aedb2cde9c799b9a6c18b9c3..0eda1caf82dd86b74a6b94eba03b66d85ee71b19 100644 (file)
@@ -71,43 +71,29 @@ pub struct Unit<'a> {
 }
 
 /// The build context, containing all information about a build task
-pub struct Context<'a, 'cfg: 'a> {
+pub struct BuildContext<'a, 'cfg: 'a> {
     /// The workspace the build is for
     pub ws: &'a Workspace<'cfg>,
     /// The cargo configuration
     pub config: &'cfg Config,
     /// The dependency graph for our build
     pub resolve: &'a Resolve,
-    /// Information on the compilation output
-    pub compilation: Compilation<'cfg>,
-    pub packages: &'a PackageSet<'cfg>,
-    pub build_state: Arc<BuildState>,
-    pub build_script_overridden: HashSet<(PackageId, Kind)>,
-    pub build_explicit_deps: HashMap<Unit<'a>, BuildDeps>,
-    pub fingerprints: HashMap<Unit<'a>, Arc<Fingerprint>>,
-    pub compiled: HashSet<Unit<'a>>,
-    pub build_config: &'a BuildConfig,
-    pub build_scripts: HashMap<Unit<'a>, Arc<BuildScripts>>,
-    pub links: Links<'a>,
-    pub used_in_plugin: HashSet<Unit<'a>>,
-    pub jobserver: Client,
     pub profiles: &'a Profiles,
+    pub build_config: &'a BuildConfig,
     /// This is a workaround to carry the extra compiler args for either
     /// `rustc` or `rustdoc` given on the command-line for the commands `cargo
     /// rustc` and `cargo rustdoc`.  These commands only support one target,
     /// but we don't want the args passed to any dependencies, so we include
     /// the `Unit` corresponding to the top-level target.
     extra_compiler_args: Option<(Unit<'a>, Vec<String>)>,
+    pub packages: &'a PackageSet<'cfg>,
 
     target_info: TargetInfo,
     host_info: TargetInfo,
     incremental_env: Option<bool>,
-
-    unit_dependencies: HashMap<Unit<'a>, Vec<Unit<'a>>>,
-    files: Option<CompilationFiles<'a, 'cfg>>,
 }
 
-impl<'a, 'cfg> Context<'a, 'cfg> {
+impl<'a, 'cfg> BuildContext<'a, 'cfg> {
     pub fn new(
         ws: &'a Workspace<'cfg>,
         resolve: &'a Resolve,
@@ -116,63 +102,205 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
         build_config: &'a BuildConfig,
         profiles: &'a Profiles,
         extra_compiler_args: Option<(Unit<'a>, Vec<String>)>,
-    ) -> CargoResult<Context<'a, 'cfg>> {
+    ) -> CargoResult<BuildContext<'a, 'cfg>> {
         let incremental_env = match env::var("CARGO_INCREMENTAL") {
             Ok(v) => Some(v == "1"),
             Err(_) => None,
         };
 
-        // Load up the jobserver that we'll use to manage our parallelism. This
-        // is the same as the GNU make implementation of a jobserver, and
-        // intentionally so! It's hoped that we can interact with GNU make and
-        // all share the same jobserver.
-        //
-        // Note that if we don't have a jobserver in our environment then we
-        // create our own, and we create it with `n-1` tokens because one token
-        // is ourself, a running process.
-        let jobserver = match config.jobserver_from_env() {
-            Some(c) => c.clone(),
-            None => Client::new(build_config.jobs as usize - 1)
-                .chain_err(|| "failed to create jobserver")?,
-        };
-
         let (host_info, target_info) = {
-            let _p = profile::start("Context::probe_target_info");
+            let _p = profile::start("BuildContext::probe_target_info");
             debug!("probe_target_info");
             let host_info = TargetInfo::new(config, &build_config, Kind::Host)?;
             let target_info = TargetInfo::new(config, &build_config, Kind::Target)?;
             (host_info, target_info)
         };
 
-        let mut cx = Context {
+        Ok(BuildContext {
             ws,
             resolve,
             packages,
             config,
             target_info,
             host_info,
-            compilation: Compilation::new(config, build_config.rustc.process()),
-            build_state: Arc::new(BuildState::new(&build_config)),
             build_config,
-            fingerprints: HashMap::new(),
             profiles,
+            incremental_env,
+            extra_compiler_args,
+        })
+    }
+
+    pub fn extern_crate_name(&self, unit: &Unit<'a>, dep: &Unit<'a>) -> CargoResult<String> {
+        let deps = {
+            let a = unit.pkg.package_id();
+            let b = dep.pkg.package_id();
+            if a == b {
+                &[]
+            } else {
+                self.resolve.dependencies_listed(a, b)
+            }
+        };
+
+        let crate_name = dep.target.crate_name();
+        let mut names = deps.iter()
+            .map(|d| d.rename().unwrap_or(&crate_name));
+        let name = names.next().unwrap_or(&crate_name);
+        for n in names {
+            if n == name {
+                continue
+            }
+            bail!("multiple dependencies listed for the same crate must \
+                   all have the same name, but the dependency on `{}` \
+                   is listed as having different names", dep.pkg.package_id());
+        }
+        Ok(name.to_string())
+    }
+
+    /// Whether a dependency should be compiled for the host or target platform,
+    /// specified by `Kind`.
+    fn dep_platform_activated(&self, dep: &Dependency, kind: Kind) -> bool {
+        // If this dependency is only available for certain platforms,
+        // make sure we're only enabling it for that platform.
+        let platform = match dep.platform() {
+            Some(p) => p,
+            None => return true,
+        };
+        let (name, info) = match kind {
+            Kind::Host => (self.build_config.host_triple(), &self.host_info),
+            Kind::Target => (self.build_config.target_triple(), &self.target_info),
+        };
+        platform.matches(name, info.cfg())
+    }
+
+    /// Gets a package for the given package id.
+    pub fn get_package(&self, id: &PackageId) -> CargoResult<&'a Package> {
+        self.packages.get(id)
+    }
+
+    /// Get the user-specified linker for a particular host or target
+    pub fn linker(&self, kind: Kind) -> Option<&Path> {
+        self.target_config(kind).linker.as_ref().map(|s| s.as_ref())
+    }
+
+    /// Get the user-specified `ar` program for a particular host or target
+    pub fn ar(&self, kind: Kind) -> Option<&Path> {
+        self.target_config(kind).ar.as_ref().map(|s| s.as_ref())
+    }
+
+    /// Get the list of cfg printed out from the compiler for the specified kind
+    pub fn cfg(&self, kind: Kind) -> &[Cfg] {
+        let info = match kind {
+            Kind::Host => &self.host_info,
+            Kind::Target => &self.target_info,
+        };
+        info.cfg().unwrap_or(&[])
+    }
+
+    /// Get the target configuration for a particular host or target
+    fn target_config(&self, kind: Kind) -> &TargetConfig {
+        match kind {
+            Kind::Host => &self.build_config.host,
+            Kind::Target => &self.build_config.target,
+        }
+    }
+
+    /// Number of jobs specified for this build
+    pub fn jobs(&self) -> u32 {
+        self.build_config.jobs
+    }
+
+    pub fn rustflags_args(&self, unit: &Unit) -> CargoResult<Vec<String>> {
+        env_args(
+            self.config,
+            &self.build_config,
+            self.info(&unit.kind).cfg(),
+            unit.kind,
+            "RUSTFLAGS",
+        )
+    }
+
+    pub fn rustdocflags_args(&self, unit: &Unit) -> CargoResult<Vec<String>> {
+        env_args(
+            self.config,
+            &self.build_config,
+            self.info(&unit.kind).cfg(),
+            unit.kind,
+            "RUSTDOCFLAGS",
+        )
+    }
+
+    pub fn show_warnings(&self, pkg: &PackageId) -> bool {
+        pkg.source_id().is_path() || self.config.extra_verbose()
+    }
+
+    fn info(&self, kind: &Kind) -> &TargetInfo {
+        match *kind {
+            Kind::Host => &self.host_info,
+            Kind::Target => &self.target_info,
+        }
+    }
+
+    pub fn extra_args_for(&self, unit: &Unit<'a>) -> Option<&Vec<String>> {
+        if let Some((ref args_unit, ref args)) = self.extra_compiler_args {
+            if args_unit == unit {
+                return Some(args);
+            }
+        }
+        None
+    }
+}
+
+pub struct Context<'a, 'cfg: 'a> {
+    pub bcx: &'a BuildContext<'a, 'cfg>,
+    pub compilation: Compilation<'cfg>,
+    pub build_state: Arc<BuildState>,
+    pub build_script_overridden: HashSet<(PackageId, Kind)>,
+    pub build_explicit_deps: HashMap<Unit<'a>, BuildDeps>,
+    pub fingerprints: HashMap<Unit<'a>, Arc<Fingerprint>>,
+    pub compiled: HashSet<Unit<'a>>,
+    pub build_scripts: HashMap<Unit<'a>, Arc<BuildScripts>>,
+    pub links: Links<'a>,
+    pub used_in_plugin: HashSet<Unit<'a>>,
+    pub jobserver: Client,
+    unit_dependencies: HashMap<Unit<'a>, Vec<Unit<'a>>>,
+    files: Option<CompilationFiles<'a, 'cfg>>,
+}
+
+impl<'a, 'cfg> Context<'a, 'cfg> {
+    pub fn new(config: &'cfg Config, bcx: &'a BuildContext<'a, 'cfg>) -> CargoResult<Self> {
+        // Load up the jobserver that we'll use to manage our parallelism. This
+        // is the same as the GNU make implementation of a jobserver, and
+        // intentionally so! It's hoped that we can interact with GNU make and
+        // all share the same jobserver.
+        //
+        // Note that if we don't have a jobserver in our environment then we
+        // create our own, and we create it with `n-1` tokens because one token
+        // is ourself, a running process.
+        let jobserver = match config.jobserver_from_env() {
+            Some(c) => c.clone(),
+            None => Client::new(bcx.build_config.jobs as usize - 1)
+                .chain_err(|| "failed to create jobserver")?,
+        };
+
+        let mut compilation = Compilation::new(config, bcx.build_config.rustc.process());
+        compilation.host_dylib_path = bcx.host_info.sysroot_libdir.clone();
+        compilation.target_dylib_path = bcx.target_info.sysroot_libdir.clone();
+        Ok(Self {
+            bcx,
+            compilation,
+            build_state: Arc::new(BuildState::new(&bcx.build_config)),
+            fingerprints: HashMap::new(),
             compiled: HashSet::new(),
             build_scripts: HashMap::new(),
             build_explicit_deps: HashMap::new(),
             links: Links::new(),
             used_in_plugin: HashSet::new(),
-            incremental_env,
             jobserver,
             build_script_overridden: HashSet::new(),
 
             unit_dependencies: HashMap::new(),
             files: None,
-            extra_compiler_args,
-        };
-
-        cx.compilation.host_dylib_path = cx.host_info.sysroot_libdir.clone();
-        cx.compilation.target_dylib_path = cx.target_info.sysroot_libdir.clone();
-        Ok(cx)
+        })
     }
 
     // Returns a mapping of the root package plus its immediate dependencies to
@@ -183,7 +311,7 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
         export_dir: Option<PathBuf>,
         exec: &Arc<Executor>,
     ) -> CargoResult<Compilation<'cfg>> {
-        let mut queue = JobQueue::new(&self);
+        let mut queue = JobQueue::new(self.bcx);
         self.prepare_units(export_dir, units)?;
         self.prepare()?;
         self.build_used_in_plugin_map(units)?;
@@ -264,7 +392,7 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
                     );
             }
 
-            let feats = self.resolve.features(unit.pkg.package_id());
+            let feats = self.bcx.resolve.features(unit.pkg.package_id());
             if !feats.is_empty() {
                 self.compilation
                     .cfgs
@@ -276,7 +404,7 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
                             .collect()
                     });
             }
-            let rustdocflags = self.rustdocflags_args(unit)?;
+            let rustdocflags = self.bcx.rustdocflags_args(unit)?;
             if !rustdocflags.is_empty() {
                 self.compilation
                     .rustdocflags
@@ -304,8 +432,8 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
                 self.compilation.native_dirs.insert(dir.clone());
             }
         }
-        self.compilation.host = self.build_config.host_triple().to_string();
-        self.compilation.target = self.build_config.target_triple().to_string();
+        self.compilation.host = self.bcx.build_config.host_triple().to_string();
+        self.compilation.target = self.bcx.build_config.target_triple().to_string();
         Ok(self.compilation)
     }
 
@@ -314,21 +442,27 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
         export_dir: Option<PathBuf>,
         units: &[Unit<'a>],
     ) -> CargoResult<()> {
-        let dest = if self.build_config.release {
+        let dest = if self.bcx.build_config.release {
             "release"
         } else {
             "debug"
         };
-        let host_layout = Layout::new(self.ws, None, dest)?;
-        let target_layout = match self.build_config.requested_target.as_ref() {
-            Some(target) => Some(Layout::new(self.ws, Some(target), dest)?),
+        let host_layout = Layout::new(self.bcx.ws, None, dest)?;
+        let target_layout = match self.bcx.build_config.requested_target.as_ref() {
+            Some(target) => Some(Layout::new(self.bcx.ws, Some(target), dest)?),
             None => None,
         };
 
-        let deps = build_unit_dependencies(units, self)?;
+        let deps = build_unit_dependencies(units, self.bcx)?;
         self.unit_dependencies = deps;
-        let files =
-            CompilationFiles::new(units, host_layout, target_layout, export_dir, self.ws, self);
+        let files = CompilationFiles::new(
+            units,
+            host_layout,
+            target_layout,
+            export_dir,
+            self.bcx.ws,
+            self,
+        );
         self.files = Some(files);
         Ok(())
     }
@@ -403,7 +537,7 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
     ///  - link_dst: Optional file to link/copy the result to (without metadata suffix)
     ///  - linkable: Whether possible to link against file (eg it's a library)
     pub fn outputs(&mut self, unit: &Unit<'a>) -> CargoResult<Arc<Vec<OutputFile>>> {
-        self.files.as_ref().unwrap().outputs(unit, self)
+        self.files.as_ref().unwrap().outputs(unit, self.bcx)
     }
 
     /// For a package, return all targets which are registered as dependencies
@@ -429,85 +563,6 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
         self.unit_dependencies[unit].clone()
     }
 
-    pub fn extern_crate_name(&self, unit: &Unit<'a>, dep: &Unit<'a>) -> CargoResult<String> {
-        let deps = {
-            let a = unit.pkg.package_id();
-            let b = dep.pkg.package_id();
-            if a == b {
-                &[]
-            } else {
-                self.resolve.dependencies_listed(a, b)
-            }
-        };
-
-        let crate_name = dep.target.crate_name();
-        let mut names = deps.iter()
-            .map(|d| d.rename().unwrap_or(&crate_name));
-        let name = names.next().unwrap_or(&crate_name);
-        for n in names {
-            if n == name {
-                continue
-            }
-            bail!("multiple dependencies listed for the same crate must \
-                   all have the same name, but the dependency on `{}` \
-                   is listed as having different names", dep.pkg.package_id());
-        }
-        Ok(name.to_string())
-    }
-
-    /// Whether a dependency should be compiled for the host or target platform,
-    /// specified by `Kind`.
-    fn dep_platform_activated(&self, dep: &Dependency, kind: Kind) -> bool {
-        // If this dependency is only available for certain platforms,
-        // make sure we're only enabling it for that platform.
-        let platform = match dep.platform() {
-            Some(p) => p,
-            None => return true,
-        };
-        let (name, info) = match kind {
-            Kind::Host => (self.build_config.host_triple(), &self.host_info),
-            Kind::Target => (self.build_config.target_triple(), &self.target_info),
-        };
-        platform.matches(name, info.cfg())
-    }
-
-    /// Gets a package for the given package id.
-    pub fn get_package(&self, id: &PackageId) -> CargoResult<&'a Package> {
-        self.packages.get(id)
-    }
-
-    /// Get the user-specified linker for a particular host or target
-    pub fn linker(&self, kind: Kind) -> Option<&Path> {
-        self.target_config(kind).linker.as_ref().map(|s| s.as_ref())
-    }
-
-    /// Get the user-specified `ar` program for a particular host or target
-    pub fn ar(&self, kind: Kind) -> Option<&Path> {
-        self.target_config(kind).ar.as_ref().map(|s| s.as_ref())
-    }
-
-    /// Get the list of cfg printed out from the compiler for the specified kind
-    pub fn cfg(&self, kind: Kind) -> &[Cfg] {
-        let info = match kind {
-            Kind::Host => &self.host_info,
-            Kind::Target => &self.target_info,
-        };
-        info.cfg().unwrap_or(&[])
-    }
-
-    /// Get the target configuration for a particular host or target
-    fn target_config(&self, kind: Kind) -> &TargetConfig {
-        match kind {
-            Kind::Host => &self.build_config.host,
-            Kind::Target => &self.build_config.target,
-        }
-    }
-
-    /// Number of jobs specified for this build
-    pub fn jobs(&self) -> u32 {
-        self.build_config.jobs
-    }
-
     pub fn incremental_args(&self, unit: &Unit) -> CargoResult<Vec<String>> {
         // There's a number of ways to configure incremental compilation right
         // now. In order of descending priority (first is highest priority) we
@@ -530,8 +585,15 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
         //   incremental compilation or not. Primarily development profiles
         //   have it enabled by default while release profiles have it disabled
         //   by default.
-        let global_cfg = self.config.get_bool("build.incremental")?.map(|c| c.val);
-        let incremental = match (self.incremental_env, global_cfg, unit.profile.incremental) {
+        let global_cfg = self.bcx
+            .config
+            .get_bool("build.incremental")?
+            .map(|c| c.val);
+        let incremental = match (
+            self.bcx.incremental_env,
+            global_cfg,
+            unit.profile.incremental,
+        ) {
             (Some(v), _, _) => v,
             (None, Some(false), _) => false,
             (None, _, other) => other,
@@ -554,46 +616,6 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
         let dir = self.files().layout(unit.kind).incremental().display();
         Ok(vec!["-C".to_string(), format!("incremental={}", dir)])
     }
-
-    pub fn rustflags_args(&self, unit: &Unit) -> CargoResult<Vec<String>> {
-        env_args(
-            self.config,
-            &self.build_config,
-            self.info(&unit.kind).cfg(),
-            unit.kind,
-            "RUSTFLAGS",
-        )
-    }
-
-    pub fn rustdocflags_args(&self, unit: &Unit) -> CargoResult<Vec<String>> {
-        env_args(
-            self.config,
-            &self.build_config,
-            self.info(&unit.kind).cfg(),
-            unit.kind,
-            "RUSTDOCFLAGS",
-        )
-    }
-
-    pub fn show_warnings(&self, pkg: &PackageId) -> bool {
-        pkg.source_id().is_path() || self.config.extra_verbose()
-    }
-
-    fn info(&self, kind: &Kind) -> &TargetInfo {
-        match *kind {
-            Kind::Host => &self.host_info,
-            Kind::Target => &self.target_info,
-        }
-    }
-
-    pub fn extra_args_for(&self, unit: &Unit<'a>) -> Option<&Vec<String>> {
-        if let Some((ref args_unit, ref args)) = self.extra_compiler_args {
-            if args_unit == unit {
-                return Some(args);
-            }
-        }
-        None
-    }
 }
 
 /// Acquire extra flags to pass to the compiler from various locations.
index 84ee755b7329678fb5385e347c05faa5a55cea00..08d7ed41066d51f56dbc7e08dff854919f4025f4 100644 (file)
@@ -15,7 +15,7 @@
 //! (for example, with and without tests), so we actually build a dependency
 //! graph of `Unit`s, which capture these properties.
 
-use super::{Context, Kind, Unit};
+use super::{BuildContext, Kind, Unit};
 use core::dependency::Kind as DepKind;
 use core::profiles::ProfileFor;
 use core::{Package, Target};
@@ -25,7 +25,7 @@ use CargoResult;
 
 pub fn build_unit_dependencies<'a, 'cfg>(
     roots: &[Unit<'a>],
-    cx: &Context<'a, 'cfg>,
+    bcx: &BuildContext<'a, 'cfg>,
 ) -> CargoResult<HashMap<Unit<'a>, Vec<Unit<'a>>>> {
     let mut deps = HashMap::new();
     for unit in roots.iter() {
@@ -35,12 +35,12 @@ pub fn build_unit_dependencies<'a, 'cfg>(
         // cleared, and avoid building the lib thrice (once with `panic`, once
         // without, once for --test).  In particular, the lib included for
         // doctests and examples are `Build` mode here.
-        let profile_for = if unit.mode.is_any_test() || cx.build_config.test {
+        let profile_for = if unit.mode.is_any_test() || bcx.build_config.test {
             ProfileFor::TestDependency
         } else {
             ProfileFor::Any
         };
-        deps_of(unit, cx, &mut deps, profile_for)?;
+        deps_of(unit, bcx, &mut deps, profile_for)?;
     }
 
     Ok(deps)
@@ -48,7 +48,7 @@ pub fn build_unit_dependencies<'a, 'cfg>(
 
 fn deps_of<'a, 'b, 'cfg>(
     unit: &Unit<'a>,
-    cx: &Context<'a, 'cfg>,
+    bcx: &BuildContext<'a, 'cfg>,
     deps: &'b mut HashMap<Unit<'a>, Vec<Unit<'a>>>,
     profile_for: ProfileFor,
 ) -> CargoResult<&'b [Unit<'a>]> {
@@ -59,11 +59,11 @@ fn deps_of<'a, 'b, 'cfg>(
     // requested unit's settings are the same as `Any`, `CustomBuild` can't
     // affect anything else in the hierarchy.
     if !deps.contains_key(unit) {
-        let unit_deps = compute_deps(unit, cx, deps, profile_for)?;
+        let unit_deps = compute_deps(unit, bcx, deps, profile_for)?;
         let to_insert: Vec<_> = unit_deps.iter().map(|&(unit, _)| unit).collect();
         deps.insert(*unit, to_insert);
         for (unit, profile_for) in unit_deps {
-            deps_of(&unit, cx, deps, profile_for)?;
+            deps_of(&unit, bcx, deps, profile_for)?;
         }
     }
     Ok(deps[unit].as_ref())
@@ -75,19 +75,19 @@ fn deps_of<'a, 'b, 'cfg>(
 /// is the profile type that should be used for dependencies of the unit.
 fn compute_deps<'a, 'b, 'cfg>(
     unit: &Unit<'a>,
-    cx: &Context<'a, 'cfg>,
+    bcx: &BuildContext<'a, 'cfg>,
     deps: &'b mut HashMap<Unit<'a>, Vec<Unit<'a>>>,
     profile_for: ProfileFor,
 ) -> CargoResult<Vec<(Unit<'a>, ProfileFor)>> {
     if unit.mode.is_run_custom_build() {
-        return compute_deps_custom_build(unit, cx, deps);
+        return compute_deps_custom_build(unit, bcx, deps);
     } else if unit.mode.is_doc() && !unit.mode.is_any_test() {
         // Note: This does not include Doctest.
-        return compute_deps_doc(unit, cx);
+        return compute_deps_doc(unit, bcx);
     }
 
     let id = unit.pkg.package_id();
-    let deps = cx.resolve.deps(id);
+    let deps = bcx.resolve.deps(id);
     let mut ret = deps.filter(|&(_id, deps)| {
         assert!(deps.len() > 0);
         deps.iter().any(|dep| {
@@ -108,13 +108,13 @@ fn compute_deps<'a, 'b, 'cfg>(
 
             // If this dependency is only available for certain platforms,
             // make sure we're only enabling it for that platform.
-            if !cx.dep_platform_activated(dep, unit.kind) {
+            if !bcx.dep_platform_activated(dep, unit.kind) {
                 return false;
             }
 
             // If the dependency is optional, then we're only activating it
             // if the corresponding feature was activated
-            if dep.is_optional() && !cx.resolve.features(id).contains(&*dep.name()) {
+            if dep.is_optional() && !bcx.resolve.features(id).contains(&*dep.name()) {
                 return false;
             }
 
@@ -122,10 +122,10 @@ fn compute_deps<'a, 'b, 'cfg>(
             // actually used!
             true
         })
-    }).filter_map(|(id, _)| match cx.get_package(id) {
+    }).filter_map(|(id, _)| match bcx.get_package(id) {
             Ok(pkg) => pkg.targets().iter().find(|t| t.is_lib()).map(|t| {
                 let mode = check_or_build_mode(&unit.mode, t);
-                let unit = new_unit(cx, pkg, t, profile_for, unit.kind.for_target(t), mode);
+                let unit = new_unit(bcx, pkg, t, profile_for, unit.kind.for_target(t), mode);
                 Ok((unit, profile_for))
             }),
             Err(e) => Some(Err(e)),
@@ -138,7 +138,7 @@ fn compute_deps<'a, 'b, 'cfg>(
     if unit.target.is_custom_build() {
         return Ok(ret);
     }
-    ret.extend(dep_build_script(unit, cx));
+    ret.extend(dep_build_script(unit, bcx));
 
     // If this target is a binary, test, example, etc, then it depends on
     // the library of the same package. The call to `resolve.deps` above
@@ -147,7 +147,7 @@ fn compute_deps<'a, 'b, 'cfg>(
     if unit.target.is_lib() && unit.mode != CompileMode::Doctest {
         return Ok(ret);
     }
-    ret.extend(maybe_lib(unit, cx, profile_for));
+    ret.extend(maybe_lib(unit, bcx, profile_for));
 
     Ok(ret)
 }
@@ -158,7 +158,7 @@ fn compute_deps<'a, 'b, 'cfg>(
 /// the returned set of units must all be run before `unit` is run.
 fn compute_deps_custom_build<'a, 'cfg>(
     unit: &Unit<'a>,
-    cx: &Context<'a, 'cfg>,
+    bcx: &BuildContext<'a, 'cfg>,
     deps: &mut HashMap<Unit<'a>, Vec<Unit<'a>>>,
 ) -> CargoResult<Vec<(Unit<'a>, ProfileFor)>> {
     // When not overridden, then the dependencies to run a build script are:
@@ -178,17 +178,17 @@ fn compute_deps_custom_build<'a, 'cfg>(
         kind: unit.kind,
         mode: CompileMode::Build,
     };
-    let deps = deps_of(&tmp, cx, deps, ProfileFor::Any)?;
+    let deps = deps_of(&tmp, bcx, deps, ProfileFor::Any)?;
     Ok(deps.iter()
         .filter_map(|unit| {
             if !unit.target.linkable() || unit.pkg.manifest().links().is_none() {
                 return None;
             }
-            dep_build_script(unit, cx)
+            dep_build_script(unit, bcx)
         })
         .chain(Some((
             new_unit(
-                cx,
+                bcx,
                 unit.pkg,
                 unit.target,
                 ProfileFor::CustomBuild,
@@ -205,17 +205,17 @@ fn compute_deps_custom_build<'a, 'cfg>(
 /// Returns the dependencies necessary to document a package
 fn compute_deps_doc<'a, 'cfg>(
     unit: &Unit<'a>,
-    cx: &Context<'a, 'cfg>,
+    bcx: &BuildContext<'a, 'cfg>,
 ) -> CargoResult<Vec<(Unit<'a>, ProfileFor)>> {
-    let deps = cx.resolve
+    let deps = bcx.resolve
         .deps(unit.pkg.package_id())
         .filter(|&(_id, deps)| {
             deps.iter().any(|dep| match dep.kind() {
-                DepKind::Normal => cx.dep_platform_activated(dep, unit.kind),
+                DepKind::Normal => bcx.dep_platform_activated(dep, unit.kind),
                 _ => false,
             })
         })
-        .map(|(id, _deps)| cx.get_package(id));
+        .map(|(id, _deps)| bcx.get_package(id));
 
     // To document a library, we depend on dependencies actually being
     // built. If we're documenting *all* libraries, then we also depend on
@@ -231,7 +231,7 @@ fn compute_deps_doc<'a, 'cfg>(
         // However, for plugins/proc-macros, deps should be built like normal.
         let mode = check_or_build_mode(&unit.mode, lib);
         let lib_unit = new_unit(
-            cx,
+            bcx,
             dep,
             lib,
             ProfileFor::Any,
@@ -242,7 +242,7 @@ fn compute_deps_doc<'a, 'cfg>(
         if let CompileMode::Doc { deps: true } = unit.mode {
             // Document this lib as well.
             let doc_unit = new_unit(
-                cx,
+                bcx,
                 dep,
                 lib,
                 ProfileFor::Any,
@@ -254,23 +254,23 @@ fn compute_deps_doc<'a, 'cfg>(
     }
 
     // Be sure to build/run the build script for documented libraries as
-    ret.extend(dep_build_script(unit, cx));
+    ret.extend(dep_build_script(unit, bcx));
 
     // If we document a binary, we need the library available
     if unit.target.is_bin() {
-        ret.extend(maybe_lib(unit, cx, ProfileFor::Any));
+        ret.extend(maybe_lib(unit, bcx, ProfileFor::Any));
     }
     Ok(ret)
 }
 
 fn maybe_lib<'a>(
     unit: &Unit<'a>,
-    cx: &Context,
+    bcx: &BuildContext,
     profile_for: ProfileFor,
 ) -> Option<(Unit<'a>, ProfileFor)> {
     let mode = check_or_build_mode(&unit.mode, unit.target);
     unit.pkg.targets().iter().find(|t| t.linkable()).map(|t| {
-        let unit = new_unit(cx, unit.pkg, t, profile_for, unit.kind.for_target(t), mode);
+        let unit = new_unit(bcx, unit.pkg, t, profile_for, unit.kind.for_target(t), mode);
         (unit, profile_for)
     })
 }
@@ -282,7 +282,7 @@ fn maybe_lib<'a>(
 /// script itself doesn't have any dependencies, so even in that case a unit
 /// of work is still returned. `None` is only returned if the package has no
 /// build script.
-fn dep_build_script<'a>(unit: &Unit<'a>, cx: &Context) -> Option<(Unit<'a>, ProfileFor)> {
+fn dep_build_script<'a>(unit: &Unit<'a>, bcx: &BuildContext) -> Option<(Unit<'a>, ProfileFor)> {
     unit.pkg
         .targets()
         .iter()
@@ -294,7 +294,7 @@ fn dep_build_script<'a>(unit: &Unit<'a>, cx: &Context) -> Option<(Unit<'a>, Prof
                 Unit {
                     pkg: unit.pkg,
                     target: t,
-                    profile: cx.profiles.get_profile_run_custom_build(&unit.profile),
+                    profile: bcx.profiles.get_profile_run_custom_build(&unit.profile),
                     kind: unit.kind,
                     mode: CompileMode::RunCustomBuild,
                 },
@@ -322,19 +322,19 @@ fn check_or_build_mode(mode: &CompileMode, target: &Target) -> CompileMode {
 }
 
 fn new_unit<'a>(
-    cx: &Context,
+    bcx: &BuildContext,
     pkg: &'a Package,
     target: &'a Target,
     profile_for: ProfileFor,
     kind: Kind,
     mode: CompileMode,
 ) -> Unit<'a> {
-    let profile = cx.profiles.get_profile(
+    let profile = bcx.profiles.get_profile(
         &pkg.name(),
-        cx.ws.is_member(pkg),
+        bcx.ws.is_member(pkg),
         profile_for,
         mode,
-        cx.build_config.release,
+        bcx.build_config.release,
     );
     Unit {
         pkg,
index 59cb9b81aee46fb26563e1d91db2a8e6f8c29ea6..b23b1256d66f010f14ca688653cc700404cffeb1 100644 (file)
@@ -103,6 +103,7 @@ pub fn prepare<'a, 'cfg>(
 
 fn build_work<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> CargoResult<(Work, Work)> {
     assert!(unit.mode.is_run_custom_build());
+    let bcx = &cx.bcx;
     let dependencies = cx.dep_targets(unit);
     let build_script_unit = dependencies
         .iter()
@@ -126,30 +127,30 @@ fn build_work<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> CargoRes
     let debug = unit.profile.debuginfo.unwrap_or(0) != 0;
     cmd.env("OUT_DIR", &build_output)
         .env("CARGO_MANIFEST_DIR", unit.pkg.root())
-        .env("NUM_JOBS", &cx.jobs().to_string())
+        .env("NUM_JOBS", &bcx.jobs().to_string())
         .env(
             "TARGET",
             &match unit.kind {
-                Kind::Host => &cx.build_config.host_triple(),
-                Kind::Target => cx.build_config.target_triple(),
+                Kind::Host => &bcx.build_config.host_triple(),
+                Kind::Target => bcx.build_config.target_triple(),
             },
         )
         .env("DEBUG", debug.to_string())
         .env("OPT_LEVEL", &unit.profile.opt_level.to_string())
         .env(
             "PROFILE",
-            if cx.build_config.release {
+            if bcx.build_config.release {
                 "release"
             } else {
                 "debug"
             },
         )
-        .env("HOST", &cx.build_config.host_triple())
-        .env("RUSTC", &cx.build_config.rustc.path)
-        .env("RUSTDOC", &*cx.config.rustdoc()?)
+        .env("HOST", &bcx.build_config.host_triple())
+        .env("RUSTC", &bcx.build_config.rustc.path)
+        .env("RUSTDOC", &*bcx.config.rustdoc()?)
         .inherit_jobserver(&cx.jobserver);
 
-    if let Some(ref linker) = cx.build_config.target.linker {
+    if let Some(ref linker) = bcx.build_config.target.linker {
         cmd.env("RUSTC_LINKER", linker);
     }
 
@@ -159,12 +160,12 @@ fn build_work<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> CargoRes
 
     // Be sure to pass along all enabled features for this package, this is the
     // last piece of statically known information that we have.
-    for feat in cx.resolve.features(unit.pkg.package_id()).iter() {
+    for feat in bcx.resolve.features(unit.pkg.package_id()).iter() {
         cmd.env(&format!("CARGO_FEATURE_{}", super::envify(feat)), "1");
     }
 
     let mut cfg_map = HashMap::new();
-    for cfg in cx.cfg(unit.kind) {
+    for cfg in bcx.cfg(unit.kind) {
         match *cfg {
             Cfg::Name(ref n) => {
                 cfg_map.insert(n.clone(), None);
@@ -230,7 +231,7 @@ fn build_work<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> CargoRes
     );
     let build_scripts = super::load_build_deps(cx, unit);
     let kind = unit.kind;
-    let json_messages = cx.build_config.json_messages;
+    let json_messages = bcx.build_config.json_messages;
 
     // Check to see if the build script has already run, and if it has keep
     // track of whether it has told us about some explicit dependencies
index 73bd44bf3eb27e034904a0a9a70443b50a877367..6eba514052c051a196495bdc5db538c7364b0118 100644 (file)
@@ -15,7 +15,7 @@ use util::errors::{CargoResult, CargoResultExt};
 use util::paths;
 use util::{internal, profile, Dirty, Fresh, Freshness};
 
-use super::context::{Context, FileFlavor, Unit};
+use super::context::{BuildContext, Context, FileFlavor, Unit};
 use super::custom_build::BuildDeps;
 use super::job::Work;
 
@@ -56,6 +56,7 @@ pub fn prepare_target<'a, 'cfg>(
         unit.pkg.package_id(),
         unit.target.name()
     ));
+    let bcx = cx.bcx;
     let new = cx.files().fingerprint_dir(unit);
     let loc = new.join(&filename(cx, unit));
 
@@ -77,7 +78,7 @@ pub fn prepare_target<'a, 'cfg>(
     // changed then an error is issued.
     if compare.is_err() {
         let source_id = unit.pkg.package_id().source_id();
-        let sources = cx.packages.sources();
+        let sources = bcx.packages.sources();
         let source = sources
             .get(source_id)
             .ok_or_else(|| internal("missing package source"))?;
@@ -102,7 +103,7 @@ pub fn prepare_target<'a, 'cfg>(
         }
     }
 
-    let allow_failure = cx.extra_args_for(unit).is_some();
+    let allow_failure = bcx.extra_args_for(unit).is_some();
     let target_root = cx.files().target_root().to_path_buf();
     let write_fingerprint = Work::new(move |_| {
         match fingerprint.update_local(&target_root) {
@@ -414,6 +415,7 @@ fn calculate<'a, 'cfg>(
     cx: &mut Context<'a, 'cfg>,
     unit: &Unit<'a>,
 ) -> CargoResult<Arc<Fingerprint>> {
+    let bcx = cx.bcx;
     if let Some(s) = cx.fingerprints.get(unit) {
         return Ok(Arc::clone(s));
     }
@@ -430,7 +432,7 @@ fn calculate<'a, 'cfg>(
         .filter(|u| !u.target.is_custom_build() && !u.target.is_bin())
         .map(|dep| {
             calculate(cx, dep).and_then(|fingerprint| {
-                let name = cx.extern_crate_name(unit, dep)?;
+                let name = cx.bcx.extern_crate_name(unit, dep)?;
                 Ok((dep.pkg.package_id().to_string(), name, fingerprint))
             })
         })
@@ -442,30 +444,30 @@ fn calculate<'a, 'cfg>(
         let mtime = dep_info_mtime_if_fresh(unit.pkg, &dep_info)?;
         LocalFingerprint::mtime(cx.files().target_root(), mtime, &dep_info)
     } else {
-        let fingerprint = pkg_fingerprint(cx, unit.pkg)?;
+        let fingerprint = pkg_fingerprint(&cx.bcx, unit.pkg)?;
         LocalFingerprint::Precalculated(fingerprint)
     };
     let mut deps = deps;
     deps.sort_by(|&(ref a, _, _), &(ref b, _, _)| a.cmp(b));
     let extra_flags = if unit.mode.is_doc() {
-        cx.rustdocflags_args(unit)?
+        bcx.rustdocflags_args(unit)?
     } else {
-        cx.rustflags_args(unit)?
+        bcx.rustflags_args(unit)?
     };
     let profile_hash = util::hash_u64(&(
         &unit.profile,
         unit.mode,
-        cx.extra_args_for(unit),
+        bcx.extra_args_for(unit),
         cx.incremental_args(unit)?,
     ));
     let fingerprint = Arc::new(Fingerprint {
-        rustc: util::hash_u64(&cx.build_config.rustc.verbose_version),
+        rustc: util::hash_u64(&bcx.build_config.rustc.verbose_version),
         target: util::hash_u64(&unit.target),
         profile: profile_hash,
         // Note that .0 is hashed here, not .1 which is the cwd. That doesn't
         // actually affect the output artifact so there's no need to hash it.
-        path: util::hash_u64(&super::path_args(cx, unit).0),
-        features: format!("{:?}", cx.resolve.features_sorted(unit.pkg.package_id())),
+        path: util::hash_u64(&super::path_args(&cx.bcx, unit).0),
+        features: format!("{:?}", bcx.resolve.features_sorted(unit.pkg.package_id())),
         deps,
         local: vec![local],
         memoized_hash: Mutex::new(None),
@@ -591,7 +593,7 @@ fn build_script_local_fingerprints<'a, 'cfg>(
     let output = deps.build_script_output.clone();
     if deps.rerun_if_changed.is_empty() && deps.rerun_if_env_changed.is_empty() {
         debug!("old local fingerprints deps");
-        let s = pkg_fingerprint(cx, unit.pkg)?;
+        let s = pkg_fingerprint(&cx.bcx, unit.pkg)?;
         return Ok((vec![LocalFingerprint::Precalculated(s)], Some(output)));
     }
 
@@ -705,9 +707,9 @@ fn dep_info_mtime_if_fresh(pkg: &Package, dep_info: &Path) -> CargoResult<Option
     }
 }
 
-fn pkg_fingerprint(cx: &Context, pkg: &Package) -> CargoResult<String> {
+fn pkg_fingerprint(bcx: &BuildContext, pkg: &Package) -> CargoResult<String> {
     let source_id = pkg.package_id().source_id();
-    let sources = cx.packages.sources();
+    let sources = bcx.packages.sources();
 
     let source = sources
         .get(source_id)
index 026ac0962baa41678ce82bf82ce3c386a95eb3c2..cd8496202650a63fb142d844a4045444b0facc0d 100644 (file)
@@ -16,7 +16,7 @@ use util::{internal, profile, CargoResult, CargoResultExt, ProcessBuilder};
 use util::{Config, DependencyQueue, Dirty, Fresh, Freshness};
 
 use super::job::Job;
-use super::{Context, Kind, Unit};
+use super::{BuildContext, Context, Kind, Unit};
 
 /// A management structure of the entire dependency graph to compile.
 ///
@@ -80,7 +80,7 @@ impl<'a> JobState<'a> {
 }
 
 impl<'a> JobQueue<'a> {
-    pub fn new<'cfg>(cx: &Context<'a, 'cfg>) -> JobQueue<'a> {
+    pub fn new<'cfg>(bcx: &BuildContext<'a, 'cfg>) -> JobQueue<'a> {
         let (tx, rx) = channel();
         JobQueue {
             queue: DependencyQueue::new(),
@@ -91,7 +91,7 @@ impl<'a> JobQueue<'a> {
             compiled: HashSet::new(),
             documented: HashSet::new(),
             counts: HashMap::new(),
-            is_release: cx.build_config.release,
+            is_release: bcx.build_config.release,
         }
     }
 
@@ -193,7 +193,7 @@ impl<'a> JobQueue<'a> {
             // we're able to perform some parallel work.
             while error.is_none() && self.active < tokens.len() + 1 && !queue.is_empty() {
                 let (key, job, fresh) = queue.remove(0);
-                self.run(key, fresh, job, cx.config, scope)?;
+                self.run(key, fresh, job, cx.bcx.config, scope)?;
             }
 
             // If after all that we're not actually running anything then we're
@@ -211,16 +211,19 @@ impl<'a> JobQueue<'a> {
 
             match self.rx.recv().unwrap() {
                 Message::Run(cmd) => {
-                    cx.config.shell().verbose(|c| c.status("Running", &cmd))?;
+                    cx.bcx
+                        .config
+                        .shell()
+                        .verbose(|c| c.status("Running", &cmd))?;
                 }
                 Message::Stdout(out) => {
-                    if cx.config.extra_verbose() {
+                    if cx.bcx.config.extra_verbose() {
                         println!("{}", out);
                     }
                 }
                 Message::Stderr(err) => {
-                    if cx.config.extra_verbose() {
-                        writeln!(cx.config.shell().err(), "{}", err)?;
+                    if cx.bcx.config.extra_verbose() {
+                        writeln!(cx.bcx.config.shell().err(), "{}", err)?;
                     }
                 }
                 Message::Finish(key, result) => {
@@ -238,8 +241,8 @@ impl<'a> JobQueue<'a> {
 
                             if self.active > 0 {
                                 error = Some(format_err!("build failed"));
-                                handle_error(e, &mut *cx.config.shell());
-                                cx.config.shell().warn(
+                                handle_error(e, &mut *cx.bcx.config.shell());
+                                cx.bcx.config.shell().warn(
                                     "build failed, waiting for other \
                                      jobs to finish...",
                                 )?;
@@ -263,7 +266,7 @@ impl<'a> JobQueue<'a> {
         // list of Units built, and maybe display a list of the different
         // profiles used.  However, to keep it simple and compatible with old
         // behavior, we just display what the base profile is.
-        let profile = cx.profiles.base_profile(self.is_release);
+        let profile = cx.bcx.profiles.base_profile(self.is_release);
         let mut opt_type = String::from(if profile.opt_level.as_str() == "0" {
             "unoptimized"
         } else {
@@ -272,7 +275,7 @@ impl<'a> JobQueue<'a> {
         if profile.debuginfo.is_some() {
             opt_type += " + debuginfo";
         }
-        let duration = cx.config.creation_time().elapsed();
+        let duration = cx.bcx.config.creation_time().elapsed();
         let time_elapsed = format!(
             "{}.{:02} secs",
             duration.as_secs(),
@@ -283,7 +286,7 @@ impl<'a> JobQueue<'a> {
                 "{} [{}] target(s) in {}",
                 build_type, opt_type, time_elapsed
             );
-            cx.config.shell().status("Finished", message)?;
+            cx.bcx.config.shell().status("Finished", message)?;
             Ok(())
         } else if let Some(e) = error {
             Err(e)
@@ -328,20 +331,21 @@ impl<'a> JobQueue<'a> {
 
     fn emit_warnings(&self, msg: Option<&str>, key: &Key<'a>, cx: &mut Context) -> CargoResult<()> {
         let output = cx.build_state.outputs.lock().unwrap();
+        let bcx = &mut cx.bcx;
         if let Some(output) = output.get(&(key.pkg.clone(), key.kind)) {
             if let Some(msg) = msg {
                 if !output.warnings.is_empty() {
-                    writeln!(cx.config.shell().err(), "{}\n", msg)?;
+                    writeln!(bcx.config.shell().err(), "{}\n", msg)?;
                 }
             }
 
             for warning in output.warnings.iter() {
-                cx.config.shell().warn(warning)?;
+                bcx.config.shell().warn(warning)?;
             }
 
             if !output.warnings.is_empty() && msg.is_some() {
                 // Output an empty line.
-                writeln!(cx.config.shell().err(), "")?;
+                writeln!(bcx.config.shell().err(), "")?;
             }
         }
 
@@ -349,7 +353,7 @@ impl<'a> JobQueue<'a> {
     }
 
     fn finish(&mut self, key: Key<'a>, cx: &mut Context) -> CargoResult<()> {
-        if key.mode.is_run_custom_build() && cx.show_warnings(key.pkg) {
+        if key.mode.is_run_custom_build() && cx.bcx.show_warnings(key.pkg) {
             self.emit_warnings(None, &key, cx)?;
         }
 
@@ -424,7 +428,7 @@ impl<'a> Key<'a> {
 
     fn dependencies<'cfg>(&self, cx: &Context<'a, 'cfg>) -> CargoResult<Vec<Key<'a>>> {
         let unit = Unit {
-            pkg: cx.get_package(self.pkg)?,
+            pkg: cx.bcx.get_package(self.pkg)?,
             target: self.target,
             profile: self.profile,
             kind: self.kind,
index 28718a67f78da15db530b5ed239ab46a5623612b..2becebccd6d2b684bdfeff854f2ced8a2914f41f 100644 (file)
@@ -24,7 +24,7 @@ use self::job_queue::JobQueue;
 use self::output_depinfo::output_depinfo;
 
 pub use self::compilation::Compilation;
-pub use self::context::{Context, FileFlavor, TargetInfo, Unit};
+pub use self::context::{BuildContext, Context, FileFlavor, TargetInfo, Unit};
 pub use self::custom_build::{BuildMap, BuildOutput, BuildScripts};
 pub use self::layout::is_bad_artifact_name;
 
@@ -292,6 +292,7 @@ fn compile<'a, 'cfg: 'a>(
     unit: &Unit<'a>,
     exec: &Arc<Executor>,
 ) -> CargoResult<()> {
+    let bcx = cx.bcx;
     if !cx.compiled.insert(*unit) {
         return Ok(());
     }
@@ -300,7 +301,7 @@ fn compile<'a, 'cfg: 'a>(
     // we've got everything constructed.
     let p = profile::start(format!("preparing: {}/{}", unit.pkg, unit.target.name()));
     fingerprint::prepare_init(cx, unit)?;
-    cx.links.validate(cx.resolve, unit)?;
+    cx.links.validate(bcx.resolve, unit)?;
 
     let (dirty, fresh, freshness) = if unit.mode.is_run_custom_build() {
         custom_build::prepare(cx, unit)?
@@ -336,7 +337,7 @@ fn compile<'a, 'cfg: 'a>(
 }
 
 fn rustc<'a, 'cfg>(
-    cx: &mut Context<'a, 'cfg>,
+    mut cx: &mut Context<'a, 'cfg>,
     unit: &Unit<'a>,
     exec: &Arc<Executor>,
 ) -> CargoResult<Work> {
@@ -346,7 +347,7 @@ fn rustc<'a, 'cfg>(
 
     // If this is an upstream dep we don't want warnings from, turn off all
     // lints.
-    if !cx.show_warnings(unit.pkg.package_id()) {
+    if !cx.bcx.show_warnings(unit.pkg.package_id()) {
         rustc.arg("--cap-lints").arg("allow");
 
     // If this is an upstream dep but we *do* want warnings, make sure that they
@@ -377,10 +378,10 @@ fn rustc<'a, 'cfg>(
     } else {
         root.join(&cx.files().file_stem(unit))
     }.with_extension("d");
-    let dep_info_loc = fingerprint::dep_info_loc(cx, unit);
+    let dep_info_loc = fingerprint::dep_info_loc(&mut cx, unit);
 
-    rustc.args(&cx.rustflags_args(unit)?);
-    let json_messages = cx.build_config.json_messages;
+    rustc.args(&cx.bcx.rustflags_args(unit)?);
+    let json_messages = cx.bcx.build_config.json_messages;
     let package_id = unit.pkg.package_id().clone();
     let target = unit.target.clone();
 
@@ -391,7 +392,7 @@ fn rustc<'a, 'cfg>(
     let pkg_root = unit.pkg.root().to_path_buf();
     let cwd = rustc
         .get_cwd()
-        .unwrap_or_else(|| cx.config.cwd())
+        .unwrap_or_else(|| cx.bcx.config.cwd())
         .to_path_buf();
 
     return Ok(Work::new(move |state| {
@@ -555,18 +556,19 @@ fn link_targets<'a, 'cfg>(
     unit: &Unit<'a>,
     fresh: bool,
 ) -> CargoResult<Work> {
+    let bcx = cx.bcx;
     let outputs = cx.outputs(unit)?;
     let export_dir = cx.files().export_dir(unit);
     let package_id = unit.pkg.package_id().clone();
     let target = unit.target.clone();
     let profile = unit.profile;
     let unit_mode = unit.mode;
-    let features = cx.resolve
+    let features = bcx.resolve
         .features_sorted(&package_id)
         .into_iter()
         .map(|s| s.to_owned())
         .collect();
-    let json_messages = cx.build_config.json_messages;
+    let json_messages = bcx.build_config.json_messages;
 
     Ok(Work::new(move |_| {
         // If we're a "root crate", e.g. the target of this compilation, then we
@@ -746,13 +748,14 @@ fn prepare_rustc<'a, 'cfg>(
 }
 
 fn rustdoc<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> CargoResult<Work> {
+    let bcx = cx.bcx;
     let mut rustdoc = cx.compilation.rustdoc_process(unit.pkg)?;
     rustdoc.inherit_jobserver(&cx.jobserver);
     rustdoc.arg("--crate-name").arg(&unit.target.crate_name());
-    add_path_args(cx, unit, &mut rustdoc);
+    add_path_args(&cx.bcx, unit, &mut rustdoc);
 
     if unit.kind != Kind::Host {
-        if let Some(ref target) = cx.build_config.requested_target {
+        if let Some(ref target) = bcx.build_config.requested_target {
             rustdoc.arg("--target").arg(target);
         }
     }
@@ -766,7 +769,7 @@ fn rustdoc<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> CargoResult
 
     rustdoc.arg("-o").arg(doc_dir);
 
-    for feat in cx.resolve.features_sorted(unit.pkg.package_id()) {
+    for feat in bcx.resolve.features_sorted(unit.pkg.package_id()) {
         rustdoc.arg("--cfg").arg(&format!("feature=\"{}\"", feat));
     }
 
@@ -777,13 +780,13 @@ fn rustdoc<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> CargoResult
         rustdoc.arg(format!("--edition={}", &manifest.edition()));
     }
 
-    if let Some(ref args) = cx.extra_args_for(unit) {
+    if let Some(ref args) = bcx.extra_args_for(unit) {
         rustdoc.args(args);
     }
 
     build_deps_args(&mut rustdoc, cx, unit)?;
 
-    rustdoc.args(&cx.rustdocflags_args(unit)?);
+    rustdoc.args(&bcx.rustdocflags_args(unit)?);
 
     let name = unit.pkg.name().to_string();
     let build_state = cx.build_state.clone();
@@ -820,8 +823,8 @@ fn rustdoc<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> CargoResult
 //
 // The first returned value here is the argument to pass to rustc, and the
 // second is the cwd that rustc should operate in.
-fn path_args(cx: &Context, unit: &Unit) -> (PathBuf, PathBuf) {
-    let ws_root = cx.ws.root();
+fn path_args(bcx: &BuildContext, unit: &Unit) -> (PathBuf, PathBuf) {
+    let ws_root = bcx.ws.root();
     let src = unit.target.src_path();
     assert!(src.is_absolute());
     match src.strip_prefix(ws_root) {
@@ -830,8 +833,8 @@ fn path_args(cx: &Context, unit: &Unit) -> (PathBuf, PathBuf) {
     }
 }
 
-fn add_path_args(cx: &Context, unit: &Unit, cmd: &mut ProcessBuilder) {
-    let (arg, cwd) = path_args(cx, unit);
+fn add_path_args(bcx: &BuildContext, unit: &Unit, cmd: &mut ProcessBuilder) {
+    let (arg, cwd) = path_args(bcx, unit);
     cmd.arg(arg);
     cmd.cwd(cwd);
 }
@@ -844,6 +847,7 @@ fn build_base_args<'a, 'cfg>(
 ) -> CargoResult<()> {
     assert!(!unit.mode.is_run_custom_build());
 
+    let bcx = cx.bcx;
     let Profile {
         ref opt_level,
         ref lto,
@@ -859,9 +863,9 @@ fn build_base_args<'a, 'cfg>(
 
     cmd.arg("--crate-name").arg(&unit.target.crate_name());
 
-    add_path_args(cx, unit, cmd);
+    add_path_args(&cx.bcx, unit, cmd);
 
-    match cx.config.shell().color_choice() {
+    match bcx.config.shell().color_choice() {
         ColorChoice::Always => {
             cmd.arg("--color").arg("always");
         }
@@ -871,7 +875,7 @@ fn build_base_args<'a, 'cfg>(
         ColorChoice::CargoAuto => {}
     }
 
-    if cx.build_config.json_messages {
+    if bcx.build_config.json_messages {
         cmd.arg("--error-format").arg("json");
     }
 
@@ -888,7 +892,7 @@ fn build_base_args<'a, 'cfg>(
     }
 
     let prefer_dynamic = (unit.target.for_host() && !unit.target.is_custom_build())
-        || (crate_types.contains(&"dylib") && cx.ws.members().any(|p| p != unit.pkg));
+        || (crate_types.contains(&"dylib") && bcx.ws.members().any(|p| p != unit.pkg));
     if prefer_dynamic {
         cmd.arg("-C").arg("prefer-dynamic");
     }
@@ -942,7 +946,7 @@ fn build_base_args<'a, 'cfg>(
         cmd.arg("-C").arg(format!("debuginfo={}", debuginfo));
     }
 
-    if let Some(ref args) = cx.extra_args_for(unit) {
+    if let Some(ref args) = bcx.extra_args_for(unit) {
         cmd.args(args);
     }
 
@@ -976,7 +980,7 @@ fn build_base_args<'a, 'cfg>(
     // We ideally want deterministic invocations of rustc to ensure that
     // rustc-caching strategies like sccache are able to cache more, so sort the
     // feature list here.
-    for feat in cx.resolve.features_sorted(unit.pkg.package_id()) {
+    for feat in bcx.resolve.features_sorted(unit.pkg.package_id()) {
         cmd.arg("--cfg").arg(&format!("feature=\"{}\"", feat));
     }
 
@@ -1010,19 +1014,19 @@ fn build_base_args<'a, 'cfg>(
             cmd,
             "--target",
             "",
-            cx.build_config
+            bcx.build_config
                 .requested_target
                 .as_ref()
                 .map(|s| s.as_ref()),
         );
     }
 
-    opt(cmd, "-C", "ar=", cx.ar(unit.kind).map(|s| s.as_ref()));
+    opt(cmd, "-C", "ar=", bcx.ar(unit.kind).map(|s| s.as_ref()));
     opt(
         cmd,
         "-C",
         "linker=",
-        cx.linker(unit.kind).map(|s| s.as_ref()),
+        bcx.linker(unit.kind).map(|s| s.as_ref()),
     );
     cmd.args(&cx.incremental_args(unit)?);
 
@@ -1034,6 +1038,7 @@ fn build_deps_args<'a, 'cfg>(
     cx: &mut Context<'a, 'cfg>,
     unit: &Unit<'a>,
 ) -> CargoResult<()> {
+    let bcx = cx.bcx;
     cmd.arg("-L").arg(&{
         let mut deps = OsString::from("dependency=");
         deps.push(cx.files().deps_dir(unit));
@@ -1063,7 +1068,7 @@ fn build_deps_args<'a, 'cfg>(
             .iter()
             .find(|u| !u.mode.is_doc() && u.target.is_lib())
         {
-            cx.config.shell().warn(format!(
+            bcx.config.shell().warn(format!(
                 "The package `{}` \
                  provides no linkable target. The compiler might raise an error while compiling \
                  `{}`. Consider adding 'dylib' or 'rlib' to key `crate-type` in `{}`'s \
@@ -1092,12 +1097,13 @@ fn build_deps_args<'a, 'cfg>(
         current: &Unit<'a>,
         dep: &Unit<'a>,
     ) -> CargoResult<()> {
+        let bcx = cx.bcx;
         for output in cx.outputs(dep)?.iter() {
             if output.flavor != FileFlavor::Linkable {
                 continue;
             }
             let mut v = OsString::new();
-            let name = cx.extern_crate_name(current, dep)?;
+            let name = bcx.extern_crate_name(current, dep)?;
             v.push(name);
             v.push("=");
             v.push(cx.files().out_dir(dep));
index a0a006a5d0a5f718a5c541d66a4ff6d782b88db3..6142e32eec2c882ce261a0852843b23ff3befb78 100644 (file)
@@ -69,12 +69,13 @@ fn add_deps_for_unit<'a, 'b>(
     Ok(())
 }
 
-pub fn output_depinfo<'a, 'b>(context: &mut Context<'a, 'b>, unit: &Unit<'a>) -> CargoResult<()> {
+pub fn output_depinfo<'a, 'b>(cx: &mut Context<'a, 'b>, unit: &Unit<'a>) -> CargoResult<()> {
+    let bcx = cx.bcx;
     let mut deps = BTreeSet::new();
     let mut visited = HashSet::new();
-    let success = add_deps_for_unit(&mut deps, context, unit, &mut visited).is_ok();
+    let success = add_deps_for_unit(&mut deps, cx, unit, &mut visited).is_ok();
     let basedir_string;
-    let basedir = match context.config.get_path("build.dep-info-basedir")? {
+    let basedir = match bcx.config.get_path("build.dep-info-basedir")? {
         Some(value) => {
             basedir_string = value
                 .val
@@ -90,7 +91,7 @@ pub fn output_depinfo<'a, 'b>(context: &mut Context<'a, 'b>, unit: &Unit<'a>) ->
         .map(|f| render_filename(f, basedir))
         .collect::<CargoResult<Vec<_>>>()?;
 
-    for output in context.outputs(unit)?.iter() {
+    for output in cx.outputs(unit)?.iter() {
         if let Some(ref link_dst) = output.hardlink {
             let output_path = link_dst.with_extension("d");
             if success {
index a120ef6c015e9d06b1032965ffd805adb20d39f7..04d0aaba9a49dd21936ceb7919f5a8e4963a8957 100644 (file)
@@ -1,7 +1,7 @@
 use std::fs;
 use std::path::Path;
 
-use core::compiler::{BuildConfig, Context, Kind, Unit};
+use core::compiler::{BuildConfig, BuildContext, Context, Kind, Unit};
 use core::profiles::ProfileFor;
 use core::Workspace;
 use ops::{self, CompileMode};
@@ -81,7 +81,7 @@ pub fn clean(ws: &Workspace, opts: &CleanOptions) -> CargoResult<()> {
 
     let mut build_config = BuildConfig::new(config, Some(1), &opts.target, None)?;
     build_config.release = opts.release;
-    let mut cx = Context::new(
+    let bcx = BuildContext::new(
         ws,
         &resolve,
         &packages,
@@ -90,6 +90,7 @@ pub fn clean(ws: &Workspace, opts: &CleanOptions) -> CargoResult<()> {
         profiles,
         None,
     )?;
+    let mut cx = Context::new(config, &bcx)?;
     cx.prepare_units(None, &units)?;
 
     for unit in units.iter() {
index 53e19723f8551b039dcc6e24bc5dcad71d2c649f..594c7b43020f7d7bea96c2225bd0b7fa98ad2c5c 100644 (file)
@@ -26,7 +26,7 @@ use std::collections::HashSet;
 use std::path::{Path, PathBuf};
 use std::sync::Arc;
 
-use core::compiler::{BuildConfig, Compilation, Context, DefaultExecutor, Executor};
+use core::compiler::{BuildConfig, BuildContext, Compilation, Context, DefaultExecutor, Executor};
 use core::compiler::{Kind, Unit};
 use core::profiles::{ProfileFor, Profiles};
 use core::resolver::{Method, Resolve};
@@ -416,7 +416,7 @@ pub fn compile_ws<'a>(
 
     let mut ret = {
         let _p = profile::start("compiling");
-        let mut cx = Context::new(
+        let bcx = BuildContext::new(
             ws,
             &resolve_with_overrides,
             &packages,
@@ -425,6 +425,7 @@ pub fn compile_ws<'a>(
             profiles,
             extra_compiler_args,
         )?;
+        let mut cx = Context::new(config, &bcx)?;
         cx.compile(&units, export_dir.clone(), &exec)?
     };