Compilación Condicional

Rust posee un atributo especial, #[cfg], que te permite compilar código basado en una opción proporcionada al compilador. Tiene dos formas:

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

#[cfg(bar = "baz")]

También posee algunos helpers:

fn main() { #[cfg(any(unix, windows))] fn foo() {} #[cfg(all(unix, target_pointer_width = "32"))] fn bar() {} #[cfg(not(foo))] fn not_foo() {} }
#[cfg(any(unix, windows))]

#[cfg(all(unix, target_pointer_width = "32"))]

#[cfg(not(foo))]

Los cuales pueden ser anidados de manera arbitraria:

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

Para activar o desactivar estos switches, si estas usando Cargo, se configuran en la sección [features] de tu Cargo.toml

[features]
# No features por defecto
default = []

# El feature “secure-password” depende en el paquete bcrypt.
secure-password = ["bcrypt"]

Cuando hacemos esto, Cargo pasa una opción a rustc:

--cfg feature="${feature_name}"

La suma de esas opciones cfg determinara cuales son activadas, y en consecuencia, cual código sera compilado. Tomemos este código:

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

Si lo compilamos con cargo build --features "foo", Cargo enviara la opción --cfg feature="foo" a rustc, y la salida tendrára el mod foo. Si compilamos con un cargo build normal, ninguna opción extra sera proporcionada, y debido a esto, ningún modulo foo existirá.

cfg_attr

También puedes configurar otro atributo basado en una variable cfg con cfg_attr:

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

Sera lo mismo que #[b] si a es configurado por un atributo cfg, y nada de cualquier otra manera.

cfg!

La extension de sintaxis te permite también usar este tipo de opciones en cualquier otro punto de tu código:

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

Estos serán reemplazado por true o false en tiempo de compilación, dependiendo en las opciones de la configuración.