Just an FYI for other hacky programmers like myself
Our CI, which calls a bunch of cargo x
commands (clippy, test, udeps, audit etc.) on the root workspace worked fine, but then building an individual crate, which was included and built successfully by CI failed.
It failed because it depended on a feature in an external crate but hadn't declared that feature.
NOTE: the actually buggy crate (nhg-std-web) is a library crate depended upon by the crate I'm building (reference-data). Both crates are in the same workspace.
Running cargo check
at the workspace root (irrelevance snipped):
Blocking waiting for file lock on build directory
Checking reference-data v0.1.0 (/Users/coliny/Dev/com.qfi.health-CLEAN/src/rust/common-crates/reference-data)
Checking dashboard_backend_server v0.1.0 (/Users/coliny/Dev/com.qfi.health-CLEAN/src/rust/common-crates/dashboard_backend_server)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 11.84s
cargo check
in the failing crate:
cargo check
Checking nhg-std-web v0.1.0 (/Users/coliny/Dev/com.qfi.health-CLEAN/src/rust/nhg-std/nhg-std-web)
error[E0432]: unresolved import `tower_http::cors`
--> nhg-std/nhg-std-web/src/lib.rs:16:21
|
16 | use tower_http::cors::{Any, CorsLayer};
| ^^^^ could not find `cors` in `tower_http`
|
note: found an item that was configured out
--> /Users/coliny/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tower-http-0.5.2/src/lib.rs:316:9
|
316 | pub mod cors;
| ^^^^
= note: the item is gated behind the `cors` feature
For more information about this error, try `rustc --explain E0432`.
error: could not compile `nhg-std-web` (lib) due to 1 previous error
~/Dev/com.qfi.health-CLEAN/sr/rust/c/reference-data on 573-ude-brok…t-through-ci !1 ?1
❯
Adding the missing feature to the failing crate's Cargo.toml works and everything works at the root level and the individual crate level.
Feature unification (Features - The Cargo Book) suggests that this can happen if another crate requires that feature. However, no other crate in my workspace does. Many other crates in my workspace are using the external crate in question, but none are adding that feature:
rg -g Cargo.toml cors
~/Dev/com.qfi.health-CLEAN/src/rust
What the heck? Is it possible an external crate is adding the feature? I'd "ass u me"d unification would only consider crates in my workspace. Is that right?
So I don't understand:
- if this is feature unification - where is the
cor
feature being activated - does feature unification consider flags set by external dependencies (e.g. "my-crate -> external-crate->(features=["abc"])->external-crate-b; my-crate -> external-crate-b" will cause external-crate-b to be compiled with feature "abc" for any of my crates that depend on external-crate-b)?
- how can I find out why and where a feature is activated? grep might not be sufficient if one feature (e.g. feature-a) activates another feature (e.g. feature-a) and I'm only depending on one (e.g. feature-a)
If this is feature unification, isn't this, like, horrendously dangerous/fragile? I know features are supposed to be discrete and atomic but hey, we're all human(ish). Isn't this a perfect recipe for "works on my machine/specific crate but fails on your machine/crate root"?
Of course, the "bug" here is that my crate didn't specify its requirements and should have listed cors
as the feature it needs, but heck, I'm glad it did, as it forced me to confront this nightmare.
What am I missing? Isn't this, well, crazy?
Thanks!