#features #cargo-workspace #workspace-dependencies #lint #cargo

app cargo-feature-guard

Validate Cargo feature propagation, detect forbidden features, and find duplicate dependencies

7 releases (4 breaking)

Uses new Rust 2024

0.5.1 Mar 7, 2026
0.5.0 Mar 6, 2026
0.4.1 Mar 5, 2026
0.3.1 Mar 5, 2026
0.1.0 Mar 4, 2026

#204 in Cargo plugins

Download history 5/week @ 2026-03-06 29/week @ 2026-03-13 18/week @ 2026-03-20 1/week @ 2026-03-27

53 downloads per month

MIT license

47KB
1K SLoC

cargo-feature-guard

Crates.io CI

Validate Cargo feature propagation across a workspace. Catches common mistakes like forgetting to forward a feature flag through intermediate crates.

What it checks

  1. Feature propagation — detects crates that define a feature F but don't receive it when building an entry point with --features F
  2. Never-enables — verifies that a forbidden feature is never activated in a given build context (e.g. mock must never reach c_api)
  3. Duplicate dependencies — reports dependencies present in multiple versions (informational, does not fail the build)

Uses cargo tree as the source of truth, which accounts for feature unification by the Cargo resolver.

Installation

# From crates.io
cargo install cargo-feature-guard

# Or with cargo-binstall (downloads pre-built binary)
cargo binstall cargo-feature-guard

Usage

# Run in your workspace root (looks for feature-guard.toml)
cargo feature-guard

# Specify a custom config file
cargo feature-guard --config path/to/config.toml

Configuration

Create a feature-guard.toml in your workspace root:

# Define entry points and which features they should be built with.
# The tool checks that every crate defining one of these features actually
# receives it through the dependency graph.
[[entry-points]]
package = "my-app"
features = ["mock", "nfc"]

[[entry-points]]
package = "my-lib"
features = ["nfc"]

# Verify that a feature is NEVER enabled for a given package.
# Useful to ensure test-only features don't leak into production builds.
[[never-enables]]
package = "my-lib"
forbidden = "mock"

# Multiple forbidden features can be specified as an array.
[[never-enables]]
package = "my-other-lib"
forbidden = ["mock", "test-only"]

[[entry-points]]

Field Description
package The -p package name passed to cargo tree
features Features to enable. Each feature is checked: if a workspace crate defines it but doesn't receive it, that's a gap.

[[never-enables]]

Field Description
package The -p package name
forbidden Feature(s) that must never be activated in this package's dependency tree. Accepts a single string ("mock") or an array (["mock", "test-only"]).

Exit codes

Code Meaning
0 All checks passed
1 Feature gaps or never-enables violations found
2 CLI usage error (bad arguments, missing config)

License

MIT

Dependencies

~2.4–4MB
~77K SLoC