rust-lang / cargo

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

Cannot declare different version of dependencies in mutually exclusive targets #3195

Open wagenet opened 7 years ago

wagenet commented 7 years ago

Maintainer's update


That's a mouthful, but here's an example:

[target.'cfg(not(target_os = "linux"))'.dependencies]
nix = "0.5.0"

[target.'cfg(target_os = "linux")'.dependencies]
nix = "0.4.3"

Unfortunately, right now this isn't allowed as it's considered a duplicate declaration per #2491.

The use case for this is that FreeBSD requires a newer version of nix to work. However, Linuxes with glibc 2.5 require an older version of nix.

My very ugly workaround is to fork nix and rename it. Then I can use cfg to import the correct crate in the source.

alexcrichton commented 7 years ago

Yeah unfortunately Cargo doesn't handle this case very well in general (depending on two versions of a library). If this works at all I'd be pretty surprised!

wagenet commented 7 years ago

It works, but only if the libraries are forked an renamed to avoid actual duplicate names.

alexcrichton commented 7 years ago

Yeah Cargo should definitely have built-in support for that kind of operation.

TheNeikos commented 7 years ago

Interesting, there is this test: https://github.com/rust-lang/cargo/blob/be010b545fef76858ad74a5f4a188e42e1fffb91/tests/cfg.rs#L232

That seems to test exactly that, and it checks for success

damaex commented 7 years ago

I somewhat have an equal problem with the feature-dependencies for mysql-crate:

[target.'cfg(any(unix, macos))'.dependencies.mysql]
version = "*"
default-features = false
features = ["socket"]

[target.'cfg(windows)'.dependencies.mysql]
version = "*"
default-features = false
features = ["pipe"]
alexcrichton commented 7 years ago

@TheNeikos oh interesting! @wagenet maybe this was fixed in nightly at some point? Or perhaps you could gist the exact error?

@damaex ah I think that my actually be an unrelated failure (e.g. another bug in Cargo). Enabling separate features for different targets unfortunately isn't supported right now.

wagenet commented 7 years ago

@alexcrichton looks like you're right about this being fixed on the latest nightly. Thanks!

wagenet commented 7 years ago

Looks like there are still issues around git dependencies. This doesn't work:

[target.'cfg(not(target_os = "linux"))'.dependencies]
nix     = "0.5.0"
pidfile = { git = "https://github.com/wagenet/pidfile-rust", rev = "a0fe92915e419938d8d33f5cefb6e8f50b89d174" }

[target.'cfg(target_os = "linux")'.dependencies]
nix     = "0.4.3"
pidfile = { git = "https://github.com/carllerche/pidfile-rust", rev = "7516edfc9af2c0480e9f187c87de8cf6323c1ee3" }

It complains about pidfile being a duplicate, but not nix.

wagenet commented 7 years ago

Initial work on a PR to fix this here: #3275

Eh2406 commented 5 years ago

Note that https://github.com/rust-lang/cargo/issues/6179#issuecomment-431544643 may provide a workaround by using --minimal-cargo-lock to build only for the current platform.

wagenet commented 5 years ago

See #6212.

alexcrichton commented 5 years ago

I don't personally know how we'd solve this today or whether it's easily solvable, but PRs to implement it are of course always welcome!

RalfJung commented 5 years ago

Looks like a duplicate of https://github.com/rust-lang/cargo/issues/2524.

ehuss commented 5 years ago

@RalfJung I don't see this as a duplicate. The issue here is that two different targets using git dependencies does not work. #2524 is about using different features.

RalfJung commented 5 years ago

Sorry for that then, seems I didn't understand what this bug is about.

Autoparallel commented 2 months ago

I have an issue that is very similar to this. Essentially, when you run cargo check or cargo build, cargo will compile dependencies for all the targets provided. For example, I have a case like this:

[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
tokio       ={ version="1", features=["rt", "rt-multi-thread", "macros", "net", "io-std", "fs"] }
# snip

[target.'cfg(target_arch = "wasm32")'.dependencies]
# No use of `tokio`
# snip

There are, of course, other dependencies that change between the wasm32 and non-wasm32 targets, but what I find is that cargo check builds tokio for wasm32.

This is happening given that distinct portions of code are gated with:

#[cfg(not(target_arch = "wasm32"))] pub mod my_mod;
#[cfg(target_arch = "wasm32")] pub mod my_wasm_mod;

Now, I can resolve this by compiling targets separately:

cargo check --target wasm32-unknown-unknown
cargo check --target aarch64-apple-ios

But this leaves a lot to be desired. It's not really very easy to then have rust-analyzer use cargo check as we need to adjust its settings to only focus on a single target at a time. We also cannot build both targets with a single command.

What would be great is, like with features as well, we can have cargo check and cargo build only compile the features and dependencies necessary for the specific target in mind.