特性示例

以下是一些特性在实际应用中的例子。

最小化构建时间和文件大小

一些包使用特性,以便在未启用这些特性时,可以减少 crate 的大小并缩短编译时间。一些例子是:

扩展行为

serde_json 包有一个preserve_order 特性,它可以改变 JSON 映射的行为,以保留键插入的顺序。请注意,它启用了一个可选依赖indexmap来实现新行为。

当像这样改变行为时,请务必确保这些更改是SemVer 兼容的。也就是说,启用该特性不应破坏通常在禁用该特性时构建的代码。

no_std 支持

一些包希望同时支持no_stdstd 环境。这对于支持嵌入式和资源受限的平台很有用,但仍然允许支持完整标准库的平台具有扩展功能。

wasm-bindgen 包定义了一个std 特性,该特性默认启用。在库的顶部,它无条件地启用 no_std 属性。这确保了 stdstd prelude 不会自动进入作用域。然后,在代码的各个位置(示例 1示例 2),它使用 #[cfg(feature = "std")] 属性来有条件地启用需要 std 的额外功能。

重新导出依赖项特性

重新导出依赖项的特性可能很方便。这允许依赖于该 crate 的用户控制这些特性,而无需直接指定这些依赖项。例如,regex 重新导出regex_syntax 包中的特性。regex 的用户不需要了解 regex_syntax 包,但他们仍然可以访问它包含的特性。

C 库的捆绑

一些包提供对常见 C 库的绑定(有时称为 “sys” crate)。有时,这些包允许您选择使用系统上安装的 C 库,或者从源代码构建它。例如,openssl 包有一个vendored 特性,它启用了 openssl-sys 的相应 vendored 特性。openssl-sys 的构建脚本有一些条件逻辑,使其从 OpenSSL 源代码的本地副本构建,而不是使用系统中的版本。

curl-sys 包是另一个例子,其中static-curl 特性导致它从源代码构建 libcurl。请注意,它还有一个force-system-lib-on-osx 特性,该特性强制它使用系统 libcurl,覆盖 static-curl 设置。

特性优先级

某些包可能具有互斥的特性。处理此问题的一种方法是优先选择一个特性而不是另一个特性。log 包就是一个例子。它有几个特性用于选择编译时的最大日志级别,这些特性在这里描述。它使用cfg-if选择优先级。如果启用了多个特性,则会优先选择较高的“max”级别而不是较低的级别。

Proc-macro 伴侣包

某些包具有与之紧密相关的 proc-macro。但是,并非所有用户都需要使用 proc-macro。通过使 proc-macro 成为可选依赖项,这使您可以方便地选择是否包含它。这很有帮助,因为有时 proc-macro 版本必须与父包保持同步,并且您不希望强制用户必须指定两个依赖项并使它们保持同步。

一个例子是 serde,它具有derive 特性,该特性启用 serde_derive proc-macro。serde_derive crate 与 serde 紧密相关,因此它使用相等版本要求以确保它们保持同步。

仅限 Nightly 的特性

某些包希望试验仅在 Rust nightly 通道上可用的 API 或语言特性。但是,他们可能不希望要求其用户也使用 nightly 通道。一个例子是 wasm-bindgen,它有一个nightly 特性,该特性启用了扩展 API,该 API 使用 Unsize 标记 trait,该 trait 在撰写本文时仅在 nightly 通道上可用。

请注意,在 crate 的根目录,它使用 cfg_attr 来启用 nightly 特性。请记住,feature 属性与 Cargo 特性无关,用于选择使用实验性语言特性。

rand 包的 simd_support 特性是另一个例子,它依赖于仅在 nightly 通道上构建的依赖项。

实验性特性

某些包具有他们可能想要尝试的新功能,而无需承诺这些 API 的稳定性。这些特性通常会被记录为实验性的,因此即使在次要版本中,它们也可能会在未来发生更改或中断。一个例子是 async-std 包,它具有一个unstable 特性,该特性控制新 API,人们可以选择使用这些 API,但可能尚未完全准备好被依赖。