rust-lang / cargo

The Rust package manager
https://doc.rust-lang.org/cargo
Apache License 2.0
12.5k stars 2.37k forks source link

dep-features can't reference dev-dependencies features #9060

Open mankinskin opened 3 years ago

mankinskin commented 3 years ago

Say we have:

activating a feature in the dev-dependency through a feature in awesome does not work:

# cookie/Cargo.toml
[features]
session = []
# awesome/Cargo.toml
[features]
session = ["cookie/session"]

[dev-dependencies.cookie]
path = "../cookie"
# app/Cargo.toml
[dependencies.awesome]
path = "../awesome"
features = ["session"]

The error message is this:

error: failed to select a version for `awesome`.
    ... required by package `app v0.1.0 (/home/$USER/git/app)`
versions that meet the requirements `=0.1.0` are: 0.1.0

the package `app` depends on `awesome`, with features: `cookie` but `awesome` does not have these features.

failed to select a version for `awesome` which could resolve this conflict

Notes

Output of cargo version: cargo 1.49.0-nightly (2af662e22 2020-11-12)

mankinskin commented 3 years ago

5139

hvenev commented 3 years ago

dev-dependencies only exist when building the crate that defines them, right? When building app the awesome crate does not have any dependency named cookie, not even an optional one.

mankinskin commented 3 years ago

Oh, that explains this. But then I can't use features of crates which conditionally enable features in their dev-dependencies, right? In this case, awesome might want to run different tests using cookie/session when the feature session is enabled. But when awesome/session is set by a downstream crate (app), cookie is not a dependency and cookie/session can't be set, resulting in this error.

I don't know if this approach should be encouraged, but the purpose of this is obviously to test the session feature, which depends on a feature in a dev-dependency.

I think we should either

mankinskin commented 3 years ago

Maybe the problem becomes more clear when awesome/session does actually change something for downstream crates aswell:

# cookie/Cargo.toml
[features]
session = []
# awesome/Cargo.toml
[features]
session = ["cookie/session", "tide"]

[dependencies.tide]
path = "../tide"
optional = true

[dev-dependencies.cookie]
path = "../cookie"
# app/Cargo.toml
[dependencies.awesome]
path = "../awesome"
features = ["session"]

Now awesome behaves differently when session is enabled, and cookie/session is needed in the dev-dependencies to test this feature.

Eh2406 commented 3 years ago

One workaround is for awesome to have two features session = ["tide"] for users to use, and session-testing = ["cookie/session", "tide"] for developers of awesome to use while testing.

mankinskin commented 3 years ago

This bug is now blocking me, because I need to enable a feature of a dependency which depends on my crate itself. This means I can only use dev-dependencies, because otherwise it would be a dependency cycle. But the features don't work correctly for dev-dependencies.

# riker
[features]
default = []
tokio_executor = ["riker-macros/tokio_executor"]

[dependencies]
riker-macros = { path = "riker-macros" }
# riker/riker-macros
[features]
default = []
tokio_executor = ["tokio", "riker-testkit/tokio_executor", "riker/tokio_executor"]

# ...

[dev-dependencies]
riker = { path = ".." }
error: failed to select a version for `riker`.
    ... required by package `riker-macros v0.2.0 (/home/#/git/riker/riker-macros)`
versions that meet the requirements `=0.4.2` are: 0.4.2

the package `riker-macros` depends on `riker`, with features: `riker-testkit` but `riker` does not have these features.

failed to select a version for `riker` which could resolve this conflict
mankinskin commented 3 years ago

I guess the solution to this would be to ignore "cookie/session" as a feature switch when building "awsome" as a dependency because it references a feature of a dev-dependency, which is not available when building as a dependency. I will see if I can make a PR for this.