User-defined features with values? (for conditional compilation)

Hello dear Rustaceans,

I'm wondering whether it is possible to do conditional compilation in Rust as in Example1.

// EXAMPLE 1 (C)
#define A 0
#define B 1
#define C 2
#ifndef WHICH
#define WHICH A
#endif

#if (WHICH == A)
char gift() { return 'A'; }
#elif (WHICH == B)
char gift() { return 'B'; }
#elif (WHICH == C)
char gift() { return 'C'; }
#else 
#error "Please define WHICH"
#endif

void main() { printf("%c", gift()); }

I know it is possible to do conditional compilation in Rust as below with default Configuration Options(or features) provided with Rust.

// EXAMPLE 2 (Rust)
#[cfg(target_os="linux")]
println!("HELLO LINUX USER");

As in Example-3, it seems like it is only possible to use user-defined features as boolean properties when using them for conditional compilation in Rust. It is possible to do conditional compilation in Rust by comparing a user-defined feature to different values?? (as in Example 1 or 2)

// Example 3 (Rust)
//// Cargo.toml
...
[features]
WHICH = [] 

//// main.rs
fn main() {
    #[cfg(feature="WHICH")]
    println!("HELLO WHICH");
}

Thank you for reading :smile: :smiley_cat:

AFAIK, it is not possible to get arbitrary features (e.g., something like an integer or an arbitrary string).

If, however, the set of values is finite, you can create all the needed features:

[features]
which-A = []
which-B = []
which-C = []
fn gift () -> char
{
    ::cfg_if::cfg_if! {
        if #[cfg(feature = "which-A")] {
            #[cfg(any(
                feature = "which-B",
                feature = "which-C",
            ))] compile_error!("Please define only one value for `which`");
            'A'
        } else if #[cfg(feature = "which-B")] {
            #[cfg(any(
                feature = "which-C",
            ))] compile_error!("Please define only one value for `which`");
           'B'
        } else if #[cfg(feature = "which-C")] {
            'C'
        } else {
            compile_error!("Please provide one of `which-A`, `which-B` or `which-C` features");
            unreachable!()
        }
    }
}

It is, as you can see, ugly, and does not scale well (if crate B depends on this and enables which-B, and crate C depends on this and enable which-C, you will not be able to depend on both B and C...).


So in general environment variables are the tool used for this kind of thing: they can be manipulated at compile time thanks to the env! macro, and since it expands to a &'static str (compatible with concat! by the way), you get to .parse() it or whatever your want to extract values out of it.

1 Like

The cfg_if crate would be very useful for me! Thank you :smiley: