๐Ÿฆ€ Functional Rust

419: cfg! and cfg_attr for Conditional Code

Difficulty: 2 Level: Intermediate Compile-time conditional compilation โ€” include code only for specific targets, features, or test builds.

The Problem This Solves

A single codebase needs to run on Linux and Windows, in debug and release, with and without optional features, and in test builds that need extra derives for mocking. Duplicating code per target is unmanageable. Runtime `if cfg!(target_os = "windows")` works but wastes binary space compiling both branches. You need compile-time branching. `#[cfg(...)]` annotations remove items from compilation entirely โ€” the excluded code doesn't exist in the binary. `cfg_attr` goes further: conditionally apply attributes based on the same predicates. The common use is `#[cfg_attr(test, derive(Mock))]` โ€” only derive the test-heavy mock implementation in test builds, keeping production binaries lean. `cfg!` (with `!`) works inside expressions, returning a `bool` at compile time. It's useful for conditional logic within a function body. But prefer `#[cfg]` on whole items where possible โ€” it eliminates dead code entirely instead of just branching over it.

The Intuition

`#[cfg(condition)]` is a compile-time `if` that removes the entire item from the binary when the condition is false; `cfg_attr` conditionally applies attributes like `derive` based on the same conditions.

How It Works in Rust

// #[cfg] โ€” include item only when condition holds
#[cfg(target_os = "linux")]
fn platform_info() -> &'static str { "Running on Linux" }

#[cfg(target_os = "windows")]
fn platform_info() -> &'static str { "Running on Windows" }

// cfg_attr โ€” apply derive only in test builds
#[derive(Debug, Clone)]
#[cfg_attr(test, derive(PartialEq))]  // PartialEq only for tests
struct Config { host: String, port: u16 }

// Feature flags (Cargo.toml: [features] async-support = [])
#[cfg(feature = "async-support")]
async fn fetch_data() -> String { todo!() }

// cfg! macro โ€” inline boolean expression
fn describe_build() -> &'static str {
 if cfg!(debug_assertions) { "debug" } else { "release" }
}

// Combine conditions
#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
fn optimized_path() { /* x86_64 Linux only */ }

#[cfg(any(target_os = "macos", target_os = "ios"))]
fn apple_only() { /* macOS or iOS */ }
1. `#[cfg(condition)]` on an item โ€” item vanishes from binary if false. 2. `#[cfg_attr(condition, attribute)]` โ€” apply `attribute` only when condition holds. 3. `cfg!()` in expressions โ€” compile-time `bool`, both branches still compiled. 4. Conditions: `target_os`, `target_arch`, `feature = "..."`, `test`, `debug_assertions`.

What This Unlocks

Key Differences

ConceptOCamlRust
Conditional compilation`#ifdef` via C preprocessor (FFI) or Dune conditions`#[cfg(...)]` built into language
Feature flagsopam optional dependencies, Dune `(enabled_if ...)``Cargo.toml` `[features]`, `#[cfg(feature="...")]`
Platform detection`Sys.os_type` at runtime`cfg!(target_os)` at compile time
Conditional attributesNot applicable`#[cfg_attr(test, derive(...))]`
Test-only code`let%test` or `(test (libraries ...))``#[cfg(test)]` module
// cfg! and cfg_attr for conditional code in Rust

// Conditional function โ€” only exists on Unix
#[cfg(unix)]
fn platform_info() -> &'static str { "Unix-like (Linux/macOS)" }

#[cfg(windows)]
fn platform_info() -> &'static str { "Windows" }

// Fallback for other platforms
#[cfg(not(any(unix, windows)))]
fn platform_info() -> &'static str { "Unknown platform" }

// Debug-only logging
macro_rules! debug_log {
    ($($arg:tt)*) => {
        if cfg!(debug_assertions) {
            println!("[DEBUG] {}", format!($($arg)*));
        }
    };
}

// Conditional derives via cfg_attr
#[cfg_attr(test, derive(PartialEq))] // only derive PartialEq in test builds
#[derive(Debug, Clone)]
struct Config {
    host: String,
    port: u16,
}

// Feature-gated code (simulated โ€” real features defined in Cargo.toml)
// #[cfg(feature = "json")]
// fn to_json(&self) -> String { ... }

// Conditional test helper
#[cfg(test)]
fn make_test_config() -> Config {
    Config { host: "localhost".to_string(), port: 8080 }
}

// Target-specific code
fn word_size() -> usize {
    if cfg!(target_pointer_width = "64") { 64 }
    else if cfg!(target_pointer_width = "32") { 32 }
    else { 0 }
}

// Endianness
fn endian() -> &'static str {
    if cfg!(target_endian = "big") { "big-endian" }
    else { "little-endian" }
}

fn main() {
    println!("Platform: {}", platform_info());
    println!("Word size: {} bits", word_size());
    println!("Endian: {}", endian());

    debug_log!("This appears in debug builds");
    debug_log!("Value: {}", 42);

    // cfg! as expression
    let is_debug = cfg!(debug_assertions);
    println!("Debug build: {}", is_debug);

    let c = Config { host: "example.com".to_string(), port: 443 };
    println!("{:?}", c);
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_config() {
        let c = make_test_config();
        assert_eq!(c.host, "localhost");
        assert_eq!(c.port, 8080);
    }

    #[test]
    fn test_cfg_expr() {
        let word_sz = word_size();
        assert!(word_sz == 32 || word_sz == 64 || word_sz == 0);
    }

    // This test only runs on Unix
    #[cfg(unix)]
    #[test]
    fn test_unix_platform() {
        assert_eq!(platform_info(), "Unix-like (Linux/macOS)");
    }
}
(* cfg! concepts in OCaml *)

(* OCaml conditional compilation via ppx or Sys module *)

let () =
  (* Runtime platform detection (not compile-time like cfg!) *)
  let platform = match Sys.os_type with
    | "Unix" -> "Unix/Linux/macOS"
    | "Win32" -> "Windows"
    | "Cygwin" -> "Cygwin"
    | _ -> "Unknown"
  in
  Printf.printf "Platform: %s\n" platform;

  (* Simulate debug mode *)
  let debug = true in (* would be set by build system *)
  if debug then
    Printf.printf "[DEBUG] Debug mode enabled\n";

  Printf.printf "Endianness: %s\n"
    (if Sys.big_endian then "big" else "little")