Compilación Condicional
Tanto .NET como Rust proporcionan la posibilidad de compilar código específico basado en condiciones externas.
En .NET es posible utilizar algunas directivas del preprocesador para controlar la compilación condicional.
#if debug
Console.WriteLine("Debug");
#else
Console.WriteLine("No debug");
#endif
Además de los símbolos predefinidos, también es posible utilizar la opción del
compilador DefineConstants para definir símbolos que se pueden utilizar con
#if
, #else
, #elif
y #endif
para compilar archivos fuente de forma
condicional en .NET.
En Rust, es posible utilizar el atributo cfg
, el
atributo cfg_attr
o el macro cfg
para controlar la
compilación condicional.
Al igual que en .NET, además de los símbolos predefinidos, también es posible
utilizar la bandera del compilador --cfg
para establecer
arbitrariamente opciones de configuración.
El atributo cfg
requiere y evalúa un ConfigurationPredicate
.
use std::fmt::{Display, Formatter};
struct MyStruct;
// Esta implementación de Display solo se incluye cuando el SO es Unix pero foo no es igual a bar
// Puedes compilar un ejecutable para esta versión, en Linux, con 'rustc main.rs --cfg foo=\"baz\"'
#[cfg(all(unix, not(foo = "bar")))]
impl Display for MyStruct {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.write_str("Ejecutando sin la configuración foo=bar")
}
}
// Esta función solo se incluye cuando tanto unix como foo=bar están definidos
// Puedes compilar un ejecutable para esta versión, en Linux, con 'rustc main.rs --cfg foo=\"bar\"'
#[cfg(all(unix, foo = "bar"))]
impl Display for MyStruct {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.write_str("Ejecutando con la configuración foo=bar")
}
}
// Esta función provoca un pánico cuando no se compila para Unix
// Puedes compilar un ejecutable para esta versión, en Windows, con 'rustc main.rs'
#[cfg(not(unix))]
impl Display for MyStruct {
fn fmt(&self, _f: &mut Formatter<'_>) -> std::fmt::Result {
panic!()
}
}
fn main() {
println!("{}", MyStruct);
}
El atributo cfg_attr
incluye condicionalmente atributos basados en
un predicado de configuración.
#[cfg_attr(feature = "serialization_support", derive(Serialize, Deserialize))]
pub struct MaybeSerializableStruct;
// Cuando la feature flag `serialization_support` está habilitada, lo anterior se expandirá a:
// #[derive(Serialize, Deserialize)]
// pub struct MaybeSerializableStruct;
The built-in cfg macro
takes in a single configuration predicate
and evaluates to the true literal when the predicate is true and the false
literal when it is false.
El macro cfg
incorporado toma un solo predicado de configuración
y evalúa al literal verdadero cuando el predicado es verdadero y al literal
falso cuando es falso.
if cfg!(unix) {
println!("¡Estoy ejecutándome en una máquina Unix!");
}
Mira también:
Features
La compilación condicional también es útil cuando es necesario proporcionar
dependencias opcionales. Con las "features" de Cargo, un paquete define
un conjunto de funcionalidades nombradas en la tabla [features]
de Cargo.toml,
y cada funcionalidad puede estar habilitada o deshabilitada. Las funcionalidades
del paquete que se está construyendo pueden habilitarse en la línea de comandos
con banderas como --features
. Las funcionalidades para las dependencias pueden
habilitarse en la declaración de dependencia en Cargo.toml.
Mira también: