#conditional-compilation #build-script #cargo-build #build #cfg #conditional #compilation

build cfg_aliases

A tiny utility to help save you a lot of effort with long winded #[cfg()] checks

6 releases

0.2.1 May 10, 2024
0.2.0 Dec 19, 2023
0.1.1 Oct 20, 2020
0.1.0 Apr 8, 2020
0.1.0-alpha.1 Apr 5, 2020

#59 in Rust patterns

Download history 775198/week @ 2024-07-12 813773/week @ 2024-07-19 834102/week @ 2024-07-26 811024/week @ 2024-08-02 866708/week @ 2024-08-09 830220/week @ 2024-08-16 896598/week @ 2024-08-23 880128/week @ 2024-08-30 896487/week @ 2024-09-06 876284/week @ 2024-09-13 1086952/week @ 2024-09-20 1105095/week @ 2024-09-27 1600751/week @ 2024-10-04 1484942/week @ 2024-10-11 1553254/week @ 2024-10-18 1122924/week @ 2024-10-25

5,931,137 downloads per month
Used in 7,137 crates (101 directly)

MIT license

20KB
202 lines

CFG Aliases

CFG Aliases is a tiny utility to help save you a lot of effort with long winded #[cfg()] checks. This crate provides a single cfg_aliases! macro that doesn't have any dependencies and specifically avoids pulling in syn or quote so that the impact on your comile times should be negligible.

You use the the cfg_aliases! macro in your build.rs script to define aliases such as x11 that could then be used in the cfg attribute or macro for conditional compilation: #[cfg(x11)].

Example

Cargo.toml:

[build-dependencies]
cfg_aliases = "0.1.0"

build.rs:

use cfg_aliases::cfg_aliases;

fn main() {
    // Setup cfg aliases
    cfg_aliases! {
        // Platforms
        wasm: { target_arch = "wasm32" },
        android: { target_os = "android" },
        macos: { target_os = "macos" },
        linux: { target_os = "linux" },
        // Backends
        surfman: { all(unix, feature = "surfman", not(wasm)) },
        glutin: { all(feature = "glutin", not(wasm)) },
        wgl: { all(windows, feature = "wgl", not(wasm)) },
        dummy: { not(any(wasm, glutin, wgl, surfman)) },
    }
}

Now that we have our aliases setup we can use them just like you would expect:

#[cfg(wasm)]
println!("This is running in WASM");

#[cfg(surfman)]
{
    // Do stuff related to surfman
}

#[cfg(dummy)]
println!("We're in dummy mode, specify another feature if you want a smarter app!");

This greatly improves what would otherwise look like this without the aliases:

#[cfg(target_arch = "wasm32")]
println!("We're running in WASM");

#[cfg(all(unix, feature = "surfman", not(target_arch = "wasm32")))]
{
    // Do stuff related to surfman
}

#[cfg(not(any(
    target_arch = "wasm32",
    all(unix, feature = "surfman", not(target_arch = "wasm32")),
    all(windows, feature = "wgl", not(target_arch = "wasm32")),
    all(feature = "glutin", not(target_arch = "wasm32")),
)))]
println!("We're in dummy mode, specify another feature if you want a smarter app!");

You can also use the cfg! macro or combine your aliases with other checks using all(), not(), and any(). Your aliases are genuine cfg flags now!

if cfg!(glutin) {
    // use glutin
} else {
    // Do something else
}

#[cfg(all(glutin, surfman))]
compile_error!("You cannot specify both `glutin` and `surfman` features");

Syntax and Error Messages

The aliase names are restricted to the same rules as rust identifiers which, for one, means that they cannot have dashes ( - ) in them. Additionally, if you get certain syntax elements wrong, such as the alias name, the macro will error saying that the recursion limit was reached instead of giving a clear indication of what actually went wrong. This is due to a nuance with the macro parser and it might be fixed in a later release of this crate. It is also possible that aliases with dashes in the name might be supported in a later release. Open an issue if that is something that you would like implemented.

Finally, you can also induce an infinite recursion by having rules that both reference each-other, but this isn't a real limitation because that doesn't make logical sense anyway:

// This causes an error!
cfg_aliases! {
    test1: { not(test2) },
    test2: { not(test1) },
}

Attribution and Thanks

  • Thanks to my God and Father who led me through figuring this out and to whome I owe everything.
  • Thanks to @Yandros on the Rust forum for showing me some crazy macro hacks!
  • Thanks to @sfackler for pointing out the way to make cargo add the cfg flags.
  • Thanks to the authors of the tectonic_cfg_support::target_cfg macro from which most of the cfg attribute parsing logic is taken from. Also thanks to @ratmice for bringing it up on the Rust forum.

No runtime deps