Use conditional compilation to include code for selected Cargo features or target platforms. `#[cfg(predicate)]` compiles its attached item only when the predicate is true; `#[cfg_attr(predicate, attribute)]` applies an attribute only when the predicate is true. `cfg!(predicate)` instead yields a compile-time boolean for use in an expression. section 2.3 section 5.8.2
Choose the form that matches what needs to vary:
- Gate an import or implementation with `#[cfg(feature = "serde")]` when it depends on an optional feature. section 2.3
- Vary derived traits with `#[cfg_attr(feature = "serde", derive(Serialize, Deserialize, Zeroize, Debug, PartialEq))]` and a complementary `not(feature = "serde")` attribute. section 2.3
- Select OS-specific code with `#[cfg(unix)]` and `#[cfg(windows)]`; use `all`, `any`, and `not` to combine or invert predicates. section 5.8.2 section 2.3
Gate a platform implementation, then query a target feature
``` #[cfg(target_family = "unix")] fn get_platform() -> String { "UNIX".into() } #[cfg(target_family = "windows")] fn get_platform() -> String { "Windows".into() } fn main() { println!("{}", get_platform()); if cfg!(target_feature = "avx2") { println!("avx2 is enabled"); } } ``` Each `cfg` applies to its own function; `cfg!` supplies a boolean inside `main`. As written, the function definitions cover only the two named target families. section 5.8.2
Listing 2.3 Partial code for src/message.rs from the dryoc crate
#[cfg(feature = "serde")] #1
use serde::{Deserialize, Serialize};
use zeroize::Zeroize;
#[cfg_attr( #2
feature = "serde", #2
derive(Serialize, Deserialize, Zeroize, Debug, PartialEq) #2
)]
#[cfg_attr(not(feature = "serde"), derive(Zeroize, Debug, PartialEq))] #3
#[zeroize(drop)]
/// Message container, for use with unencrypted messages
pub struct Message(pub Box<InputBase>);
The feature-gated import and paired conditional derives show how an optional dependency changes attributes on one struct. section 2.3
Keep feature combinations manageable. When flags proliferate, consider separate subcrates; some optional trait implementations still require flags in the top-level crate. Do not assume a pair of backend features is interchangeable: the shown `u32_backend` and default `u64_backend` are mutually exclusive. section 2.3




