diff --git a/src/cargo/reference/features/examples.md b/src/cargo/reference/features/examples.md index 00d50d22..feed1ec0 100644 --- a/src/cargo/reference/features/examples.md +++ b/src/cargo/reference/features/examples.md @@ -12,7 +12,7 @@ ### 行为扩展 -[`serde_json`](https://crates.io/crates/serde_json) 拥有一个 [`preserve_order` feature](https://github.com/serde-rs/json/blob/v1.0.60/Cargo.toml#L53-L56),可以用于在序列化时保留 JSON 键值队的顺序。同时,该 feature 还会启用一个可选依赖 [indexmap](https://crates.io/crates/indexmap)。 +[`serde_json`](https://crates.io/crates/serde_json) 拥有一个 [`preserve_order` feature](https://github.com/serde-rs/json/blob/v1.0.60/Cargo.toml#L53-L56),可以用于在序列化时保留 JSON 键值对的顺序。同时,该 feature 还会启用一个可选依赖 [indexmap](https://crates.io/crates/indexmap)。 当这么做时,一定要小心不要破坏了 SemVer 的版本兼容性,也就是说:启用 feature 后,代码依然要能正常工作。 @@ -40,7 +40,7 @@ 在这种情况下,将过程宏所在的包定义为可选依赖,是很不错的选择。这样做还有一个好处:有时过程宏的版本必须要跟父包进行同步,但是我们又不希望所有的用户都进行同步。 -其中给一个例子就是 [serde](https://crates.io/crates/serde) ,它有一个 [derive](https://github.com/serde-rs/serde/blob/v1.0.118/serde/Cargo.toml#L34-L35) feature 可以启用 [serde_derive](https://crates.io/crates/serde_derive) 过程宏。由于 `serde_derive` 包跟 `serde` 的关系非常紧密,因此它使用了[版本相同的需求](https://github.com/serde-rs/serde/blob/v1.0.118/serde/Cargo.toml#L17)来保证两者的版本同步性。 +其中一个例子就是 [serde](https://crates.io/crates/serde) ,它有一个 [derive](https://github.com/serde-rs/serde/blob/v1.0.118/serde/Cargo.toml#L34-L35) feature 可以启用 [serde_derive](https://crates.io/crates/serde_derive) 过程宏。由于 `serde_derive` 包跟 `serde` 的关系非常紧密,因此它使用了[版本相同的需求](https://github.com/serde-rs/serde/blob/v1.0.118/serde/Cargo.toml#L17)来保证两者的版本同步性。 ## 只能用于 nightly 的 feature @@ -52,7 +52,7 @@ Rust 有些实验性的 API 或语言特性只能在 nightly 版本下使用, ## 实验性 feature -有一些包会提前将一些实验性的 API 放出去,既然是实验性的,自然无法保证其稳定性。在这种情况下,通过会在文档中将相应的 features 标记为实验性,意味着它们在未来可能会发生大的改变(甚至 minor 版本都可能发生)。 +有一些包会提前将一些实验性的 API 放出去,既然是实验性的,自然无法保证其稳定性。在这种情况下,通常会在文档中将相应的 features 标记为实验性,意味着它们在未来可能会发生大的改变(甚至 minor 版本都可能发生)。 其中一个例子是 [async-std](https://crates.io/crates/async-std) 包,它拥有一个 [unstable feature](https://github.com/async-rs/async-std/blob/v1.8.0/Cargo.toml#L38-L42),用来[标记一些新的 API](https://github.com/async-rs/async-std/blob/v1.8.0/src/macros.rs#L46),表示人们已经可以选择性的使用但是还没有准备好去依赖它。 diff --git a/src/cargo/reference/features/intro.md b/src/cargo/reference/features/intro.md index e91fa58d..77fd08ee 100644 --- a/src/cargo/reference/features/intro.md +++ b/src/cargo/reference/features/intro.md @@ -25,7 +25,7 @@ pub mod webp; 在 `Cargo.toml` 中定义的 `feature` 会被 `Cargo` 通过命令行参数 `--cfg` 传给 `rustc`,最终由后者完成编译:`rustc --cfg ...`。若项目中的代码想要测试 `feature` 是否存在,可以使用 [`cfg` 属性](https://doc.rust-lang.org/stable/reference/conditional-compilation.html#the-cfg-attribute)或 [`cfg` 宏](https://doc.rust-lang.org/stable/std/macro.cfg.html)。 -之前我们提到了一个 `feature` 还可以开启其他 `feature`,举个例子,例如 `ICO` 图片格式包含 `BMP` 和 `PNG`,因此当 `ICO` 图片格式被启用后,它还得确保启用 `BMP` 和 `PNG` 格式: +之前我们提到了一个 `feature` 还可以开启其他 `feature`,举个例子,例如 ICO 图片格式包含 BMP 和 PNG 格式,因此当 `ico` 被启用后,它还得确保启用 `bmp` 和 `png` : ```toml [features] @@ -70,11 +70,11 @@ webp = [] gif = { version = "0.11.1", optional = true } ``` -**这种可选依赖的写法会自动定义一个与依赖同名的 feature,也就是 `gif` feature**,这样一来,当我们启用 `gif` feautre 时,该依赖库也会被自动引入并启用:例如通过 `--feature gif` 的方式启用 feauture。 +**这种可选依赖的写法会自动定义一个与依赖同名的 feature,也就是 `gif` feature**,这样一来,当我们启用 `gif` feature 时,该依赖库也会被自动引入并启用:例如通过 `--feature gif` 的方式启用 feature 。 -> 注意:目前来说,`[fetuare]` 中定义的 feature 还不能与已引入的依赖库同名。但是在 `nightly` 中已经提供了实验性的功能用于改变这一点: [namespaced features](https://doc.rust-lang.org/stable/cargo/reference/unstable.html#namespaced-features) +> 注意:目前来说,`[feature]` 中定义的 feature 还不能与已引入的依赖库同名。但是在 `nightly` 中已经提供了实验性的功能用于改变这一点: [namespaced features](https://doc.rust-lang.org/stable/cargo/reference/unstable.html#namespaced-features) -当然,**我们还可以通过显式定义 feature 的方式来启用这些可选依赖库**,例如为了支持 `AVIF` 图片格式,我们需要引入两个依赖包,由于 `AVIF` 是通过 feature 引入的可选格式,因此它依赖的两个包也必须声明为可选的: +当然,**我们还可以通过显式定义 feature 的方式来启用这些可选依赖库**,例如为了支持 AVIF 图片格式,我们需要引入两个依赖包,由于 `avif` 是通过 feature 引入的可选格式,因此它依赖的两个包也必须声明为可选的: ```toml [dependencies] @@ -91,7 +91,7 @@ avif = ["ravif", "rgb"] ## 依赖库自身的 feature -就像我们的项目可以定义 `feature` 一样,依赖库也可以定义它自己的 feature、也有需要启用的 feature 列表,当引入该依赖库时,我们可以通过以下方式为其启用相关的 features : +就像我们的项目可以定义 `feature` 一样,依赖库也可以定义它自己的 `feature`,也有需要启用的 `feature` 列表,当引入该依赖库时,我们可以通过以下方式为其启用相关的 `features` : ```toml [dependencies] @@ -109,7 +109,7 @@ flate2 = { version = "1.0.3", default-features = false, features = ["zlib"] } > 注意:这种方式未必能成功禁用 `default`,原因是可能会有其它依赖也引入了 `flate2`,并且没有对 `default` 进行禁用,那此时 `default` 依然会被启用。 > -> 查看下文的 [feature 同一化](#feature同一化) 获取更多信息 +> 查看下文的 [feature 同一化](#feature-同一化) 获取更多信息 除此之外,还能通过下面的方式来间接开启依赖库的 feature : @@ -134,7 +134,7 @@ parallel = ["jpeg-decoder/rayon"] - `--features FEATURES`: 启用给出的 feature 列表,可以使用逗号或空格进行分隔,若你是在终端中使用,还需要加上双引号,例如 `--features "foo bar"`。 若在工作空间中构建多个 `package`,可以使用 `package-name/feature-name` 为特定的成员启用 features - `--all-features`: 启用命令行上所选择的所有包的所有 features -- `--no-default-features`: 对选择的包禁用 `default` featue +- `--no-default-features`: 对选择的包禁用 `default` feature ## feature 同一化 @@ -150,7 +150,7 @@ parallel = ["jpeg-decoder/rayon"] 例如,如果我们想可选的支持 `no_std` 环境(不使用标准库),那么有两种做法: -- 默认代码使用标准库的,当该 `no_std` feature 启用时,禁用相关的标准库代码 +- 默认代码使用标准库的,当 `no_std` feature 启用时,禁用相关的标准库代码 - 默认代码使用非标准库的,当 `std` feature 启用时,才使用标准库的代码 前者就是功能削减,与之相对,后者是功能添加,根据之前的内容,我们应该选择后者的做法: @@ -203,7 +203,7 @@ test_cargo v0.1.0 (/Users/sunfei/development/rust/demos/test_cargo) `cargo tree -f "{p} {f}"` 命令会提供一个更加紧凑的视图: ```shell -% cargo tree -f "{p} {f}" +$ cargo tree -f "{p} {f}" test_cargo v0.1.0 (/Users/sunfei/development/rust/demos/test_cargo) └── uuid v0.8.2 default,std ``` @@ -211,7 +211,7 @@ test_cargo v0.1.0 (/Users/sunfei/development/rust/demos/test_cargo) `cargo tree -e features -i foo`,该命令会显示 `features` 会如何"流入"指定的包 `foo` 中: ```shell -cargo tree -e features -i uuid +$ cargo tree -e features -i uuid uuid v0.8.2 ├── uuid feature "default" │ └── test_cargo v0.1.0 (/Users/sunfei/development/rust/demos/test_cargo) @@ -238,8 +238,8 @@ resolver = "2" V2 版本的解析器可以在某些情况下避免 feature 同一化的发生,具体的情况在[这里](https://doc.rust-lang.org/stable/cargo/reference/resolver.html#feature-resolver-version-2)有描述,下面做下简单的总结: - 为特定平台开启的 `features` 且此时并没有被构建,会被忽略 -- `Build-dependencies` 和 `proc-macros` 不再跟普通的依赖共享 `features` -- `Dev-dependencies` 的 `features` 不会被启用,除非正在构建的对象需要它们(例如测试对象、示例对象等) +- `build-dependencies` 和 `proc-macros` 不再跟普通的依赖共享 `features` +- `dev-dependencies` 的 `features` 不会被启用,除非正在构建的对象需要它们(例如测试对象、示例对象等) 对于部分场景而言,feature 同一化确实是需要避免的,例如,一个构建依赖开启了 `std` feature,而同一个依赖又被用于 `no_std` 环境,很明显,开启 `std` 将导致错误的发生。 @@ -249,7 +249,7 @@ V2 版本的解析器可以在某些情况下避免 feature 同一化的发生 ## 构建脚本 -[构建脚本](https://course.rs/cargo/reference/build-script/intro.html)可以通过 `CARGO_FEATURE_` 环境变量获取启用的 `feauture` 列表,其中 `` 是 feature 的名称,该名称被转换成大全写字母,且 `-` 被转换为 `_`。 +[构建脚本](https://course.rs/cargo/reference/build-script/intro.html)可以通过 `CARGO_FEATURE_` 环境变量获取启用的 `feature` 列表,其中 `` 是 feature 的名称,该名称被转换成大全写字母,且 `-` 被转换为 `_`。 ## required-features @@ -257,14 +257,14 @@ V2 版本的解析器可以在某些情况下避免 feature 同一化的发生 ## SemVer 兼容性 -启用一个 feautre 不应该引入一个不兼容 SemVer 的改变。例如,启用的 feature 不应该改变现有的 API,因为这会给用户造成不兼容的破坏性变更。 如果大家想知道哪些变化是兼容的,可以参见[官方文档](https://doc.rust-lang.org/stable/cargo/reference/semver.html)。 +启用一个 feature 不应该引入一个不兼容 SemVer 的改变。例如,启用的 feature 不应该改变现有的 API,因为这会给用户造成不兼容的破坏性变更。 如果大家想知道哪些变化是兼容的,可以参见[官方文档](https://doc.rust-lang.org/stable/cargo/reference/semver.html)。 总之,在新增/移除 feature 或可选依赖时,你需要小心,因此这些可能会造成向后不兼容性。更多信息参见[这里](https://doc.rust-lang.org/stable/cargo/reference/semver.html#cargo),简单总结如下: - 在发布 `minor` 版本时,以下通常是安全的: - [新增 feature](https://doc.rust-lang.org/stable/cargo/reference/semver.html#cargo-feature-add) 或[可选依赖](https://doc.rust-lang.org/stable/cargo/reference/semver.html#cargo-dep-add) - [修改某个依赖的 features](https://doc.rust-lang.org/stable/cargo/reference/semver.html#cargo-change-dep-feature) -- 在发布 `minor` 时,以下操作应该避免: +- 在发布 `minor` 版本时,以下操作应该避免: - [移除 feature](https://doc.rust-lang.org/stable/cargo/reference/semver.html#cargo-feature-remove) 或[可选依赖](https://doc.rust-lang.org/stable/cargo/reference/semver.html#cargo-remove-opt-dep) - [将现有的公有代码放在某个 feature 之后](https://doc.rust-lang.org/stable/cargo/reference/semver.html#cargo-remove-opt-dep) - [从 feature 列表中移除一个 feature](https://doc.rust-lang.org/stable/cargo/reference/semver.html#cargo-feature-remove-another)