I've made a simplified example of my question in this github repo: https://github.com/JackSpagnoli/rust_features
I have a library "auth" handling api authentication, which in prod I would like to pull a value from an environment variable, but in testing and lower environments to use a constant value.
I've added compiler cfgs to handle this, using a dev
flag, as below:
#[cfg(not(feature = "dev"))]
let api_key = std::env::var(API_KEY_HEADER).unwrap();
#[cfg(any(feature = "dev", test))]
let api_key = "test".to_string();
Cargo.toml
for this crate has features defined as
[features]
default = []
dev=[]
some_other_feature=[]
Tests in this file can expect an api_key
value of test
.
This library is used in a binary crate api
, which imports lib
as follows
[dependencies]
lib = { path = "../lib", default-features=false, features=["some_other_feature"] }
[dev-dependencies]
lib = { path = "../lib", default-features=false, features=["dev"] }
In main.rs
for api
, unit tests can expect an api_key
value of test
, and I would presume that in main()
, when running with a --release
build, I can expect an api_key
value set from the environment. However, when running the code is getting an api_key
value of test
.
This doesn't seem like intended behaviour, as dev-only features are getting compiled into release builds.
You are using a workspace with a virtual manifest. Add resolver = "2"
to your root Cargo.toml
:
[workspace]
resolver = "2"
# ...
Cargo's "feature unification" was improved with edition = "2021"
crates to be smarter about separating [build-dependencies]
and [dev-dependencies]
from the build. However this is overridden by the root Cargo.toml
when in a workspace and virtual manifests don't have a [package]
section to define an edition
field to indicate which feature-resolver to use. So it must be specified explicitly.
See: