Skip to content

cargo metadata should be able to ignore dev-dependencies for better feature resolution #10718

@sffc

Description

@sffc

Problem

cargo metadata includes both normal dependencies and dev-dependencies, distinguishing them with either "kind": null or "kind": "dev" in the dependency list for a package.

The problem is when there is a package that is used as both a normal dependency and as a dev-dependency with different sets of features. For example, consider the following packages:

# package_a/Cargo.toml
[dependencies]
package_b = { path = "../package_b" }

# package_b/Cargo.toml
[dependencies]
package_c = { path = "../package_c" }
[dev-dependencies]
package_d = { path = "../package_d", features = ["dev_only"] }

# package_c/Cargo.toml
[dependencies]
package_d = { path = "../package_d" }

# package_d/Cargo.toml
[dependencies]
some_big_dep = { version = "0.1", optional = true }
[features]
dev_only = ["some_big_dep"]

In this setup, cargo metadata will happily enable the "dev_only" feature of package_d, resulting in some_big_dep and all of its dependencies being included in the output.

This is undesirable because:

  1. It makes the metadata.json file significantly larger than it would be if only regular dependencies were included
  2. In order to manually drop packages that are only reachable via dev-dependencies, consumers of cargo metadata need to do a lot of work to track which features are used when; this is something cargo metadata should do automatically.

Proposed Solution

Add the following flag to cargo metadata:

  • --dep-kinds: only include the selected dependency kinds. Options (multiple can be specified):
    • all (default)
    • normal
    • build
    • dev

This is similar to the --edges flag in cargo tree. If desired, the no-normal, no-build, and no-dev options could be included in order for more complete parity between cargo metadata and cargo tree.

If cargo metadata --dep-kinds normal were run on the example above, then some_big_dep should be fully dropped from the output, as if I deleted it from the Cargo.toml file.

Notes

The --no-default-features and --features flags on cargo metadata have extremely limited use with the limitation of not being able to ignore dev-dependencies. Projects that are careful about their dependencies and feature sets are the ones that benefit most from those flags, but any dev-dependency anywhere in the tree may still enable an undesired feature.

CC @Manishearth

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-feature-requestCategory: proposal for a feature. Before PR, ping rust-lang/cargo if this is not `Feature accepted`Command-metadataS-needs-designStatus: Needs someone to work further on the design for the feature or fix. NOT YET accepted.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions