From bd31c081efdbb9ed5d4add121638c064c0d519d2 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Fri, 2 Aug 2019 16:05:18 -0700 Subject: [PATCH] Clean up build script stuff and documentation. --- src/cargo/core/compiler/build_context/mod.rs | 22 ++- src/cargo/core/compiler/context/mod.rs | 54 +++--- .../compiler/context/unit_dependencies.rs | 7 + src/cargo/core/compiler/custom_build.rs | 174 +++++++++--------- src/cargo/core/compiler/fingerprint.rs | 11 +- src/cargo/core/compiler/job_queue.rs | 4 +- src/cargo/core/compiler/mod.rs | 46 +++-- src/cargo/core/compiler/output_depinfo.rs | 2 +- src/cargo/core/manifest.rs | 1 + 9 files changed, 180 insertions(+), 141 deletions(-) diff --git a/src/cargo/core/compiler/build_context/mod.rs b/src/cargo/core/compiler/build_context/mod.rs index 18956632152..7eab9dea45f 100644 --- a/src/cargo/core/compiler/build_context/mod.rs +++ b/src/cargo/core/compiler/build_context/mod.rs @@ -16,6 +16,11 @@ mod target_info; pub use self::target_info::{FileFlavor, TargetInfo}; /// The build context, containing all information about a build task. +/// +/// It is intended that this is mostly static information. Stuff that mutates +/// during the build can be found in the parent `Context`. (I say mostly, +/// because this has internal caching, but nothing that should be observable +/// or require &mut.) pub struct BuildContext<'a, 'cfg> { /// The workspace the build is for. pub ws: &'a Workspace<'cfg>, @@ -183,6 +188,17 @@ impl<'a, 'cfg> BuildContext<'a, 'cfg> { pub fn extra_args_for(&self, unit: &Unit<'a>) -> Option<&Vec> { self.extra_compiler_args.get(unit) } + + /// If a build script is overridden, this returns the `BuildOutput` to use. + /// + /// `lib_name` is the `links` library name and `kind` is whether it is for + /// Host or Target. + pub fn script_override(&self, lib_name: &str, kind: Kind) -> Option<&BuildOutput> { + match kind { + Kind::Host => self.host_config.overrides.get(lib_name), + Kind::Target => self.target_config.overrides.get(lib_name), + } + } } /// Information required to build for a target. @@ -192,7 +208,11 @@ pub struct TargetConfig { pub ar: Option, /// The path of the linker for this target. pub linker: Option, - /// Special build options for any necessary input files (filename -> options). + /// Build script override for the given library name. + /// + /// Any package with a `links` value for the given library name will skip + /// running its build script and instead use the given output from the + /// config file. pub overrides: HashMap, } diff --git a/src/cargo/core/compiler/context/mod.rs b/src/cargo/core/compiler/context/mod.rs index 7ab5f5b74b1..47f03308cf4 100644 --- a/src/cargo/core/compiler/context/mod.rs +++ b/src/cargo/core/compiler/context/mod.rs @@ -3,7 +3,7 @@ use std::collections::{HashMap, HashSet}; use std::ffi::OsStr; use std::fmt::Write; use std::path::PathBuf; -use std::sync::Arc; +use std::sync::{Arc, Mutex}; use filetime::FileTime; use jobserver::Client; @@ -15,7 +15,7 @@ use crate::util::errors::{CargoResult, CargoResultExt}; use crate::util::{internal, profile, Config}; use super::build_plan::BuildPlan; -use super::custom_build::{self, BuildDeps, BuildScripts, BuildState}; +use super::custom_build::{self, BuildDeps, BuildScriptOutputs, BuildScripts}; use super::fingerprint::Fingerprint; use super::job_queue::JobQueue; use super::layout::Layout; @@ -28,21 +28,45 @@ mod compilation_files; use self::compilation_files::CompilationFiles; pub use self::compilation_files::{Metadata, OutputFile}; +/// Collection of all the stuff that is needed to perform a build. pub struct Context<'a, 'cfg> { + /// Mostly static information about the build task. pub bcx: &'a BuildContext<'a, 'cfg>, + /// A large collection of information about the result of the entire compilation. pub compilation: Compilation<'cfg>, - pub build_state: Arc, - pub build_script_overridden: HashSet<(PackageId, Kind)>, + /// Output from build scripts, updated after each build script runs. + pub build_script_outputs: Arc>, + /// Dependencies (like rerun-if-changed) declared by a build script. + /// This is *only* populated from the output from previous runs. + /// If the build script hasn't ever been run, then it must be run. pub build_explicit_deps: HashMap, BuildDeps>, + /// Fingerprints used to detect if a unit is out-of-date. pub fingerprints: HashMap, Arc>, + /// Cache of file mtimes to reduce filesystem hits. pub mtime_cache: HashMap, + /// A set used to track which units have been compiled. + /// A unit may appear in the job graph multiple times as a dependency of + /// multiple packages, but it only needs to run once. pub compiled: HashSet>, + /// Linking information for each `Unit`. + /// See `build_map` for details. pub build_scripts: HashMap, Arc>, + /// Used to check the `links` field in the manifest is not duplicated and + /// is used correctly. pub links: Links, + /// Job server client to manage concurrency with other processes. pub jobserver: Client, + /// "Primary" packages are the ones the user selected on the command-line + /// with `-p` flags. If no flags are specified, then it is the defaults + /// based on the current directory and the default workspace members. primary_packages: HashSet, + /// The dependency graph of units to compile. unit_dependencies: HashMap, Vec>>, + /// An abstraction of the files and directories that will be generated by + /// the compilation. This is `None` until after `unit_dependencies` has + /// been computed. files: Option>, + /// Cache of packages, populated when they are downloaded. package_cache: HashMap, /// A flag indicating whether pipelining is enabled for this compilation @@ -82,7 +106,7 @@ impl<'a, 'cfg> Context<'a, 'cfg> { Ok(Self { bcx, compilation: Compilation::new(bcx)?, - build_state: Arc::new(BuildState::new(&bcx.host_config, &bcx.target_config)), + build_script_outputs: Arc::new(Mutex::new(BuildScriptOutputs::default())), fingerprints: HashMap::new(), mtime_cache: HashMap::new(), compiled: HashSet::new(), @@ -90,8 +114,6 @@ impl<'a, 'cfg> Context<'a, 'cfg> { build_explicit_deps: HashMap::new(), links: Links::new(), jobserver, - build_script_overridden: HashSet::new(), - primary_packages: HashSet::new(), unit_dependencies: HashMap::new(), files: None, @@ -228,7 +250,7 @@ impl<'a, 'cfg> Context<'a, 'cfg> { super::output_depinfo(&mut self, unit)?; } - for (&(ref pkg, _), output) in self.build_state.outputs.lock().unwrap().iter() { + for (&(ref pkg, _), output) in self.build_script_outputs.lock().unwrap().iter() { self.compilation .cfgs .entry(pkg.clone()) @@ -338,22 +360,6 @@ impl<'a, 'cfg> Context<'a, 'cfg> { // // TODO: this ideally should be `-> &[Unit<'a>]`. pub fn dep_targets(&self, unit: &Unit<'a>) -> Vec> { - // If this build script's execution has been overridden then we don't - // actually depend on anything, we've reached the end of the dependency - // chain as we've got all the info we're gonna get. - // - // Note there's a subtlety about this piece of code! The - // `build_script_overridden` map here is populated in - // `custom_build::build_map` which you need to call before inspecting - // dependencies. However, that code itself calls this method and - // gets a full pre-filtered set of dependencies. This is not super - // obvious, and clear, but it does work at the moment. - if unit.target.is_custom_build() { - let key = (unit.pkg.package_id(), unit.kind); - if self.build_script_overridden.contains(&key) { - return Vec::new(); - } - } self.unit_dependencies[unit].clone() } diff --git a/src/cargo/core/compiler/context/unit_dependencies.rs b/src/cargo/core/compiler/context/unit_dependencies.rs index 6e80f31a195..5cb41e6385d 100644 --- a/src/cargo/core/compiler/context/unit_dependencies.rs +++ b/src/cargo/core/compiler/context/unit_dependencies.rs @@ -258,6 +258,13 @@ fn compute_deps_custom_build<'a, 'cfg>( unit: &Unit<'a>, bcx: &BuildContext<'a, 'cfg>, ) -> CargoResult, UnitFor)>> { + if let Some(links) = unit.pkg.manifest().links() { + if bcx.script_override(links, unit.kind).is_some() { + // Overridden build scripts don't have any dependencies. + return Ok(Vec::new()); + } + } + // When not overridden, then the dependencies to run a build script are: // // 1. Compiling the build script itself. diff --git a/src/cargo/core/compiler/custom_build.rs b/src/cargo/core/compiler/custom_build.rs index 7978d1d480e..db621aa7eb8 100644 --- a/src/cargo/core/compiler/custom_build.rs +++ b/src/cargo/core/compiler/custom_build.rs @@ -3,7 +3,7 @@ use std::collections::{BTreeSet, HashSet}; use std::fs; use std::path::{Path, PathBuf}; use std::str; -use std::sync::{Arc, Mutex}; +use std::sync::Arc; use crate::core::compiler::job_queue::JobState; use crate::core::PackageId; @@ -13,7 +13,7 @@ use crate::util::Cfg; use crate::util::{self, internal, paths, profile}; use super::job::{Freshness, Job, Work}; -use super::{fingerprint, Context, Kind, TargetConfig, Unit}; +use super::{fingerprint, Context, Kind, Unit}; /// Contains the parsed output of a custom build script. #[derive(Clone, Debug, Hash)] @@ -39,48 +39,57 @@ pub struct BuildOutput { pub warnings: Vec, } -/// Map of packages to build info. -pub type BuildMap = HashMap<(PackageId, Kind), BuildOutput>; - -/// Build info and overrides. -pub struct BuildState { - pub outputs: Mutex, - overrides: HashMap<(String, Kind), BuildOutput>, -} +/// Map of packages to build script output. +/// +/// This initially starts out as empty. Overridden build scripts get +/// inserted during `build_map`. The rest of the entries are added +/// immediately after each build script runs. +pub type BuildScriptOutputs = HashMap<(PackageId, Kind), BuildOutput>; +/// Linking information for a `Unit`. +/// +/// See `build_map` for more details. #[derive(Default)] pub struct BuildScripts { - // Cargo will use this `to_link` vector to add `-L` flags to compiles as we - // propagate them upwards towards the final build. Note, however, that we - // need to preserve the ordering of `to_link` to be topologically sorted. - // This will ensure that build scripts which print their paths properly will - // correctly pick up the files they generated (if there are duplicates - // elsewhere). - // - // To preserve this ordering, the (id, kind) is stored in two places, once - // in the `Vec` and once in `seen_to_link` for a fast lookup. We maintain - // this as we're building interactively below to ensure that the memory - // usage here doesn't blow up too much. - // - // For more information, see #2354. + /// Cargo will use this `to_link` vector to add `-L` flags to compiles as we + /// propagate them upwards towards the final build. Note, however, that we + /// need to preserve the ordering of `to_link` to be topologically sorted. + /// This will ensure that build scripts which print their paths properly will + /// correctly pick up the files they generated (if there are duplicates + /// elsewhere). + /// + /// To preserve this ordering, the (id, kind) is stored in two places, once + /// in the `Vec` and once in `seen_to_link` for a fast lookup. We maintain + /// this as we're building interactively below to ensure that the memory + /// usage here doesn't blow up too much. + /// + /// For more information, see #2354. pub to_link: Vec<(PackageId, Kind)>, + /// This is only used while constructing `to_link` to avoid duplicates. seen_to_link: HashSet<(PackageId, Kind)>, + /// Host-only dependencies that have build scripts. + /// + /// This is the set of transitive dependencies that are host-only + /// (proc-macro, plugin, build-dependency) that contain a build script. + /// Any `BuildOutput::library_paths` path relative to `target` will be + /// added to LD_LIBRARY_PATH so that the compiler can find any dynamic + /// libraries a build script may have generated. pub plugins: BTreeSet, } +/// Dependency information as declared by a build script. #[derive(Debug)] pub struct BuildDeps { + /// Absolute path to the file in the target directory that stores the + /// output of the build script. pub build_script_output: PathBuf, + /// Files that trigger a rebuild if they change. pub rerun_if_changed: Vec, + /// Environment variables that trigger a rebuild if they change. pub rerun_if_env_changed: Vec, } /// Prepares a `Work` that executes the target as a custom build script. -/// -/// The `req` given is the requirement which this run of the build script will -/// prepare work for. If the requirement is specified as both the target and the -/// host platforms it is assumed that the two are equal and the build script is -/// only run once (not twice). pub fn prepare<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> CargoResult { let _p = profile::start(format!( "build script prepare: {}/{}", @@ -90,7 +99,8 @@ pub fn prepare<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> CargoRe let key = (unit.pkg.package_id(), unit.kind); - if cx.build_script_overridden.contains(&key) { + if cx.build_script_outputs.lock().unwrap().contains_key(&key) { + // The output is already set, thus the build script is overridden. fingerprint::prepare_target(cx, unit, false) } else { build_work(cx, unit) @@ -233,7 +243,7 @@ fn build_work<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> CargoRes .collect::>() }; let pkg_name = unit.pkg.to_string(); - let build_state = Arc::clone(&cx.build_state); + let build_script_outputs = Arc::clone(&cx.build_script_outputs); let id = unit.pkg.package_id(); let output_file = script_run_dir.join("output"); let err_file = script_run_dir.join("stderr"); @@ -242,11 +252,11 @@ fn build_work<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> CargoRes let all = ( id, pkg_name.clone(), - Arc::clone(&build_state), + Arc::clone(&build_script_outputs), output_file.clone(), script_out_dir.clone(), ); - let build_scripts = super::load_build_deps(cx, unit); + let build_scripts = cx.build_scripts.get(unit).cloned(); let kind = unit.kind; let json_messages = bcx.build_config.emit_json(); let extra_verbose = bcx.config.extra_verbose(); @@ -279,17 +289,17 @@ fn build_work<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> CargoRes // dynamic library search path in case the build script depended on any // native dynamic libraries. if !build_plan { - let build_state = build_state.outputs.lock().unwrap(); + let build_script_outputs = build_script_outputs.lock().unwrap(); for (name, id) in lib_deps { let key = (id, kind); - let state = build_state.get(&key).ok_or_else(|| { + let script_output = build_script_outputs.get(&key).ok_or_else(|| { internal(format!( "failed to locate build state for env \ vars: {}/{:?}", id, kind )) })?; - let data = &state.metadata; + let data = &script_output.metadata; for &(ref key, ref value) in data.iter() { cmd.env( &format!("DEP_{}_{}", super::envify(&name), super::envify(key)), @@ -298,7 +308,12 @@ fn build_work<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> CargoRes } } if let Some(build_scripts) = build_scripts { - super::add_plugin_deps(&mut cmd, &build_state, &build_scripts, &host_target_root)?; + super::add_plugin_deps( + &mut cmd, + &build_script_outputs, + &build_scripts, + &host_target_root, + )?; } } @@ -346,7 +361,10 @@ fn build_work<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> CargoRes if json_messages { emit_build_output(state, &parsed_output, id); } - build_state.insert(id, kind, parsed_output); + build_script_outputs + .lock() + .unwrap() + .insert((id, kind), parsed_output); Ok(()) }); @@ -354,7 +372,7 @@ fn build_work<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> CargoRes // itself to run when we actually end up just discarding what we calculated // above. let fresh = Work::new(move |state| { - let (id, pkg_name, build_state, output_file, script_out_dir) = all; + let (id, pkg_name, build_script_outputs, output_file, script_out_dir) = all; let output = match prev_output { Some(output) => output, None => BuildOutput::parse_file( @@ -369,7 +387,10 @@ fn build_work<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> CargoRes emit_build_output(state, &output, id); } - build_state.insert(id, kind, output); + build_script_outputs + .lock() + .unwrap() + .insert((id, kind), output); Ok(()) }); @@ -386,25 +407,6 @@ fn build_work<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> CargoRes Ok(job) } -impl BuildState { - pub fn new(host_config: &TargetConfig, target_config: &TargetConfig) -> BuildState { - let mut overrides = HashMap::new(); - let i1 = host_config.overrides.iter().map(|p| (p, Kind::Host)); - let i2 = target_config.overrides.iter().map(|p| (p, Kind::Target)); - for ((name, output), kind) in i1.chain(i2) { - overrides.insert((name.clone(), kind), output.clone()); - } - BuildState { - outputs: Mutex::new(HashMap::new()), - overrides, - } - } - - fn insert(&self, id: PackageId, kind: Kind, output: BuildOutput) { - self.outputs.lock().unwrap().insert((id, kind), output); - } -} - impl BuildOutput { pub fn parse_file( path: &Path, @@ -471,6 +473,7 @@ impl BuildOutput { script_out_dir.to_str().unwrap(), ); + // Keep in sync with TargetConfig::new. match key { "rustc-flags" => { let (paths, links) = BuildOutput::parse_rustc_flags(&value, &whence)?; @@ -597,14 +600,21 @@ impl BuildDeps { } } -/// Computes the `build_scripts` map in the `Context` which tracks what build -/// scripts each package depends on. +/// Computes several maps in `Context`: +/// - `build_scripts`: A map that tracks which build scripts each package +/// depends on. +/// - `build_explicit_deps`: Dependency statements emitted by build scripts +/// from a previous run. +/// - `build_script_outputs`: Pre-populates this with any overridden build +/// scripts. /// -/// The global `build_scripts` map lists for all (package, kind) tuples what set -/// of packages' build script outputs must be considered. For example this lists -/// all dependencies' `-L` flags which need to be propagated transitively. +/// The important one here is `build_scripts`, which for each `(package, +/// kind)` stores a `BuildScripts` object which contains a list of +/// dependencies with build scripts that the unit should consider when +/// linking. For example this lists all dependencies' `-L` flags which need to +/// be propagated transitively. /// -/// The given set of targets to this function is the initial set of +/// The given set of units to this function is the initial set of /// targets/profiles which are being built. pub fn build_map<'b, 'cfg>(cx: &mut Context<'b, 'cfg>, units: &[Unit<'b>]) -> CargoResult<()> { let mut ret = HashMap::new(); @@ -628,20 +638,15 @@ pub fn build_map<'b, 'cfg>(cx: &mut Context<'b, 'cfg>, units: &[Unit<'b>]) -> Ca return Ok(&out[unit]); } - let key = unit - .pkg - .manifest() - .links() - .map(|l| (l.to_string(), unit.kind)); - let build_state = &cx.build_state; - if let Some(output) = key.and_then(|k| build_state.overrides.get(&k)) { - let key = (unit.pkg.package_id(), unit.kind); - cx.build_script_overridden.insert(key); - build_state - .outputs - .lock() - .unwrap() - .insert(key, output.clone()); + // If there is a build script override, pre-fill the build output. + if let Some(links) = unit.pkg.manifest().links() { + if let Some(output) = cx.bcx.script_override(links, unit.kind) { + let key = (unit.pkg.package_id(), unit.kind); + cx.build_script_outputs + .lock() + .unwrap() + .insert(key, output.clone()); + } } let mut ret = BuildScripts::default(); @@ -650,6 +655,7 @@ pub fn build_map<'b, 'cfg>(cx: &mut Context<'b, 'cfg>, units: &[Unit<'b>]) -> Ca add_to_link(&mut ret, unit.pkg.package_id(), unit.kind); } + // Load any dependency declarations from a previous run. if unit.mode.is_run_custom_build() { parse_previous_explicit_deps(cx, unit)?; } @@ -658,16 +664,16 @@ pub fn build_map<'b, 'cfg>(cx: &mut Context<'b, 'cfg>, units: &[Unit<'b>]) -> Ca // to rustc invocation caching schemes, so be sure to generate the same // set of build script dependency orderings via sorting the targets that // come out of the `Context`. - let mut targets = cx.dep_targets(unit); - targets.sort_by_key(|u| u.pkg.package_id()); + let mut dependencies = cx.dep_targets(unit); + dependencies.sort_by_key(|u| u.pkg.package_id()); - for unit in targets.iter() { - let dep_scripts = build(out, cx, unit)?; + for dep_unit in dependencies.iter() { + let dep_scripts = build(out, cx, dep_unit)?; - if unit.target.for_host() { + if dep_unit.target.for_host() { ret.plugins .extend(dep_scripts.to_link.iter().map(|p| &p.0).cloned()); - } else if unit.target.linkable() { + } else if dep_unit.target.linkable() { for &(pkg, kind) in dep_scripts.to_link.iter() { add_to_link(&mut ret, pkg, kind); } diff --git a/src/cargo/core/compiler/fingerprint.rs b/src/cargo/core/compiler/fingerprint.rs index 3ce3c04a0f4..e7cccc818f8 100644 --- a/src/cargo/core/compiler/fingerprint.rs +++ b/src/cargo/core/compiler/fingerprint.rs @@ -286,12 +286,12 @@ pub fn prepare_target<'a, 'cfg>( // build script's fingerprint after it's executed. We do this by // using the `build_script_local_fingerprints` function which returns a // thunk we can invoke on a foreign thread to calculate this. - let state = Arc::clone(&cx.build_state); + let build_script_outputs = Arc::clone(&cx.build_script_outputs); let key = (unit.pkg.package_id(), unit.kind); let (gen_local, _overridden) = build_script_local_fingerprints(cx, unit); let output_path = cx.build_explicit_deps[unit].build_script_output.clone(); Work::new(move |_| { - let outputs = state.outputs.lock().unwrap(); + let outputs = build_script_outputs.lock().unwrap(); let outputs = &outputs[&key]; let deps = BuildDeps::new(&output_path, Some(outputs)); @@ -1264,8 +1264,11 @@ fn build_script_override_fingerprint<'a, 'cfg>( cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>, ) -> Option { - let state = cx.build_state.outputs.lock().unwrap(); - let output = state.get(&(unit.pkg.package_id(), unit.kind))?; + // Build script output is only populated at this stage when it is + // overridden. + let build_script_outputs = cx.build_script_outputs.lock().unwrap(); + // Returns None if it is not overridden. + let output = build_script_outputs.get(&(unit.pkg.package_id(), unit.kind))?; let s = format!( "overridden build state with hash: {}", util::hash_u64(output) diff --git a/src/cargo/core/compiler/job_queue.rs b/src/cargo/core/compiler/job_queue.rs index 1b999be7f42..cea9e4e23db 100644 --- a/src/cargo/core/compiler/job_queue.rs +++ b/src/cargo/core/compiler/job_queue.rs @@ -534,9 +534,9 @@ impl<'a, 'cfg> JobQueue<'a, 'cfg> { unit: &Unit<'a>, cx: &mut Context<'_, '_>, ) -> CargoResult<()> { - let output = cx.build_state.outputs.lock().unwrap(); + let outputs = cx.build_script_outputs.lock().unwrap(); let bcx = &mut cx.bcx; - if let Some(output) = output.get(&(unit.pkg.package_id(), unit.kind)) { + if let Some(output) = outputs.get(&(unit.pkg.package_id(), unit.kind)) { if !output.warnings.is_empty() { if let Some(msg) = msg { writeln!(bcx.config.shell().err(), "{}\n", msg)?; diff --git a/src/cargo/core/compiler/mod.rs b/src/cargo/core/compiler/mod.rs index efe332a93eb..cf885e77595 100644 --- a/src/cargo/core/compiler/mod.rs +++ b/src/cargo/core/compiler/mod.rs @@ -29,7 +29,7 @@ pub use self::build_context::{BuildContext, FileFlavor, TargetConfig, TargetInfo use self::build_plan::BuildPlan; pub use self::compilation::{Compilation, Doctest}; pub use self::context::Context; -pub use self::custom_build::{BuildMap, BuildOutput, BuildScripts}; +pub use self::custom_build::{BuildOutput, BuildScriptOutputs, BuildScripts}; pub use self::job::Freshness; use self::job::{Job, Work}; use self::job_queue::{JobQueue, JobState}; @@ -192,9 +192,9 @@ fn rustc<'a, 'cfg>( let kind = unit.kind; // Prepare the native lib state (extra `-L` and `-l` flags). - let build_state = cx.build_state.clone(); + let build_script_outputs = Arc::clone(&cx.build_script_outputs); let current_id = unit.pkg.package_id(); - let build_deps = load_build_deps(cx, unit); + let build_scripts = cx.build_scripts.get(unit).cloned(); // If we are a binary and the package also contains a library, then we // don't pass the `-l` flags. @@ -242,20 +242,20 @@ fn rustc<'a, 'cfg>( // located somewhere in there. // Finally, if custom environment variables have been produced by // previous build scripts, we include them in the rustc invocation. - if let Some(build_deps) = build_deps { - let build_state = build_state.outputs.lock().unwrap(); + if let Some(build_scripts) = build_scripts { + let script_outputs = build_script_outputs.lock().unwrap(); if !build_plan { add_native_deps( &mut rustc, - &build_state, - &build_deps, + &script_outputs, + &build_scripts, pass_l_flag, pass_cdylib_link_args, current_id, )?; - add_plugin_deps(&mut rustc, &build_state, &build_deps, &root_output)?; + add_plugin_deps(&mut rustc, &script_outputs, &build_scripts, &root_output)?; } - add_custom_env(&mut rustc, &build_state, current_id, kind)?; + add_custom_env(&mut rustc, &script_outputs, current_id, kind)?; } for output in outputs.iter() { @@ -341,16 +341,16 @@ fn rustc<'a, 'cfg>( // present in `state`) to the command provided. fn add_native_deps( rustc: &mut ProcessBuilder, - build_state: &BuildMap, + build_script_outputs: &BuildScriptOutputs, build_scripts: &BuildScripts, pass_l_flag: bool, pass_cdylib_link_args: bool, current_id: PackageId, ) -> CargoResult<()> { for key in build_scripts.to_link.iter() { - let output = build_state.get(key).ok_or_else(|| { + let output = build_script_outputs.get(key).ok_or_else(|| { internal(format!( - "couldn't find build state for {}/{:?}", + "couldn't find build script output for {}/{:?}", key.0, key.1 )) })?; @@ -381,12 +381,12 @@ fn rustc<'a, 'cfg>( // been put there by one of the `build_scripts`) to the command provided. fn add_custom_env( rustc: &mut ProcessBuilder, - build_state: &BuildMap, + build_script_outputs: &BuildScriptOutputs, current_id: PackageId, kind: Kind, ) -> CargoResult<()> { let key = (current_id, kind); - if let Some(output) = build_state.get(&key) { + if let Some(output) = build_script_outputs.get(&key) { for &(ref name, ref value) in output.env.iter() { rustc.env(name, value); } @@ -522,16 +522,12 @@ fn hardlink_or_copy(src: &Path, dst: &Path) -> CargoResult<()> { Ok(()) } -fn load_build_deps(cx: &Context<'_, '_>, unit: &Unit<'_>) -> Option> { - cx.build_scripts.get(unit).cloned() -} - -// For all plugin dependencies, add their -L paths (now calculated and -// present in `state`) to the dynamic library load path for the command to -// execute. +// For all plugin dependencies, add their -L paths (now calculated and present +// in `build_script_outputs`) to the dynamic library load path for the command +// to execute. fn add_plugin_deps( rustc: &mut ProcessBuilder, - build_state: &BuildMap, + build_script_outputs: &BuildScriptOutputs, build_scripts: &BuildScripts, root_output: &PathBuf, ) -> CargoResult<()> { @@ -539,7 +535,7 @@ fn add_plugin_deps( let search_path = rustc.get_env(var).unwrap_or_default(); let mut search_path = env::split_paths(&search_path).collect::>(); for &id in build_scripts.plugins.iter() { - let output = build_state + let output = build_script_outputs .get(&(id, Kind::Host)) .ok_or_else(|| internal(format!("couldn't find libs for plugin dep {}", id)))?; search_path.append(&mut filter_dynamic_search_path( @@ -645,14 +641,14 @@ fn rustdoc<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> CargoResult rustdoc.args(bcx.rustdocflags_args(unit)); let name = unit.pkg.name().to_string(); - let build_state = cx.build_state.clone(); + let build_script_outputs = Arc::clone(&cx.build_script_outputs); let key = (unit.pkg.package_id(), unit.kind); let package_id = unit.pkg.package_id(); let target = unit.target.clone(); let mut output_options = OutputOptions::new(cx, unit); Ok(Work::new(move |state| { - if let Some(output) = build_state.outputs.lock().unwrap().get(&key) { + if let Some(output) = build_script_outputs.lock().unwrap().get(&key) { for cfg in output.cfgs.iter() { rustdoc.arg("--cfg").arg(cfg); } diff --git a/src/cargo/core/compiler/output_depinfo.rs b/src/cargo/core/compiler/output_depinfo.rs index 86cb7b2180d..a7acc8c4e08 100644 --- a/src/cargo/core/compiler/output_depinfo.rs +++ b/src/cargo/core/compiler/output_depinfo.rs @@ -59,7 +59,7 @@ fn add_deps_for_unit<'a, 'b>( // Add rerun-if-changed dependencies let key = (unit.pkg.package_id(), unit.kind); - if let Some(output) = context.build_state.outputs.lock().unwrap().get(&key) { + if let Some(output) = context.build_script_outputs.lock().unwrap().get(&key) { for path in &output.rerun_if_changed { deps.insert(path.into()); } diff --git a/src/cargo/core/manifest.rs b/src/cargo/core/manifest.rs index 2c57c9e4a43..acda0e5700b 100644 --- a/src/cargo/core/manifest.rs +++ b/src/cargo/core/manifest.rs @@ -761,6 +761,7 @@ impl Target { pub fn documented(&self) -> bool { self.doc } + // A plugin, proc-macro, or build-script. pub fn for_host(&self) -> bool { self.for_host }