crossfig

Crates.iocrossfig
lib.rscrossfig
version0.1.3
created_at2025-06-22 07:37:39.283745+00
updated_at2025-06-23 07:29:52.917128+00
descriptionProvides compile-time feature aliases and introspection.
homepage
repositoryhttps://github.com/bushrat011899/crossfig
max_upload_size
id1721359
size38,845
Zachary Harrold (bushrat011899)

documentation

README

crossfig

Provides two macros to assist with managing conditional compilation in Rust.

  • no_std
  • No build.rs
  • Zero features
  • Zero dependencies
  • No proc-macros

Instead, this crate defines 4 macro_rules macros:

  • switch
  • alias
  • enabled
  • disabled

Tl;Dr

crossfig::alias! {
    /// Indicates whether the `std` feature is enabled.
    pub std: { #[cfg(feature = "std")] }
}

crossfig::switch! {
    std => {
        extern crate std;
        std::println!("Can use std!");
    }
    _ => {
        // no_std
    }
}

enabled and disabled

enabled and disabled are the simplest to explain: they either pass their contents unchanged or suppress them.

crossfig::enabled! {
    println!("I will print!");
}

crossfig::disabled! {
    compile_error!("I won't be triggered!");
}

If no content is provided to either macro, an appropriate bool value will be returned, allowing use in if statements and other logical operations.

if crossfig::enabled!() {
    println!("I will print!");
}

if crossfig::disabled!() {
    println!("I won't print!");
}

alias

On their own, these macros aren't very helpful. That's where alias comes in. The alias macro will use either enabled or disabled with a new provided identifier based on an arbitrary conditional compilation configuration.

crossfig::alias! {
    std: { #[cfg(feature = "std")] }
}

// Is roughly equivalent to:
#[cfg(feature = "std")]
use crossfig::enabled as std;
#[cfg(not(feature = "std"))]
use crossfig::disabled as std;

Since the aliases created by alias are macro_rules items, they can be documented and even publicly exported.

crossfig::alias! {
    /// Indicates the log feature is enabled.
    pub log: { #[cfg(feature = "log")] }
}

When publicly exported, it's important to understand that an alias is evaluated as either enabled or disabled at the definition site, not the call site. This means aliases can be used to determine what features are enabled in dependencies.

// In a crate `foo`
crossfig::alias! {
    /// Indicates the log feature is enabled.
    pub log: { #[cfg(feature = "log")] }
}

// In a consuming crate
if foo::log!() {
    // `foo`'s `log` feature has been enabled!
}

Note that aliases and standard #[cfg(...)] attributes can be mixed and matched within definitions, and combined with not, any and all operators:

crossfig::alias! {
    a: { #[cfg(feature = "a")] }
    b: { #[cfg(feature = "b")] }
    c: { all(a, not(b), #[cfg(feature = "c")]) }
}

While aliases are powerful, they still don't solve a common issue: ranked choice. It's common to have multiple features in a crate which all contribute to a single choice. For example, you may have a parking_lot, std and spin set of features to choose what Mutex implementation is used internally.

switch

To make this particular problem nicer, we use the final macro in this crate, switch:

crossfig::alias! {
    parking_lot: { #[cfg(feature = "parking_lot")] }
    std: { #[cfg(feature = "std")] }
    spin: { #[cfg(feature = "spin")] }
}

crossfig::switch! {
    parking_lot => {
        use parking_lot::Mutex;
    }
    std => {
        use std::sync::Mutex;
    }
    spin => {
        use spin::Mutex;
    }
    _ => {
        compile_error!("Must select a `Mutex` provider!");
    }
}

MSRV

The minimum supported Rust version for this crate is 1.54.0, with the 2015 edition, allowing it to be used in virtually any Rust project. Note that support for earlier versions are blocked by the unavailability of #![no_std], vis types in macro_rules, and concat! in documentation. If support for earlier versions of Rust would help you, please create an issue!

Changelog

Refer to the git history for detailed changes. This crate is intending on hitting 1.0 in the near-term, so don't expect major changes between now and then.

Commit count: 0

cargo fmt