macro_rules! define_alias {
(
#[cfg($meta:meta)] => $p:ident
$(, $( $rest:tt )+)?
) => { ... };
(
#[cfg($meta:meta)] => $p:ident,
$($( $rest:tt )+)?
) => { ... };
(
#[cfg($meta:meta)] => {
$(#[$p_meta:meta])*
$p:ident
}
$($( $rest:tt )+)?
) => { ... };
}
Expand description
Defines an alias for a particular configuration.
This has two advantages over directly using #[cfg(...)]
:
- Complex configurations can be abbreviated to more meaningful shorthand.
- Features are evaluated in the context of the defining crate, not the consuming.
The second advantage is a particularly powerful tool, as it allows consuming crates to use functionality in a defining crate regardless of what crate in the dependency graph enabled the relevant feature.
For example, consider a crate foo
that depends on another crate bar
.
bar
has a feature “faster_algorithms
”.
If bar
defines a “faster_algorithms
” alias:
define_alias! {
#[cfg(feature = "faster_algorithms")] => { faster_algorithms }
}
Now, foo
can gate its usage of those faster algorithms on the alias, avoiding the need to
expose its own “faster_algorithms
” feature.
This also avoids the unfortunate situation where one crate activates “faster_algorithms
” on
bar
without activating that same feature on foo
.
Once an alias is defined, there are 4 ways you can use it:
- Evaluate with no contents to return a
bool
indicating if the alias is active.if cfg::std!() { // Have `std`! } else { // No `std`... }
- Pass a single code block which will only be compiled if the alias is active.
cfg::std! { // Have `std`! }
- Pass a single
if { ... } else { ... }
expression to conditionally compile either the first or the second code block.cfg::std! { if { // Have `std`! } else { // No `std`... } }
- Use in a
switch
arm for more complex conditional compilation.cfg::switch! { cfg::std => { // Have `std`! } cfg::alloc => { // No `std`, but do have `alloc`! } _ => { // No `std` or `alloc`... } }