Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stabilize Workspace Inheritance #10859

Merged
merged 1 commit into from
Jul 23, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/cargo/core/features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -416,7 +416,7 @@ features! {
(unstable, profile_rustflags, "", "reference/unstable.html#profile-rustflags-option"),

// Allow specifying rustflags directly in a profile
(unstable, workspace_inheritance, "", "reference/unstable.html#workspace-inheritance"),
(stable, workspace_inheritance, "1.64", "reference/unstable.html#workspace-inheritance"),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm assuming 1.64 is correct

}

pub struct Feature {
Expand Down
65 changes: 24 additions & 41 deletions src/cargo/util/toml/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1017,19 +1017,16 @@ pub enum MaybeWorkspace<T> {
impl<T> MaybeWorkspace<T> {
fn resolve<'a>(
self,
cargo_features: &Features,
label: &str,
get_ws_field: impl FnOnce() -> CargoResult<T>,
) -> CargoResult<T> {
match self {
MaybeWorkspace::Defined(value) => Ok(value),
MaybeWorkspace::Workspace(TomlWorkspaceField { workspace: true }) => {
cargo_features.require(Feature::workspace_inheritance())?;
get_ws_field().context(format!(
MaybeWorkspace::Workspace(TomlWorkspaceField { workspace: true }) => get_ws_field()
.context(format!(
"error inheriting `{}` from workspace root manifest's `workspace.package.{}`",
label, label
))
}
)),
MaybeWorkspace::Workspace(TomlWorkspaceField { workspace: false }) => Err(anyhow!(
"`workspace=false` is unsupported for `package.{}`",
label,
Expand Down Expand Up @@ -1592,15 +1589,15 @@ impl TomlManifest {
let version = project
.version
.clone()
.resolve(&features, "version", || inherit()?.version())?;
.resolve("version", || inherit()?.version())?;

project.version = MaybeWorkspace::Defined(version.clone());

let pkgid = project.to_package_id(source_id, version)?;

let edition = if let Some(edition) = project.edition.clone() {
let edition: Edition = edition
.resolve(&features, "edition", || inherit()?.edition())?
.resolve("edition", || inherit()?.edition())?
.parse()
.with_context(|| "failed to parse the `edition` key")?;
project.edition = Some(MaybeWorkspace::Defined(edition.to_string()));
Expand All @@ -1625,7 +1622,7 @@ impl TomlManifest {
let rust_version = if let Some(rust_version) = &project.rust_version {
let rust_version = rust_version
.clone()
.resolve(&features, "rust_version", || inherit()?.rust_version())?;
.resolve("rust_version", || inherit()?.rust_version())?;
let req = match semver::VersionReq::parse(&rust_version) {
// Exclude semver operators like `^` and pre-release identifiers
Ok(req) if rust_version.chars().all(|c| c.is_ascii_digit() || c == '.') => req,
Expand Down Expand Up @@ -1716,7 +1713,6 @@ impl TomlManifest {
};

fn process_dependencies(
features: &Features,
cx: &mut Context<'_, '_>,
new_deps: Option<&BTreeMap<String, TomlDependency>>,
kind: Option<DepKind>,
Expand All @@ -1736,7 +1732,7 @@ impl TomlManifest {

let mut deps: BTreeMap<String, TomlDependency> = BTreeMap::new();
for (n, v) in dependencies.iter() {
let resolved = v.clone().resolve(features, n, cx, || inherit())?;
let resolved = v.clone().resolve(n, cx, || inherit())?;
let dep = resolved.to_dependency(n, cx, kind)?;
validate_package_name(dep.name_in_toml().as_str(), "dependency name", "")?;
cx.deps.push(dep);
Expand All @@ -1747,7 +1743,6 @@ impl TomlManifest {

// Collect the dependencies.
let dependencies = process_dependencies(
&features,
&mut cx,
me.dependencies.as_ref(),
None,
Expand All @@ -1762,7 +1757,6 @@ impl TomlManifest {
.as_ref()
.or_else(|| me.dev_dependencies2.as_ref());
let dev_deps = process_dependencies(
&features,
&mut cx,
dev_deps,
Some(DepKind::Development),
Expand All @@ -1777,7 +1771,6 @@ impl TomlManifest {
.as_ref()
.or_else(|| me.build_dependencies2.as_ref());
let build_deps = process_dependencies(
&features,
&mut cx,
build_deps,
Some(DepKind::Build),
Expand All @@ -1793,7 +1786,6 @@ impl TomlManifest {
Some(platform)
};
let deps = process_dependencies(
&features,
&mut cx,
platform.dependencies.as_ref(),
None,
Expand All @@ -1809,7 +1801,6 @@ impl TomlManifest {
.as_ref()
.or_else(|| platform.build_dependencies2.as_ref());
let build_deps = process_dependencies(
&features,
&mut cx,
build_deps,
Some(DepKind::Build),
Expand All @@ -1825,7 +1816,6 @@ impl TomlManifest {
.as_ref()
.or_else(|| platform.dev_dependencies2.as_ref());
let dev_deps = process_dependencies(
&features,
&mut cx,
dev_deps,
Some(DepKind::Development),
Expand Down Expand Up @@ -1872,13 +1862,13 @@ impl TomlManifest {
let exclude = project
.exclude
.clone()
.map(|mw| mw.resolve(&features, "exclude", || inherit()?.exclude()))
.map(|mw| mw.resolve("exclude", || inherit()?.exclude()))
.transpose()?
.unwrap_or_default();
let include = project
.include
.clone()
.map(|mw| mw.resolve(&features, "include", || inherit()?.include()))
.map(|mw| mw.resolve("include", || inherit()?.include()))
.transpose()?
.unwrap_or_default();
let empty_features = BTreeMap::new();
Expand All @@ -1895,67 +1885,63 @@ impl TomlManifest {
description: project
.description
.clone()
.map(|mw| mw.resolve(&features, "description", || inherit()?.description()))
.map(|mw| mw.resolve("description", || inherit()?.description()))
.transpose()?,
homepage: project
.homepage
.clone()
.map(|mw| mw.resolve(&features, "homepage", || inherit()?.homepage()))
.map(|mw| mw.resolve("homepage", || inherit()?.homepage()))
.transpose()?,
documentation: project
.documentation
.clone()
.map(|mw| mw.resolve(&features, "documentation", || inherit()?.documentation()))
.map(|mw| mw.resolve("documentation", || inherit()?.documentation()))
.transpose()?,
readme: readme_for_project(
package_root,
project
.readme
.clone()
.map(|mw| mw.resolve(&features, "readme", || inherit()?.readme(package_root)))
.map(|mw| mw.resolve("readme", || inherit()?.readme(package_root)))
.transpose()?,
),
authors: project
.authors
.clone()
.map(|mw| mw.resolve(&features, "authors", || inherit()?.authors()))
.map(|mw| mw.resolve("authors", || inherit()?.authors()))
.transpose()?
.unwrap_or_default(),
license: project
.license
.clone()
.map(|mw| mw.resolve(&features, "license", || inherit()?.license()))
.map(|mw| mw.resolve("license", || inherit()?.license()))
.transpose()?,
license_file: project
.license_file
.clone()
.map(|mw| {
mw.resolve(&features, "license", || {
inherit()?.license_file(package_root)
})
})
.map(|mw| mw.resolve("license", || inherit()?.license_file(package_root)))
.transpose()?,
repository: project
.repository
.clone()
.map(|mw| mw.resolve(&features, "repository", || inherit()?.repository()))
.map(|mw| mw.resolve("repository", || inherit()?.repository()))
.transpose()?,
keywords: project
.keywords
.clone()
.map(|mw| mw.resolve(&features, "keywords", || inherit()?.keywords()))
.map(|mw| mw.resolve("keywords", || inherit()?.keywords()))
.transpose()?
.unwrap_or_default(),
categories: project
.categories
.clone()
.map(|mw| mw.resolve(&features, "categories", || inherit()?.categories()))
.map(|mw| mw.resolve("categories", || inherit()?.categories()))
.transpose()?
.unwrap_or_default(),
badges: me
.badges
.clone()
.map(|mw| mw.resolve(&features, "badges", || inherit()?.badges()))
.map(|mw| mw.resolve("badges", || inherit()?.badges()))
.transpose()?
.unwrap_or_default(),
links: project.links.clone(),
Expand Down Expand Up @@ -2015,11 +2001,10 @@ impl TomlManifest {
profiles.validate(&features, &mut warnings)?;
}

let publish = project.publish.clone().map(|publish| {
publish
.resolve(&features, "publish", || inherit()?.publish())
.unwrap()
});
let publish = project
.publish
.clone()
.map(|publish| publish.resolve("publish", || inherit()?.publish()).unwrap());

project.publish = publish.clone().map(|p| MaybeWorkspace::Defined(p));

Expand Down Expand Up @@ -2479,7 +2464,6 @@ impl<P: ResolveToPath + Clone> TomlDependency<P> {
impl TomlDependency {
fn resolve<'a>(
self,
cargo_features: &Features,
label: &str,
cx: &mut Context<'_, '_>,
get_inheritable: impl FnOnce() -> CargoResult<&'a InheritableFields>,
Expand All @@ -2492,7 +2476,6 @@ impl TomlDependency {
features,
optional,
}) => {
cargo_features.require(Feature::workspace_inheritance())?;
let inheritable = get_inheritable()?;
inheritable.get_dependency(label).context(format!(
"error reading `dependencies.{}` from workspace root manifest's `workspace.dependencies.{}`",
Expand Down
36 changes: 36 additions & 0 deletions src/doc/src/reference/specifying-dependencies.md
Original file line number Diff line number Diff line change
Expand Up @@ -454,8 +454,44 @@ following to the above manifest:
log-debug = ['bar/log-debug'] # using 'foo/log-debug' would be an error!
```

### Inheriting a dependency from a workspace

Dependencies can be inherited from a workspace by specifying the
dependency in the workspace's [`[workspace.dependencies]`][workspace.dependencies] table.
After that add it to the `[dependencies]` table with `workspace = true`.

Along with the `workspace` key, dependencies can also include these keys:
- [`optional`][optional]: Note that the`[workspace.dependencies]` table is not allowed to specify `optional`.
- [`features`][features]: These are additive with the features declared in the `[workspace.dependencies]`

Other than `optional` and `features`, inherited dependencies cannot use any other
dependency key (such as `version` or `default-features`).

Dependencies in the `[dependencies]`, `[dev-dependencies]`, `[build-dependencies]`, and
`[target."...".dependencies]` sections support the ability to reference the
`[workspace.dependencies]` definition of dependencies.

```toml
[project]
name = "bar"
version = "0.2.0"

[dependencies]
regex = { workspace = true, features = ["unicode"] }

[build-dependencies]
cc.workspace = true

[dev-dependencies]
rand = { workspace = true, optional = true }
```


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

<script>
(function() {
Expand Down
10 changes: 9 additions & 1 deletion src/doc/src/reference/unstable.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ Each new feature described below should explain how to use it.
* [avoid-dev-deps](#avoid-dev-deps) — Prevents the resolver from including dev-dependencies during resolution.
* [minimal-versions](#minimal-versions) — Forces the resolver to use the lowest compatible version instead of the highest.
* [public-dependency](#public-dependency) — Allows dependencies to be classified as either public or private.
* [workspace-inheritance](#workspace-inheritance) - Allow workspace members to share fields and dependencies
* Output behavior
* [out-dir](#out-dir) — Adds a directory where artifacts are copied to.
* [terminal-width](#terminal-width) — Tells rustc the width of the terminal so that long diagnostic messages can be truncated to be more readable.
Expand Down Expand Up @@ -1536,3 +1535,12 @@ setting the default target platform triples.
The `--crate-type` flag for `cargo rustc` has been stabilized in the 1.64
release. See the [`cargo rustc` documentation](../commands/cargo-rustc.md)
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),
and [inheriting-a-dependency-from-a-workspace](specifying-dependencies.md#inheriting-a-dependency-from-a-workspace)
for more information.
Loading