工作区

工作区 是一个或多个包的集合,称为工作区成员,它们被一起管理。

工作区的要点是

  • 常见的命令可以跨所有工作区成员运行,例如 cargo check --workspace
  • 所有包共享一个公共的 Cargo.lock 文件,该文件位于工作区根目录中。
  • 所有包共享一个公共的 输出目录,该目录默认为工作区根目录中名为 target 的目录。
  • 共享包元数据,例如使用 workspace.package
  • Cargo.toml 中的 [patch][replace][profile.*] 部分仅在清单中被识别,而在成员 crate 的清单中被忽略。

工作区的根 Cargo.toml 支持以下部分

  • [workspace] — 定义工作区。
    • resolver — 设置要使用的依赖解析器。
    • members — 要包含在工作区中的包。
    • exclude — 要从工作区中排除的包。
    • default-members — 当未选择特定包时要操作的包。
    • package — 用于在包中继承的键。
    • dependencies — 用于在包依赖项中继承的键。
    • lints — 用于在包 lint 中继承的键。
    • metadata — 外部工具的额外设置。
  • [patch] — 覆盖依赖项。
  • [replace] — 覆盖依赖项(已弃用)。
  • [profile] — 编译器设置和优化。

[workspace] 部分

要创建工作区,请将 [workspace] 表添加到 Cargo.toml

[workspace]
# ...

至少,工作区必须有一个成员,或者具有根包或者作为虚拟清单。

根包

如果 [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
authors = ["Alice <[email protected]>", "Bob <[email protected]>"]

虚拟工作区

或者,可以创建一个 Cargo.toml 文件,其中包含 [workspace] 部分,但不包含 [package] 部分。这称为虚拟清单。当没有“主”包,或者您想将所有包组织在单独的目录中时,这通常很有用。

# [PROJECT_DIR]/Cargo.toml
[workspace]
members = ["hello_world"]
resolver = "2"
# [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 = "2021"     # the edition, will have no effect on a resolver used in the workspace
authors = ["Alice <[email protected]>", "Bob <[email protected]>"]

通过拥有一个没有根包的工作区,

membersexclude 字段

membersexclude 字段定义了哪些包是工作区的成员

[workspace]
members = ["member1", "path/to/member2", "crates/*"]
exclude = ["crates/foo", "path/to/other"]

位于工作区目录中的所有 path 依赖项都会自动成为成员。可以使用 members 键列出其他成员,该键应是包含 Cargo.toml 文件的目录的字符串数组。

members 列表还支持 glob 来匹配多个路径,使用典型的文件名 glob 模式,如 *?

exclude 键可用于防止路径被包含在工作区中。如果某些路径依赖项根本不希望在工作区中,或者使用 glob 模式并且您想删除一个目录,这会很有用。

当位于工作区内的子目录中时,Cargo 会自动在父目录中搜索具有 [workspace] 定义的 Cargo.toml 文件,以确定要使用哪个工作区。成员 crate 中的 package.workspace 清单键可用于指向工作区的根,以覆盖此自动搜索。如果成员不在工作区根目录的子目录内,则手动设置会很有用。

包选择

在工作区中,与包相关的 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 来继承这些键。

支持的键

authorscategories
descriptiondocumentation
editionexclude
homepageinclude
keywordslicense
license-filepublish
readmerepository
rust-versionversion
  • license-filereadme 相对于工作区根目录
  • includeexclude 相对于您的包根目录

示例

# [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

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 中的数据(如果这对于相关工具来说有意义的话)。