-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Feature dependencies #2325
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature dependencies #2325
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,7 +22,7 @@ | |
//! previously compiled dependency | ||
//! | ||
|
||
use std::collections::HashMap; | ||
use std::collections::{HashMap, HashSet}; | ||
use std::default::Default; | ||
use std::path::{Path, PathBuf}; | ||
use std::sync::Arc; | ||
|
@@ -155,6 +155,11 @@ pub fn compile_pkg<'a>(root_package: &Package, | |
s.split(' ') | ||
}).map(|s| s.to_string()).collect::<Vec<String>>(); | ||
|
||
if spec.len() > 0 && (no_default_features || features.len() > 0) { | ||
bail!("features cannot be modified when the main package \ | ||
is not being built"); | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah this was removed in 3332c91, so perhaps a rebase brought it back in by accident? |
||
|
||
if jobs == Some(0) { | ||
bail!("jobs must be at least 1") | ||
} | ||
|
@@ -194,8 +199,9 @@ pub fn compile_pkg<'a>(root_package: &Package, | |
panic!("`rustc` and `rustdoc` should not accept multiple `-p` flags") | ||
} | ||
(Some(args), _) => { | ||
let all_features = resolve_with_overrides.features(to_builds[0].package_id()); | ||
let targets = try!(generate_targets(to_builds[0], profiles, | ||
mode, filter, release)); | ||
mode, filter, all_features, release)); | ||
if targets.len() == 1 { | ||
let (target, profile) = targets[0]; | ||
let mut profile = profile.clone(); | ||
|
@@ -208,8 +214,9 @@ pub fn compile_pkg<'a>(root_package: &Package, | |
} | ||
} | ||
(None, Some(args)) => { | ||
let all_features = resolve_with_overrides.features(to_builds[0].package_id()); | ||
let targets = try!(generate_targets(to_builds[0], profiles, | ||
mode, filter, release)); | ||
mode, filter, all_features, release)); | ||
if targets.len() == 1 { | ||
let (target, profile) = targets[0]; | ||
let mut profile = profile.clone(); | ||
|
@@ -223,8 +230,9 @@ pub fn compile_pkg<'a>(root_package: &Package, | |
} | ||
(None, None) => { | ||
for &to_build in to_builds.iter() { | ||
let all_features = resolve_with_overrides.features(to_build.package_id()); | ||
let targets = try!(generate_targets(to_build, profiles, mode, | ||
filter, release)); | ||
filter, all_features, release)); | ||
package_targets.push((to_build, targets)); | ||
} | ||
} | ||
|
@@ -301,6 +309,7 @@ fn generate_targets<'a>(pkg: &'a Package, | |
profiles: &'a Profiles, | ||
mode: CompileMode, | ||
filter: &CompileFilter, | ||
features: Option<&HashSet<String>>, | ||
release: bool) | ||
-> CargoResult<Vec<(&'a Target, &'a Profile)>> { | ||
let build = if release {&profiles.release} else {&profiles.dev}; | ||
|
@@ -311,13 +320,13 @@ fn generate_targets<'a>(pkg: &'a Package, | |
CompileMode::Build => build, | ||
CompileMode::Doc { .. } => &profiles.doc, | ||
}; | ||
match *filter { | ||
let mut targets = match *filter { | ||
CompileFilter::Everything => { | ||
match mode { | ||
CompileMode::Bench => { | ||
Ok(pkg.targets().iter().filter(|t| t.benched()).map(|t| { | ||
pkg.targets().iter().filter(|t| t.benched()).map(|t| { | ||
(t, profile) | ||
}).collect::<Vec<_>>()) | ||
}).collect::<Vec<_>>() | ||
} | ||
CompileMode::Test => { | ||
let mut base = pkg.targets().iter().filter(|t| { | ||
|
@@ -333,16 +342,16 @@ fn generate_targets<'a>(pkg: &'a Package, | |
base.push((t, build)); | ||
} | ||
} | ||
Ok(base) | ||
base | ||
} | ||
CompileMode::Build => { | ||
Ok(pkg.targets().iter().filter(|t| { | ||
pkg.targets().iter().filter(|t| { | ||
t.is_bin() || t.is_lib() | ||
}).map(|t| (t, profile)).collect()) | ||
}).map(|t| (t, profile)).collect() | ||
} | ||
CompileMode::Doc { .. } => { | ||
Ok(pkg.targets().iter().filter(|t| t.documented()) | ||
.map(|t| (t, profile)).collect()) | ||
pkg.targets().iter().filter(|t| t.documented()) | ||
.map(|t| (t, profile)).collect() | ||
} | ||
} | ||
} | ||
|
@@ -377,9 +386,19 @@ fn generate_targets<'a>(pkg: &'a Package, | |
try!(find(tests, "test", TargetKind::Test, test)); | ||
try!(find(benches, "bench", TargetKind::Bench, &profiles.bench)); | ||
} | ||
Ok(targets) | ||
targets | ||
} | ||
} | ||
}; | ||
|
||
targets.retain(|&(t, _)| { | ||
t.is_lib() || | ||
t.features().is_none() || | ||
t.features().unwrap().iter().filter(|&f| { | ||
features.map_or(true, |x| !x.contains(f)) | ||
}).count() == 0 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It probably doesn't make sense to have lib targets with features, so can that be prevented during decoding of a manifest? That means this could look like: match t.features() {
Some(f) => f.iter().any(|f| features.contains(f))
None => true,
} (or something like that). In general I'd recommend avoiding patterns like:
|
||
}); | ||
|
||
Ok(targets) | ||
} | ||
|
||
/// Read the `paths` configuration variable to discover all path overrides that | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
use support::{project, execs}; | ||
use hamcrest::{assert_that, existing_file, not}; | ||
|
||
fn setup() { | ||
} | ||
|
||
test!(compile_simple_feature_deps { | ||
let p = project("foo") | ||
.file("Cargo.toml", r#" | ||
[project] | ||
name = "foo" | ||
version = "0.0.1" | ||
authors = [] | ||
|
||
[features] | ||
default = ["a"] | ||
a = [] | ||
|
||
[[bin]] | ||
name = "foo" | ||
features = ["a"] | ||
"#) | ||
.file("src/main.rs", "fn main() {}"); | ||
|
||
assert_that(p.cargo_process("build"), | ||
execs().with_status(0)); | ||
|
||
assert_that(&p.bin("foo"), existing_file()); | ||
|
||
assert_that(p.cargo_process("build").arg("--no-default-features"), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Currently the |
||
execs().with_status(0)); | ||
|
||
assert_that(&p.bin("foo"), not(existing_file())); | ||
}); | ||
|
||
test!(compile_simple_feature_deps_args { | ||
let p = project("foo") | ||
.file("Cargo.toml", r#" | ||
[project] | ||
name = "foo" | ||
version = "0.0.1" | ||
authors = [] | ||
|
||
[features] | ||
a = [] | ||
|
||
[[bin]] | ||
name = "foo" | ||
features = ["a"] | ||
"#) | ||
.file("src/main.rs", "fn main() {}"); | ||
|
||
assert_that(p.cargo_process("build").arg("--features").arg("a"), | ||
execs().with_status(0)); | ||
|
||
assert_that(&p.bin("foo"), existing_file()); | ||
}); | ||
|
||
test!(compile_multiple_feature_deps { | ||
let p = project("foo") | ||
.file("Cargo.toml", r#" | ||
[project] | ||
name = "foo" | ||
version = "0.0.1" | ||
authors = [] | ||
|
||
[features] | ||
default = ["a", "b"] | ||
a = [] | ||
b = ["a"] | ||
c = [] | ||
|
||
[[bin]] | ||
name = "foo_1" | ||
path = "src/foo_1.rs" | ||
features = ["b", "c"] | ||
|
||
[[bin]] | ||
name = "foo_2" | ||
path = "src/foo_2.rs" | ||
features = ["a"] | ||
"#) | ||
.file("src/foo_1.rs", "fn main() {}") | ||
.file("src/foo_2.rs", "fn main() {}"); | ||
|
||
assert_that(p.cargo_process("build"), | ||
execs().with_status(0)); | ||
|
||
assert_that(&p.bin("foo_1"), not(existing_file())); | ||
assert_that(&p.bin("foo_2"), existing_file()); | ||
|
||
assert_that(p.cargo_process("build").arg("--features").arg("c"), | ||
execs().with_status(0)); | ||
|
||
assert_that(&p.bin("foo_1"), existing_file()); | ||
assert_that(&p.bin("foo_2"), existing_file()); | ||
|
||
assert_that(p.cargo_process("build").arg("--no-default-features"), | ||
execs().with_status(0)); | ||
|
||
assert_that(&p.bin("foo_1"), not(existing_file())); | ||
assert_that(&p.bin("foo_2"), not(existing_file())); | ||
}); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could this change to returning
Option<&[T]>
instead ofOption<&Vec<T>>
? (generally a little more ergonomic)