From 7de30dd21a6b78c718c9ee88b661bd0575542884 Mon Sep 17 00:00:00 2001 From: Ximin Luo Date: Mon, 29 Jan 2018 05:03:51 +0100 Subject: [PATCH] Don't check for dev-dependencies when not needed --- src/cargo/core/resolver/mod.rs | 21 +++++++++++++++++--- src/cargo/ops/cargo_compile.rs | 28 ++++++++++++++++++++------- src/cargo/ops/mod.rs | 2 +- src/cargo/ops/resolve.rs | 35 ++++++++++++++++++---------------- 4 files changed, 59 insertions(+), 27 deletions(-) diff --git a/src/cargo/core/resolver/mod.rs b/src/cargo/core/resolver/mod.rs index dc109191d0b..7b33cba2cd4 100644 --- a/src/cargo/core/resolver/mod.rs +++ b/src/cargo/core/resolver/mod.rs @@ -96,14 +96,26 @@ pub struct DepsNotReplaced<'a> { #[derive(Clone, Copy)] pub enum Method<'a> { - Everything, + Everything, // equivalent to Required { dev_deps: true, all_features: true, .. } Required { dev_deps: bool, features: &'a [String], + all_features: bool, uses_default_features: bool, }, } +impl<'r> Method<'r> { + pub fn split_features(features: &[String]) -> Vec { + features.iter() + .flat_map(|s| s.split_whitespace()) + .flat_map(|s| s.split(',')) + .filter(|s| !s.is_empty()) + .map(|s| s.to_string()) + .collect::>() + } +} + // Information about the dependencies for a crate, a tuple of: // // (dependency info, candidates, features activated) @@ -731,6 +743,7 @@ fn activate_deps_loop<'a>(mut cx: Context<'a>, let method = Method::Required { dev_deps: false, features: &features, + all_features: false, uses_default_features: dep.uses_default_features(), }; trace!("{}[{}]>{} trying {}", parent.name(), cur, dep.name(), @@ -1006,7 +1019,8 @@ fn build_requirements<'a, 'b: 'a>(s: &'a Summary, method: &'b Method) -> CargoResult> { let mut reqs = Requirements::new(s); match *method { - Method::Everything => { + Method::Everything | + Method::Required { all_features: true, .. } => { for key in s.features().keys() { reqs.require_feature(key)?; } @@ -1052,10 +1066,11 @@ impl<'a> Context<'a> { } debug!("checking if {} is already activated", summary.package_id()); let (features, use_default) = match *method { + Method::Everything | + Method::Required { all_features: true, .. } => return false, Method::Required { features, uses_default_features, .. } => { (features, uses_default_features) } - Method::Everything => return false, }; let has_default_feature = summary.features().contains_key("default"); diff --git a/src/cargo/ops/cargo_compile.rs b/src/cargo/ops/cargo_compile.rs index cc3400268f9..a212a64552e 100644 --- a/src/cargo/ops/cargo_compile.rs +++ b/src/cargo/ops/cargo_compile.rs @@ -29,7 +29,7 @@ use std::sync::Arc; use core::{Source, Package, Target}; use core::{Profile, TargetKind, Profiles, Workspace, PackageId, PackageIdSpec}; -use core::resolver::Resolve; +use core::resolver::{Resolve, Method}; use ops::{self, BuildOutput, Executor, DefaultExecutor}; use util::config::Config; use util::{CargoResult, profile}; @@ -226,12 +226,18 @@ pub fn compile_ws<'a>(ws: &Workspace<'a>, let profiles = ws.profiles(); let specs = spec.into_package_id_specs(ws)?; - let resolve = ops::resolve_ws_precisely(ws, - source, - features, - all_features, - no_default_features, - &specs)?; + let features = Method::split_features(features); + let method = Method::Required { + dev_deps: filter.need_dev_deps(), + features: &features, + all_features, + uses_default_features: !no_default_features, + }; + let resolve = ops::resolve_ws_with_method(ws, + source, + method, + &specs, + )?; let (packages, resolve_with_overrides) = resolve; if specs.is_empty() { @@ -413,6 +419,14 @@ impl<'a> CompileFilter<'a> { } } + pub fn need_dev_deps(&self) -> bool { + match *self { + CompileFilter::Default { .. } => true, + CompileFilter::Only { examples, tests, benches, .. } => + examples.is_specific() || tests.is_specific() || benches.is_specific() + } + } + pub fn matches(&self, target: &Target) -> bool { match *self { CompileFilter::Default { .. } => true, diff --git a/src/cargo/ops/mod.rs b/src/cargo/ops/mod.rs index 7c4a33d4ba2..5da0781ec87 100644 --- a/src/cargo/ops/mod.rs +++ b/src/cargo/ops/mod.rs @@ -22,7 +22,7 @@ pub use self::registry::{modify_owners, yank, OwnersOptions, PublishOpts}; pub use self::registry::configure_http_handle; pub use self::cargo_fetch::fetch; pub use self::cargo_pkgid::pkgid; -pub use self::resolve::{resolve_ws, resolve_ws_precisely, resolve_with_previous}; +pub use self::resolve::{resolve_ws, resolve_ws_precisely, resolve_ws_with_method, resolve_with_previous}; pub use self::cargo_output_metadata::{output_metadata, OutputMetadataOptions, ExportInfo}; mod cargo_clean; diff --git a/src/cargo/ops/resolve.rs b/src/cargo/ops/resolve.rs index 8a49de85dc4..7a2c3d48bca 100644 --- a/src/cargo/ops/resolve.rs +++ b/src/cargo/ops/resolve.rs @@ -29,13 +29,25 @@ pub fn resolve_ws_precisely<'a>(ws: &Workspace<'a>, no_default_features: bool, specs: &[PackageIdSpec]) -> CargoResult<(PackageSet<'a>, Resolve)> { - let features = features.iter() - .flat_map(|s| s.split_whitespace()) - .flat_map(|s| s.split(',')) - .filter(|s| !s.is_empty()) - .map(|s| s.to_string()) - .collect::>(); + let features = Method::split_features(features); + let method = if all_features { + Method::Everything + } else { + Method::Required { + dev_deps: true, + features: &features, + all_features: false, + uses_default_features: !no_default_features, + } + }; + resolve_ws_with_method(ws, source, method, specs) +} +pub fn resolve_ws_with_method<'a>(ws: &Workspace<'a>, + source: Option>, + method: Method, + specs: &[PackageIdSpec]) + -> CargoResult<(PackageSet<'a>, Resolve)> { let mut registry = PackageRegistry::new(ws.config())?; if let Some(source) = source { registry.add_preloaded(source); @@ -68,16 +80,6 @@ pub fn resolve_ws_precisely<'a>(ws: &Workspace<'a>, None }; - let method = if all_features { - Method::Everything - } else { - Method::Required { - dev_deps: true, // TODO: remove this option? - features: &features, - uses_default_features: !no_default_features, - } - }; - let resolved_with_overrides = ops::resolve_with_previous(&mut registry, ws, @@ -236,6 +238,7 @@ pub fn resolve_with_previous<'a>(registry: &mut PackageRegistry, let base = Method::Required { dev_deps: dev_deps, features: &[], + all_features: false, uses_default_features: true, }; let member_id = member.package_id();