Skip to content

Regression: build-dependencies and dependencies should not have features unified #12676

@Imisnew2

Description

@Imisnew2

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:

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

  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/*"]
  1. Build the workspace: cargo build
  2. 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 of bar.path = "../bar"
  • bar has a build-dependency of foo = { path = "../foo", features["build_feature"] }
  • Running cargo test -p foo builds foo'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]

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-bugCategory: bugS-triageStatus: This issue is waiting on initial triage.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions