Skip to content
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

Platform specific dependencies failing to resolve dependencies with different path #7753

Open
Nazariglez opened this issue Dec 29, 2019 · 9 comments
Labels
A-target-dependencies Area: [target.'cfg(foo)'.dependencies] C-bug Category: bug S-needs-design Status: Needs someone to work further on the design for the feature or fix. NOT YET accepted.

Comments

@Nazariglez
Copy link

Problem
Adding different dependencies using the same name and different path for different platforms display this error:
Dependency 'backend' has different source paths depending on the build target. Each dependency must have a single canonical source path irrespective of build target.

The book says that this is allowed here: https://doc.rust-lang.org/1.32.0/cargo/reference/specifying-dependencies.html#platform-specific-dependencies

[target.'cfg(target_arch = "x86")'.dependencies]
native = { path = "native/i686" }

[target.'cfg(target_arch = "x86_64")'.dependencies]
native = { path = "native/x86_64" }

This is my code:

[target.'cfg(target_arch = "wasm32")'.dependencies]
backend = { path = "./web-backend", package = "web-backend"}

[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
backend = { path = "./native-backend", package = "native-backend"}

[workspace]
members = [
    "web-backend",
    "native-backend"
]

I think that this should compile and use inside the code web-backend as backend for wasm32 and native-backend as backend for different targets.

Steps
I made a simple test project: https://github.com/Nazariglez/cargo-dep-bug

Possible Solution(s)
Not sure how to fix this, or what is the solution, but maybe is related to this other (closed) issue: #5345

Notes
Output of cargo version: cargo 1.40.0 (bc8e4c8 2019-11-22)
Output of rustc --version: rustc 1.40.0 (73528e339 2019-12-16)
OS: MacOS Mojave 10.14.6
Target: wasm32-unknown-unknown and default
Channel: Stable and nightly

@Nazariglez Nazariglez added the C-bug Category: bug label Dec 29, 2019
@ehuss ehuss added A-documenting-cargo-itself Area: Cargo's documentation A-target-dependencies Area: [target.'cfg(foo)'.dependencies] labels Dec 30, 2019
@ehuss
Copy link
Contributor

ehuss commented Dec 30, 2019

Hmm, at a minimum the documentation is wrong.

I'm not sure what the feasibility is of supporting that use case. It can be tricky to ensure that different target expressions are mutually exclusive. For example, cfg(target_os="windows") and cfg(target_arch="x86_64") can both be true, so Cargo would need to defer the duplication check until very late.

Maybe @Eh2406 can comment on the feasibility of the resolver supporting that. But I suspect overall this would be hard to support reliably.

@Eh2406
Copy link
Contributor

Eh2406 commented Dec 30, 2019

@Nazariglez Thanks for such a high quality report!

My main question is why do the docs say that!? Did it ever work!? Git blame thinks it goes back to 4d590f9

The mutual exclusivity also needs to be global, the question is not the straightforward "does this computer have both of these flags" but the much harder "is there a computer that has both of these flags".

@paulirotta
Copy link

We can guarantee exclusive if the not structure is baked into any future fix. Moving from

(this fails)

[target.'cfg(target_arch = "x86_64")'.dependencies]
quicksilver = {git = "https://github.com/paulirotta/quicksilver.git", branch="image-fix-test"}

[target.'cfg(not(target_arch = "x86_64"))'.dependencies]
quicksilver = {git = "https://github.com/paulirotta/quicksilver.git", branch="v3-gl3-i8u8-fix"}

to something along the lines of

[target.'cfg(target_arch = "x86_64")'.dependencies]
quicksilver = {git = "https://github.com/paulirotta/quicksilver.git", branch="image-fix-test"}
[else]
quicksilver = {git = "https://github.com/paulirotta/quicksilver.git", branch="v3-gl3-i8u8-fix"}

As there seems to be no orthodox solution, I'll just continue to ugly through it.

@dalcde
Copy link

dalcde commented Jan 5, 2021

I think it would make sense to allow this and error only when there is a conflict for the specific target you are actually building.

@azerupi
Copy link
Contributor

azerupi commented Nov 4, 2021

The Cargo book still gives this as a valid example: https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#platform-specific-dependencies

In the meantime we have used this simple workaround:

Cargo.toml

# Compile with the simulator on Windows and Unix (dev machines)
[target.'cfg(any(windows, unix))'.dependencies]
simulator = { path = "../simulator" }

# Compile with real remote bindings on other targets
[target.'cfg(not(any(windows, unix)))'.dependencies]
real = { path = "../real" }

lib.rs

#[cfg(not(any(windows, unix)))]
pub use real as remote;
#[cfg(any(windows, unix))]
pub use simulator as remote;

Maybe this might be a good enough solution to propose in the documentation?

@joshmarinacci
Copy link

I just ran into this issue as well. It should be updated to say that you have to name each crate differently and then import them conditionally.

bors added a commit that referenced this issue Feb 22, 2022
Remove invalid target-specific dependency example.

The example with disjoint target configs does not work (and AFAIK has never worked).  It fails with the error:

```
  Dependency 'native' has different source paths depending on the build target. Each dependency must have a single canonical source path irrespective of build target.
```

This removes it to avoid confusion.

cc #7753
@alexzanderr
Copy link

hello. im trying to use a workaround with git.

# linux
[target.'cfg(all(not(target_family = "wasm"), target_os = "linux"))'.dependencies]
dioxus = { version = "0.3.0", git = "https://github.com/DioxusLabs/dioxus", rev = "faf94c7b4e44edcdf2a04506122cf8ba6a1587e3" }

# android
[target.'cfg(all(not(target_family = "wasm"), target_os = "android"))'.dependencies]
dioxus = { version = "0.2.4", git = "https://github.com/DioxusLabs/dioxus", rev = "1e99e355" }

doesnt seem to work

Caused by:
  Dependency 'dioxus' has different source paths depending 
on the build target. Each dependency must have a single 
canonical source path irrespective of build target.

why this example doesnt work?

its not a different source path, its the same repository but a different state of the source code.

and so im using a different state of the source code depending on the target_os, why this isnt allowed?

how can i fix this?

thanks.

@alexzanderr
Copy link

#[cfg(not(any(windows, unix)))]
pub use real as remote;
#[cfg(any(windows, unix))]
pub use simulator as remote;

this is a good solution. i've tried this.

but this solution doesnt work then you have proc-macros and macros that do expansion of the some code what will include the dependency remote as ::remote in the proc-macro or macro source.

i've experienced this with the dioxus crate which has the rsx! macro that when expanded imports dioxus like this: ::dioxus.

and doesnt work because i was importing dioxus as dioxus_030 in Cargo.toml and use dioxus_030 as dioxus; in the source files

so there was no ::dioxus in my crate, but ::dioxus_030

@epage epage added S-needs-design Status: Needs someone to work further on the design for the feature or fix. NOT YET accepted. and removed A-documenting-cargo-itself Area: Cargo's documentation labels Nov 3, 2023
@epage
Copy link
Contributor

epage commented Nov 3, 2023

As far as I can tell, the documentation side to this is resolved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-target-dependencies Area: [target.'cfg(foo)'.dependencies] C-bug Category: bug S-needs-design Status: Needs someone to work further on the design for the feature or fix. NOT YET accepted.
Projects
None yet
Development

No branches or pull requests

9 participants