From 97d49c29eb2719089c68c072c989160865479d52 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 11 Sep 2024 13:49:49 -0500 Subject: [PATCH 01/37] Skeleton --- text/0000-feature-unification.md | 97 ++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 text/0000-feature-unification.md diff --git a/text/0000-feature-unification.md b/text/0000-feature-unification.md new file mode 100644 index 00000000000..a2ab4c4c8a6 --- /dev/null +++ b/text/0000-feature-unification.md @@ -0,0 +1,97 @@ +- Feature Name: (fill me in with a unique ident, `my_awesome_feature`) +- Start Date: (fill me in with today's date, YYYY-MM-DD) +- RFC PR: [rust-lang/rfcs#0000](https://github.com/rust-lang/rfcs/pull/0000) +- Rust Issue: [rust-lang/rust#0000](https://github.com/rust-lang/rust/issues/0000) + +# Summary +[summary]: #summary + +One paragraph explanation of the feature. + +# Motivation +[motivation]: #motivation + +Why are we doing this? What use cases does it support? What is the expected outcome? + +# Guide-level explanation +[guide-level-explanation]: #guide-level-explanation + +Explain the proposal as if it was already included in the language and you were teaching it to another Rust programmer. That generally means: + +- Introducing new named concepts. +- Explaining the feature largely in terms of examples. +- Explaining how Rust programmers should *think* about the feature, and how it should impact the way they use Rust. It should explain the impact as concretely as possible. +- If applicable, provide sample error messages, deprecation warnings, or migration guidance. +- If applicable, describe the differences between teaching this to existing Rust programmers and new Rust programmers. +- Discuss how this impacts the ability to read, understand, and maintain Rust code. Code is read and modified far more often than written; will the proposed feature make code easier to maintain? + +For implementation-oriented RFCs (e.g. for compiler internals), this section should focus on how compiler contributors should think about the change, and give examples of its concrete impact. For policy RFCs, this section should provide an example-driven introduction to the policy, and explain its impact in concrete terms. + +# Reference-level explanation +[reference-level-explanation]: #reference-level-explanation + +This is the technical portion of the RFC. Explain the design in sufficient detail that: + +- Its interaction with other features is clear. +- It is reasonably clear how the feature would be implemented. +- Corner cases are dissected by example. + +The section should return to the examples given in the previous section, and explain more fully how the detailed proposal makes those examples work. + +# Drawbacks +[drawbacks]: #drawbacks + +Why should we *not* do this? + +# Rationale and alternatives +[rationale-and-alternatives]: #rationale-and-alternatives + +- Why is this design the best in the space of possible designs? +- What other designs have been considered and what is the rationale for not choosing them? +- What is the impact of not doing this? +- If this is a language proposal, could this be done in a library or macro instead? Does the proposed change make Rust code easier or harder to read, understand, and maintain? + +# Prior art +[prior-art]: #prior-art + +Discuss prior art, both the good and the bad, in relation to this proposal. +A few examples of what this can include are: + +- For language, library, cargo, tools, and compiler proposals: Does this feature exist in other programming languages and what experience have their community had? +- For community proposals: Is this done by some other community and what were their experiences with it? +- For other teams: What lessons can we learn from what other communities have done here? +- Papers: Are there any published papers or great posts that discuss this? If you have some relevant papers to refer to, this can serve as a more detailed theoretical background. + +This section is intended to encourage you as an author to think about the lessons from other languages, provide readers of your RFC with a fuller picture. +If there is no prior art, that is fine - your ideas are interesting to us whether they are brand new or if it is an adaptation from other languages. + +Note that while precedent set by other languages is some motivation, it does not on its own motivate an RFC. +Please also take into consideration that rust sometimes intentionally diverges from common language features. + +# Unresolved questions +[unresolved-questions]: #unresolved-questions + +- What parts of the design do you expect to resolve through the RFC process before this gets merged? +- What parts of the design do you expect to resolve through the implementation of this feature before stabilization? +- What related issues do you consider out of scope for this RFC that could be addressed in the future independently of the solution that comes out of this RFC? + +# Future possibilities +[future-possibilities]: #future-possibilities + +Think about what the natural extension and evolution of your proposal would +be and how it would affect the language and project as a whole in a holistic +way. Try to use this section as a tool to more fully consider all possible +interactions with the project and language in your proposal. +Also consider how this all fits into the roadmap for the project +and of the relevant sub-team. + +This is also a good place to "dump ideas", if they are out of scope for the +RFC you are writing but otherwise related. + +If you have tried and cannot think of any future possibilities, +you may simply state that you cannot think of anything. + +Note that having something written down in the future-possibilities section +is not a reason to accept the current or a future RFC; such notes should be +in the section on motivation or rationale in this or subsequent RFCs. +The section merely provides additional information. From c3b17e86577870afb774e9df5e6d20b655c63a95 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 11 Sep 2024 18:20:13 -0400 Subject: [PATCH 02/37] Initial --- text/0000-feature-unification.md | 125 +++++++++++++++++++------------ 1 file changed, 79 insertions(+), 46 deletions(-) diff --git a/text/0000-feature-unification.md b/text/0000-feature-unification.md index a2ab4c4c8a6..79babe72831 100644 --- a/text/0000-feature-unification.md +++ b/text/0000-feature-unification.md @@ -1,17 +1,40 @@ -- Feature Name: (fill me in with a unique ident, `my_awesome_feature`) -- Start Date: (fill me in with today's date, YYYY-MM-DD) +- Feature Name: `feature-unification` +- Start Date: 2024-09-11 - RFC PR: [rust-lang/rfcs#0000](https://github.com/rust-lang/rfcs/pull/0000) - Rust Issue: [rust-lang/rust#0000](https://github.com/rust-lang/rust/issues/0000) # Summary [summary]: #summary -One paragraph explanation of the feature. +Allow users to control feature unifcation. + +Related issues: +- [#4463: Feature selection in workspace depends on the set of packages compiled](https://github.com/rust-lang/cargo/issues/4463) +- [#8157: --bin B resolves features differently than -p B in a workspace](https://github.com/rust-lang/cargo/issues/8157) +- [#13844: The cargo build --bins re-builds binaries again after cargo build --all-targets](https://github.com/rust-lang/cargo/issues/13844) # Motivation [motivation]: #motivation -Why are we doing this? What use cases does it support? What is the expected outcome? +Today, when Cargo is building, features in dependencies are enabled baed on the set of packages selected to build. +This is an attempt to balance +- Build speed: we should reuse builds between packages within the same invocation +- Ability to verify features for a given package + +This isn't always ideal. + +If a user is building an application, they may be jumping around the application's components which are packages within the workspace. +The final artifact is the same but Cargo will select different features depending on which package they are currently building, +causing build churn for the same set of dependencies that, in the end, will only be used with the same set of features. +The "cargo-workspace-hack" is a pattern that has existed for years +(e.g. [`rustc-workspace-hack`](https://crates.io/crates/rustc-workspace-hack)) +where users have all workspace members that depend on a generated package that depends on direct-dependemncies in the workspace along with their features. +Tools like [`cargo-hakari`](https://crates.io/crates/cargo-hakari) automate this process. +To allow others to pull in a package depending on a workspace-hack package as a git dependency, you then need to publish the workspace-hack as an empty package with no dependencies +and then locally patch in the real instance of it. + +This also makes testing of features more difficult because a user can't just run `cargo check --workspace` to verify that the correct set of features are enabled. +This has led to the rise of tools like [cargo-hack](https://crates.io/crates/cargo-hack) which de-unify packages. # Guide-level explanation [guide-level-explanation]: #guide-level-explanation @@ -30,68 +53,78 @@ For implementation-oriented RFCs (e.g. for compiler internals), this section sho # Reference-level explanation [reference-level-explanation]: #reference-level-explanation -This is the technical portion of the RFC. Explain the design in sufficient detail that: +### Rust Version + +We'll add two new modes to feature unifcation: + +**Unify features across the workspace, independent of the selected packages** + +This would be built-in support for "cargo-workspace-hack". + +This would require effectively changing from +1. Resolve dependencies +2. Filter dependencies down for current target and selected packages +3. Resolve features + +To +1. Resolve dependencies +2. Filter dependencies down for current target +3. Resolve features +4. Filter for selected packages + +**Features will be evaluated for each package in isolation** + +This will require building duplicate copies of build units when there is disjoint sets of features. + +For example purposes., this could be implemented as either +- Loop over the packages, resolving, and then run a build plan for that package +- Resolve for each package and generate everything into the same build plan -- Its interaction with other features is clear. -- It is reasonably clear how the feature would be implemented. -- Corner cases are dissected by example. +This is not prescriptive of the implementation but to illustrate what the feature does. -The section should return to the examples given in the previous section, and explain more fully how the detailed proposal makes those examples work. +**Note:** these features do not need to be stabilized together. + +##### `resolver.feature-unification` + +*(update to [Configuration](https://doc.rust-lang.org/cargo/reference/config.html))* + +* Type: string +* Default: "selected" +* Environment: `CARGO_RESOLVER_FEATURE_UNIFICATION` + +Specify which packages participate in [feature unification](https://doc.rust-lang.org/cargo/reference/features.html#feature-unification). + +* `selected`: merge dependency features from all package specified for the current build +* `workspace`: merge dependency features across all workspace members, regardless of which packages are specified for the current build +* `package`: dependency features are only enabled for each package, preferring duplicate builds of dependencies to when different feature sets are selected # Drawbacks [drawbacks]: #drawbacks -Why should we *not* do this? +This increases entropy within Cargo and the universe at large. # Rationale and alternatives [rationale-and-alternatives]: #rationale-and-alternatives -- Why is this design the best in the space of possible designs? -- What other designs have been considered and what is the rationale for not choosing them? -- What is the impact of not doing this? -- If this is a language proposal, could this be done in a library or macro instead? Does the proposed change make Rust code easier or harder to read, understand, and maintain? +This is done in the config instead of the manifest: +- As this can change from run-to-run, this covers more use cases +- As this fits easily into the `resolver` table. there is less design work + +This will not support exceptions for mutually exclusive features because those are officially unsupported. +Instead, effort should be put towards [official mutually exclusive globals](https://internals.rust-lang.org/t/pre-rfc-mutually-excusive-global-features/19618). # Prior art [prior-art]: #prior-art -Discuss prior art, both the good and the bad, in relation to this proposal. -A few examples of what this can include are: +[`cargo-hakari`](https://crates.io/crates/cargo-hakari) is a "cargo-workspace-hack" generator that builds a graph off of `cargo metadata` and re-implements feature unification. -- For language, library, cargo, tools, and compiler proposals: Does this feature exist in other programming languages and what experience have their community had? -- For community proposals: Is this done by some other community and what were their experiences with it? -- For other teams: What lessons can we learn from what other communities have done here? -- Papers: Are there any published papers or great posts that discuss this? If you have some relevant papers to refer to, this can serve as a more detailed theoretical background. - -This section is intended to encourage you as an author to think about the lessons from other languages, provide readers of your RFC with a fuller picture. -If there is no prior art, that is fine - your ideas are interesting to us whether they are brand new or if it is an adaptation from other languages. - -Note that while precedent set by other languages is some motivation, it does not on its own motivate an RFC. -Please also take into consideration that rust sometimes intentionally diverges from common language features. +[cargo-hack](https://crates.io/crates/cargo-hack) can run each selected package in a separate `cargo` invocation to prevent unification. # Unresolved questions [unresolved-questions]: #unresolved-questions -- What parts of the design do you expect to resolve through the RFC process before this gets merged? -- What parts of the design do you expect to resolve through the implementation of this feature before stabilization? -- What related issues do you consider out of scope for this RFC that could be addressed in the future independently of the solution that comes out of this RFC? # Future possibilities [future-possibilities]: #future-possibilities -Think about what the natural extension and evolution of your proposal would -be and how it would affect the language and project as a whole in a holistic -way. Try to use this section as a tool to more fully consider all possible -interactions with the project and language in your proposal. -Also consider how this all fits into the roadmap for the project -and of the relevant sub-team. - -This is also a good place to "dump ideas", if they are out of scope for the -RFC you are writing but otherwise related. - -If you have tried and cannot think of any future possibilities, -you may simply state that you cannot think of anything. - -Note that having something written down in the future-possibilities section -is not a reason to accept the current or a future RFC; such notes should be -in the section on motivation or rationale in this or subsequent RFCs. -The section merely provides additional information. +Add a related field to manifests that the config can override. From a921e096b6ce4b44cfdf7acc8c699747ff9a4eb4 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 11 Sep 2024 18:22:51 -0400 Subject: [PATCH 03/37] Set RFC number --- ...000-feature-unification.md => 3692-feature-unification.md} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename text/{0000-feature-unification.md => 3692-feature-unification.md} (97%) diff --git a/text/0000-feature-unification.md b/text/3692-feature-unification.md similarity index 97% rename from text/0000-feature-unification.md rename to text/3692-feature-unification.md index 79babe72831..97374c8be84 100644 --- a/text/0000-feature-unification.md +++ b/text/3692-feature-unification.md @@ -1,7 +1,7 @@ - Feature Name: `feature-unification` - Start Date: 2024-09-11 -- RFC PR: [rust-lang/rfcs#0000](https://github.com/rust-lang/rfcs/pull/0000) -- Rust Issue: [rust-lang/rust#0000](https://github.com/rust-lang/rust/issues/0000) +- RFC PR: [rust-lang/rfcs#3692](https://github.com/rust-lang/rfcs/pull/3692) +- Rust Issue: [rust-lang/rust#3692](https://github.com/rust-lang/rust/issues/3692) # Summary [summary]: #summary From 7d6810df89d077660ac6f2f3d7f6a1ec2bff304c Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 11 Sep 2024 22:35:09 -0400 Subject: [PATCH 04/37] Fix typo Co-authored-by: Josh Triplett --- text/3692-feature-unification.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/3692-feature-unification.md b/text/3692-feature-unification.md index 97374c8be84..994ed53025e 100644 --- a/text/3692-feature-unification.md +++ b/text/3692-feature-unification.md @@ -55,7 +55,7 @@ For implementation-oriented RFCs (e.g. for compiler internals), this section sho ### Rust Version -We'll add two new modes to feature unifcation: +We'll add two new modes to feature unification: **Unify features across the workspace, independent of the selected packages** From 5b13f939c92bd6d610a8a741db8ee784b132bdb1 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 11 Sep 2024 22:35:27 -0400 Subject: [PATCH 05/37] Fix typo Co-authored-by: Josh Triplett --- text/3692-feature-unification.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/3692-feature-unification.md b/text/3692-feature-unification.md index 994ed53025e..50bf5487b1d 100644 --- a/text/3692-feature-unification.md +++ b/text/3692-feature-unification.md @@ -74,7 +74,7 @@ To **Features will be evaluated for each package in isolation** -This will require building duplicate copies of build units when there is disjoint sets of features. +This will require building duplicate copies of build units when there are disjoint sets of features. For example purposes., this could be implemented as either - Loop over the packages, resolving, and then run a build plan for that package From 750b5f1621b73f3f83c30b9144a8d0ac04f4c5f1 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 12 Sep 2024 06:32:00 -0500 Subject: [PATCH 06/37] Fix typo Co-authored-by: Juniper Tyree <50025784+juntyr@users.noreply.github.com> --- text/3692-feature-unification.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/3692-feature-unification.md b/text/3692-feature-unification.md index 50bf5487b1d..593c2cf87ab 100644 --- a/text/3692-feature-unification.md +++ b/text/3692-feature-unification.md @@ -28,7 +28,7 @@ The final artifact is the same but Cargo will select different features dependin causing build churn for the same set of dependencies that, in the end, will only be used with the same set of features. The "cargo-workspace-hack" is a pattern that has existed for years (e.g. [`rustc-workspace-hack`](https://crates.io/crates/rustc-workspace-hack)) -where users have all workspace members that depend on a generated package that depends on direct-dependemncies in the workspace along with their features. +where users have all workspace members that depend on a generated package that depends on direct-dependencies in the workspace along with their features. Tools like [`cargo-hakari`](https://crates.io/crates/cargo-hakari) automate this process. To allow others to pull in a package depending on a workspace-hack package as a git dependency, you then need to publish the workspace-hack as an empty package with no dependencies and then locally patch in the real instance of it. From 4ebf0ff4b96f81fd903fe3e494ad753c617ecfe7 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 12 Sep 2024 10:19:12 -0400 Subject: [PATCH 07/37] Remove boilerplate --- text/3692-feature-unification.md | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/text/3692-feature-unification.md b/text/3692-feature-unification.md index 593c2cf87ab..b254e23cbad 100644 --- a/text/3692-feature-unification.md +++ b/text/3692-feature-unification.md @@ -39,16 +39,6 @@ This has led to the rise of tools like [cargo-hack](https://crates.io/crates/car # Guide-level explanation [guide-level-explanation]: #guide-level-explanation -Explain the proposal as if it was already included in the language and you were teaching it to another Rust programmer. That generally means: - -- Introducing new named concepts. -- Explaining the feature largely in terms of examples. -- Explaining how Rust programmers should *think* about the feature, and how it should impact the way they use Rust. It should explain the impact as concretely as possible. -- If applicable, provide sample error messages, deprecation warnings, or migration guidance. -- If applicable, describe the differences between teaching this to existing Rust programmers and new Rust programmers. -- Discuss how this impacts the ability to read, understand, and maintain Rust code. Code is read and modified far more often than written; will the proposed feature make code easier to maintain? - -For implementation-oriented RFCs (e.g. for compiler internals), this section should focus on how compiler contributors should think about the change, and give examples of its concrete impact. For policy RFCs, this section should provide an example-driven introduction to the policy, and explain its impact in concrete terms. # Reference-level explanation [reference-level-explanation]: #reference-level-explanation From 703a636e87eb577cc049c4ff01f4d2ab577db2dc Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 12 Sep 2024 10:19:19 -0400 Subject: [PATCH 08/37] Remove copy/pasted header --- text/3692-feature-unification.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/text/3692-feature-unification.md b/text/3692-feature-unification.md index b254e23cbad..86b4464cfe8 100644 --- a/text/3692-feature-unification.md +++ b/text/3692-feature-unification.md @@ -43,8 +43,6 @@ This has led to the rise of tools like [cargo-hack](https://crates.io/crates/car # Reference-level explanation [reference-level-explanation]: #reference-level-explanation -### Rust Version - We'll add two new modes to feature unification: **Unify features across the workspace, independent of the selected packages** From e7a4f27c66dcb320b30b307e0c555af12f8c4315 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 12 Sep 2024 10:21:32 -0400 Subject: [PATCH 09/37] Move mutually exclusive features to a Drawback --- text/3692-feature-unification.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/text/3692-feature-unification.md b/text/3692-feature-unification.md index 86b4464cfe8..c845e55ab3a 100644 --- a/text/3692-feature-unification.md +++ b/text/3692-feature-unification.md @@ -91,6 +91,10 @@ Specify which packages participate in [feature unification](https://doc.rust-lan This increases entropy within Cargo and the universe at large. +If someone enables mutually exclusive features in different packages, then `workspace` unification will fail. +Officially, features are supposedd to be additive., making mutuallyu exclusive features officially unsupported. +Instead, effort should be put towards [official mutually exclusive globals](https://internals.rust-lang.org/t/pre-rfc-mutually-excusive-global-features/19618). + # Rationale and alternatives [rationale-and-alternatives]: #rationale-and-alternatives @@ -98,9 +102,6 @@ This is done in the config instead of the manifest: - As this can change from run-to-run, this covers more use cases - As this fits easily into the `resolver` table. there is less design work -This will not support exceptions for mutually exclusive features because those are officially unsupported. -Instead, effort should be put towards [official mutually exclusive globals](https://internals.rust-lang.org/t/pre-rfc-mutually-excusive-global-features/19618). - # Prior art [prior-art]: #prior-art From f2bb64a01af60e125eb709677eeb95a0711c9cf3 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 12 Sep 2024 10:38:24 -0400 Subject: [PATCH 10/37] Cover no_std with std features being unified --- text/3692-feature-unification.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/text/3692-feature-unification.md b/text/3692-feature-unification.md index c845e55ab3a..276b50f8717 100644 --- a/text/3692-feature-unification.md +++ b/text/3692-feature-unification.md @@ -95,6 +95,9 @@ If someone enables mutually exclusive features in different packages, then `work Officially, features are supposedd to be additive., making mutuallyu exclusive features officially unsupported. Instead, effort should be put towards [official mutually exclusive globals](https://internals.rust-lang.org/t/pre-rfc-mutually-excusive-global-features/19618). +Some features cannot be enabled in some packages, like a `no_std` package not wanting `std` features. +These workspaces will not be able to use `workspace` unification. + # Rationale and alternatives [rationale-and-alternatives]: #rationale-and-alternatives From c5bbeeeab229a107ccaf12721fbdfba38b93a59e Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 12 Sep 2024 11:03:11 -0400 Subject: [PATCH 11/37] Fix typo --- text/3692-feature-unification.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/3692-feature-unification.md b/text/3692-feature-unification.md index 276b50f8717..14e09d146be 100644 --- a/text/3692-feature-unification.md +++ b/text/3692-feature-unification.md @@ -16,7 +16,7 @@ Related issues: # Motivation [motivation]: #motivation -Today, when Cargo is building, features in dependencies are enabled baed on the set of packages selected to build. +Today, when Cargo is building, features in dependencies are enabled based on the set of packages selected to build. This is an attempt to balance - Build speed: we should reuse builds between packages within the same invocation - Ability to verify features for a given package From 65e6988f020c7f0080169e4fbf5a0db99505260f Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 12 Sep 2024 11:04:34 -0400 Subject: [PATCH 12/37] Note cargo-hakari's build/host unification features --- text/3692-feature-unification.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/text/3692-feature-unification.md b/text/3692-feature-unification.md index 14e09d146be..20dc09cd1bb 100644 --- a/text/3692-feature-unification.md +++ b/text/3692-feature-unification.md @@ -115,6 +115,10 @@ This is done in the config instead of the manifest: # Unresolved questions [unresolved-questions]: #unresolved-questions +- This keeps buid/host feature unification behavior delegated to `workspace.resolver` + - `cargo hakari` exposes multiple ways to configure this, see [unify-target-host](https://docs.rs/cargo-hakari/latest/cargo_hakari/config/index.html#unify-target-host) + - For Oxide this reduced build units from 1900 to 1500, dramatically improving compile times (remembered off the top of head) + - This might be somewhat related to [`-Ztarget-applies-to-host`](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#target-applies-to-host) # Future possibilities [future-possibilities]: #future-possibilities From e752830aaecd1cf0e4b8c7a7331c7671f886d1c6 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 12 Sep 2024 11:05:55 -0400 Subject: [PATCH 13/37] Add build/host unification qualification --- text/3692-feature-unification.md | 1 + 1 file changed, 1 insertion(+) diff --git a/text/3692-feature-unification.md b/text/3692-feature-unification.md index 20dc09cd1bb..2fd90b2e7fc 100644 --- a/text/3692-feature-unification.md +++ b/text/3692-feature-unification.md @@ -118,6 +118,7 @@ This is done in the config instead of the manifest: - This keeps buid/host feature unification behavior delegated to `workspace.resolver` - `cargo hakari` exposes multiple ways to configure this, see [unify-target-host](https://docs.rs/cargo-hakari/latest/cargo_hakari/config/index.html#unify-target-host) - For Oxide this reduced build units from 1900 to 1500, dramatically improving compile times (remembered off the top of head) + - However, this required effort to make sure additional settings are unified between host and target - This might be somewhat related to [`-Ztarget-applies-to-host`](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#target-applies-to-host) # Future possibilities From 0cebf5ff6d8457e292b882227162270d5f17f52e Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 12 Sep 2024 11:10:26 -0400 Subject: [PATCH 14/37] Fix typo --- text/3692-feature-unification.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/3692-feature-unification.md b/text/3692-feature-unification.md index 2fd90b2e7fc..3003f2ead6e 100644 --- a/text/3692-feature-unification.md +++ b/text/3692-feature-unification.md @@ -115,7 +115,7 @@ This is done in the config instead of the manifest: # Unresolved questions [unresolved-questions]: #unresolved-questions -- This keeps buid/host feature unification behavior delegated to `workspace.resolver` +- This keeps build/host feature unification behavior delegated to `workspace.resolver` - `cargo hakari` exposes multiple ways to configure this, see [unify-target-host](https://docs.rs/cargo-hakari/latest/cargo_hakari/config/index.html#unify-target-host) - For Oxide this reduced build units from 1900 to 1500, dramatically improving compile times (remembered off the top of head) - However, this required effort to make sure additional settings are unified between host and target From 363be827ead2ee13d291d5a74fce8901e0e5d9d6 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 12 Sep 2024 11:10:40 -0400 Subject: [PATCH 15/37] Add citation --- text/3692-feature-unification.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/3692-feature-unification.md b/text/3692-feature-unification.md index 3003f2ead6e..75f3bc73d24 100644 --- a/text/3692-feature-unification.md +++ b/text/3692-feature-unification.md @@ -117,7 +117,7 @@ This is done in the config instead of the manifest: - This keeps build/host feature unification behavior delegated to `workspace.resolver` - `cargo hakari` exposes multiple ways to configure this, see [unify-target-host](https://docs.rs/cargo-hakari/latest/cargo_hakari/config/index.html#unify-target-host) - - For Oxide this reduced build units from 1900 to 1500, dramatically improving compile times (remembered off the top of head) + - For Oxide this reduced build units from 1900 to 1500, dramatically improving compile times, see https://github.com/oxidecomputer/omicron/pull/4535 - However, this required effort to make sure additional settings are unified between host and target - This might be somewhat related to [`-Ztarget-applies-to-host`](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#target-applies-to-host) From 6860e51e3462879324a3f57182ed7feb2a162745 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 12 Sep 2024 11:12:49 -0400 Subject: [PATCH 16/37] Note ecosystem importance of build/host unification --- text/3692-feature-unification.md | 1 + 1 file changed, 1 insertion(+) diff --git a/text/3692-feature-unification.md b/text/3692-feature-unification.md index 75f3bc73d24..a2c2286fa6a 100644 --- a/text/3692-feature-unification.md +++ b/text/3692-feature-unification.md @@ -120,6 +120,7 @@ This is done in the config instead of the manifest: - For Oxide this reduced build units from 1900 to 1500, dramatically improving compile times, see https://github.com/oxidecomputer/omicron/pull/4535 - However, this required effort to make sure additional settings are unified between host and target - This might be somewhat related to [`-Ztarget-applies-to-host`](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#target-applies-to-host) + - If this got pulled in, there would no longer be enough of a case to justify `cargo-hakari` development # Future possibilities [future-possibilities]: #future-possibilities From 8b114b31928fe04d4a399e69e6c5be8fa666e606 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 12 Sep 2024 10:14:12 -0500 Subject: [PATCH 17/37] Fix typos Co-authored-by: Ralf Jung --- text/3692-feature-unification.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/3692-feature-unification.md b/text/3692-feature-unification.md index a2c2286fa6a..94b5956a180 100644 --- a/text/3692-feature-unification.md +++ b/text/3692-feature-unification.md @@ -92,7 +92,7 @@ Specify which packages participate in [feature unification](https://doc.rust-lan This increases entropy within Cargo and the universe at large. If someone enables mutually exclusive features in different packages, then `workspace` unification will fail. -Officially, features are supposedd to be additive., making mutuallyu exclusive features officially unsupported. +Officially, features are supposed to be additive, making mutually exclusive features officially unsupported. Instead, effort should be put towards [official mutually exclusive globals](https://internals.rust-lang.org/t/pre-rfc-mutually-excusive-global-features/19618). Some features cannot be enabled in some packages, like a `no_std` package not wanting `std` features. From 4bbdc5135a495b55b60fe37e33584d86445a0a11 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Tue, 17 Sep 2024 12:20:00 -0500 Subject: [PATCH 18/37] fix: Clarify some points --- text/3692-feature-unification.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/text/3692-feature-unification.md b/text/3692-feature-unification.md index 94b5956a180..d7cc20e38d7 100644 --- a/text/3692-feature-unification.md +++ b/text/3692-feature-unification.md @@ -69,6 +69,8 @@ For example purposes., this could be implemented as either - Resolve for each package and generate everything into the same build plan This is not prescriptive of the implementation but to illustrate what the feature does. +The initial implementation may be sub-optimal. +Likely, the implementation could be improved over time. **Note:** these features do not need to be stabilized together. @@ -97,6 +99,8 @@ Instead, effort should be put towards [official mutually exclusive globals](http Some features cannot be enabled in some packages, like a `no_std` package not wanting `std` features. These workspaces will not be able to use `workspace` unification. +For now, unifying for the `"workspace"` is primarily targeted at single-application workspaces. +The other config fields can always be used instead. # Rationale and alternatives [rationale-and-alternatives]: #rationale-and-alternatives @@ -105,6 +109,9 @@ This is done in the config instead of the manifest: - As this can change from run-to-run, this covers more use cases - As this fits easily into the `resolver` table. there is less design work +We could extend this with configuration for to exclude packages for the various use cases mentioned. +Supporting excludes as environemnt/project configuration complexity as well as implementation complexity. + # Prior art [prior-art]: #prior-art From 8f848a40680882f624eb68dae8e4beb58bc2cf4b Mon Sep 17 00:00:00 2001 From: Ed Page Date: Tue, 17 Sep 2024 12:20:19 -0500 Subject: [PATCH 19/37] Expand on future possibilities --- text/3692-feature-unification.md | 60 ++++++++++++++++++++++++++++---- 1 file changed, 54 insertions(+), 6 deletions(-) diff --git a/text/3692-feature-unification.md b/text/3692-feature-unification.md index d7cc20e38d7..e821d9bcd61 100644 --- a/text/3692-feature-unification.md +++ b/text/3692-feature-unification.md @@ -122,14 +122,62 @@ Supporting excludes as environemnt/project configuration complexity as well as i # Unresolved questions [unresolved-questions]: #unresolved-questions -- This keeps build/host feature unification behavior delegated to `workspace.resolver` - - `cargo hakari` exposes multiple ways to configure this, see [unify-target-host](https://docs.rs/cargo-hakari/latest/cargo_hakari/config/index.html#unify-target-host) - - For Oxide this reduced build units from 1900 to 1500, dramatically improving compile times, see https://github.com/oxidecomputer/omicron/pull/4535 - - However, this required effort to make sure additional settings are unified between host and target - - This might be somewhat related to [`-Ztarget-applies-to-host`](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#target-applies-to-host) - - If this got pulled in, there would no longer be enough of a case to justify `cargo-hakari` development +- How to name the config field to not block the future possibilities # Future possibilities [future-possibilities]: #future-possibilities +### Manifest support + Add a related field to manifests that the config can override. + +### Dependency version unification + +Unlike feature unification, dependency versions are alwayd unified across the +entire workspace, making `Cargo.lock` the same regardless of which package you +select or how you build. + +This can mask minimal-version bugs. +If a version-req is lower than it needs, `-Zminimal-versions` won't resolve down to that to show the problem if another version req in the workspace is higher. +We have `-Zdirect-minimal-versions` which will error if workspace members do not have the lowest version reqs of all of the workspace but that is brittle. + +If you have a workspace with multiple MSRVs, you can't verify your MSRV if you +set a high-MSRV package's version req for a dependency that invalidates the +MSRV-requirements of a low-MSRV package. + +We could offer an opt-in to per-package `Cargo.lock` files. For builds, this +could be implemented similar to `resolver.feature-unification = "package"`. + +This could run into problems with +- `cargo update` being workspace-focused +- third-party updating tools + +As for the MSRV-case, this would only help if you develop with the latest +versions locally and then have a job that resolves down to your MSRVs. + +### Unify features in other settings + +[`workspace.resolver = "2"`](https://doc.rust-lang.org/cargo/reference/resolver.html#features) removed unification from the following scenarios +- Cross-platform target unification +- `build-dependencies` / `dependencies` unification +- `dev-dependencies` / `dependencies` unification unless a dev target is enabled + +Depending on how we design this, the solution might be good enough to +re-evaluate +[build-target features](https://github.com/rust-lang/rfcs/pull/3374) as we +could offer a way for users to opt-out of build-target unification. + +Like with `resolver.incompatible-rust-version`, a solution for this would override the defaults of `workspace.resolver`. + +`cargo hakaro` gives control over `build-dependencies` / `dependencies` unification with +[`unify-target-host`](https://docs.rs/cargo-hakari/latest/cargo_hakari/config/index.html#unify-target-host): +- [`none`](https://docs.rs/hakari/0.17.4/hakari/enum.UnifyTargetHost.html#variant.None): Perform no unification across the target and host feature sets. + - The same as `resolver = "2"` +- [`unify-if-both`](https://docs.rs/hakari/0.17.4/hakari/enum.UnifyTargetHost.html#variant.UnifyIfBoth): Perform unification across target and host feature sets, but only if a dependency is built on both the target and the host. +- [`replicate-target-on-host`](https://docs.rs/hakari/0.17.4/hakari/enum.UnifyTargetHost.html#variant.ReplicateTargetOnHost): Perform unification across target and host feature sets, and also replicate all target-only lines to the host. +- [`auto`](https://docs.rs/hakari/0.17.4/hakari/enum.UnifyTargetHost.html#variant.Auto) (default): select `replicate-target-on-host` if a workspace member may be built for the host (used as a proc-macro or build-dependency) + +`unify-target-host` might be somewhat related to [`-Ztarget-applies-to-host`](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#target-applies-to-host) + +For Oxide `unify-target-host` reduced build units from 1900 to 1500, dramatically improving compile times, see https://github.com/oxidecomputer/omicron/pull/4535 +If integrated into cargo, there would no longer be a use case for the current maintainer of `cargo-hakari` to continue maintenance. From c2a4ac12eef7037884df2fed7e1c8849af21f080 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Tue, 17 Sep 2024 12:24:12 -0500 Subject: [PATCH 20/37] Expand on dev/normal unification --- text/3692-feature-unification.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/text/3692-feature-unification.md b/text/3692-feature-unification.md index e821d9bcd61..5eaa0a3c7d4 100644 --- a/text/3692-feature-unification.md +++ b/text/3692-feature-unification.md @@ -181,3 +181,13 @@ Like with `resolver.incompatible-rust-version`, a solution for this would overri For Oxide `unify-target-host` reduced build units from 1900 to 1500, dramatically improving compile times, see https://github.com/oxidecomputer/omicron/pull/4535 If integrated into cargo, there would no longer be a use case for the current maintainer of `cargo-hakari` to continue maintenance. + +If we supported `dev-dependencies` / `dependencies` like `resolver = "1"`, it +could help with cases like `cargo miri` where through `dev-dependencies` a +`libc` feature is enabled. preventing reuse of builds between `cargo build` and +`cargo test` for local development. + +In helping this case, we should make clear that this can also break people +- `fail` injects failures into your production code, only wanting it enabled for tests +- Tests generally enabled `std` on dependencies for `no_std` packages +- We were told of use cases around private keys where `Clone` is only provided when testing but not for production to help catch the leaking of secrets From d35c62642d22aa2f92efe4c18edaf9d4a98f120a Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 19 Sep 2024 16:37:42 -0500 Subject: [PATCH 21/37] fix: Typo Co-authored-by: Kevin Reid --- text/3692-feature-unification.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/3692-feature-unification.md b/text/3692-feature-unification.md index 5eaa0a3c7d4..e25ae492a7d 100644 --- a/text/3692-feature-unification.md +++ b/text/3692-feature-unification.md @@ -6,7 +6,7 @@ # Summary [summary]: #summary -Allow users to control feature unifcation. +Allow users to control feature unification. Related issues: - [#4463: Feature selection in workspace depends on the set of packages compiled](https://github.com/rust-lang/cargo/issues/4463) From 760b6186b74c40e26831c3f47b75873d536bc96d Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 19 Sep 2024 16:37:57 -0500 Subject: [PATCH 22/37] fix: Clarify statement Co-authored-by: Kevin Reid --- text/3692-feature-unification.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/3692-feature-unification.md b/text/3692-feature-unification.md index e25ae492a7d..1d02e22319a 100644 --- a/text/3692-feature-unification.md +++ b/text/3692-feature-unification.md @@ -64,7 +64,7 @@ To This will require building duplicate copies of build units when there are disjoint sets of features. -For example purposes., this could be implemented as either +For example, this could be implemented as either - Loop over the packages, resolving, and then run a build plan for that package - Resolve for each package and generate everything into the same build plan From cf07a12a8408aa93fe8329109747272c266262e6 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 19 Sep 2024 16:39:25 -0500 Subject: [PATCH 23/37] fix: Whatever Co-authored-by: Kevin Reid --- text/3692-feature-unification.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/text/3692-feature-unification.md b/text/3692-feature-unification.md index 1d02e22319a..960c3e199af 100644 --- a/text/3692-feature-unification.md +++ b/text/3692-feature-unification.md @@ -106,8 +106,8 @@ The other config fields can always be used instead. [rationale-and-alternatives]: #rationale-and-alternatives This is done in the config instead of the manifest: -- As this can change from run-to-run, this covers more use cases -- As this fits easily into the `resolver` table. there is less design work +- As this can change from run to run, this covers more use cases. +- As this fits easily into the `resolver` table, there is less design work. We could extend this with configuration for to exclude packages for the various use cases mentioned. Supporting excludes as environemnt/project configuration complexity as well as implementation complexity. From 51839e569332ca3187ed8528560d60bec1646734 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 19 Sep 2024 16:39:59 -0500 Subject: [PATCH 24/37] fix: Clarify statements Co-authored-by: Kevin Reid --- text/3692-feature-unification.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/text/3692-feature-unification.md b/text/3692-feature-unification.md index 960c3e199af..4be2721d997 100644 --- a/text/3692-feature-unification.md +++ b/text/3692-feature-unification.md @@ -109,8 +109,8 @@ This is done in the config instead of the manifest: - As this can change from run to run, this covers more use cases. - As this fits easily into the `resolver` table, there is less design work. -We could extend this with configuration for to exclude packages for the various use cases mentioned. -Supporting excludes as environemnt/project configuration complexity as well as implementation complexity. +We could extend this with configuration to exclude packages for the various use cases mentioned. +Supporting excludes adds environment/project configuration complexity as well as implementation complexity. # Prior art [prior-art]: #prior-art From 6318f47f1b0e16145a17370dcce2705c642943ee Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 19 Sep 2024 16:40:11 -0500 Subject: [PATCH 25/37] fix: Clarify statement Co-authored-by: Kevin Reid --- text/3692-feature-unification.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/3692-feature-unification.md b/text/3692-feature-unification.md index 4be2721d997..fe2facbd49d 100644 --- a/text/3692-feature-unification.md +++ b/text/3692-feature-unification.md @@ -127,7 +127,7 @@ Supporting excludes adds environment/project configuration complexity as well as # Future possibilities [future-possibilities]: #future-possibilities -### Manifest support +### Support in manifests Add a related field to manifests that the config can override. From cd2af9a3a5277b533337d4443f7f7b90469b2f22 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 19 Sep 2024 16:40:37 -0500 Subject: [PATCH 26/37] fix: Typi Co-authored-by: Kevin Reid --- text/3692-feature-unification.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/3692-feature-unification.md b/text/3692-feature-unification.md index fe2facbd49d..1e1b5148927 100644 --- a/text/3692-feature-unification.md +++ b/text/3692-feature-unification.md @@ -169,7 +169,7 @@ could offer a way for users to opt-out of build-target unification. Like with `resolver.incompatible-rust-version`, a solution for this would override the defaults of `workspace.resolver`. -`cargo hakaro` gives control over `build-dependencies` / `dependencies` unification with +`cargo hakari` gives control over `build-dependencies` / `dependencies` unification with [`unify-target-host`](https://docs.rs/cargo-hakari/latest/cargo_hakari/config/index.html#unify-target-host): - [`none`](https://docs.rs/hakari/0.17.4/hakari/enum.UnifyTargetHost.html#variant.None): Perform no unification across the target and host feature sets. - The same as `resolver = "2"` From 1b2a3d2aa6ba8f553097c36ef7caf43ba31959af Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 19 Sep 2024 16:42:37 -0500 Subject: [PATCH 27/37] fix: Clarify statement --- text/3692-feature-unification.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/3692-feature-unification.md b/text/3692-feature-unification.md index 1e1b5148927..0d89cefbf34 100644 --- a/text/3692-feature-unification.md +++ b/text/3692-feature-unification.md @@ -86,7 +86,7 @@ Specify which packages participate in [feature unification](https://doc.rust-lan * `selected`: merge dependency features from all package specified for the current build * `workspace`: merge dependency features across all workspace members, regardless of which packages are specified for the current build -* `package`: dependency features are only enabled for each package, preferring duplicate builds of dependencies to when different feature sets are selected +* `package`: dependency features are only considered on a package-by-package basis, preferring duplicate builds of dependencies when different sets of feature are activated by the packages. # Drawbacks [drawbacks]: #drawbacks From eb8ffb2b7558e035d47c01b7c4de42dba4515034 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 19 Sep 2024 16:43:06 -0500 Subject: [PATCH 28/37] fix: Typo --- text/3692-feature-unification.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/3692-feature-unification.md b/text/3692-feature-unification.md index 0d89cefbf34..3e956c143f0 100644 --- a/text/3692-feature-unification.md +++ b/text/3692-feature-unification.md @@ -133,7 +133,7 @@ Add a related field to manifests that the config can override. ### Dependency version unification -Unlike feature unification, dependency versions are alwayd unified across the +Unlike feature unification, dependency versions are always unified across the entire workspace, making `Cargo.lock` the same regardless of which package you select or how you build. From ff5e82a19a5744bace0210df5ed0cdd29f0495b2 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Fri, 20 Sep 2024 13:53:05 -0500 Subject: [PATCH 29/37] fix: Link out to another related Issue --- text/3692-feature-unification.md | 1 + 1 file changed, 1 insertion(+) diff --git a/text/3692-feature-unification.md b/text/3692-feature-unification.md index 3e956c143f0..a923df23e40 100644 --- a/text/3692-feature-unification.md +++ b/text/3692-feature-unification.md @@ -9,6 +9,7 @@ Allow users to control feature unification. Related issues: +- [#5210: Resolve feature and optional dependencies for workspace as a whole](https://github.com/rust-lang/cargo/issues/5210) - [#4463: Feature selection in workspace depends on the set of packages compiled](https://github.com/rust-lang/cargo/issues/4463) - [#8157: --bin B resolves features differently than -p B in a workspace](https://github.com/rust-lang/cargo/issues/8157) - [#13844: The cargo build --bins re-builds binaries again after cargo build --all-targets](https://github.com/rust-lang/cargo/issues/13844) From 0aac9abc2e517f548fd6c51ddea7394784abceea Mon Sep 17 00:00:00 2001 From: Ed Page Date: Mon, 30 Sep 2024 10:09:04 -0500 Subject: [PATCH 30/37] fix: Remove issue link --- text/3692-feature-unification.md | 1 - 1 file changed, 1 deletion(-) diff --git a/text/3692-feature-unification.md b/text/3692-feature-unification.md index a923df23e40..23a8042831e 100644 --- a/text/3692-feature-unification.md +++ b/text/3692-feature-unification.md @@ -1,7 +1,6 @@ - Feature Name: `feature-unification` - Start Date: 2024-09-11 - RFC PR: [rust-lang/rfcs#3692](https://github.com/rust-lang/rfcs/pull/3692) -- Rust Issue: [rust-lang/rust#3692](https://github.com/rust-lang/rust/issues/3692) # Summary [summary]: #summary From c0158e71d470b555e2b91b900784aadbad0d39b9 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Tue, 1 Oct 2024 09:39:51 -0500 Subject: [PATCH 31/37] fix: Disambiguate each use of 'target' --- text/3692-feature-unification.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/text/3692-feature-unification.md b/text/3692-feature-unification.md index 23a8042831e..a5899500c3b 100644 --- a/text/3692-feature-unification.md +++ b/text/3692-feature-unification.md @@ -51,12 +51,12 @@ This would be built-in support for "cargo-workspace-hack". This would require effectively changing from 1. Resolve dependencies -2. Filter dependencies down for current target and selected packages +2. Filter dependencies down for current build-target and selected packages 3. Resolve features To 1. Resolve dependencies -2. Filter dependencies down for current target +2. Filter dependencies down for current build-target 3. Resolve features 4. Filter for selected packages @@ -158,9 +158,9 @@ versions locally and then have a job that resolves down to your MSRVs. ### Unify features in other settings [`workspace.resolver = "2"`](https://doc.rust-lang.org/cargo/reference/resolver.html#features) removed unification from the following scenarios -- Cross-platform target unification +- Cross-platform build-target unification - `build-dependencies` / `dependencies` unification -- `dev-dependencies` / `dependencies` unification unless a dev target is enabled +- `dev-dependencies` / `dependencies` unification unless a dev build-target is enabled Depending on how we design this, the solution might be good enough to re-evaluate @@ -173,8 +173,8 @@ Like with `resolver.incompatible-rust-version`, a solution for this would overri [`unify-target-host`](https://docs.rs/cargo-hakari/latest/cargo_hakari/config/index.html#unify-target-host): - [`none`](https://docs.rs/hakari/0.17.4/hakari/enum.UnifyTargetHost.html#variant.None): Perform no unification across the target and host feature sets. - The same as `resolver = "2"` -- [`unify-if-both`](https://docs.rs/hakari/0.17.4/hakari/enum.UnifyTargetHost.html#variant.UnifyIfBoth): Perform unification across target and host feature sets, but only if a dependency is built on both the target and the host. -- [`replicate-target-on-host`](https://docs.rs/hakari/0.17.4/hakari/enum.UnifyTargetHost.html#variant.ReplicateTargetOnHost): Perform unification across target and host feature sets, and also replicate all target-only lines to the host. +- [`unify-if-both`](https://docs.rs/hakari/0.17.4/hakari/enum.UnifyTargetHost.html#variant.UnifyIfBoth): Perform unification across target and host feature sets, but only if a dependency is built on both the platform-target and the host. +- [`replicate-target-on-host`](https://docs.rs/hakari/0.17.4/hakari/enum.UnifyTargetHost.html#variant.ReplicateTargetOnHost): Perform unification across platform-target and host feature sets, and also replicate all target-only lines to the host. - [`auto`](https://docs.rs/hakari/0.17.4/hakari/enum.UnifyTargetHost.html#variant.Auto) (default): select `replicate-target-on-host` if a workspace member may be built for the host (used as a proc-macro or build-dependency) `unify-target-host` might be somewhat related to [`-Ztarget-applies-to-host`](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#target-applies-to-host) From 969cb03e4374cf537c21ff0cfd242a23f83aad3f Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 2 Oct 2024 09:31:01 -0500 Subject: [PATCH 32/37] Make cargo-install interaction explicit --- text/3692-feature-unification.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/text/3692-feature-unification.md b/text/3692-feature-unification.md index a5899500c3b..13f41e25227 100644 --- a/text/3692-feature-unification.md +++ b/text/3692-feature-unification.md @@ -112,6 +112,8 @@ This is done in the config instead of the manifest: We could extend this with configuration to exclude packages for the various use cases mentioned. Supporting excludes adds environment/project configuration complexity as well as implementation complexity. +This field will not apply to `cargo install` to match the behavior of `resolver.incompatible-rust-versions`. + # Prior art [prior-art]: #prior-art From a071fe46daa48b07c2ab713917411e121cd2b783 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 3 Oct 2024 13:43:10 -0500 Subject: [PATCH 33/37] alt: Build X as if its a dependency of Y --- text/3692-feature-unification.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/text/3692-feature-unification.md b/text/3692-feature-unification.md index 13f41e25227..887bf8b4d5a 100644 --- a/text/3692-feature-unification.md +++ b/text/3692-feature-unification.md @@ -114,6 +114,15 @@ Supporting excludes adds environment/project configuration complexity as well as This field will not apply to `cargo install` to match the behavior of `resolver.incompatible-rust-versions`. +The `workspace` setting breaks down if there are more than one "application" in +a workspace, particularly if there are shared dependencies with intentionally +disjoint feature sets. +What this use case is really modeling is being able to tell Cargo "build package X as if its a dependency of package Y". +There are many similar use cases to this (e.g. [cargo#2644](https://github.com/rust-lang/cargo/issues/2644), [cargo#14434](https://github.com/rust-lang/cargo/issues/14434)). +While a solution that targeted this higher-level need would cover more uses cases, +there is a lot more work to do within the design space and it could end up being more unwieldy. +The solution offered in this RFC is simple in that it is just a re-framing of what already happens on the command line. + # Prior art [prior-art]: #prior-art From 0e1fbc4cb8b19c6a8a35128a5907a98056460fb6 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 3 Oct 2024 13:45:11 -0500 Subject: [PATCH 34/37] fix: Clarify summary --- text/3692-feature-unification.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/text/3692-feature-unification.md b/text/3692-feature-unification.md index 887bf8b4d5a..718f2083e61 100644 --- a/text/3692-feature-unification.md +++ b/text/3692-feature-unification.md @@ -5,7 +5,9 @@ # Summary [summary]: #summary -Allow users to control feature unification. +Give users control over the feature unification that happens based on the packages they select. +- A way for `cargo check -p foo -p bar` to build like `cargo check -p foo && cargo check -p bar` +- A way for `cargo check -p foo` to build `foo` as if `cargo check --workspace` was used Related issues: - [#5210: Resolve feature and optional dependencies for workspace as a whole](https://github.com/rust-lang/cargo/issues/5210) From e3fa0729156add210de9ed9d48726e247c68269b Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 3 Oct 2024 13:48:58 -0500 Subject: [PATCH 35/37] fix: Clarify this RFC offers no new concepts --- text/3692-feature-unification.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/text/3692-feature-unification.md b/text/3692-feature-unification.md index 718f2083e61..35a0a683ca4 100644 --- a/text/3692-feature-unification.md +++ b/text/3692-feature-unification.md @@ -62,6 +62,10 @@ To 3. Resolve features 4. Filter for selected packages +The same result can be achieved with `cargo check --workspace`, +but with fewer packages built. +Therefore, no fundamentally new "mode" is being introduced. + **Features will be evaluated for each package in isolation** This will require building duplicate copies of build units when there are disjoint sets of features. @@ -74,6 +78,10 @@ This is not prescriptive of the implementation but to illustrate what the featur The initial implementation may be sub-optimal. Likely, the implementation could be improved over time. +The same result can be achieved with `cargo check -p foo && cargo check -p bar`, +but with the potential for optimizing the build further. +Therefore, no fundamentally new "mode" is being introduced. + **Note:** these features do not need to be stabilized together. ##### `resolver.feature-unification` From f2075e11fb5cb1c96f33d5a46a72b5b2e7a6d6a9 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Mon, 28 Oct 2024 11:36:19 -0500 Subject: [PATCH 36/37] fix(drawbacks): Put more emphasis on relationship with --workspace, mutually exclusive features is just an example --- text/3692-feature-unification.md | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/text/3692-feature-unification.md b/text/3692-feature-unification.md index 35a0a683ca4..a551b9550ec 100644 --- a/text/3692-feature-unification.md +++ b/text/3692-feature-unification.md @@ -103,14 +103,13 @@ Specify which packages participate in [feature unification](https://doc.rust-lan This increases entropy within Cargo and the universe at large. -If someone enables mutually exclusive features in different packages, then `workspace` unification will fail. -Officially, features are supposed to be additive, making mutually exclusive features officially unsupported. -Instead, effort should be put towards [official mutually exclusive globals](https://internals.rust-lang.org/t/pre-rfc-mutually-excusive-global-features/19618). - -Some features cannot be enabled in some packages, like a `no_std` package not wanting `std` features. -These workspaces will not be able to use `workspace` unification. -For now, unifying for the `"workspace"` is primarily targeted at single-application workspaces. -The other config fields can always be used instead. +As `workspace` unifcation builds dependencies the same way as `--workspace`, it has the same drawbacks as `--workspace`, including +- If a build would fail with `--workspace`, then it will fail with `workspace` unification as well. + - For example, if two packages in a workspace enable mutually exclusive features, builds will fail with both `--workspace` and `workspace` unification. + Officially, features are supposed to be additive, making mutually exclusive features officially unsupported. + Instead, effort should be put towards [official mutually exclusive globals](https://internals.rust-lang.org/t/pre-rfc-mutually-excusive-global-features/19618). +- If `--workspace` would produce an invalid binary for your requirements, then it will do so with `workspace` unification as well. + - For example, if you have regular packages and a `no_std` package in the same workspace, the `no_std` package may end up with dependnencies built with `std` features. # Rationale and alternatives [rationale-and-alternatives]: #rationale-and-alternatives From 203e6fcc0dd95f114a3ca66c6f0851cd828222bd Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sat, 2 Nov 2024 09:16:26 -0700 Subject: [PATCH 37/37] Add tracking issue --- text/3692-feature-unification.md | 1 + 1 file changed, 1 insertion(+) diff --git a/text/3692-feature-unification.md b/text/3692-feature-unification.md index a551b9550ec..862cbadc7b1 100644 --- a/text/3692-feature-unification.md +++ b/text/3692-feature-unification.md @@ -1,6 +1,7 @@ - Feature Name: `feature-unification` - Start Date: 2024-09-11 - RFC PR: [rust-lang/rfcs#3692](https://github.com/rust-lang/rfcs/pull/3692) +- Tracking Issue: [rust-lang/cargo#14774](https://github.com/rust-lang/cargo/issues/14774) # Summary [summary]: #summary