Workspaces
Aworkspace is a collection of one or more packages, calledworkspacemembers, that are managed together.
The key points of workspaces are:
- Common commands can run across all workspace members, like
cargo check --workspace. - All packages share a common
Cargo.lockfile which resides in theworkspace root. - All packages share a commonoutput directory, which defaults to adirectory named
targetin theworkspace root. - Sharing package metadata, like with
workspace.package. - The
[patch],[replace]and[profile.*]sections inCargo.tomlare only recognized in theroot manifest, andignored in member crates’ manifests.
The rootCargo.toml of a workspace 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.lints— Keys for inheriting in package lints.metadata— Extra settings for external tools.
[patch]— Override dependencies.[replace]— Override dependencies (deprecated).[profile]— Compiler settings and optimizations.
The[workspace] section
To create a workspace, you add the[workspace] table to aCargo.toml:
[workspace]# ...At minimum, a workspace has to have a member, either with a root package or asa virtual manifest.
Root package
If the[workspace] section is added to aCargo.toml that already defines a[package], the package istheroot package of the workspace. Theworkspace root is the directorywhere the workspace’sCargo.toml is located.
[workspace][package]name = "hello_world" # the name of the packageversion = "0.1.0" # the current version, obeying semverVirtual workspace
Alternatively, aCargo.toml file can be created with a[workspace] sectionbut without a[package] section. This is called avirtualmanifest. This is typically useful when there isn’t a “primary” package, oryou want to keep all the packages organized in separate directories.
# [PROJECT_DIR]/Cargo.toml[workspace]members = ["hello_world"]resolver = "3"# [PROJECT_DIR]/hello_world/Cargo.toml[package]name = "hello_world" # the name of the packageversion = "0.1.0" # the current version, obeying semveredition = "2024" # the edition, will have no effect on a resolver used in the workspaceBy having a workspace without a root package,
resolvermust beset explicitly in virtual workspaces as they have nopackage.editionto infer it fromresolver version.- Commands run in the workspace root will run against all workspacemembers by default, see
default-members.
Themembers andexclude fields
Themembers andexclude fields define which packages are members ofthe workspace:
[workspace]members = ["member1", "path/to/member2", "crates/*"]exclude = ["crates/foo", "path/to/other"]Allpath dependencies residing in the workspace directory automaticallybecome members. Additional members can be listed with themembers key, whichshould be an array of strings containing directories withCargo.toml files.
Themembers list also supportsglobs to match multiple paths, usingtypical filename glob patterns like* and?.
Theexclude key can be used to prevent paths from being included in aworkspace. This can be useful if some path dependencies aren’t desired to bein the workspace at all, or using a glob pattern and you want to remove adirectory.
When inside a subdirectory within the workspace, Cargo will automaticallysearch the parent directories for aCargo.toml file with a[workspace]definition to determine which workspace to use. Thepackage.workspacemanifest key can be used in member crates to point at a workspace’s root tooverride this automatic search. The manual setting can be useful if the memberis not inside a subdirectory of the workspace root.
Package selection
In a workspace, package-related Cargo commands likecargo build can usethe-p /--package or--workspace command-line flags to determine whichpackages to operate on. If neither of those flags are specified, Cargo willuse the package in the current working directory. However, if the current directory isa workspace root, thedefault-members will be used.
Thedefault-members field
Thedefault-members field specifies paths ofmembers tooperate on when in the workspace root and the package selection flags are notused:
[workspace]members = ["path/to/member1", "path/to/member2", "path/to/member3/*"]default-members = ["path/to/member2", "path/to/member3/foo"]Note: when aroot package is present,you can only operate on it using
--packageand--workspaceflags.
When unspecified, theroot package will be used.In the case of avirtual workspace, all members will be used(as if--workspace were specified on the command-line).
Thepackage table
Theworkspace.package table is where you define keys that can beinherited by members of a workspace. These keys can be inherited bydefining 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-fileandreadmeare relative to the workspace rootincludeandexcludeare relative to your package root
Example:
# [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 = trueauthors.workspace = truedescription.workspace = truedocumentation.workspace = trueMSRV: Requires 1.64+
Thedependencies table
Theworkspace.dependencies table is where you define dependencies to beinherited by members of a workspace.
Specifying a workspace dependency is similar topackage dependencies except:
- Dependencies from this table cannot be declared as
optional featuresdeclared in this table are additive with thefeaturesfrom[dependencies]
You can theninherit 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 = trueMSRV: Requires 1.64+
Thelints table
Theworkspace.lints table is where you define lint configuration to be inherited by members of a workspace.
Specifying a workspace lint configuration is similar topackage lints.
Example:
# [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 = trueMSRV: Respected as of 1.74
Themetadata table
Theworkspace.metadata table is ignored by Cargo and will not be warnedabout. This section can be used for tools that would like to store workspaceconfiguration inCargo.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 atpackage.metadata. While cargo does not specify aformat for the content of either of these tables, it is suggested thatexternal tools may wish to use them in a consistent fashion, such as referringto the data inworkspace.metadata if data is missing frompackage.metadata,if that makes sense for the tool in question.