# Cargo - Preventing Feature Unification
Links: [[Cargo]]
**Motivation:** Prevent accidental introduction of insecure features via workspace feature unification
- Example: `lsp` uses `rustls` without `dangerous_configuration`, but then `runner` uses `rustls` with `dangerous_configuration`. The runner's `rustls` will affect the `lsp`'s rustls, even when `lsp` is being built for SGX.
## Resources
### (Blog) [Cargo Workspace and the Feature Unification Pitfall](https://nickb.dev/blog/cargo-workspace-and-the-feature-unification-pitfall/)
### (Cargo book) [Features](https://doc.rust-lang.org/nightly/cargo/reference/features.html)
- [Feature unification](https://doc.rust-lang.org/nightly/cargo/reference/features.html#feature-unification)
- [Feature resolver version 2](https://doc.rust-lang.org/nightly/cargo/reference/features.html#feature-resolver-version-2)
- The version `"2"` resolver avoids unifying features in a few situations where that unification can be unwanted. The exact situations are described in the [resolver chapter](https://doc.rust-lang.org/nightly/cargo/reference/resolver.html#feature-resolver-version-2), but in short, it avoids unifying in these situations:
- Features enabled on [platform-specific dependencies](https://doc.rust-lang.org/nightly/cargo/reference/specifying-dependencies.html#platform-specific-dependencies) for targets not currently being built are ignored.
- [Build-dependencies](https://doc.rust-lang.org/nightly/cargo/reference/specifying-dependencies.html#build-dependencies) and proc-macros do not share features with normal dependencies.
- [Dev-dependencies](https://doc.rust-lang.org/nightly/cargo/reference/specifying-dependencies.html#development-dependencies) do not activate features unless building a target that needs them (like tests or examples).
### (Cargo book) [Dependency Resolution](https://doc.rust-lang.org/nightly/cargo/reference/resolver.html)
### (GitHub issue) [rust-lang/cargo#5042](https://github.com/rust-lang/cargo/issues/5042): Nested workspaces
### (RFC) [1525-cargo-workspace](https://rust-lang.github.io/rfcs/1525-cargo-workspace.html#validating-a-workspace)
### (Cargo book) [Workspaces](https://doc.rust-lang.org/cargo/reference/workspaces.html)
### (RFC) [2957-cargo-features2](https://rust-lang.github.io/rfcs/2957-cargo-features2.html)
Feature resolver enhancements
> Workspace feature unification. Currently the features enabled in a workspace depend on which workspace members are built (and those members' dependency tree). Sometimes projects want to ensure a dependency is only built once, regardless of which member included it, to avoid duplicate builds, or surprising changes in behavior. ==Sometimes projects want to ensure dependencies are _not_ unified, since they don't want unrelated workspace members to affect one another. It seems likely this may require explicit notation to control the behavior, so it may be possible to add in a backwards-compatible fashion. There are also workarounds for this behavior, so it is not as urgent.==
- what workarounds tho????
### (Rust Blog) [Announcing Rust 1.51.0 > Cargo's New F eature Resolver](https://blog.rust-lang.org/2021/03/25/Rust-1.51.0.html#cargos-new-feature-resolver)
### (Edition Guide) [Default Cargo feature resolver](https://doc.rust-lang.org/edition-guide/rust-2021/default-cargo-resolver.html)
### (Effective Rust): [Item 26: Be wary of `feature` creep](# [Item 26](https://www.lurklurk.org/effective-rust/features.html): Be wary of `feature` creep)
### (GitHub Issue) [Feature selection in workspace depends on the set of packages compiled](# Feature selection in workspace depends on the set of packages compiled)
## Workarounds
#### Approach 1: Add `cfg(unix)` to all dependencies on all other crates
- Lots of redundancy and you have to remember to do this every time you add a new crate.
- It adds overhead and seems to work, since most crates are designed to run only outside of SGX, but seems like such a weird and suboptimal solution?
#### Approach 2: Multiple cargo invocations using `-p` prevents feature unification.
- Unergonomic.
- Could get around it with a justfile?
- So long as it is possible for a "local CI" to run without issue, it shouldn't matter whether
#### Nested workspaces
- rust-lang/cargo#5042 includes [this comment](https://github.com/rust-lang/cargo/issues/5042#issuecomment-368788583) which elaborates a workaround for having nested workspaces. Their invokation of `cargo build` appears to build the crate inside the nested workspace which was excluded from the root workspace. However, this does not appear to work in our project?