rust/src/doc/book/conditional-compilation.md
Steve Klabnik 024aa9a345 src/doc/trpl -> src/doc/book
The book was located under 'src/doc/trpl' because originally, it was
going to be hosted under that URL. Late in the game, before 1.0, we
decided that /book was a better one, so we changed the output, but
not the input. This causes confusion for no good reason. So we'll change
the source directory to look like the output directory, like for every
other thing in src/doc.
2015-11-19 11:30:18 -05:00

2.0 KiB
Raw Blame History

% Conditional Compilation

Rust has a special attribute, #[cfg], which allows you to compile code based on a flag passed to the compiler. It has two forms:

#[cfg(foo)]
# fn foo() {}

#[cfg(bar = "baz")]
# fn bar() {}

They also have some helpers:

#[cfg(any(unix, windows))]
# fn foo() {}

#[cfg(all(unix, target_pointer_width = "32"))]
# fn bar() {}

#[cfg(not(foo))]
# fn not_foo() {}

These can nest arbitrarily:

#[cfg(any(not(unix), all(target_os="macos", target_arch = "powerpc")))]
# fn foo() {}

As for how to enable or disable these switches, if youre using Cargo, they get set in the [features] section of your Cargo.toml:

[features]
# no features by default
default = []

# The “secure-password” feature depends on the bcrypt package.
secure-password = ["bcrypt"]

When you do this, Cargo passes along a flag to rustc:

--cfg feature="${feature_name}"

The sum of these cfg flags will determine which ones get activated, and therefore, which code gets compiled. Lets take this code:

#[cfg(feature = "foo")]
mod foo {
}

If we compile it with cargo build --features "foo", it will send the --cfg feature="foo" flag to rustc, and the output will have the mod foo in it. If we compile it with a regular cargo build, no extra flags get passed on, and so, no foo module will exist.

cfg_attr

You can also set another attribute based on a cfg variable with cfg_attr:

#[cfg_attr(a, b)]
# fn foo() {}

Will be the same as #[b] if a is set by cfg attribute, and nothing otherwise.

cfg!

The cfg! syntax extension lets you use these kinds of flags elsewhere in your code, too:

if cfg!(target_os = "macos") || cfg!(target_os = "ios") {
    println!("Think Different!");
}

These will be replaced by a true or false at compile-time, depending on the configuration settings.