我的创建包如何检查依赖项的选择功能?

7

我正在寻找一种方法,根据依赖项的功能选择提供特殊功能。

有一个名为crate-a的库,其中包含feature-afeature-b两个功能。我想创建一个新的库crate-b,该库依赖于crate-a

二进制文件crate-c同时依赖于crate-acrate-b,并且为crate-a指定了功能。

我想根据对crate-a所选的功能集,提供crate-b函数的不同实现方式。

我尝试了这种不起作用的方法:

// 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-b 检查 crate-a 的功能?

我控制着 crate-acrate-b。 即使采用应该在 crate-a 中更改某些内容的方法也适用于我。


运行时检查对您是否有效,还是需要在编译时由crate-b决定? - Cerberus
嗨@ Cerberus。我正在寻找编译时检查。 - MaxV
1个回答

5
我唯一能想到的在编译时实现这一点的方法是,根据启用的功能条件性地在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 )* ) => {}
}

这些宏可被其他创建的使用,但通过`#[doc(hidden)]`隐藏在`crate-a`的公共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的解决方案,并需要大量的样板定义宏来处理您使用的每个特性标志的组合,但应该适用于基于crate-a功能的编译时条件编译。

编辑:参考serde采用类似方法使用其serde_if_integer128宏。


谢谢@apetranzilla!幸运的是,crate-a中只有两三个功能,所以你的解决方案对我很有效。 - MaxV

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接