Just writing this down in case it helps someone else – this is just a consequence of Cargo's build model, but it was unintuitive to me at least:
Consider a (virtual) Cargo workspace with
members = ['core', 'extra']:
core has a non-default feature
extra depends on
Now, if I execute
cargo test --workspace with no features enabled, Cargo nevertheless builds
extra enables that feature in
I was trying to make sure that
core compiles and the relevant tests run even without
foo, but unknowingly I wasn't actually testing that at all! I was really baffled when I realized that the
foo feature somehow gets enabled even when I thought it wouldn't, and it took me a while to realize what was going on.
The IMO even worse features footgun is: You write a crate
foo that depends on crates
bar depends on
baz with feature
feat. Now your crate
foo also makes use of API behind
baz/feat. But you don’t notice because
bar activated that feature for you. But
bar’s dependency on
baz is a private dependency (just for functionality, no publicly used / re-exported types). So one day
bar decides to change up its dependency on
baz (e.g. updating to a different version of
baz, or removing the feature
feat because they no longer need it or noticed they never needed it in the first place) and suddenly your crate
foo breaks, and you’re even to blame for that.
One thing to note is that it can depend upon which directory in the workspace you run
cargo build from.
So if you are in a subdirectory of the workspace, where the dependency graph does not enable
features="foo", you can get build failures if it doesn't depend upon anything that enables it.
But when building from the top-level of the workspace, it can be built with the feature enabled if there are other siblings that depend upon it. That is potentially a way to test your feature isn't depended upon in CI once you know about it.
Perhaps in addition to that you could make some tool similar to the
cargo tree -e features which errors if the feature gets enabled in the direct dependency graph.
--package option has the same effect.
For testing features in workspaces without tripping over this, I recommend
cargo-hack. If you just run
cargo hack --workspace --feature-powerset test, then each package in the workspace will be tested separated, and each package that has multiple features will be tested with each possible feature combination.
Ah, awesome. I've been wondering if something like that exists, but been too lazy to search. Thanks!