-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Description
Problem
It appears that cargo regressed on #4866 -- when a dependency exists as both a build-dependency and normal dependency, but they use different features, the features are unified. The documentation around features explicitly states otherwise:
The version "2" resolver avoids unifying features in a few situations where that unification can be unwanted. The exact situations are described in the resolver chapter, but in short, it avoids unifying in these situations:
- Features enabled on platform-specific dependencies for targets not currently being built are ignored.
- Build-dependencies and proc-macros do not share features with normal dependencies.
- Dev-dependencies do not activate features unless building a target that needs them (like tests or examples).
Avoiding the unification is necessary for some situations. For example, if a build-dependency enables a std feature, and the same dependency is used as a normal dependency for a no_std environment, enabling std would break the build.
Steps
Reproducer 1
- Setup the following workspace:
<directory layout>
crates/
- foo/
- src/
- main.rs
- Cargo.toml
- bar/
- src/
- lib.rs
- Cargo.toml
Cargo.toml
crates/foo/src/main.rs
fn main() {
println!("Hello from foo");
bar::lib();
}
crates/foo/Cargo.toml
[package]
name = "foo"
version = "0.1.0"
[dependencies]
bar.path = "../bar"
[build-dependencies]
bar = { path = "../bar", features = ["build_feature"] }
crates/bar/src/lib.rs
pub fn lib() {
println!("Hello from bar");
#[cfg(feature = "build_feature")]
println!(" bar build_feature on!");
}
crates/bar/Cargo.toml
[package]
name = "bar"
version = "0.1.0"
[features]
build_feature = []
Cargo.toml
[workspace]
members = ["crates/*"]
- Build the workspace:
cargo build
- Run the
foo
binary:./target/debug/foo
Expected Result:
Hello from foo
Hello from bar
Actual Result:
Hello from foo
Hello from bar
bar build_feature on!
Reproducer 2
The above is a simplified version of what I found was happening in our code base. Just in case there's a difference I'm not aware of, the specific issue I noticed in our code base was structured as follows:
foo
has a featured called"build_feature"
.foo
has a dev-dependency ofbar.path = "../bar"
bar
has a build-dependency offoo = { path = "../foo", features["build_feature"] }
- Running
cargo test -p foo
buildsfoo
's tests with"build_feature"
enabled.
crates/foo/src/lib.rs
pub fn lib() {
println!("Hello from foo");
#[cfg(feature = "build_feature")]
panic!("foo build_feature on!");
}
#[cfg(test)]
mod test {
#[test]
fn basic() {
bar::lib();
super::lib();
}
}
crates/foo/Cargo.toml
[package]
name = "foo"
version = "0.1.0"
[features]
build_feature = []
[dev-dependencies]
bar.path = "../bar"
crates/bar/src/lib.rs
pub fn lib() {
println!("Hello from bar");
}
crates/bar/Cargo.toml
[package]
name = "bar"
version = "0.1.0"
[build-dependencies]
foo = { path = "../foo", features = ["build_feature"] }
Cargo.toml
[workspace]
members = ["crates/*"]
Expected Result:
<test succeeds>
Actual Result:
---- test::basic stdout ----
Hello from bar
Hello from foo
thread 'test::basic' panicked at 'foo build_feature on!', crates/foo/src/lib.rs:4:5
Possible Solution(s)
No response
Notes
No response
Version
$ cargo version --verbose
cargo 1.71.1 (7f1d04c00 2023-07-29)
release: 1.71.1
commit-hash: 7f1d04c0053083b98fa50b69b6f56e339b0556a8
commit-date: 2023-07-29
host: aarch64-apple-darwin
libgit2: 1.6.4 (sys:0.17.1 vendored)
libcurl: 7.88.1 (sys:0.4.61+curl-8.0.1 system ssl:(SecureTransport) LibreSSL/3.3.6)
ssl: OpenSSL 1.1.1t 7 Feb 2023
os: Mac OS 13.4.1 [64-bit]