-
Notifications
You must be signed in to change notification settings - Fork 2.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Incorrect dev-dependency feature resolution #1796
Comments
I traced it down to https://github.com/rust-lang/cargo/blob/master/src/cargo/ops/cargo_compile.rs#L152 which seem to be the problem. This simple patch works for me (both diff --git a/src/cargo/ops/cargo_compile.rs b/src/cargo/ops/cargo_compile.rs
index a927208..5d9ff3e 100644
--- a/src/cargo/ops/cargo_compile.rs
+++ b/src/cargo/ops/cargo_compile.rs
@@ -149,7 +149,8 @@ pub fn compile_pkg<'a>(package: &Package,
let platform = target.as_ref().map(|e| &e[..]).or(Some(&rustc_host[..]));
let method = Method::Required{
- dev_deps: true, // TODO: remove this option?
+ dev_deps: options.mode == CompileMode::Test ||
+ options.mode == CompileMode::Bench,
features: &features,
uses_default_features: !no_default_features,
target_platform: platform}; |
After tinkering around the source it seems that it's more of an architectural problem.
This makes me come to a conclusion that the only difference between To sum up why am I here at this point: So far all my attempts to unbreak the examples (building them with dev-deps) failed and it looks like the change is beyond my understanding of cargo source so I'm closing the PR and bringing the discussion back here in hopes that someone else will give me a hint on how to fix this or provide a better PR. |
For the reference, here's a unit test exposing the problem: test!(dev_dependencies_dont_leak_features {
let p = project("foo")
.file("Cargo.toml", r#"
[package]
name = "foo"
version = "0.1.0"
authors = []
[dependencies.a]
path = "a"
[dev-dependencies.a]
path = "a"
features = ["badfeature"]
"#)
.file("src/main.rs", r#"
extern crate a;
pub fn main() { a::a(); }
"#)
.file("a/Cargo.toml", r#"
[package]
name = "a"
version = "0.1.0"
authors = []
[features]
badfeature = []
"#)
.file("a/src/lib.rs", r#"
#[cfg(feature = "badfeature")]
pub fn a() { panic!(); }
#[cfg(not(feature = "badfeature"))]
pub fn a() { }
"#);
assert_that(p.cargo_process("run"), execs().with_status(0));
}); |
Hm, upon thinking on this again I don't think there's actually any alternative here. Architecturally Cargo will union all features when compiling a crate, so even if we kept
This means that even if we were to draw the distinction between I'll also clarify that this is a very specific problem, it only shows up when:
All in all I'm starting to think that this is working as intended rather than a bug. |
Here's my practical concern. zinc pulls in volatile_cell in either runtime or test. It also pulls in expectest for testing. volatile_cell supports mocking if built with I can't change expectest to dev-dependency for volatile_cell as it doesn't propagate when I build zinc crate for tests and I can't use it as non-dev dependency now as building zinc for release pulls in expectest and its dependencies all way down to libstd. Is it a wrong use of cargo or unsupported usecase? It would be sad for us to drop cargo support again, but we really need to have both cross-builds and unit tests done in a reasonable manner (i.e. without |
Could you put the activation of |
I ran into this bug this week. I've got a feature |
@apoelstra the bug here should just be that when building the crate itself the feature leaks into the dependency, but when you crate is itself used as a dependency it shouldn't activate the features activated as part of the dev-dependencies. Does this differ from what you're seeing though? |
@alexcrichton The crate that depends on my library is a binary; it's never used as a dependency. It's when I'm building the binary that I'm having problems. |
Ah yes that'd do it. Can you elaborate on the problems you're seeing though? I understand that the dependence is built with the extra features during a normal |
@alexcrichton Sure. My application is an always-on network node which communicates with its peers as well as another application which feeds it information about the outside world. It is controlled by a .toml configuration file which describes the network address of its peers, authentication keys, etc. Most of the application logic lives in a library separate from the main binary. This includes the logic for parsing the configuration file. (This sounds iffy but we have a few projects which use almost the same configuration file, and I just use cargo features to handle the small parts that differ.) The library has a feature However, when I build my binary, the |
Thanks for the info! FWIW I think this is unlikely to be fixed in the near future. I'm not 100% convinced there's a great way to fix this, so you may want to add a separate "foo-tests" project which pulls in the dev-dep with the feature enabled if that's possible. |
Right, this is exactly what I want. My library would ideally set
And remember to always run
Actually, it also shows up when:
|
I think the following problem is related to this issue too, but should be simpler to fix. Let us have 3 crates with following
Rationale behind such structure is to disable some parts of test suit which are not compatible with
As I understand problem is that As a quick fix we can simple ignore dev-dependencies listed in |
I have a problem with cbindgen and serde, I cannot use them together This is what I have in my Cargo.toml [dependencies.serde]
version = "*"
default-features = false
[dev-dependencies]
cbindgen = "*" And I get this error
Removing cbindgen fixes the build. It looks like cbindgen in [dev-depencies] somehow enables the |
Anyone working to fix this? |
Just discovered that features also leak between targets. You cannot turn on a feature just when compiling for |
One more example, the following will fail to build on no-std targets because [dependencies]
itertools = { version = "0.8.0", default_features = false }
[dev-dependencies]
criterion = "0.2.10" My 2cts: |
I opened a tread for discussing workarounds here: https://users.rust-lang.org/t/no-std-builds-and-dev-dependencies-with-feature-unification/31582 |
I also hit the bug in quite an awkward situation while combining tokio's feature-flags. Here's a short MRE:
[dependencies]
tokio = { version = "0.2" }
[dev-dependencies]
tokio = { version = "0.2", features = [ "stream" ] }
#[allow(unused_imports)]
use tokio::stream; So the child build OK since the But if I try to build the following parent....
[dependencies]
child = { path = "../child" } It fails with an unresolved import So I've tested the |
Non-unification of dev-dependency features has been implemented and is available as a nightly-only feature on the latest nightly 2020-02-23. See the tracking issue at #7916. If people following this issue could try it out, and leave your feedback on the tracking issue (#7916), I would appreciate it. Particularly we'd like to know if it helps your project, does it cause any breakage, and is it a problem that binaries are still unified with |
If we don't do this, package becomes unusable as dependency rust-lang/cargo#1796 rust-lang/cargo#7916
If same crate is used in both
dependencies
anddev-dependencies
with the only change of features, that features leak fromdev-dependencies
todependencies
.Here's the smallest test case I managed to generate.
Root crate Cargo.toml:
this crate uses
expectest
for testing only and adep
crate for either testing or runtime build. It is expected to be a cross-compiled staticlib, so it does not depend on core (neither isdep
).Dep is defined like this:
If the replayer feature is used, this crate is being built for test, thus requiring
expectest
in runtime. Otherwise this crate is std-less as well.When cross-compiled, the expected outcome is to have
test
anddep
crates being cross-built, wheredep
is being built withoutexpectest
. This is not the case:rustc_serialize
is being pulled in as atest
dependency throughtest
->dep
->expectest
chain and fails to compile in cross environment.The text was updated successfully, but these errors were encountered: