工作区
一个工作区是一系列一个或多个被称为工作区成员的包的集合,它们被统一管理。
工作区的要点包括
- 通用命令可以应用于所有工作区成员,例如
cargo check --workspace
。 - 所有包共享一个共同的
Cargo.lock
文件,它位于 工作区根目录。 - 所有包共享一个共同的 输出目录,默认是一个名为
target
的目录,位于 工作区根目录。 - 共享包的元数据,例如通过
workspace.package
。 Cargo.toml
文件中的[patch]
、[replace]
和[profile.*]
部分只在 根 manifest 中被识别,并在成员 crate 的 manifest 中被忽略。
工作区的根 Cargo.toml
文件支持以下部分
[workspace]
— 定义一个工作区。resolver
— 设置要使用的依赖解析器。members
— 要包含在工作区中的包。exclude
— 要从工作区中排除的包。default-members
— 未选择特定包时要操作的包。package
— 包中可继承的键。dependencies
— 包依赖项中可继承的键。lints
— 包 lint 中可继承的键。metadata
— 外部工具的额外设置。
[patch]
— 覆盖依赖项。[replace]
— 覆盖依赖项 (已弃用)。[profile]
— 编译器设置和优化。
[workspace]
部分
要创建一个工作区,需要在 Cargo.toml
文件中添加 [workspace]
表
[workspace]
# ...
一个工作区至少需要有一个成员,可以是一个根包,也可以是一个虚拟 manifest。
根包
如果将 [workspace]
部分 添加到已经定义了 [package]
的 Cargo.toml
文件中,则该包就是工作区的 根包。工作区根目录 是工作区的 Cargo.toml
所在目录。
[workspace]
[package]
name = "hello_world" # the name of the package
version = "0.1.0" # the current version, obeying semver
虚拟工作区
或者,可以创建一个包含 [workspace]
部分但不包含 [package]
部分 的 Cargo.toml
文件。这被称为一个 虚拟 manifest。这通常在你没有“主”包,或者想将所有包组织在单独的目录中时很有用。
# [PROJECT_DIR]/Cargo.toml
[workspace]
members = ["hello_world"]
resolver = "3"
# [PROJECT_DIR]/hello_world/Cargo.toml
[package]
name = "hello_world" # the name of the package
version = "0.1.0" # the current version, obeying semver
edition = "2024" # the edition, will have no effect on a resolver used in the workspace
如果一个工作区没有根包,则
resolver
必须在虚拟工作区中显式设置,因为它们没有package.edition
可以从中推断出 解析器版本。- 在工作区根目录中运行的命令默认将应用于所有工作区成员,参见
default-members
。
members
和 exclude
字段
members
和 exclude
字段定义了哪些包是工作区的成员
[workspace]
members = ["member1", "path/to/member2", "crates/*"]
exclude = ["crates/foo", "path/to/other"]
所有位于工作区目录中的 path
依赖 会自动成为成员。可以通过 members
键列出额外的成员,它应该是一个字符串数组,包含具有 Cargo.toml
文件的目录。
members
列表还支持 通配符模式 用于匹配多个路径,使用典型的文件名通配符模式,如 *
和 ?
。
exclude
键可以用来防止某些路径被包含在工作区中。如果某些路径依赖项不希望包含在工作区中,或者你使用了通配符模式并想排除某个目录,这会很有用。
当在工作区内的子目录中时,Cargo 会自动向上搜索父目录,查找包含 [workspace]
定义的 Cargo.toml
文件来确定使用哪个工作区。package.workspace
manifest 键可以在成员 crate 中用来指定工作区的根目录,从而覆盖这种自动搜索。如果成员不在工作区根目录的子目录中,手动设置此项会很有用。
包选择
在工作区中,与包相关的 Cargo 命令,如 cargo build
,可以使用 -p
/ --package
或 --workspace
命令行标志来确定要操作哪些包。如果未指定这些标志,Cargo 将使用当前工作目录中的包。然而,如果当前目录是工作区根目录,将使用 default-members
。
default-members
字段
default-members
字段指定了在工作区根目录中且未使用包选择标志时,要操作的 成员 的路径
[workspace]
members = ["path/to/member1", "path/to/member2", "path/to/member3/*"]
default-members = ["path/to/member2", "path/to/member3/foo"]
注意:当存在 根包 时,你只能使用
--package
和--workspace
标志对其进行操作。
未指定时,将使用 根包。对于 虚拟工作区,将使用所有成员 (就像在命令行上指定了 --workspace
一样)。
package
表
workspace.package
表用于定义工作区成员可以继承的键。通过在成员包中定义 {key}.workspace = true
,可以继承这些键。
支持的键
authors | categories |
description | documentation |
edition | exclude |
homepage | include |
keywords | license |
license-file | publish |
readme | repository |
rust-version | version |
license-file
和readme
相对于工作区根目录include
和exclude
相对于你的包根目录
示例
# [PROJECT_DIR]/Cargo.toml
[workspace]
members = ["bar"]
[workspace.package]
version = "1.2.3"
authors = ["Nice Folks"]
description = "A short description of my package"
documentation = "https://example.com/bar"
# [PROJECT_DIR]/bar/Cargo.toml
[package]
name = "bar"
version.workspace = true
authors.workspace = true
description.workspace = true
documentation.workspace = true
MSRV: 需要 1.64+
dependencies
表
workspace.dependencies
表用于定义工作区成员可以继承的依赖项。
指定工作区依赖项类似于 包依赖项,除了
- 此表中的依赖项不能声明为
optional
- 在此表中声明的
features
是累加性的,与来自[dependencies]
的features
叠加
然后你可以将工作区依赖项作为包依赖项继承
示例
# [PROJECT_DIR]/Cargo.toml
[workspace]
members = ["bar"]
[workspace.dependencies]
cc = "1.0.73"
rand = "0.8.5"
regex = { version = "1.6.0", default-features = false, features = ["std"] }
# [PROJECT_DIR]/bar/Cargo.toml
[package]
name = "bar"
version = "0.2.0"
[dependencies]
regex = { workspace = true, features = ["unicode"] }
[build-dependencies]
cc.workspace = true
[dev-dependencies]
rand.workspace = true
MSRV: 需要 1.64+
lints
表
workspace.lints
表用于定义工作区成员可以继承的 lint 配置。
指定工作区 lint 配置类似于 包 lint。
示例
# [PROJECT_DIR]/Cargo.toml
[workspace]
members = ["crates/*"]
[workspace.lints.rust]
unsafe_code = "forbid"
# [PROJECT_DIR]/crates/bar/Cargo.toml
[package]
name = "bar"
version = "0.1.0"
[lints]
workspace = true
MSRV: 从 1.74 版本开始生效
metadata
表
workspace.metadata
表会被 Cargo 忽略,并且不会产生警告。此部分可用于希望在 Cargo.toml
中存储工作区配置的工具。例如
[workspace]
members = ["member1", "member2"]
[workspace.metadata.webcontents]
root = "path/to/webproject"
tool = ["npm", "run", "build"]
# ...
在包级别有一个类似的表,位于 package.metadata
。虽然 Cargo 没有指定这些表的具体内容格式,但建议外部工具可以以一致的方式使用它们,例如,如果在 package.metadata
中缺少数据时,可以参考 workspace.metadata
中的数据(如果这对该工具有意义)。