Skip to content

Commit d14e1df

Browse files
committed
feat: implement workspace feature unification
1 parent 2928e32 commit d14e1df

File tree

5 files changed

+140
-5
lines changed

5 files changed

+140
-5
lines changed

src/cargo/core/workspace.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -307,9 +307,10 @@ impl<'gctx> Workspace<'gctx> {
307307
}
308308
}
309309
}
310-
if let CargoResolverConfig {
311-
incompatible_rust_versions: Some(incompatible_rust_versions),
312-
} = self.gctx().get::<CargoResolverConfig>("resolver")?
310+
if let Some(incompatible_rust_versions) = self
311+
.gctx()
312+
.get::<CargoResolverConfig>("resolver")?
313+
.incompatible_rust_versions
313314
{
314315
self.resolve_honors_rust_version =
315316
incompatible_rust_versions == IncompatibleRustVersions::Fallback;

src/cargo/ops/cargo_compile/mod.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,9 @@ use crate::core::{PackageId, PackageSet, SourceId, TargetKind, Workspace};
5252
use crate::drop_println;
5353
use crate::ops;
5454
use crate::ops::resolve::WorkspaceResolve;
55-
use crate::util::context::{GlobalContext, WarningHandling};
55+
use crate::util::context::{
56+
CargoResolverConfig, FeatureUnification, GlobalContext, WarningHandling,
57+
};
5658
use crate::util::interning::InternedString;
5759
use crate::util::{CargoResult, StableHasher};
5860

@@ -272,13 +274,23 @@ pub fn create_bcx<'a, 'gctx>(
272274
HasDevUnits::No
273275
}
274276
};
277+
let feature_unification = ws
278+
.gctx()
279+
.get::<CargoResolverConfig>("resolver")?
280+
.feature_unification
281+
.unwrap_or_default();
282+
let resolve_specs = if let FeatureUnification::Workspace = feature_unification {
283+
&Packages::All(Vec::new()).to_package_id_specs(ws)?
284+
} else {
285+
&specs
286+
};
275287
let dry_run = false;
276288
let resolve = ops::resolve_ws_with_opts(
277289
ws,
278290
&mut target_data,
279291
&build_config.requested_kinds,
280292
cli_features,
281-
&specs,
293+
resolve_specs,
282294
has_dev_units,
283295
crate::core::resolver::features::ForceAllTargets::No,
284296
dry_run,

src/cargo/util/context/mod.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2745,6 +2745,7 @@ impl BuildTargetConfig {
27452745
#[serde(rename_all = "kebab-case")]
27462746
pub struct CargoResolverConfig {
27472747
pub incompatible_rust_versions: Option<IncompatibleRustVersions>,
2748+
pub feature_unification: Option<FeatureUnification>,
27482749
}
27492750

27502751
#[derive(Debug, Deserialize, PartialEq, Eq)]
@@ -2754,6 +2755,14 @@ pub enum IncompatibleRustVersions {
27542755
Fallback,
27552756
}
27562757

2758+
#[derive(Debug, Default, Deserialize)]
2759+
#[serde(rename_all = "kebab-case")]
2760+
pub enum FeatureUnification {
2761+
#[default]
2762+
Selected,
2763+
Workspace,
2764+
}
2765+
27572766
#[derive(Deserialize, Default)]
27582767
#[serde(rename_all = "kebab-case")]
27592768
pub struct TermConfig {
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
//! Tests for workspace feature unification.
2+
3+
use cargo_test_support::prelude::*;
4+
use cargo_test_support::{project, str};
5+
6+
#[cargo_test]
7+
fn feature_unification() {
8+
let p = project()
9+
.file(
10+
".cargo/config.toml",
11+
r#"
12+
[resolver]
13+
feature-unification = "workspace"
14+
"#,
15+
)
16+
.file(
17+
"Cargo.toml",
18+
r#"
19+
[workspace]
20+
resolver = "2"
21+
members = ["common", "ab", "bc"]
22+
"#,
23+
)
24+
.file(
25+
"common/Cargo.toml",
26+
r#"
27+
[package]
28+
name = "common"
29+
version = "0.1.0"
30+
edition = "2021"
31+
32+
[features]
33+
a = []
34+
b = []
35+
c = []
36+
"#,
37+
)
38+
.file(
39+
"common/src/lib.rs",
40+
r#"
41+
pub fn features() {
42+
#[cfg(feature = "a")]
43+
print!("a");
44+
#[cfg(feature = "b")]
45+
print!("b");
46+
#[cfg(feature = "c")]
47+
print!("c");
48+
}
49+
"#,
50+
)
51+
.file(
52+
"ab/Cargo.toml",
53+
r#"
54+
[package]
55+
name = "ab"
56+
version = "0.1.0"
57+
edition = "2021"
58+
59+
[dependencies]
60+
common = { path = "../common", features = ["a", "b"] }
61+
"#,
62+
)
63+
.file("ab/src/main.rs", "fn main() { common::features(); }")
64+
.file(
65+
"bc/Cargo.toml",
66+
r#"
67+
[package]
68+
name = "bc"
69+
version = "0.1.0"
70+
edition = "2021"
71+
72+
[dependencies]
73+
common = { path = "../common", features = ["b", "c"] }
74+
"#,
75+
)
76+
.file("bc/src/main.rs", "fn main() { common::features(); }")
77+
.build();
78+
79+
p.cargo("build -p common")
80+
.with_stderr_data(str![[r#"
81+
[COMPILING] common v0.1.0 ([ROOT]/foo/common)
82+
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
83+
84+
"#]])
85+
.run();
86+
87+
// `common` should not be rebuilt when building `ab` or `bc`
88+
p.cargo("build -p ab")
89+
.with_stderr_data(str![[r#"
90+
[COMPILING] ab v0.1.0 ([ROOT]/foo/ab)
91+
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
92+
93+
"#]])
94+
.run();
95+
p.cargo("build -p bc")
96+
.with_stderr_data(str![[r#"
97+
[COMPILING] bc v0.1.0 ([ROOT]/foo/bc)
98+
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
99+
100+
"#]])
101+
.run();
102+
103+
p.cargo("build --workspace")
104+
.with_stderr_data(str![[r#"
105+
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
106+
107+
"#]])
108+
.run();
109+
110+
p.process(&p.bin("ab")).with_stdout_data(str!["abc"]).run();
111+
p.process(&p.bin("bc")).with_stdout_data(str!["abc"]).run();
112+
}

tests/testsuite/main.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ mod doc;
8585
mod docscrape;
8686
mod edition;
8787
mod error;
88+
mod feature_unification;
8889
mod features;
8990
mod features2;
9091
mod features_namespaced;

0 commit comments

Comments
 (0)