Skip to content

Commit 038eec5

Browse files
committed
Enable new behavior of --feature
1 parent 5ac4ab1 commit 038eec5

File tree

6 files changed

+50
-144
lines changed

6 files changed

+50
-144
lines changed

src/cargo/core/features.rs

-2
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,6 @@ pub struct CliUnstable {
292292
pub no_index_update: bool,
293293
pub avoid_dev_deps: bool,
294294
pub minimal_versions: bool,
295-
pub package_features: bool,
296295
}
297296

298297
impl CliUnstable {
@@ -326,7 +325,6 @@ impl CliUnstable {
326325
"no-index-update" => self.no_index_update = true,
327326
"avoid-dev-deps" => self.avoid_dev_deps = true,
328327
"minimal-versions" => self.minimal_versions = true,
329-
"package-features" => self.package_features = true,
330328
_ => bail!("unknown `-Z` flag specified: {}", k),
331329
}
332330

src/cargo/core/resolver/types.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ impl<'a> RegistryQueryer<'a> {
155155
}
156156
}
157157

158-
#[derive(Clone, Copy)]
158+
#[derive(Clone, Copy, Eq, PartialEq)]
159159
pub enum Method<'a> {
160160
Everything, // equivalent to Required { dev_deps: true, all_features: true, .. }
161161
Required {

src/cargo/core/workspace.rs

+1
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ pub struct WorkspaceRootConfig {
117117

118118
/// An iterator over the member packages of a workspace, returned by
119119
/// `Workspace::members`
120+
#[derive(Clone)]
120121
pub struct Members<'a, 'cfg: 'a> {
121122
ws: &'a Workspace<'cfg>,
122123
iter: slice::Iter<'a, PathBuf>,

src/cargo/ops/resolve.rs

+31-74
Original file line numberDiff line numberDiff line change
@@ -217,86 +217,43 @@ pub fn resolve_with_previous<'a, 'cfg>(
217217
registry.add_sources(&[member.package_id().source_id().clone()])?;
218218
}
219219

220-
let mut summaries = Vec::new();
221-
if ws.config().cli_unstable().package_features {
222-
let mut members = Vec::new();
223-
match method {
224-
Method::Everything => members.extend(ws.members()),
225-
Method::Required {
226-
features,
227-
all_features,
228-
uses_default_features,
229-
..
230-
} => {
231-
if specs.len() > 1 && !features.is_empty() {
232-
bail!("cannot specify features for more than one package");
233-
}
234-
members.extend(
235-
ws.members()
236-
.filter(|m| specs.iter().any(|spec| spec.matches(m.package_id()))),
237-
);
220+
let method = match method {
221+
Method::Everything => Method::Everything,
222+
Method::Required {
223+
features,
224+
all_features,
225+
uses_default_features,
226+
..
227+
} => {
228+
if specs.len() > 1 && !features.is_empty() {
229+
bail!("cannot specify features for more than one package");
230+
}
231+
let members_requested = ws.members()
232+
.filter(|m| specs.iter().any(|spec| spec.matches(m.package_id())))
233+
.count();
234+
if members_requested == 0 {
238235
// Edge case: running `cargo build -p foo`, where `foo` is not a member
239-
// of current workspace. Add all packages from workspace to get `foo`
240-
// into the resolution graph.
241-
if members.is_empty() {
242-
if !(features.is_empty() && !all_features && uses_default_features) {
243-
bail!("cannot specify features for packages outside of workspace");
244-
}
245-
members.extend(ws.members());
236+
// of current workspace. Resolve whole workspace to get `foo` into the
237+
// resolution graph.
238+
if !(features.is_empty() && !all_features && uses_default_features) {
239+
bail!("cannot specify features for packages outside of workspace");
246240
}
241+
Method::Everything
242+
} else {
243+
method
247244
}
248245
}
249-
for member in members {
250-
let summary = registry.lock(member.summary().clone());
251-
summaries.push((summary, method))
252-
}
253-
} else {
254-
for member in ws.members() {
255-
let method_to_resolve = match method {
256-
// When everything for a workspace we want to be sure to resolve all
257-
// members in the workspace, so propagate the `Method::Everything`.
258-
Method::Everything => Method::Everything,
259-
260-
// If we're not resolving everything though then we're constructing the
261-
// exact crate graph we're going to build. Here we don't necessarily
262-
// want to keep around all workspace crates as they may not all be
263-
// built/tested.
264-
//
265-
// Additionally, the `method` specified represents command line
266-
// flags, which really only matters for the current package
267-
// (determined by the cwd). If other packages are specified (via
268-
// `-p`) then the command line flags like features don't apply to
269-
// them.
270-
//
271-
// As a result, if this `member` is the current member of the
272-
// workspace, then we use `method` specified. Otherwise we use a
273-
// base method with no features specified but using default features
274-
// for any other packages specified with `-p`.
275-
Method::Required { dev_deps, .. } => {
276-
let base = Method::Required {
277-
dev_deps,
278-
features: &[],
279-
all_features: false,
280-
uses_default_features: true,
281-
};
282-
let member_id = member.package_id();
283-
match ws.current_opt() {
284-
Some(current) if member_id == current.package_id() => method,
285-
_ => {
286-
if specs.iter().any(|spec| spec.matches(member_id)) {
287-
base
288-
} else {
289-
continue;
290-
}
291-
}
292-
}
293-
}
294-
};
246+
};
295247

248+
let summaries = ws.members()
249+
.filter(|m| {
250+
method == Method::Everything || specs.iter().any(|spec| spec.matches(m.package_id()))
251+
})
252+
.map(|member| {
296253
let summary = registry.lock(member.summary().clone());
297-
summaries.push((summary, method_to_resolve));
298-
}
299-
};
254+
(summary, method)
255+
})
256+
.collect::<Vec<_>>();
300257

301258
let root_replace = ws.root_replace();
302259

tests/testsuite/features.rs

+12-16
Original file line numberDiff line numberDiff line change
@@ -1674,46 +1674,42 @@ fn combining_features_and_package() {
16741674
.build();
16751675

16761676
assert_that(
1677-
p.cargo("build -Z package-features --all --features main")
1677+
p.cargo("build --all --features main")
16781678
.masquerade_as_nightly_cargo(),
1679-
execs().with_status(101).with_stderr_contains(
1680-
"\
1681-
[ERROR] cannot specify features for more than one package",
1682-
),
1679+
execs()
1680+
.with_status(101)
1681+
.with_stderr_contains("[ERROR] cannot specify features for more than one package"),
16831682
);
16841683

16851684
assert_that(
1686-
p.cargo("build -Z package-features --package dep --features main")
1685+
p.cargo("build --package dep --features main")
16871686
.masquerade_as_nightly_cargo(),
16881687
execs().with_status(101).with_stderr_contains(
1689-
"\
1690-
[ERROR] cannot specify features for packages outside of workspace",
1688+
"[ERROR] cannot specify features for packages outside of workspace",
16911689
),
16921690
);
16931691
assert_that(
1694-
p.cargo("build -Z package-features --package dep --all-features")
1692+
p.cargo("build --package dep --all-features")
16951693
.masquerade_as_nightly_cargo(),
16961694
execs().with_status(101).with_stderr_contains(
1697-
"\
1698-
[ERROR] cannot specify features for packages outside of workspace",
1695+
"[ERROR] cannot specify features for packages outside of workspace",
16991696
),
17001697
);
17011698
assert_that(
1702-
p.cargo("build -Z package-features --package dep --no-default-features")
1699+
p.cargo("build --package dep --no-default-features")
17031700
.masquerade_as_nightly_cargo(),
17041701
execs().with_status(101).with_stderr_contains(
1705-
"\
1706-
[ERROR] cannot specify features for packages outside of workspace",
1702+
"[ERROR] cannot specify features for packages outside of workspace",
17071703
),
17081704
);
17091705

17101706
assert_that(
1711-
p.cargo("build -Z package-features --all --all-features")
1707+
p.cargo("build --all --all-features")
17121708
.masquerade_as_nightly_cargo(),
17131709
execs().with_status(0),
17141710
);
17151711
assert_that(
1716-
p.cargo("run -Z package-features --package foo --features main")
1712+
p.cargo("run --package foo --features main")
17171713
.masquerade_as_nightly_cargo(),
17181714
execs().with_status(0),
17191715
);

tests/testsuite/test.rs

+5-51
Original file line numberDiff line numberDiff line change
@@ -2867,13 +2867,7 @@ fn selective_test_optional_dep() {
28672867
let p = p.build();
28682868

28692869
assert_that(
2870-
p.cargo("test")
2871-
.arg("-v")
2872-
.arg("--no-run")
2873-
.arg("--features")
2874-
.arg("a")
2875-
.arg("-p")
2876-
.arg("a"),
2870+
p.cargo("test -v --no-run --package a"),
28772871
execs().with_status(0).with_stderr(
28782872
"\
28792873
[COMPILING] a v0.0.1 ([..])
@@ -3060,6 +3054,8 @@ fn pass_correct_cfgs_flags_to_rustdoc() {
30603054
version = "0.1.0"
30613055
authors = []
30623056
3057+
[workspace]
3058+
30633059
[features]
30643060
default = ["feature_a/default"]
30653061
nightly = ["feature_a/nightly"]
@@ -3137,10 +3133,7 @@ fn pass_correct_cfgs_flags_to_rustdoc() {
31373133
let p = p.build();
31383134

31393135
assert_that(
3140-
p.cargo("test")
3141-
.arg("--package")
3142-
.arg("feature_a")
3143-
.arg("--verbose"),
3136+
p.cargo("test --package feature_a --verbose"),
31443137
execs().with_status(0).with_stderr_contains(
31453138
"\
31463139
[DOCTEST] feature_a
@@ -3149,7 +3142,7 @@ fn pass_correct_cfgs_flags_to_rustdoc() {
31493142
);
31503143

31513144
assert_that(
3152-
p.cargo("test").arg("--verbose"),
3145+
p.cargo("test --verbose"),
31533146
execs().with_status(0).with_stderr_contains(
31543147
"\
31553148
[DOCTEST] foo
@@ -3199,45 +3192,6 @@ fn test_release_ignore_panic() {
31993192
assert_that(p.cargo("bench").arg("-v"), execs().with_status(0));
32003193
}
32013194

3202-
#[test]
3203-
fn test_many_with_features() {
3204-
let p = project("foo")
3205-
.file(
3206-
"Cargo.toml",
3207-
r#"
3208-
[package]
3209-
name = "foo"
3210-
version = "0.0.1"
3211-
authors = []
3212-
3213-
[dependencies]
3214-
a = { path = "a" }
3215-
3216-
[features]
3217-
foo = []
3218-
3219-
[workspace]
3220-
"#,
3221-
)
3222-
.file("src/lib.rs", "")
3223-
.file(
3224-
"a/Cargo.toml",
3225-
r#"
3226-
[package]
3227-
name = "a"
3228-
version = "0.0.1"
3229-
authors = []
3230-
"#,
3231-
)
3232-
.file("a/src/lib.rs", "")
3233-
.build();
3234-
3235-
assert_that(
3236-
p.cargo("test -v -p a -p foo --features foo"),
3237-
execs().with_status(0),
3238-
);
3239-
}
3240-
32413195
#[test]
32423196
fn test_all_workspace() {
32433197
let p = project("foo")

0 commit comments

Comments
 (0)