I want to conditionally enable run-time checks and logging, independently from each other and from debug and release mode. So I've started adding two features to my project, one called "invariant-checking" and one called "logging". Ultimately i want their use to be through macros I define in a crate which is visible project-wide.
I had assumed that if I filled out the features section the same way in all of the crates the same way then when I activated the feature while compiling the bin crate, then all the lib crates would also have the feature enabled, but this is not the case! How can I enable and disable features across multiple crates? Hopefully this can be done by only changing one thing like the command-line arguments to cargo.
To clarify exactly what I want, here's an example, which I will also reproduce below:
There are three crates, the main, bin, crate, and two lib crates, called "middle" and "common". Here are the relevant parts of the relevant files:
main.rs
extern crate common;
extern crate middle;
fn main() {
common::check!();
middle::run();
println!("done");
}
the main Cargo.toml
[dependencies]
[dependencies.common]
path = "libs/common"
[dependencies.middle]
path = "libs/middle"
[features]
default = []
invariant-checking = []
logging = []
middle's lib.rs
extern crate common;
pub fn run() {
common::check!();
common::run();
}
middle's Cargo.toml
[dependencies]
[dependencies.common]
path = "../common"
[features]
default = []
invariant-checking = []
logging = []
common's lib.rs
#[macro_export]
macro_rules! check {
() => {{
if cfg!(feature = "invariant-checking") {
println!("invariant-checking {}:{}", file!(), line!());
}
if cfg!(feature = "logging") {
println!("logging {}:{}", file!(), line!());
}
}};
}
pub fn run() {
check!()
}
and finally common's Cargo.toml
[dependencies]
[features]
default = []
invariant-checking = []
logging = []
When i run cargo run --features "invariant-checking,logging"
I get the following output
invariant-checking src\main.rs:5
logging src\main.rs:5
done
but want it to log in middle and common as well. How can I transform this project such that it will do that, and still allow me to get only "done" as output by changing only one place?
common
, so feature selection happens at compile time and only in thecommon
crate. Then you only need to declare the features in that crate, and switching the features will have global effect, as long as all crates use the same version ofcommon
. – Sven Marnach#[cfg(feature = "logging")]
and#[cfg(not(feature = "logging"))]
. That works. And at least in my toy example I only need to mention the features in the main andcommon
'sCargo.toml
files! – Ryan1729