rust-lang / cargo

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

support feature gated package metadata #14770

Open nfejzic opened 4 weeks ago

nfejzic commented 4 weeks ago

Problem

Hello everyone! Sorry if similar issue already exists, I could not find something like this.

While discussing the MSRV in https://github.com/tqwewe/kameo/issues/76, we figured out that the currently MSRV could be lower, but a certain non-default feature requires the higher version.

Would it be possible for cargo to support package metadata that is feature gated? For example, rust-version is set to 1.65 per default, but if feature feat-a is enabled, that sets the rust-version to 1.75.

Proposed Solution

Syntax for dependencies already exists, as described in the Cargo book:

[dependencies]
ravif = { version = "0.6.3", optional = true }
rgb = { version = "0.8.25", optional = true }

[features]
avif = ["dep:ravif", "dep:rgb"]

Maybe similar syntax can be used for other tables:

[features]
avif = ["package:rust-version=1.75", "dep:ravif", "dep:rgb"]

Alternatively, we could extend features to support (inline) tables:

# inline tables
[features]
avif = { dependencies = ["ravif", "rgb"], package = { rust-version = "1.75" } }

# or regular tables:
[features.avif]
dependencies = ["ravif", "rgb"]
# override top-level [package] section:
package = { rust-version = "1.75" }

# maybe even with subtables:
[features.avif.dependencies]
ravif = "x.x.x" # override [dependencies] table to use specific version
rgb = true # or enable optional dependency from [dependencies] table

[features.avif.package]
# override [package] table fields
rust-version = "1.75"

Notes

No response

weihanglo commented 4 weeks ago

Thanks for the idea! The Cargo team has recently accepted an RFC extending feature metadata table: https://github.com/rust-lang/cargo/issues/14157. There are future extensions listed in that tracking issue. A similar extension is supporting stable/beta/nightly features: https://github.com/rust-lang/cargo/issues/10881, though that is not identical to this one.

Also #[cfg(version(..))] and #[cfg(accessible(..))] are compiler features you may want to pay attention to, which are nice when pairing with this proposal.

weihanglo commented 4 weeks ago

That means this is blocked on #14157, and requires an RFC to start with.

epage commented 4 weeks ago

Per-feature MSRVs came up in the MSRV RFC. It was one of the motivating cases for why we felt that Cargo shouldn't error if a dependency required a newer MSRV than your package.

For myself though, I would want to better understand the motivations for why there is a per-feature MSRV and would, in general, push back against the idea. imo this adds a lot of user and design complexity and it isn't clear to me that its worth it compared to having just one MSRV or, where possible, splitting the higher MSRV section out into a separate package.