rust-lang / cargo

The Rust package manager
https://doc.rust-lang.org/cargo
Apache License 2.0
12.73k stars 2.42k forks source link

Allow optional dev-dependencies #1596

Open bluss opened 9 years ago

bluss commented 9 years ago

Quickcheck test cases take a very long time to build (minutes) compared to the rest of my tests that take seconds.

For this reason, I use quickcheck as an optional regular dependency. It's not used in regular cargo build and cargo test.

Using an optional dev-dependency would be more correct (and info on crates.io would be more correct).

alexcrichton commented 9 years ago

I was quite surprised that there was an explicit error when I tried this out to verify it, now I need to remember why I put that in there...

alexcrichton commented 9 years ago

Hm ok I think I remember now, and I believe my hesitation here was related to feature activation. For example it may be quite surprising to enable a feature which activates both dev and non-dev dependencies when a package is itself used as a dependency (e.g. no dev-deps are built). Should Cargo issue a warning/error in this case? Should Cargo silently ignore all activated dev-dependencies?

bluss commented 9 years ago

Not sure. You're seeing the bigger picture much better than me, (thankfully!). I think I'll move to a mandatory dev dependency for now

bluss commented 9 years ago

It could issue a warning if the feature only activates dev-dependencies.

I'm already back from the "experiment" :-) I need it to be optional so that I can keep building tests on Rust 1.0, which doesn't have quickcheck_macros. How quickcheck works with testing functions (requires explicit cast to fn pointer for each tested predicate), the only sane way to use it is with macros.

alexcrichton commented 9 years ago

I think it'd be fine for now to ensure that a feature only activates only dependencies or the dev-dependencies, sending a hard error for now would allow us to possibly be more flexible in the future.

sfackler commented 9 years ago

I'd like this in the context of platform dependent features that have dev-dependencies.

huonw commented 9 years ago

I wonder if this would be better served by having dev-features, which aren't exposed downstream. The error case is then just a normal feature trying to activate a dev-feature.

(This raises the question: do we want build-features too?)

alexcrichton commented 9 years ago

@huonw, that's a good idea! I like the sound of dev-features to solve this along with static checking that the set of dev-features and regular features don't overlap (e.g. they don't reach into one another).

I don't think that we'd want build-features because this is specifically related to activation of dependencies, and a normal feature activating a fancy codegen option as part of the normal build seems fine to me. E.g. this is separating "when you build" vs "when you test".

Now all that being said, I also don't feel too bad about just silently not activating dev-dependencies if a feature includes it and it's not a direct dependency. That would at least cut down on the complexity of the manifest, which may be the best thing to optimize for here.

erickt commented 8 years ago

Ran into another case where this would be handy. I added a dependency on clippy and compiletest to aster. Both only compile on nightly, so to keep things building on stable I had to make them optional. I enabled them with the unstable feature, which also enabled a couple other things that are needed for libsyntax. Unfortunately, this caused https://github.com/serde-rs/aster/issues/63 do to some breakage do to clippy.

While the fix was pretty simple (I just used another feature), really these dependencies are only necessary for testing my project, and have no use on any of my downstream users. This really does mean that they ought to be dev-dependencies, but since there's no way to selectively enable optional crates that only build on nightly for extra special testing, I need to express them as regular dependencies.

Nemo157 commented 8 years ago

:+1: I want this for a similar reason (including plugin based macros for doc tests on nightly). I also noticed that the manifest format documentation had this in it (emphasis mine):

Cargo supports features to allow expression of:

  • [...] and possibly other packages (such as development-time mocking libraries, debugging tools, etc.)

It does say that dev dependencies can't be optional lower down, but if this isn't going to be implemented any time soon then it may be nice to get rid of that suggestion (or link it to this issue so people know it's a future feature).

mitchmindtree commented 8 years ago

I've run into a similar use case to erickt:

I've added an optional serde_serialization feature to some of the RustAudio crates. In order to be able to test their serialization without writing an entire serializer/deserializer pair in each crate, I'd like to be able to use the serde_json crate as a dev-dependency only when the serde_serialization feature is active.

shepmaster commented 7 years ago

Add me to the pile. I have the same case as @bluss - wanting to have quickcheck tests.

I also am replacing a crate that uses C code with pure Rust, so I'd like to have a dev-dependency on the replaced crate to run tests that ensure the behavior is the same between the two. Showing that I depend on the C crate would look really weird on crates.io though!

I also have a dependency on competitor crates for the purposes of benchmarking.

To solve all these in one fell swoop, I think I'm going to create a sub project that just uses my crate. This should work for me, but might not for everyone.

alexcrichton commented 7 years ago

Note that this is basically just blocked on getting the work done. I'd be most in favor of my previous comment, simply requiring that activating a feature can either enable a regular dependency or a dev-dependency, not both.

TheNeikos commented 6 years ago

What would need to be done for this? I'd be willing to try my hand at it.

stale[bot] commented 6 years ago

As there hasn't been any activity here in over 6 months I've marked this as stale and if no further activity happens for 7 days I will close it.

I'm a bot so this may be in error! If this issue should remain open, could someone (the author, a team member, or any interested party) please comment to that effect?

The team would be especially grateful if such a comment included details such as:

Thank you for contributing!

(The cargo team is currently evaluating the use of Stale bot, and using #6035 as the tracking issue to gather feedback.)

If you're reading this comment from the distant future, fear not if this was closed automatically. If you believe it's still an issue please leave a comment and a team member can reopen this issue. Opening a new issue is also acceptable!

SimonSapin commented 6 years ago

I believe this is still relevant.

lucab commented 6 years ago

This is a feature request and there seems to be general consensus that it would be nice to have. It should be labeled as https://github.com/rust-lang/cargo/labels/Feature%20accepted so that stalebot leaves this alone.

wolfiestyle commented 5 years ago

This would be a nice to have when you're playing with nightly-only crates as a separate nightly feature set. Currently you can't use nightly-only crates on your dev-dependencies without breaking your stable build. The current workaround is putting those crates on your regular dependencies under a "nightly" feature, but that's suboptimal.

phyber commented 5 years ago

While attempting to write some tests where the tests were depending on a testing crate that was nightly only just now, I was quite surprised when Rust told me I couldn't have optional dev-dependencies.

aloucks commented 4 years ago

It would be really nice to allow criterion to be an optional dev-dependency. It increases build times by a non-trivial amount of time and isn't needed when running tests.

bluss commented 4 years ago

For such cases like benchmarks, for now I'd recommend using an additional non-published crate that you keep in the same repository, that depends on your library and contains the benchmarks. It will need to use the public APIs, of course, but that's ok in most cases. As an example of this, ndarray has a subdirectory for blas-tests that runs tests that depend on BLAS.

panhania commented 4 years ago

I have a test that uses the fuse crate. However, in order to build it, libfuse-dev needs to be installed on the system. Forcing each developer to install it just to be able to run one out of many tests feels like an overkill. However, I would prefer to keep the test, e.g. for the purpose of CI, where installing extra system dependencies is not an issue.

The most natural choice is to make the dependency on fuse optional and hide tests that use behind a feature. As I understand, this is currently impossible.

jhwgh1968 commented 3 years ago

I am surprised ~no one~ few have mentioned embedded yet. It is how I came across this issue.

I am playing around with a crate that is #![no_std] with an "enable std" feature gate. Even with that feature gate off, however, I cannot build the crate for my "core only" embedded target.

Something causes the dev-dependencies to always build even for release mode, and unlike the main crate, they require "full std". As a result, I have to make an additional level of sub-package in order to build for my target. Optional dependencies would allow a cleaner solution to this.

EDIT: I originally thought this was specific to cargo xbuild, but it is not.

EDIT 2: actually read @shepmaster's comment, who pointed out a better solution than I previously typed

infinity0 commented 2 years ago

For the criterion use-case, perhaps we can just have cargo add --cfg bench then devs can define [target.'cfg(bench)'.dev-dependencies.criterion] in their Cargo.toml instead of polluting their dependencies?

Currently cargo automatically applies --cfg test so there is already precedence for this technique. Even without this feature, devs can pass RUSTFLAGS="--cfg bench" while using the other solution.

jhpratt commented 2 years ago

^^ that would be outstanding

c410-f3r commented 2 years ago

Any news?

sffc commented 2 years ago

My use case is a dev-dependency that has a dependency back to my crate:

  1. main_crate:
    • Has feature "experimental"
    • Has dev-dependency to helper_crate
  2. helper_crate:
    • Has feature "experimental"
    • Has dependency to main_crate
    • The "experimental" feature enables main_crate/experimental

I want to be able to run tests in main_crate with the experimental feature turned off and when turned on, which means that I need to be able to optionally enable a feature of a dev-dependency.

epage commented 1 year ago

One idea brought up in this thread is dev-features.

Some related proposals are

See also rust-lang/rfcs#3416

kajacx commented 1 year ago

Should Cargo silently ignore all activated dev-dependencies?

Yes. Cargo already ignores all dev dependencies when it comes to the resulting built code. If some of them are activated by a feature should have no effect on that.