Skip to content

Commit

Permalink
Auto merge of #11082 - epage:workspace, r=weihanglo
Browse files Browse the repository at this point in the history
docs(ref): Clarify workspace settings

### What does this PR try to resolve?

In reviewing the status of #10625, I was reminded
- that we are having growing pains with the workspace documentation
- that `workspace.resolver` isn't documented

So I re-organized the workspace docs to have a high level intro / behavior description and then to focus on being a field reference, much like `manifest.md`.   I could see splitting it specifically into tutorial/reference like the overriding dependencies document does it.

When adding `workspace.resolver`, I remembered in the nested workspace discussion there were other workspace related sections that are not present.  We now link out to `profile`, `patch`, and `replace`.  In doing this, I realized that `patch` and `replace` do not specify their workspace behavior, so I do that.

### How should we test and review this PR?

Look at it commit by commit to get more digestible chunks.  Unfortunately, the first commit didn't split up so easily.

### Additional information

Other information you want to mention in this PR, such as prior arts,
future extensions, an unresolved problem, or a TODO list.
-->
<!-- homu-ignore:end -->
  • Loading branch information
bors committed Sep 16, 2022
2 parents ef7ab8b + f39f8dc commit 362ce33
Show file tree
Hide file tree
Showing 6 changed files with 114 additions and 62 deletions.
4 changes: 2 additions & 2 deletions src/doc/src/reference/manifest.md
Original file line number Diff line number Diff line change
Expand Up @@ -516,7 +516,7 @@ 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.

[workspace-metadata]: workspaces.md#the-workspacemetadata-table
[workspace-metadata]: workspaces.md#the-metadata-table

#### The `default-run` field

Expand Down Expand Up @@ -603,7 +603,7 @@ more detail.
"#the-required-features-field-optional": "cargo-targets.html#the-required-features-field",
"#building-dynamic-or-static-libraries": "cargo-targets.html#the-crate-type-field",
"#the-workspace-section": "workspaces.html#the-workspace-section",
"#virtual-manifest": "workspaces.html",
"#virtual-workspace": "workspaces.html",
"#package-selection": "workspaces.html#package-selection",
"#the-features-section": "features.html#the-features-section",
"#rules": "features.html",
Expand Down
8 changes: 8 additions & 0 deletions src/doc/src/reference/overriding-dependencies.md
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,10 @@ also be patched with versions of crates that already exist. If a source is
patched with a crate version that already exists in the source, then the
source's original crate is replaced.

Cargo only looks at the patch settings in the `Cargo.toml` manifest at the
root of the workspace. Patch settings defined in dependencies will be
ignored.

### The `[replace]` section

> **Note**: `[replace]` is deprecated. You should use the
Expand All @@ -313,6 +317,10 @@ dependencies, except that you can't specify features. Note that when a crate
is overridden the copy it's overridden with must have both the same name and
version, but it can come from a different source (e.g., git or a local path).

Cargo only looks at the replace settings in the `Cargo.toml` manifest at the
root of the workspace. Replace settings defined in dependencies will be
ignored.

### `paths` overrides

Sometimes you're only temporarily working on a crate and you don't want to have
Expand Down
2 changes: 1 addition & 1 deletion src/doc/src/reference/resolver.md
Original file line number Diff line number Diff line change
Expand Up @@ -428,7 +428,7 @@ members = ["member1", "member2"]
resolver = "2"
```

[virtual workspace]: workspaces.md#virtual-manifest
[virtual workspace]: workspaces.md#virtual-workspace
[features-2]: features.md#feature-resolver-version-2

## Recommendations
Expand Down
2 changes: 1 addition & 1 deletion src/doc/src/reference/specifying-dependencies.md
Original file line number Diff line number Diff line change
Expand Up @@ -489,7 +489,7 @@ rand = { workspace = true, optional = true }

[crates.io]: https://crates.io/
[dev-dependencies]: #development-dependencies
[workspace.dependencies]: workspaces.md#the-workspacedependencies-table
[workspace.dependencies]: workspaces.md#the-dependencies-table
[optional]: features.md#optional-dependencies
[features]: features.md

Expand Down
6 changes: 3 additions & 3 deletions src/doc/src/reference/unstable.md
Original file line number Diff line number Diff line change
Expand Up @@ -1358,7 +1358,7 @@ for more information.
### Workspace Inheritance

Workspace Inheritance has been stabilized in the 1.64 release.
See [workspace.package](workspaces.md#the-workspacepackage-table),
[workspace.dependencies](workspaces.md#the-workspacedependencies-table),
See [workspace.package](workspaces.md#the-package-table),
[workspace.dependencies](workspaces.md#the-dependencies-table),
and [inheriting-a-dependency-from-a-workspace](specifying-dependencies.md#inheriting-a-dependency-from-a-workspace)
for more information.
for more information.
154 changes: 99 additions & 55 deletions src/doc/src/reference/workspaces.md
Original file line number Diff line number Diff line change
@@ -1,41 +1,86 @@
## Workspaces

A *workspace* is a collection of one or more packages that share common
dependency resolution (with a shared `Cargo.lock`), output directory, and
various settings such as profiles. Packages that are part of a workspaces are
called *workspace members*. There are two flavours of workspaces: as root
package or as virtual manifest.
A *workspace* is a collection of one or more packages, called *workspace
members*, that are managed together.

### Root package
The key points of workspaces are:

* Common commands can run across all workspace members, like `cargo check --workspace`.
* All packages share a common [`Cargo.lock`] file which resides in the
*workspace root*.
* All packages share a common [output directory], which defaults to a
directory named `target` in the *workspace root*.
* Sharing package metadata, like with [`workspace.package`](#the-package-table).
* The [`[patch]`][patch], [`[replace]`][replace] and [`[profile.*]`][profiles]
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]`](#the-workspace-section) — Defines a workspace.
* [`resolver`](resolver.md#resolver-versions) — Sets the dependency resolver to use.
* [`members`](#the-members-and-exclude-fields) — Packages to include in the workspace.
* [`exclude`](#the-members-and-exclude-fields) — Packages to exclude from the workspace.
* [`default-members`](#the-default-members-field) — Packages to operate on when a specific package wasn't selected.
* [`package`](#the-package-table) — Keys for inheriting in packages.
* [`dependencies`](#the-dependencies-table) — Keys for inheriting in package dependencies.
* [`metadata`](#the-metadata-table) — Extra settings for external tools.
* [`[patch]`](overriding-dependencies.md#the-patch-section) — Override dependencies.
* [`[replace]`](overriding-dependencies.md#the-replace-section) — Override dependencies (deprecated).
* [`[profile]`](profiles.md) — Compiler settings and optimizations.

### The `[workspace]` section

To create a workspace, you add the `[workspace]` table to a `Cargo.toml`:
```toml
[workspace]
# ...
```

A workspace can be created by adding a [`[workspace]`
section](#the-workspace-section) to `Cargo.toml`. This can be added to a
`Cargo.toml` that already defines a `[package]`, in which case the package is
At minimum, a workspace has to have a member, either with a root package or as
a virtual manifest.

#### Root package

If the [`[workspace]` section](#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.

### Virtual manifest
```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]>"]
```

<a id="virtual-manifest"></a>
#### Virtual workspace

Alternatively, a `Cargo.toml` file can be created with a `[workspace]` section
but without a [`[package]` section][package]. 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.

### Key features

The key points of workspaces are:
```toml
# [PROJECT_DIR]/Cargo.toml
[workspace]
members = ["hello_world"]
```

* All packages share a common `Cargo.lock` file which resides in the
*workspace root*.
* All packages share a common [output directory], which defaults to a
directory named `target` in the *workspace root*.
* The [`[patch]`][patch], [`[replace]`][replace] and [`[profile.*]`][profiles]
sections in `Cargo.toml` are only recognized in the *root* manifest, and
ignored in member crates' manifests.
```toml
# [PROJECT_DIR]/hello_world/Cargo.toml
[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]>"]
```

### The `[workspace]` section
### The `members` and `exclude` fields

The `[workspace]` table in `Cargo.toml` defines which packages are members of
The `members` and `exclude` fields define which packages are members of
the workspace:

```toml
Expand All @@ -56,26 +101,24 @@ 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.

An empty `[workspace]` table can be used with a `[package]` to conveniently
create a workspace with the package and all of its path dependencies.

### Workspace selection

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.

### Package selection
#### Package selection

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).
a [virtual workspace](#virtual-workspace), it will apply to all members (as if
`--workspace` were specified on the command-line). See also
[`default-members`](#the-default-members-field).

### The `default-members` field

The 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
Expand All @@ -89,30 +132,7 @@ default-members = ["path/to/member2", "path/to/member3/foo"]

When specified, `default-members` must expand to a subset of `members`.

### The `workspace.metadata` table

The `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:

```toml
[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`][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.

### The `workspace.package` table
### The `package` table

The `workspace.package` table is where you define keys that can be
inherited by members of a workspace. These keys can be inherited by
Expand Down Expand Up @@ -157,7 +177,7 @@ description.workspace = true
documentation.workspace = true
```

### The `workspace.dependencies` table
### The `dependencies` table

The `workspace.dependencies` table is where you define dependencies to be
inherited by members of a workspace.
Expand Down Expand Up @@ -196,7 +216,31 @@ cc.workspace = true
rand.workspace = true
```

### The `metadata` table

The `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:

```toml
[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`][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.

[package]: manifest.md#the-package-section
[`Cargo.lock`]: ../guide/cargo-toml-vs-cargo-lock.md
[package-metadata]: manifest.md#the-metadata-table
[output directory]: ../guide/build-cache.md
[patch]: overriding-dependencies.md#the-patch-section
Expand Down

0 comments on commit 362ce33

Please sign in to comment.