A workspace is a collection of one or more packages, called workspace members, that are managed together.
The key points of workspaces are:
cargo check --workspace
.Cargo.lock
file which resides in the workspace root.target
in the workspace root.workspace.package
.[patch]
, [replace]
and [profile.*]
sections in Cargo.toml
are only recognized in the root manifest, and ignored in member crates' manifests.In the Cargo.toml
, the [workspace]
table supports the following sections:
[workspace]
--- Defines a workspace.resolver
--- Sets the dependency resolver to use.members
--- Packages to include in the workspace.exclude
--- Packages to exclude from the workspace.default-members
--- Packages to operate on when a specific package wasn't selected.package
--- Keys for inheriting in packages.dependencies
--- Keys for inheriting in package dependencies.metadata
--- Extra settings for external tools.[patch]
--- Override dependencies.[replace]
--- Override dependencies (deprecated).[profile]
--- Compiler settings and optimizations.[workspace]
sectionTo create a workspace, you add the [workspace]
table to a Cargo.toml
:
[workspace] # ...
At minimum, a workspace has to have a member, either with a root package or as a virtual manifest.
If the [workspace]
section is added to a Cargo.toml
that already defines a [package]
, the package is the root package of the workspace. The workspace root is the directory where the workspace's Cargo.toml
is located.
[workspace] [package] name = "hello_world" # the name of the package version = "0.1.0" # the current version, obeying semver authors = ["Alice <a@example.com>", "Bob <b@example.com>"]
Alternatively, a Cargo.toml
file can be created with a [workspace]
section but without a [package]
section. This is called a virtual manifest. This is typically useful when there isn't a “primary” package, or you want to keep all the packages organized in separate directories.
# [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 <a@example.com>", "Bob <b@example.com>"]
Note that in a virtual manifest the resolver = "2"
should be specified manually. It is usually deduced from the package.edition
field which is absent in virtual manifests and the edition field of a member won't affect the resolver used by the workspace.
members
and exclude
fieldsThe members
and exclude
fields define which packages are members of the workspace:
[workspace] members = ["member1", "path/to/member2", "crates/*"] exclude = ["crates/foo", "path/to/other"]
All path
dependencies residing in the workspace directory automatically become members. Additional members can be listed with the members
key, which should be an array of strings containing directories with Cargo.toml
files.
The members
list also supports globs to match multiple paths, using typical filename glob patterns like *
and ?
.
The exclude
key can be used to prevent paths from being included in a workspace. This can be useful if some path dependencies aren't desired to be in the workspace at all, or using a glob pattern and you want to remove a directory.
When inside a subdirectory within the workspace, Cargo will automatically search the parent directories for a Cargo.toml
file with a [workspace]
definition to determine which workspace to use. The package.workspace
manifest key can be used in member crates to point at a workspace's root to override this automatic search. The manual setting can be useful if the member is not inside a subdirectory of the workspace root.
In a workspace, package-related Cargo commands like cargo build
can use the -p
/ --package
or --workspace
command-line flags to determine which packages to operate on. If neither of those flags are specified, Cargo will use the package in the current working directory. If the current directory is a virtual workspace, it will apply to all members (as if --workspace
were specified on the command-line). See also default-members
.
default-members
fieldThe optional default-members
key can be specified to set the members to operate on when in the workspace root and the package selection flags are not used:
[workspace] members = ["path/to/member1", "path/to/member2", "path/to/member3/*"] default-members = ["path/to/member2", "path/to/member3/foo"]
When specified, default-members
must expand to a subset of members
.
package
tableThe workspace.package
table is where you define keys that can be inherited by members of a workspace. These keys can be inherited by defining them in the member package with {key}.workspace = true
.
Keys that are supported:
authors | categories |
description | documentation |
edition | exclude |
homepage | include |
keywords | license |
license-file | publish |
readme | repository |
rust-version | version |
license-file
and readme
are relative to the workspace rootinclude
and exclude
are relative to your package rootExample:
# [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
tableThe workspace.dependencies
table is where you define dependencies to be inherited by members of a workspace.
Specifying a workspace dependency is similar to package dependencies except:
optional
features
declared in this table are additive with the features
from [dependencies]
You can then inherit the workspace dependency as a package dependency
Example:
# [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
tableThe workspace.metadata
table is ignored by Cargo and will not be warned about. This section can be used for tools that would like to store workspace configuration in Cargo.toml
. For example:
[workspace] members = ["member1", "member2"] [workspace.metadata.webcontents] root = "path/to/webproject" tool = ["npm", "run", "build"] # ...
There is a similar set of tables at the package level at package.metadata
. While cargo does not specify a format for the content of either of these tables, it is suggested that external tools may wish to use them in a consistent fashion, such as referring to the data in workspace.metadata
if data is missing from package.metadata
, if that makes sense for the tool in question.