liveBook · Manning

Conditional compilation

As explained in Code Like a Pro in Rust

A cfg attribute is a Rust compiler attribute that conditionally includes or excludes the attached source item according to configuration predicates.

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

How Code Like a Pro in Rust covers it

How deep it goes
Defines cfg, cfg_attr, and cfg! and demonstrates their placement in code, without detailing compiler internals.
Examples
Shows feature-gated serde derives, Unix and Windows allocator branches, and a cfg! check for AVX2.
What it assumes
Assumes familiarity with Rust code and Cargo features while defining the conditional-compilation tools used in the examples.
What you can do after
Apply it via Rust attributes and cfg! to gate feature-dependent or platform-specific code.
How it connects
Connects Cargo feature flags, optional dependencies, derived traits, target features, and platform-specific allocation.

Also explained in

Compare how 5 books explain conditional compilation →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Code Like a Pro in Rust. The section links point to the parts of the book it draws on.