Cargo: Features 2.0 meta tracking issue.

Created on 8 Apr 2020  Â·  8Comments  Â·  Source: rust-lang/cargo

This is a tracking issue for a collection of changes to features that we are considering rolling out together.

  • #7914 -Z features=itarget — Ignoring inactive targets.
  • #7915 -Z features=host_dep — Decoupling features of normal deps from host deps (build dependencies and proc-macros).
  • #7916 -Z features=dev_dep — Decoupling features of dev-dependencies from normal builds.
  • #5364 -Z package-features — Better ways to select workspace features on the command-line.

The current idea is to add a flag to [workspace] to opt-in to the new behavior for all of these at once.

C-tracking-issue Z-features

Most helpful comment

For rolling out, I think I might actually propose a scheme such as:

  • Add a package.cargo-features = "2020" option to the manifest.
  • The default, if not specified, is "2015" (the 1.0 date)
  • The "2020" value indicates "interpret cargo features according to 2020 rules", same for 2015 (basically 1.0 vs 2.0)
  • When a future edition = "2021" comes around, that implies cargo-features = "2020" or whatever is latest by that point.
  • We'll update cargo new to generate cargo-features = "2020" in all new packages
  • The selected interpretation of cargo features is the maximum of all workspace members.

I think that should satisfy all our constraints, except for maybe being a nice system. The reason I propose this is the fourth bullet, though, where eventually we do not want to require this configuration and instead we will simply want to infer it from an edition = "2021" flag. If we take that as a given, [workspace] doesn't currently have an edition flag and it'd be kind a bummer if we had to generate:

[package]
edition = "2021"

[workspace]
edition = "2021"

in the next edition. So given that constraint that we want to infer it from edition = "2021" eventually, then we need some sort of way of rationalizing what happens when you configure it in [package], which taking the maximum I think is reasonable-ish.

All 8 comments

For rolling out, I think I might actually propose a scheme such as:

  • Add a package.cargo-features = "2020" option to the manifest.
  • The default, if not specified, is "2015" (the 1.0 date)
  • The "2020" value indicates "interpret cargo features according to 2020 rules", same for 2015 (basically 1.0 vs 2.0)
  • When a future edition = "2021" comes around, that implies cargo-features = "2020" or whatever is latest by that point.
  • We'll update cargo new to generate cargo-features = "2020" in all new packages
  • The selected interpretation of cargo features is the maximum of all workspace members.

I think that should satisfy all our constraints, except for maybe being a nice system. The reason I propose this is the fourth bullet, though, where eventually we do not want to require this configuration and instead we will simply want to infer it from an edition = "2021" flag. If we take that as a given, [workspace] doesn't currently have an edition flag and it'd be kind a bummer if we had to generate:

[package]
edition = "2021"

[workspace]
edition = "2021"

in the next edition. So given that constraint that we want to infer it from edition = "2021" eventually, then we need some sort of way of rationalizing what happens when you configure it in [package], which taking the maximum I think is reasonable-ish.

I might be reluctant to use cargo-features, to avoid confusion with the top-level cargo-features which is used for nightly unstable stuff.

Hm, what about just allowing some cargo-features on stable? Like:

cargo-features = ["features2"]
[package]
name = "foo"
# …

Or we could rename that, since the word "feature" is so overloaded.

Top-level things don't work as well in a virtual manifest if we want to make it part of the next edition. Unless we move the edition field to the root.

I think with looking at every workspace member, it could be too easy to accidentally introduce a global change. Imagine a large workspace with lots of different people working on it, someone introduces a new tool or library with cargo new, and doesn't know that the flag will affect everyone in the workspace.

I would slightly prefer in terms of bikeshedding that this is placed in [package] instead of the top-level since it feels pretty weird going at the top level (very little else does on stable), but that's a minor point.

I agree that changing any package with this flag (or using cargo new to create a new one) is weird to have the subtle effect of having a global change in the workspace. That being said though I don't know how we can get away from that. If we're 5 years down the road in the new edition and you cargo new into a workspace you wrote today, what's supposed to happen? I guess I sort of see it as a sort of inevitability that we're going to need to accept this subtle changes-the-global-behavior behavior, or if not I think we should focus temporarily on where we want to be after the next edition and work backwards from there to how the opt-in should look today. (if that makes sense)

I'm personally relatively wary of trying to make cargo new super smart about workspaces and doing lots of inference about how to insert itself into a workspace (or "I would be in this workspace so let me act on that"). I do think though that cargo new should always default you to the "latest and greatest defaults", which ideally is one line in Cargo.toml in the limit of time with editions. I guess put another way I don't personally see a feasible way forward to upgrade the workspace in cargo new to give us an alternative way to implement this in the future.

The new opt-in mechanism is now on nightly:

cargo-features = ["resolver"]

[package]
name = "my-package"
version = "1.0.0"
resolver = "2"

See the docs for more details: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#resolver

So I just tried this out in one of my projects where I have a virtual workspace at the root and a bunch of crates in subdirectories. If I understand correctly, I only need to set the resolver in the workspace, not in the individual crates. However when I do that, I get a bunch of warnings from cargo:

warning: resolver for the non root package will be ignored, specify resolver at the workspace root:
[[repeats for each crate in the workspace]]

Is this the expected behavior? Do I need to specifically override the resolver for all crates in the workspace?

Nah, it looks like the warning detection is just horribly broken. It is intended that you only specify it in the root [workspace]. I'll try to get it fixed soon.

I left some glowing praise for the resolver 2 behavior in a comment on the host_dep bug, btw. Saved our bacon. Behaves well at nightly-2020-05-01.

Seems to work for me as well in a use case similar to @cbiffle when using bindgen as a build dependency for a firmware project cross-compiled to thumbv6m. Not willing to make the move to nightly at this point though.

Was this page helpful?
0 / 5 - 0 ratings