Arch-dependant dependencies

Hi magical rustaceans,

I'm trying to write a crate that compiles differently depending on the architecture. It should compile for x86_64 and wasm32. Depending on the architecture, it needs to include some libraries with specific features. So I tried this in my Cargo.toml:

[target.'cfg(target_arch = "x86_64")'.dependencies]
flnet-libc = {path = "../arch/flnet-libc", optional = true}
flmodules = {path = "../shared/flmodules", version = "0.6"}

[target.'cfg(target_arch = "wasm32")'.dependencies]
flnet-wasm = {path = "../arch/flnet-wasm", optional = true}
flmodules = {path = "../shared/flmodules", version = "0.6", features = ["nosend"]}

But I never got this to compile. cargo check fails and the error message tells me that it tried to use flnet-libc which uses the Send trait with the flmodules/nosend crate. Which doesn't work.

So in the end I used the following Cargo.toml with features:

[features]
libc = ["flnet-libc"]
wasm = ["flnet-wasm", "flmodules/nosend"]

[dependencies]

flnet-libc = {path = "../arch/flnet-libc", optional = true}
flnet-wasm = {path = "../arch/flnet-wasm", optional = true}

flmodules = {path = "../shared/flmodules", version = "0.6"}

Which works. But it would be so much nicer if it would magically work with the target.*dependencies.

I guess that rust is not happy because there are way more archs than x86_64 and wasm32, but I don't get it why it includes flmodules/nosend in the first example?

And sorry for the reduced code - I tried to write a minimal failing code to post here, but didn't manage to do so :frowning:

Thanks if somebody has a hint,

Linus

Are you using the 2021 edition or in case of a workspace the v2 resolver? If not features are unified across all targets.

I have edition = "2021" in all of my crates, if this is what you mean.

And at least with features it seems to work. So is the following correct?

  • using [target.*dependencies] unifies features across all dependencies
  • using [features], it does not unify the features of the dependencies

Which kind of makes sense, but is still surprising.

Oh my - now that I know what to search for, it starts to make sense:

https://doc.rust-lang.org/cargo/reference/features.html#feature-unification

For example, if you want to optionally support no_std environments, do not use a no_std feature. Instead, use a std feature that enables std .

If you are using a virtual workspace (that is a Cargo.toml with [workspace], but not [package]) you need to use resolver = "2" as the resolver is global to the workspace and there is no edition = key in the workspace root in that case to force the v2 resolver.

I think that was it. I'll try it when I get back from holidays. Thanks a lot!