Ignore feature in optional dependency to avoid transitive dep flag conflict

I'm working on an embedded crate and would like to use a feature flag to select between hardware variants 833 and 840.
This flag should affect not just my code but also which crates I depend on.

Here's a snippet from my Cargo.toml:

nrf52840-hal = { version = "0.11", optional = true }
nrf52833-hal = { version = "0.11", optional = true }

nrf52840 = ["nrf52840-hal"]
nrf52833 = ["nrf52833-hal"]
default = ["nrf52840"]

where my crate uses features to select the correct optional dependency.

Unfortunately, it seems that even if a dependency is optional, Cargo still considers its features when compiling transitive dependencies.

In my case both hal crates depend on nrf-hal-common and use feature flags themselves to select hardware.
But Cargo considers both features set, which causes a compilation error in the nrf-hal-common crate.

Basically, nrf52833-hal/Cargo.toml has:

version = "0.11.0"
features = ["52833"]
default-features = false

The nrf52840-hal has:

version = "0.11.0"
features = ["52840"]
default-features = false

and so nrf-hal-common is being compiled with features = ["52833" "52840"] and failing.

The only option that (I think) might work is to have a wrapper crate for each hardware variant that depends on the appropriate hal crate.
But since I need to use hardware features anyway (for my application code), also having to have separate crates would make me sad.

Is there a tidier way to resolve this?

Are you using --no-default-features when you try to build the other feature? Otherwise, you will have both the default and your manual selection added together.

I didn't know about --no-default-features, but it does resolve the issue, thanks!

I had tried

nrf52840-hal = { version = "0.11", optional = true, default-features = false }
nrf52833-hal = { version = "0.11", optional = true, default-features = false }

in my Cargo.toml already, but it has no effect.
I guess default-features applies to just the crate it's specified on, whereas --no-default-features applies transitively to the full tree?

It's still very unsettling to me that cargo adds in features of "optional" dependencies.
I couldn't find any discussion or design docs that suggest this is intentional, do you think that'd be worth filing a bug report about?

No, the command-line option just applies to the root crate, where you have default = ["nrf52840"]. So if you want to select a different feature without also applying your defaults, you need to build with --no-default-features --features nrf52833.

1 Like

Ah! Gotcha, I was entirely confused about the issue.
I was assuming cargo build --release --features=nrf52833 would override the default nrf52840 feature on my crate, when it actually adds on.

This explanation makes much more sense.
Thanks for the help!


This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.