6.2 KiB
Features示例
以下我们一起来看看一些来自真实世界的示例。
最小化构建时间和文件大小
如果一些包的部分特性不再启用,就可以减少该包占用的大小以及编译时间:
syn
包可以用来解析 Rust 代码,由于它很受欢迎,大量的项目都在引用,因此它给出了非常清晰的文档关于如何最小化使用它包含的features
regex
也有关于 features 的描述文档,例如移除 Unicode 支持的 feature 可以降低最终生成可执行文件的大小winapi
拥有众多 features,这些feature
对用了各种 Windows API,你可以只引入代码中用到的 API 所对应的 feature.
行为扩展
serde_json
拥有一个 preserve_order
feature,可以用于在序列化时保留 JSON 键值队的顺序。同时,该 feature 还会启用一个可选依赖 indexmap。
当这么做时,一定要小心不要破坏了 SemVer 的版本兼容性,也就是说:启用 feature 后,代码依然要能正常工作。
no_std支持
一些包希望能同时支持 no_std
和 std
环境,例如该包希望支持嵌入式系统或资源紧张的系统,且又希望能支持其它的平台,此时这种做法是非常有用的,因为标准库 std
会大幅增加编译出来的文件的大小,对于资源紧张的系统来说,no_std
才是最合适的。
wasm-bindgen 定义了一个 std feature,它是默认启用的。首先,在库的顶部,它无条件的启用了 no_std
属性,它可以确保 std
和 std prelude
不会自动引入到作用域中来。其次,在不同的地方(示例1,示例2),它通过 #[cfg(feature = "std")]
启用 std
feature 来添加 std
标准库支持。
对依赖库的features进行再导出
从依赖库再导出 features 在有些场景中会相当有用,这样用户就可以通过依赖包的 features 来控制功能而不是自己去手动定义。
例如 regex
将 regex_syntax
包的 features 进行了再导出,这样 regex
的用户无需知道 regex_syntax
包,但是依然可以访问后者包含的 features。
feature优先级
一些包可能会拥有彼此互斥的 features(无法共存,上一章节中有讲到),其中一个办法就是为 feature 定义优先级,这样其中一个就会优于另一个被启用。
例如 log
包,它有几个 features 可以用于在编译期选择最大的日志级别,这里,它就使用了 cfg-if
的方式来设置优先级。一旦多个 features
被启用,那更高优先级的就会优先被启用。
过程宏包
一些包拥有过程宏,这些宏必须定义在一个独立的包中。但是不是所有的用户都需要过程宏的,因此也无需引入该包。
在这种情况下,将过程宏所在的包定义为可选依赖,是很不错的选择。这样做还有一个好处:有时过程宏的版本必须要跟父包进行同步,但是我们又不希望所有的用户都进行同步。
其中给一个例子就是 serde ,它有一个 derive feature 可以启用 serde_derive 过程宏。由于 serde_derive
包跟 serde
的关系非常紧密,因此它使用了版本相同的需求来保证两者的版本同步性。
只能用于nightly的feature
Rust 有些实验性的 API 或语言特性只能在 nightly 版本下使用,但某些使用了这些 API 的包并不想强制他们的用户也使用 nightly
版本,因此他们会通过 feature 的方式来控制。
若用户希望使用这些 API 时,需要启用相应的 feature ,而这些 feature 只能在 nightly 下使用。若用户不需要使用这些 API,就无需开启 相应的 feature,自然也不需要使用 nightly 版本。
例如 rand
包有一个 simd_support feature 就只能在 nightly 下使用,若我们不使用该 feature,则在 stable 下依然可以使用 rand
。
实验性feature
有一些包会提前将一些实验性的 API 放出去,既然是实验性的,自然无法保证其稳定性。在这种情况下,通过会在文档中将相应的 features 标记为实验性,意味着它们在未来可能会发生大的改变(甚至 minor 版本都可能发生)。
其中一个例子是 async-std 包,它拥有一个 unstable feature,用来标记一些新的 API,表示人们已经可以选择性的使用但是还没有准备好去依赖它。