我的箱子如何检查依赖项的选定功能?

How can my crate check the selected features of a dependency?

我正在寻找一种基于依赖项的功能选择来提供特殊功能的方法。

有一个库 crate-a,具有 feature-afeature-b 的功能。我想创建一个依赖于 crate-a.

的新库 crate-b

二进制 crate-c 依赖于 crate-acrate-b 并指定 crate-a.

的特征

我想根据为 crate-a 选择的功能集提供 crate-b 功能 greet 的不同实现。

我试过这种方法,但行不通:

// 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");
}

有什么方法可以检查 crate-acrate-b 的功能吗?

我同时控制crate-acrate-b。即使是 crate-a 中应该更改某些内容的方法也对我有用。

我能想到的在编译时实现此目的的唯一方法是根据启用的功能有条件地在 crate-a 中定义宏。例如,指定 feature-a 时的宏如下所示:

// 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 )* ) => {}
}

这些宏可由其他 crate 使用,但通过 #[doc(hidden)]crate-a 的 public API 隐藏,并且它们扩展为与它们相同的标记给定或空体取决于功能标志。然后,您可以像这样在 crate-b 中使用它们:

// in crate-b/src/lib.rs
pub fn unconditional_fn() {}

crate_a::__cfg_feature_a! {
    pub fn cfg_feature_a_fn() {}
}

这显然是一个非常 hacky 的解决方案,需要大量样板文件为您使用的每个功能标志组合定义宏,但应该适用于 compile-time 基于 [=12= 的功能的条件编译].

编辑:作为参考,serde 在其 serde_if_integer128 宏中使用了类似的方法。