Skip to content

A procedural macro for handling mutually-exclusive crate features

License

Apache-2.0, MIT licenses found

Licenses found

Apache-2.0
LICENSE-APACHE
MIT
LICENSE-MIT
Notifications You must be signed in to change notification settings

kbknapp/cfg-exclusive

Repository files navigation

cfg-exclusive

Rust Version crates.io Documentation Dependency Status

A procedural macro for ensuring that only one of a set of features is enabled at a time.

Typically, features should be additive. However, there are times when this is not possible or desired.

For such cases, if the number of features is small, or does not change/evolve frequently some verbose #[cfg] attributes may suffice.

The Problem

For example imagine a fictional crate which should only be build with one of the features feat1 or feat2.

One could create a build script such as the one at build.rs.

fn main() {
    #[cfg(all(feature = "feat1", feature = "feat2"))]
    compile_error!("Only one of the features can be enabled at a time");
}

Now imagine, we add a feat3.

Our build.rs changes to:

fn main() {
    #[cfg(any(
        all(feature = "feat1", any(feature = "feat2", feature = "feat3")),
        all(feature = "feat2", any(feature = "feat1", feature = "feat3")),
        all(feature = "feat3", any(feature = "feat1", feature = "feat2")),
    ))]
    compile_error!("Only one of the features can be enabled at a time");
}

Adding a fourth feat4 jumps to 12 combinations!

fn main() {
    #[cfg(any(
        all(feature = "feat1", any(feature = "feat2", feature = "feat3", feature = "feat4")),
        all(feature = "feat2", any(feature = "feat1", feature = "feat3", feature = "feat4")),
        all(feature = "feat3", any(feature = "feat1", feature = "feat2", feature = "feat4")),
        all(feature = "feat4", any(feature = "feat1", feature = "feat2", feature = "feat3")),
    ))]
    compile_error!("Only one of the features can be enabled at a time");
}

This gets out of hand quickly.

The Solution

Starting of with two features, the cfg-exclusive procedural macro can be used to simplify the build.rs script.

cfg_exclusive::cfg_exclusive! {
    validate_feats,
    ["feat1", "feat2"],
    "Only one of the features can be enabled at a time"
}

fn main() {
    validate_feats();
}

If that changes to three features:

-    ["feat1", "feat2"],
+    ["feat1", "feat2", "feat3"],

Or four:

-    ["feat1", "feat2", "feat3"],
+    ["feat1", "feat2", "feat3", "feat4"],

License

This crate is licensed under either of

at your option.

Contribution

Unless you explicitly note otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

About

A procedural macro for handling mutually-exclusive crate features

Resources

License

Apache-2.0, MIT licenses found

Licenses found

Apache-2.0
LICENSE-APACHE
MIT
LICENSE-MIT

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Languages