This adds new fields to [workspace]
that allow workspaces to be nested inside of each other.
rust-lang/cargo contains multiple crates but they do not exist in a workspace because rust-lang/rust pulls cargo
into its workspace via a git submodule. This requires manually running tools across each crate in the rust-lang/cargo repo, increasing the risk that something will fall through the cracks in updating the processess (CI or manual) and increasing the friction for splitting content out into additional crates, as desired.
NOTE(weihanglo): we need to figure out some more compelling motivations. Something only nested workspaces can solve. As we haven't yet make a consensus on Cargo adopting workspace.
Open Questions
This is intended to go into the workspace reference
[workspace]
tableworkspace.members
To nest a workspace, the root workspace would add it to members
. Any of the nested workspaces members would automatically be included as a member of the root workspace. If a member of a nested workspace is added to the root workspaces members
it will be ignored. This allows the nested workspace to freely add, remove, or move crates and no updates are needed in the root workspace, this is very helpful for git submodules.
workspace.default-members
When using default-members
in the root workspace and a nested workspace is added, all of its default-members
are added. If the nested workspace does not specify default-members
and its a virtual workspace all of its members
are added. If the nested workspace does not specify default-members
and it's a non-virtual workspace, only the root crate is added. This mirrors how package selection currently works within a workspace.
default-members |
Virtual workspace | Non-virtual workspace |
---|---|---|
Specified | Uses default-members |
Uses default-members |
Unspecified | All workspace members | Only the root crate |
workspace.nested
Any worksapce that is going to be nested must set the new field nested
inside of [workspace]
. It can be specifed in a few ways:
[workspace]
nested = true
When the parent workspace might not be available, such as when the parent workspace pulls in the nested workspace through a git-submodule, the nested workspace can declare the root workspace as optional
:
[workspace]
nested = { optional = true }
Just as workspace members need to specify workspace = "path"
when they are not hierarchically below the workspace, nested workspaces must also specify the path when they are not below the root workspace:
[workspace]
nested = { path = "../parent" }
This new fields lets cargo
know to keep searching for the root workspace, since it normally would stop searching for the root workspace at the first one encountered.
workspace.name
One major concern is the workflow of using nested workspaces. To make it so you can run cargo
commands on a specfic nested workspace all nested workspaces and the root workspace must be named. You can set the name of a workspace by setting the new workspace.name
field.
[workspace]
name = "cargo"
These names will need to be distinct from one another but will be in a differnt namespace than packages.
--workspace
It was considered to make --workspace
work similar to --package
, where if it is blank a list of possible worksspaces would be displayed. It was decided against this as it would be a breaking change. To have a way to still be able
--nested
--nested
is a new CLI flag that can be used with the new workspace.name
field. It is meant to be used in the same way as --package
. When --nested
is blank it will show a list of possible nested targets. When a workspace name is specified (--nested cargo
) the command will only be ran on that workspace. Packages within the workspace to operate on will adhere to the guidelines described in Package selection
Cargo.lock
will be usedworkspace.resolver
will be used[patch]
and [replace]
will be ignored in any nested workspace
[patch]
, [replace]
, and [profile]
sections will be overwritten by their corresponding sections in the parent workspace, if present. The nested workspace will not have access to entries that only exist in the root workspace
optional = true
rust-lang
to control the behavior for all binariesoptional = true
cargo check
in a crate, how does it know what workspaces to use?). The parent workspace will discover the child workspace like any other workspace member.nested = {}
table have fields to control how to merge patch, replace, and profileCARGO_TARGET_DIR
for setting a share build cache directory..cargo/config.toml
for setting sharing rustflags and other options. Currently supports
epage worked on a proprietary build system that was a confederation of workspaces for mostly compiled code (non-Rust). Each package had its own equivelant of requirements and locked versions and its own target directory and each binary package had its own equivalent of profiles. You could build the package on its own. If a workspace was built, it would update the lockfile of the package but the most nested workspace had highest precedence. In a cross-team, cross-product setup, this allowd more local control to adapt to more specialized needs than global control would allow, in dependencies, profiles, etc.
Past discussions