Skip to content
NickelAngeStudio edited this page Apr 15, 2023 · 55 revisions

1. Simplified syntax
2. Legacy syntax
3. Macros
    target_cfg!
    match_cfg!
    meta_cfg
4. Predicates
5. Aliases
6. Modifiers
    Activate (+)
    Deactivate (-)
    Panic (@)
7. Customization

1. Simplified

Simplified syntax uses aliases and predicates separated by & and | instead of all() and any(). Negation is done via ! instead of not(). You can also group them with parenthesis ().

That means that

#[cfg(all(not(windows), any(target_architecture="x86", feature="myfeature")))]

becomes

!windows & (x86:ar | myfeature:ft)

Notes:

  • x86:ar is a predicate shortcut. ar means target_architecture while x86 is the value targeted. You can get a list of predefined shortcut here.
  • windows is an alias. Aliases don't have predicate shortcuts. You can get a list of predefined aliases here.
  • Negation ! can also be used before parenthesis (). Ex. : windows | !(x86:ar | myfeature:ft) is valid.

2. Legacy

You can also use legacy syntax instead of simplified syntax. The #[cfg()] part is mandatory.

Notes:

  • Legacy and simplified syntax can't be mixed on the same arm.

3. Macros

target_cfg!

This macro is used exclusively in the item declaration part of your code. It will panic! if used inside a function. Contrary to match_cfg!, any matching arm WILL be included and not all cases are covered with a wildcard(_).

target_cfg! {
    `simplified or legacy` => {
        ... [0..N] items ...
     },
    `simplified or legacy` => {},
}

Notes:

  • The right hand side {} braces can be ignored for just 1 item.

  • target_cfg! always wrap arm with doc | (arm) if doc is not defined in the arm (even for legacy syntax). This allow cargo doc to always generate documentation for each arm. This feature can be deactivated. More details here

match_cfg!

This macro is used exclusively inside functions. The first matching arm is evaluated and all possible values must be covered with a wildcard.

fn foo() {
    match_cfg! {
        `simplified or legacy` => {
            ... [0..N] ...
         },
        `simplified or legacy` => {},
        _ => {}   // Mandatory wildcard arm.
    }
}

// This also works
fn foo() {
    let os = match_cfg! {
        linux => "linux",
        #[cfg(windows)] => "windows",
        _ => "unknown"
    };

    println!("Your operating system is {}", os);
}

meta_cfg

meta_cfg is an attribute proc macro and work exactly like cfg but with support of simplified syntax or legacy syntax.

#[meta_cfg(`simplified or legacy`)]

// Legacy
#[meta_cfg(#[cfg(all(not(windows), target_architecture="x86", feature="myfeature")])]

// Simplified
#[meta_cfg(!windows & x86:ar & myfeature:ft)]

Notes:

  • Like target_cfg!, meta_cfg always wrap arm with doc | (arm) if doc is not defined in the arm (even for legacy syntax). This allow cargo doc to always generate documentation targeted item. This feature can be deactivated. More details here

4. Predicates

Below is the list of predefined aliases with their respective value.

Predicate Target Description Examples
ar target_arch Option set once with the target's CPU architecture. x86_64:ar
arm:ar
tf target_feature Option set for each platform feature available for the current compilation target. sse4.1:tf
avx2:tf
os target_os Option set once with the target's operating system. ios:os
android:os
fm target_family Option providing a more generic description of a target. unix:fm
wasm:fm
ev target_env Option set with further disambiguating information about the target platform. gnu:ev
msvc:ev
ed target_endian Option set once with either a value of "little" or "big" depending on the endianness of the target's CPU. little:ed
big:ed
pw target_pointer_width Option set once with the target's pointer width in bits. 32:pw
64:pw
vn target_vendor Option set once with the vendor of the target. apple:vn
fortanix:vn
at target_has_atomic Option set for each bit width that the target supports atomic loads, stores, and compare-and-swap operations. 64:at
ptr:at
ft feature Mechanism to express conditional compilation and optional dependencies. webp:ft
std:ft
pn panic Option set depending on the panic strategy. abort:pn
unwind:pn
_ n/a Wildcard is used to write value as is.
Ex. : windows:_ become #[cfg(windows)]
windows:_
unix:_

You can also define your own predicates. See here

5. Aliases

Below is the list of predefined aliases with their respective value.

Alias Value
linux linux:os
unix unix:_
windows windows:_
macos macos:os
android android:os
ios ios:os
wasm wasm:_
doc doc:_
test test:_
debug debug_assertions:_
desktop linux:os | windows: | macos:os_
mobile android:os | ios:os

You can also define your own aliases. See here

6. Modifiers

cfg_boost provides 3 arm modifier that must be written as the first character of an arm. They are used for debug testing and will panic! on release compilation.

This behaviour can be changed by inserting

cfg_boost_release_modifier_behaviour = { value = "ignore", force = true }

in the [env] section of your config.toml. By doing so, modifiers will be ignored at compile time instead of panic!.

Activate (+)

Inserting + before an arm will activate it.

// First arm will be activated even if the operating system `foo` doesn't exists.
target_cfg!{
    + foo:os => ...,
    foo:os => ...,
}

Note : match_cfg! macro can only have 1 + modifier.

Deactivate (-)

Inserting - before an arm will deactivate it, even if condition happen to be true.

// #[cfg(all())] is always true but won't activate because of `-`
target_cfg!{
    - #[cfg(all())] => ...,
    desktop => ...,
}

Note : match_cfg! wildcard arm _ cannot have - modifier.

Panic (@)

Inserting @ before one or many arms will cause the macro to panic! with the details of those arms. This allow you to see what cfg_boost write in the TokenStream. Of course they need to be removed to resume execution.

target_cfg! {
    @ desktop => mod desktop_only;,
    @ mobile => mod mobile_only;,
}

will panic! with the message

proc macro panicked
message: 
*** Macro panicked because some arm have the `@` modifier ***

Arm : desktop
Syntax : Simplified
Modifier : Panic
Predicates : any(target_os = "linux", any(windows, target_os = "macos"))
#[cfg()] : #[cfg(any(doc, any(target_os = "linux", any(windows, target_os = "macos"))))]
#[cfg_attr()] : #[cfg_attr(docsrs, doc(cfg(any(target_os = "linux", any(windows, target_os = "macos")))))]
Content : mod desktop_only

Arm : mobile
Syntax : Simplified
Modifier : Panic
Predicates : any(target_os = "android", target_os = "ios")
#[cfg()] : #[cfg(any(doc, any(target_os = "android", target_os = "ios")))]
#[cfg_attr()] : #[cfg_attr(docsrs, doc(cfg(any(target_os = "android", target_os = "ios"))))]
Content : mod mobile_only

7. Customization

Ready to customize? See here