TL;DR: if you use any of --package, --feature, --all-features, --no-default-features flags in your build, could you check that on the latest nightly, if you add -Z package-features flag as well, everything continues to work?
Hi! We’ve recently noticed a rather surprising interaction of Cargo --feature and --package flags. For command like cargo build --package foo --feature feat, the feature would be activated not for the foo package, but for the package at current working directory. Moreover, features of current package were always activated, so cargo build --package foo might have activated more features than strictly necessary for building foo! We would like to make this behavior more intuitive, and always apply features to the explicitly selected package. This is a change in behavior, so, for now, it is hidden behind an opt-in -Z package-features flag. We would like to access the real-world impact of this change, so please try building your projects with this opt-in!
Does this also affect virtual manifest handling? I’ve definitely noticed when working with futures that there is no way to activate features for sub-packages.
And testing it myself, it seems to work perfectly for futures, having --no-default-features apply to all packages and --features actually error out insteads of just being ignored is great
Even playing round with a non-virtual workspace I noticed that --features without --package correctly detects when there’s a single or multiple default-members to apply to
One potential addition: allow specifying features on packages in the current workspace when doing a full build by referring to them via <package>/<feature>, e.g. instead of having to run cargo build --package futures --features nightly it could be possible to run cargo build --features futures/nightly and have that enable the correct features on all packages based on the features specified on the command line.
Not sure how useful that would be in practice, just an idea I had while thinking about how futures Travis config could be changed with this.
Yeah, it is true that today there's simply no syntax for specifying features for different packages, and that we should probably add it. However, we might need to fix https://github.com/rust-lang/cargo/issues/4463 first, which would be not so trivial
Could you elaborate what exactly stopped working? If you specify -all, then only -all-features and -no-default-features flags are supported. —features does not work, because it is ambiguous as to which package the feature should apply.
I guess previously it was possible to do something like Cargo build —all —manifest-path foo/Cargo.toml —feature bar, but it doesn’t look that useful?
Yes, it does make sense that --features wouldn't work by itself with --all, that's why I was hoping to use the -Z package-features flag to specify which packages a given feature should apply to.
Yep, that's exactly it. It's useful to me because I can (currently) issue a single very quick cargo build command form a top-level Makefile while specifying one feature in a subcrate of my workspace (the makefile is doing other non-Rust stuff for my OS). It'd be even better to issue a single cargo build command with multiple features specified for multiple packages, but I understand if y'all don't wish to support that.
We definitely wish to support that! However, we need to fix one small and one big problem before it is possible
The small problem is that we just don't have syntax for it yet. --package foo --features "foo/bar" seems a plausible option though!
The bigger problem is that features selection works weirdly depending on the precise set of packages that you are compiling. That end result is that cargo build -p foo and cargo build -p foo -p bar can produce different artifacts for foo, because, currently, Cargo unions all the features for packages being compiled.
We've also decided to go ahead and flip the behavior hear, without explicit opt-in, so, when Cargo is updated at rust-lang/rust, the next nightly would have the new behavior. If it turns out to break code in the wild, we'll have time to revert the behavior.
It used to successfully build docs for my virtual workspace, and has now started erroring. When I tried adding -Z package-features I get the error error: unknown -Z flag specified: package-features. The full command I tried was:
The fact that this worked previously is sort of by accident. I assume that your base package has a universal-docs feature that activates all the children’s universal-docs features? Because otherwise the feature wasn’t getting activated before.
To get the previous behavior, you should just be able to remove --features universal-docs. If you want to enable universal-docs on all packages, for the time being (including on stable), you unfortunately need to iterate through all of the packages. Alternatively, add a root package that passes through --features universal-docs, don’t use --all --no-deps, and live with documenting your dependencies as well.
@matklad and the rest of the rustdoc team: any chance of a --no-foreign-crates alternative to --no-deps that travels through path dependencies but not crates-io or git dependencies?
I just realized that the change actually broke UNIC’s tests as well, but that’s because they weren’t doing what the author thought they were to begin with. Overall this change is good, because it makes it harder to expect one thing to happen and get a different one.
Quick update: we’ve enabled this on nightly for a while, and unfortunately it did break tons of code in the wild, so we are rolling this change back now!
At the risk of reviving a long dead conversation, is there any reason why, instead of disallowing it all-together, cargo {test,build} --all --features $feat doesn’t apply the feature to, err, all? Similarly for multiple packages. That seems like it would fix a lot of issues people would have in this thread (as well as issues I have with cargo’s behavior here, and will continue to have after the fix).