Cargo, Workspaces, Features, and Dependencies
Rule
Keep Cargo configuration explicit: share policy through workspaces, add dependencies only for identified needs, and keep reusable-library features additive and minimal.
Why
Cargo choices affect compilation, public API, binary size, MSRV, and downstream compatibility long after the immediate change.
Do
- Use a workspace when multiple crates share package, dependency, lint, or profile policy.
- Put shared dependency versions in
[workspace.dependencies]only after a member needs them. - Add mature domain crates when they remove real complexity or improve correctness.
- Be conservative with library dependencies and pragmatic with application dependencies.
- Prefer
clapderive for nontrivial application CLIs; hand-parse only tiny private interfaces. - Keep reusable-library features additive and opt-in.
- Make serialization optional unless it is core to the crate, and treat published formats as contracts.
- Verify changed reusable libraries with all supported features and the declared MSRV.
Avoid
- Do not prepopulate a new project with optional ecosystem dependencies.
- Do not add a crate for a trivial wrapper around
std. - Do not expose dependency types publicly unless they are an intended contract.
- Do not add mutually exclusive or speculative feature flags.
- Do not make default library features pull in heavy optional integrations.
- Do not derive public serialization without deciding compatibility behavior.
Library vs Application
Libraries minimize defaults and public dependency exposure. Applications depend directly on concrete integrations and normally do not feature-gate internal implementation details.
Example
[dependencies]
serde = { version = "1", features = ["derive"], optional = true }
[features]
serde = ["dep:serde"]
The feature exists because serialization is a real optional integration, not because the crate might need it later.
Exceptions
- Use a heavier dependency when it is the mature ecosystem standard for the domain.
- Use default features for an intentionally batteries-included library.
- Pin exact versions when reproducibility, upstream breakage, or security response requires it.
- Document a feature matrix when unavoidable integrations cannot be enabled together.