Tracking issue for -Z features=host_dep
ehuss opened this issue ยท 18 comments
Implementation: #7820
Documentation: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#features
Summary
-Z features=host_dep
causes the feature resolver to prevent features enabled on build dependencies or proc-macros from being enabled for normal dependencies. For example:
[dependencies]
log = "0.4"
[build-dependencies]
log = {version = "0.4", features=['std']}
When building the build script, the log
crate will be built with the std
feature. When building the library of your package, it will not enable the feature.
Unresolved issues
- Update
cargo metadata
- Does this cause existing projects to fail?
- Projects can add missing features as a backwards-compatible workaround. However, if it causes problems for too many projects, we may need to find some way to opt-in.
- Does this significantly increase build times?
- This can cause common dependencies to be built multiple times, when they were previously shared (when
--target
is not used). Projects can add features to re-unify if they want, but it may not be clear or obvious what to add and when. We may need something that identifies these duplicate dependencies, and give suggestions on how to unify them. Or, we may need to make this opt-in somehow so the user needs to make this an explicit decision.
- This can cause common dependencies to be built multiple times, when they were previously shared (when
- Does the feature resolver need to support decoupling of shared proc-macro dependencies?
- Currently this isn't possible because Cargo does not have the necessary information to know which dependencies are proc-macros during resolution time. Either we would need to add the proc-macro status to the index, or try to do feature resolution while dependencies are downloaded. The latter is very difficult due to the way downloading works. The former isn't too hard. Nobody has asked for this ability, so it is unclear how important it is. Presumably that is because proc-macros are relatively new, and tend to only use proc-macro-specific dependencies like syn/quote.
- Implemented in #8028.
Does the feature resolver need to support decoupling of shared proc-macro dependencies?
Yes please. I've encountered an issue related to this already when a proc-macro enabled many features in the rand
crate which caused my build to fail since my target does not have std
. See rust-lang/hashbrown#124 for details.
UPDATE: never mind, this is a red herring. the proc macro itself was referencing std
, because I forgot to disable its std
feature ๐
. With the std
feature it works, but I can see how this could come up in dependency-laden proc macros that activate the std
feature in dependencies shared by the proc macro.
I just ran into the proc macro problem trying to use displaydoc
in a no_std
project:
$ cargo build -Z features=build_dep --no-default-features --target thumbv7em-none-eabihf --release
error[E0433]: failed to resolve: use of undeclared type or module `std`
--> rust/src/error.rs:7:30
|
7 | #[derive(Copy, Clone, Debug, Display, Eq, PartialEq)]
| ^^^^^^^ use of undeclared type or module `std`
It would definitely be super duper handy to be able to use proc macros that link against std
in no_std
targets, and also to ensure there's some open issue tracking it until it's fixed.
Seeing as #4866 was about proc-macro...
@valarauca it looks like some people discussed proc macros in the comments, but #4866 itself was about build-dependencies
Perhaps it's worth opening a new issue?
I would also be interested in having -Z features=build_dep
work with proc-macro
. I would use it for the data-encoding-macro
crate.
proc-macro support has been added in #8028, and should be in the latest nightly (2020-03-27). proc-macros and build dependencies are unified (since they are all "host" artifacts), but shouldn't affect anything else. Also, the option has been renamed to -Zfeatures=host_dep
to reflect this change (the old build_dep
option is an alias). I'd appreciate it if people could take it for a test drive and let me know how it works. This resulted in a major change in how crates are downloaded, so any testing is appreciated.
I created this "project" as a slightly contrived example.
real_project
configuresfake-dep
(viafake-dev-dep
) to panic. see: linkreal_project
requiresfake-dev-dep
to panic . Thereal_project/build.rs
file willexit(1)
iffake-dep
does not panic). see: linkreal_project
by default expectsfake-dep
to not panic within itstest
link
Results:
- On
stable
runningcargo test
withinreal_project
results in test failure (test::crate_worked_successfully panicked at hello world
) - On
nightly-2020-03-18
runningcargo test
withinreal_project
results in a test failure (test::crate_worked_successfully panicked at hello world
) - On
2020-03-27
runningcargo test -Zfeatures=host_dep
the test passes!
I hope this is a valid tests. The idea is build-dependencies
and dependencies
should have different, and conflicting features.
The results seem positive. Thanks for the work on this!
For what it's worth, my sample project which cross compiles to thumbv7m-none-eabi
used to complaint about memchr
needing std
as soon as I imported bindgen
in the build-dependencies
. With the new dependency resolution strategy I can now run bindgen
in build.rs
during build time. Hooray and thank you for the great enhancement.
https://github.com/tinoadams/bluepill_mynewt_rust_blink/blob/master/rust/app/Cargo.toml
Is there a way to enable this via .cargo/config
or Cargo.toml
, or do I need to pass -Z features=host_dep
manually to Cargo every time?
Is there a way to enable this via
.cargo/config
orCargo.toml
, or do I need to pass-Z features=host_dep
manually to Cargo every time?
Probably a bit offtopic, but I opened #8127 to propose a general solution to this problem.
The availability of resolver
2 (and specifically host_dep
) has been critical for us being able to continue using Cargo in our embedded build (cross compiling for thumbv7em-none-eabihf
). We use serde
both in the build (to consume and produce metainformation), and in the firmware (to marshal IPC), and I was preparing to move us to a different build system because of Cargo blindly forcing std
on the firmware. I am delighted to report that I have not had to do this.
This has forced us onto a pretty recent nightly, though, which I had been trying to avoid -- resolver
is the only reasonable way to express this, rather than expecting all developers to remember to type -Z host_dep
every time, and we are using a virtual workspace, so I had to fast forward all the way to nightly-2020-05-01
to get a combination of features that worked / a build with all the artifacts we needed. So I look forward to the fixed resolver behavior making it to stable!
@ehuss would it make sense to change the "Summary" in the issue description to say host_dep
instead of build_dep
?
Or maybe mention that it was renamed, as it was confusing at first.
This feature is working great for an embedded project I'm working on. Like others, I was hitting no_std and bindgen conflict. It's really great to see this feature! Thanks!
Is there a way to enable this via
.cargo/config
orCargo.toml
, or do I need to pass-Z features=host_dep
manually to Cargo every time?Probably a bit offtopic, but I opened #8127 to propose a general solution to this problem.
Seems like this has been merged. Had to search a bit how to use it, so for anyone else who's using this - here's a way to enable the flag in .cargo/config
[unstable]
features = ["host_dep"]
When stable?
Works great. Would like to see this too.
Hi @ehuss,
three days ago (2021-01-05) I noticed some unstable CI build where I use -Zfeatures=dev_dep,host_dep
. I could reproduce it locally only using host_dep
, which is why I post here. I never noticed it without the feature.
Error Log
error[E0053]: method `from_list` has an incompatible type for trait
Error: --> serde_with_macros\src\lib.rs:431:14
|
431 | #[derive(FromMeta, Debug)]
| ^^^^^^^^ expected enum `syn::attr::NestedMeta`, found enum `NestedMeta`
|
= note: expected fn pointer `fn(&[syn::attr::NestedMeta]) -> std::result::Result<_, _>`
found fn pointer `fn(&[NestedMeta]) -> std::result::Result<_, _>`
= note: perhaps two different versions of crate `syn` are being used?
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0053]: method `from_field` has an incompatible type for trait
Error: --> serde_with_macros\src\lib.rs:465:14
|
465 | #[derive(FromField, Debug)]
| ^^^^^^^^^ expected struct `syn::data::Field`, found struct `syn::Field`
|
= note: expected fn pointer `fn(&syn::data::Field) -> std::result::Result<_, _>`
found fn pointer `fn(&syn::Field) -> std::result::Result<_, _>`
= note: perhaps two different versions of crate `syn` are being used?
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0053]: method `from_field` has an incompatible type for trait
Error: --> serde_with_macros\src\lib.rs:482:14
|
482 | #[derive(FromField, Debug)]
| ^^^^^^^^^ expected struct `syn::data::Field`, found struct `syn::Field`
|
= note: expected fn pointer `fn(&syn::data::Field) -> std::result::Result<_, _>`
found fn pointer `fn(&syn::Field) -> std::result::Result<_, _>`
= note: perhaps two different versions of crate `syn` are being used?
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0053]: method `from_derive_input` has an incompatible type for trait
Error: --> serde_with_macros\src\utils.rs:26:10
|
26 | #[derive(FromDeriveInput, Debug)]
| ^^^^^^^^^^^^^^^ expected struct `syn::derive::DeriveInput`, found struct `DeriveInput`
|
= note: expected fn pointer `fn(&syn::derive::DeriveInput) -> std::result::Result<_, _>`
found fn pointer `fn(&DeriveInput) -> std::result::Result<_, _>`
= note: perhaps two different versions of crate `syn` are being used?
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0308]: mismatched types
Error: --> serde_with_macros\src\lib.rs:438:68
|
438 | let container_options = match SerdeContainerOptions::from_list(&args) {
| ^^^^^ expected slice, found struct `Vec`
|
= note: expected reference `&[syn::attr::NestedMeta]`
found reference `&Vec<NestedMeta>`
error[E0308]: mismatched types
Error: --> serde_with_macros\src\lib.rs:431:14
|
431 | #[derive(FromMeta, Debug)]
| ^^^^^^^^ expected enum `syn::attr::Meta`, found enum `syn::Meta`
|
= note: expected reference `&syn::attr::Meta`
found reference `&syn::Meta`
= note: perhaps two different versions of crate `syn` are being used?
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0308]: mismatched types
Error: --> serde_with_macros\src\lib.rs:499:55
|
499 | let serde_as_options = SerdeAsOptions::from_field(field)?;
| ^^^^^ expected struct `syn::data::Field`, found struct `syn::Field`
|
= note: expected reference `&syn::data::Field`
found mutable reference `&mut syn::Field`
= note: perhaps two different versions of crate `syn` are being used?
error[E0308]: mismatched types
Error: --> serde_with_macros\src\lib.rs:500:59
|
500 | let serde_with_options = SerdeWithOptions::from_field(field)?;
| ^^^^^ expected struct `syn::data::Field`, found struct `syn::Field`
|
= note: expected reference `&syn::data::Field`
found mutable reference `&mut syn::Field`
= note: perhaps two different versions of crate `syn` are being used?
error[E0308]: mismatched types
Error: --> serde_with_macros\src\lib.rs:465:14
|
465 | #[derive(FromField, Debug)]
| ^^^^^^^^^ expected struct `syn::attr::Attribute`, found struct `Attribute`
|
= note: expected reference `&syn::attr::Attribute`
found reference `&Attribute`
= note: perhaps two different versions of crate `syn` are being used?
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0308]: mismatched types
Error: --> serde_with_macros\src\lib.rs:465:14
|
465 | #[derive(FromField, Debug)]
| ^^^^^^^^^
| |
| expected enum `syn::attr::NestedMeta`, found enum `NestedMeta`
| this expression has type `syn::attr::NestedMeta`
|
= note: perhaps two different versions of crate `syn` are being used?
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0308]: mismatched types
Error: --> serde_with_macros\src\lib.rs:465:14
|
465 | #[derive(FromField, Debug)]
| ^^^^^^^^^ expected enum `syn::attr::Meta`, found enum `syn::Meta`
|
= note: expected reference `&syn::attr::Meta`
found reference `&syn::Meta`
= note: perhaps two different versions of crate `syn` are being used?
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0308]: mismatched types
Error: --> serde_with_macros\src\lib.rs:482:14
|
482 | #[derive(FromField, Debug)]
| ^^^^^^^^^ expected struct `syn::attr::Attribute`, found struct `Attribute`
|
= note: expected reference `&syn::attr::Attribute`
found reference `&Attribute`
= note: perhaps two different versions of crate `syn` are being used?
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0308]: mismatched types
Error: --> serde_with_macros\src\lib.rs:482:14
|
482 | #[derive(FromField, Debug)]
| ^^^^^^^^^
| |
| expected enum `syn::attr::NestedMeta`, found enum `NestedMeta`
| this expression has type `syn::attr::NestedMeta`
|
= note: perhaps two different versions of crate `syn` are being used?
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0308]: mismatched types
Error: --> serde_with_macros\src\lib.rs:482:14
|
482 | #[derive(FromField, Debug)]
| ^^^^^^^^^ expected enum `syn::attr::Meta`, found enum `syn::Meta`
|
= note: expected reference `&syn::attr::Meta`
found reference `&syn::Meta`
= note: perhaps two different versions of crate `syn` are being used?
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0308]: mismatched types
Error: --> serde_with_macros\src\utils.rs:26:10
|
26 | #[derive(FromDeriveInput, Debug)]
| ^^^^^^^^^^^^^^^ expected struct `syn::attr::Attribute`, found struct `Attribute`
|
= note: expected reference `&syn::attr::Attribute`
found reference `&Attribute`
= note: perhaps two different versions of crate `syn` are being used?
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0308]: mismatched types
Error: --> serde_with_macros\src\utils.rs:26:10
|
26 | #[derive(FromDeriveInput, Debug)]
| ^^^^^^^^^^^^^^^
| |
| expected enum `syn::attr::NestedMeta`, found enum `NestedMeta`
| this expression has type `syn::attr::NestedMeta`
|
= note: perhaps two different versions of crate `syn` are being used?
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0308]: mismatched types
Error: --> serde_with_macros\src\utils.rs:26:10
|
26 | #[derive(FromDeriveInput, Debug)]
| ^^^^^^^^^^^^^^^ expected enum `syn::attr::Meta`, found enum `syn::Meta`
|
= note: expected reference `&syn::attr::Meta`
found reference `&syn::Meta`
= note: perhaps two different versions of crate `syn` are being used?
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0277]: the trait bound `syn::Path: FromMeta` is not satisfied
Error: --> serde_with_macros\src\utils.rs:26:10
|
26 | #[derive(FromDeriveInput, Debug)]
| ^^^^^^^^^^^^^^^ the trait `FromMeta` is not implemented for `syn::Path`
|
= note: required because of the requirements on the impl of `FromMeta` for `Option<syn::Path>`
= note: required by `from_meta`
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0308]: mismatched types
Error: --> serde_with_macros\src\utils.rs:36:60
|
36 | match <Self as FromDeriveInput>::from_derive_input(&input) {
| ^^^^^^ expected struct `syn::derive::DeriveInput`, found `&DeriveInput`
|
= note: expected reference `&syn::derive::DeriveInput`
found reference `&&DeriveInput`
error: aborting due to 19 previous errors
Error: aborting due to 19 previous errors
Some errors have detailed explanations: E0053, E0277, E0308.
For more information about an error, try `rustc --explain E0053`.
error: could not compile `serde_with_macros`
Error: could not compile `serde_with_macros`
To learn more, run the command again with --verbose.
warning: build failed, waiting for other jobs to finish...
Warning: error: build failed
Error: The process 'C:\Rust\.cargo\bin\cargo.exe' failed with exit code 101
Instance 1: https://github.com/jonasbb/serde_with/runs/1669122665#step:5:139
Instance 2: https://github.com/jonasbb/serde_with/runs/1658483317#step:5:139
The error occurs on both Ubuntu and Windows, but is non-deterministic. I think the first PR where I noticed that is jonasbb/serde_with#238 but I re-run the failed tests and now I cannot find the old logs. Before that point in time I haven't seen the issue before.