Rust — how to “#ifdef” Link to heading

In C/C++, #ifdef and #ifndef are fairly common macros to conditionally include/exclude some portion of code at compile time. Today, let’s take a look at how we can do the same in Rust.

C/C++ Link to heading

#ifdef and #ifndef are used for conditional compilation. An example would be to control whether or not to print debug logs. For instance, consider the following C++ program

// main.cc
#include <iostream>

void log(std::string const& msg) {
#ifdef DEBUG
    std::cerr << msg << "\n";
#endif
}

int main() {
    log("hello world!");
}

One can add or remove std::cerr << msg << "\n"; line conditionally at compile time, i.e.,

# compile with DEBUG macro
g++ -o debug main.cc -DDEBUG
# will print hello world!
./debug
hello world!

# compile without DEBUG macro (and with optimization)
g++ -o release main.cc -O3
# will not print hello world!
./release

If DEBUG macro is not defined, then log() function becomes empty and will be ignored by the compiler. If DEBUG is defined, then it will print out the log that is useful for debugging purposes.

Rust Link to heading

Rust supports the same via features. Below is the identical code in Rust

// src/main.rs
fn log(msg: &str) {
    #[cfg(feature = "debug")]
    eprintln!("{}", msg);
}

fn main() {
    log("hello world!");
}

We also need to add the following lines to Cargo.toml

[features]
debug = []

To conditionally include the debug line, simply specify --features debug option at cargo build

# compile with debug feature
cargo build --features debug
# will print hello world!
target/debug/exec_name
hello world!

# compile without debug feature (and in release mode)
cargo build --release
# will not print hello world!
target/release/exec_name

Bonus Link to heading

You can set the features for Rust Analyzer in VSCode by adding the following into .vscode/settings.json file, e.g.,

{
    ...
    "rust-analyzer.cargo.features": ["debug"]
}

References Link to heading

The Cargo Book

Cargo “features” provide a mechanism to express conditional compilation and optional dependencies. A package defines a…

doc.rust-lang.org