Cargo workspace projects are built using separate independent crates that can be tested and compiled individually, while belonging to the same project (git repository, for example). This makes it easy to isolate components, identify dependencies between sub-crates, and more.
This also comes with rough edges, as features are no longer resolved per-crate, and are instead shared across the workspace. This is documented in the Cargo book:
When building multiple packages in a workspace (such as with
--workspace
or multiple-p
flags), the features of the dependencies of all of those packages are unified.
With a disclaimer:
If you have a circumstance where you want to avoid that unification for different workspace members, you will need to build them via separate
cargo
invocations.
The described behavior is simple to reproduce: a simple workspace project with two crates (crate-a
, crate-b
) triggers this bug. Crate A uses serde
and requires the derive
feature (but doesn't use it), Crate B has a dependency (direct or not) on serde
, and its derive
feature.
- Running
cargo check
/cargo test
works. - Running
cargo check -p crate-b
works. - Running
cargo check -p crate-a
doesn't work. - Removing
crate-b
breakscrate-a
, yet they don't share a dependency relationship. - Removing the unused
serde
dependency fromcrate-b
breakscrate-a
.
In a typical setup, CI will run tests using cargo check/test
, and won't notice that crate-a
is misconfigured. In my opinion, this is a foot gun, and should be highlighted on the check / test pages. This allows the creation of "bad" crates that seem to work well, but break when unrelated changes happen.
A developer cloning a repository should expect the tests to run and pass, both globally (cargo test
), and when run individually (cargo test -p ....
and cargo test --lib ... --manifest-path ...
). This is, currently, not guaranteed due to the feature unification.
A library with examples sub-crates (eg: syn) could easily have misconfigured dependencies, as the features used by examples pollute the other crates – unless the author is careful enough to test each crate individually. (Note: I'm not saying syn is impacted, I trust dtolnay! :))
As a developer, I expect cargo check
and cargo test
to throw errors when a crate or its dependencies are misconfigured, if doesn't require the right features from its dependencies. Having a way to toggle this behavior (either command flag, or Cargo.toml
config?) would work, I believe.