工作空间
工作空间 是一个或多个包的集合,这些包称为 工作空间成员 ,它们被统一管理。
工作空间的关键目标是:
- 常规命令可以对所有工作空间成员运行,比如
cargo check --workspace。 - 所有包共享
Cargo.lock文件,该文件在 工作空间根 下。 - 所有包共享 输出目录 ,默认为 工作空间根 下的
target。 - 共享包的metadata,比如
workspace.package。 [patch],[replace]和[profile.*]仅识别 根 配置清单Cargo.toml中的,忽略其成员 crate 配置清单中的。
在 Cargo.toml 中, [workspace] 表支持以下部分:
[workspace]](#the-workspace-section) — 工作空间的定义。resolver— 设置要使用的依赖解析器。members— 包含在工作空间的包。exclude— 从工作空间排除的包。default-members— 当没有选择特定的包时,操作默认项。package— 可被成员继承的键。dependencies— 可被成员继承的依赖。metadata— 外部插件的附加设置。
[patch]— 覆盖依赖。[replace]— 覆盖依赖(已废弃)。[profile]— 编译器设置和优化。
[workspace] 部分
要创建工作空间,你需要在 Cargo.toml 中添加 [workspace] 表:
[workspace]
# ...
工作空间至少要有一个成员,要么是一个根package,或者是虚拟配置清单。
Root package
如果在已定义 [package] 的 Cargo.toml 中,添加 [workspace] 部分 ,该package就是工作空间的 Root package 。 工作空间根 指的是工作空间 Cargo.toml 所在的目录。
[workspace]
[package]
name = "hello_world" # 包的名称
version = "0.1.0" # 当前语义化版本
authors = ["Alice <a@example.com>", "Bob <b@example.com>"]
虚拟工作空间
或者,创建 Cargo.toml 的文件中,有 [workspace] 表,没有 [package] 表,则称为 虚拟配置清单 。
这通常在没有 "主" 包时很有用,可把拥有的各个包放在不同的目录里。
# [PROJECT_DIR]/Cargo.toml
[workspace]
members = ["hello_world"]
# [PROJECT_DIR]/hello_world/Cargo.toml
[package]
name = "hello_world" # package名称
version = "0.1.0" # 当前的语义化版本
authors = ["Alice <a@example.com>", "Bob <b@example.com>"]
members 和 exclude 字段
members 和 exclude 字段定义哪些包是工作空间的成员:
[workspace]
members = ["member1", "path/to/member2", "crates/*"]
exclude = ["crates/foo", "path/to/other"]
工作空间目录中的所有 path 依赖 自动成为成员。
可以用 Cargo.toml 中 members 键,以字符串数组列出其他成员。
members 列表支持用 globs 通配符来匹配多个路径,使用典型的文件名通配符模式 * 和 ? 。
exclude 键可以防止路径自动包含到工作空间,排除某些路径依赖,可用通配符模式。
当在工作空间子目录内操作时,Cargo会自动搜索父目录中的 Cargo.toml 文件,以其中的 [workspace] 定义,来确定使用的工作空间。
在工作空间成员可以使用 package.workspace 配置键来配置工作空间根,以覆盖向上自动搜索。当成员不在工作空间根的子目录内时,就需要手动设置。
Package 部分
在工作空间中,与包有关的cargo命令,如 cargo build ,可以使用 -p / -package 或 -workspace 命令行标志来选择成员进行操作。
如果这两个标志都没有指定,Cargo将使用当前工作目录的包。如果是无根包的 虚拟工作空间 ,
命令将应用于所有成员 (同指定 --workspace 一样) 。 另请参阅 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"]
当指定 default-members 时,添加的必须是 members 的子集。
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
dependencies 表
workspace.dependencies 是可以定义工作空间成员所能继承的依赖。
指定工作空间依赖与 package依赖 类似,除了:
- 此表中的依赖不能声明为
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
metadata 表
Cargo忽略对 workspace.metadata 表的检查,不会发出警告。一些工具插件可以在 Cargo.toml 的这一部分中存储配置。比如:
[workspace]
members = ["member1", "member2"]
[workspace.metadata.webcontents]
root = "path/to/webproject"
tool = ["npm", "run", "build"]
# ...
在包中也有类似的表 package.metadata 。虽然cargo没有为表的内容指定格式,
但建议外部工具以一致的方式使用,对工具来说有意义就好,在 package.metadata 中缺少数据时,会参考 workspace.metadata 中的数据。