I'm looking for a way to provide special functionality based on a dependency's feature selection.
There is a library crate-a
with features feature-a
and feature-b
. I would like to crate a new library crate-b
which depends on crate-a
.
Binary crate-c
depends on both crate-a
and crate-b
and specifies features for crate-a
.
I would like to provide a different implementation of crate-b
's function greet
based on the feature set selected for crate-a
.
I've tried this approach which doesn't work:
// at crate-b/src/lib.rs
#[cfg(not(feature = "crate-a/feature-a"))]
pub fn greet() {
println!("General impl");
}
#[cfg(feature = "crate-a/feature-a")]
pub fn greet() {
println!("Feature-A impl");
}
Is there any way to check crate-a
's features from crate-b
?
I control both crate-a
and crate-b
. Even an approach where something should be changed in crate-a
works for me.
The only way I can think of that would achieve this at compile time would be to conditionally define macros in crate-a
depending on the features enabled. For example, a macro for specifically when feature-a
is specified would look like this:
// in crate-a/src/lib.rs
#[cfg(feature = "feature-a")]
#[doc(hidden)]
#[macro_export]
macro_rules! __cfg_feature_a {
( $( $tok:tt )* ) => { $( $tok )* }
}
#[cfg(not(feature = "feature-a"))]
#[doc(hidden)]
#[macro_export]
macro_rules! __cfg_feature_a {
( $( $tok:tt )* ) => {}
}
These macros are usable by other crates, but hidden from the public API of crate-a
via #[doc(hidden)]
, and they expand to either the same tokens they were given or an empty body depending on the feature flags. You can then use them in crate-b
like so:
// in crate-b/src/lib.rs
pub fn unconditional_fn() {}
crate_a::__cfg_feature_a! {
pub fn cfg_feature_a_fn() {}
}
This is obviously a pretty hacky solution, and requires a lot of boilerplate defining macros for every combination of feature flags you use, but should work for compile-time conditional compilation based on the features of crate-a
.
Edit: for reference, serde
uses a similar approach with its serde_if_integer128
macro.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With