Master Conditional Compilation in Rust with cfg_if: A Practical Guide
This article explains how the Rust cfg_if crate simplifies conditional compilation by providing a macro that replaces nested #[cfg] attributes with clear if‑else or match structures, shows step‑by‑step usage, advanced patterns, and compares cfg_if to raw #[cfg] for readability and maintainability.
cfg_if is a Rust utility crate that streamlines conditional‑compilation code by offering the cfg_if! macro, which lets developers write compile‑time configuration logic more cleanly.
Adding the Dependency
First, add the crate to Cargo.toml:
cfg-if = "1.0.0"Basic Usage
Import the macro and write conditional blocks:
use cfg_if::cfg_if;
cfg_if! {
if #[cfg(unix)] {
fn foo() { /* unix‑specific functionality */ }
} else if #[cfg(windows)] {
fn foo() { /* windows‑specific functionality */ }
} else {
fn foo() { /* fallback implementation */ }
}
}The macro expands at compile time into an equivalent if‑else chain or match expression, so there is no runtime overhead.
Advantages of cfg_if
Simplified syntax: replaces verbose nested #[cfg()] attributes with a readable macro.
Reduces errors: ensures an else branch is present, avoiding missing cases.
Composable: multiple conditions can be combined easily.
Advanced Syntax
Complex conditions can be expressed directly in the macro:
cfg_if! {
if #[cfg(all(unix, target_pointer_width = "32"))] {
// 32‑bit unix systems
} else if #[cfg(all(unix, target_pointer_width = "64"))] {
// 64‑bit unix systems
} else if #[cfg(windows)] {
// windows systems
} else {
// other systems
}
}The Built‑in #[cfg()] Attribute
#[cfg()]is Rust’s native attribute for conditional compilation. Examples:
#[cfg(unix)]
fn unix_only() { /* compiled only on Unix */ }
#[cfg(windows)]
fn windows_only() { /* compiled only on Windows */ }Common configuration options include operating system ( unix, windows, macos, linux), architecture ( x86, x86_64, arm), feature flags defined in Cargo.toml, and compiler version ( rustc_1_40).
Logical Operators
Multiple conditions can be combined with logical operators:
#[cfg(all(unix, target_pointer_width = "64"))]
fn unix_64bit_function() { /* only on 64‑bit Unix */ }
#[cfg(any(windows, macos))]
fn windows_or_mac_function() { /* on Windows or macOS */ }
#[cfg(not(debug_assertions))]
fn release_only() { /* only in release mode */ }Typical Use Cases
Module‑level conditional compilation:
#[cfg(feature = "advanced")]
mod advanced_features {
// compiled only when the "advanced" feature is enabled
}Conditional imports:
#[cfg(unix)]
use std::os::unix::fs::MetadataExt;
#[cfg(windows)]
use std::os::windows::fs::MetadataExt;Runtime‑style checks with cfg!:
if cfg!(debug_assertions) {
println!("Debug mode");
} else {
println!("Release mode");
}Custom Feature Flags
Define a flag in Cargo.toml:
[features]
my_feature = []Then use it in code:
#[cfg(feature = "my_feature")]
fn feature_specific_function() {
// ...
}Full List of cfg Attributes
all: all conditions must be true. any: any condition true is sufficient. not: condition must be false. target_os: target operating system. target_arch: target architecture. target_feature: specific CPU feature. target_endian: byte order. target_pointer_width: pointer width. target_env: target environment. target_vendor: target vendor. feature: compile‑time feature flag. debug_assertions: whether debug assertions are enabled. test: compile only in test mode.
These attributes can be freely combined, for example:
#[cfg(all(unix, not(any(target_os = "macos", target_os = "ios"))))]Using cfg_attr for Conditional Attributes
The cfg_attr macro applies another attribute only when a condition holds:
#[cfg_attr(feature = "nightly", feature(some_unstable_feature))]
...
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
struct MyStruct {
// fields ...
}All these configurations are evaluated at compile time, incurring no runtime cost.
cfg_if vs #[cfg()]
#[cfg()]is built‑in and requires no extra dependency.
For simple conditions, #[cfg()] is more direct.
For complex, nested conditions, cfg_if! often yields clearer, more maintainable code.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
BirdNest Tech Talk
Author of the rpcx microservice framework, original book author, and chair of Baidu's Go CMC committee.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
