liveBook · Manning

Conditional compilation

As explained in Rust in Action: Systems programming concepts and techniques

A cfg attribute is a Rust attribute that conditionally includes an item based on compile-time configuration predicates.

Conditional compilation changes what goes into a Rust program according to conditions known at compile time. A common condition is the target operating system; CPU capabilities can matter too. Put a `#[cfg(...)]` attribute before an item to include that item only when its condition matches the compilation target. section 7.6.1

Give each operating system the right usage string

A command-line tool can define `USAGE` twice: `#[cfg(target_os = "windows")]` selects instructions containing an `.exe` filename, while `#[cfg(not(target_os = "windows"))]` selects instructions without it. The resulting binary contains only the usage data for its target. Write negation with `not(...)`, not `target_os != "windows"`. section 7.6.1

Choose a condition that matches what the code needs:

  • Use target settings such as `target_os`, `target_arch`, `target_pointer_width`, or `target_has_atomic` to distinguish platforms and CPU facilities. section 7.6.1
  • Use `not(...)`, `all(...)`, and `any(...)` to combine conditions. Configuration can also be adjusted when invoking the build tools with `--cfg ATTRIBUTE`. section 7.6.1

The same technique helps a cross-platform clock tool use different implementations for setting the time, because operating systems provide different mechanisms. For smaller differences, `cfg!(debug_assertions)` can guard diagnostic printing: a development run shows debug output, while the shown release run does not. section 9.7 section 1.5

Listing 7.9 Demonstrating the use of conditional compilation
 3 #[cfg(target_os = "windows")]
 4 const USAGE: &str = "
 5 Usage:
 6     akv_mem.exe FILE get KEY
 7     akv_mem.exe FILE delete KEY
 8     akv_mem.exe FILE insert KEY VALUE
 9     akv_mem.exe FILE update KEY VALUE
10 ";
11  
12 #[cfg(not(target_os = "windows"))]
13 const USAGE: &str = "
14 Usage:
15     akv_mem FILE get KEY
16     akv_mem FILE delete KEY
17     akv_mem FILE insert KEY VALUE
18     akv_mem FILE update KEY VALUE
19 ";

Compare the two `USAGE` definitions and their complementary `#[cfg(...)]` attributes. section 7.6.1

How Rust in Action: Systems programming concepts and techniques covers it

How deep it goes
Defines conditional compilation and works through cfg predicates and paired constants; does not detail compiler internals.
Examples
Uses Windows and non-Windows usage strings, debug output in development builds, and an OS-specific time-setting tool.
What it assumes
Introduces cfg attributes through simple constants while assuming familiarity with basic Rust source code and builds.
What you can do after
Practice/perform it by annotating alternative Rust items with cfg predicates for different compilation targets.
How it connects
Connects cfg attributes to compiler targets, operating-system APIs, CPU capabilities, and debug assertions.

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 Rust in Action: Systems programming concepts and techniques. The section links point to the parts of the book it draws on.