In Rust it is the best practice to have features to be strictly additive. extension-module, instead, subtracts from the crate by not linking python. This can result in weird and difficult to resolve failure modes in e.g. workspaces.
For instance consider…
💥 Reproducing
[workspace]
members = [
"extension",
"some_binary",
]
where both extension and some_binary use as a dependency pyo3, but extension enables the extension-module feature, while some_binary explicitly disables the features.
When cargo build is run from the workspace root, then both of the binaries will get a pyo3 with extension-module feature enabled and some_binary will fail to link.
This behaviour is entirely valid from cargo’s standpoint – it dictates that features should be additive and thus there must not be a way to write any single crate in a way that would fail when additional features are enabled in its dependencies.
To be honest, I don’t see a good way to fix it, other than spiting pyo3 into two separate crates.
In Rust it is the best practice to have features to be strictly additive.
extension-module, instead, subtracts from the crate by not linking python. This can result in weird and difficult to resolve failure modes in e.g. workspaces.For instance consider…
💥 Reproducing
where both
extensionandsome_binaryuse as a dependencypyo3, butextensionenables theextension-modulefeature, whilesome_binaryexplicitly disables the features.When
cargo buildis run from the workspace root, then both of the binaries will get apyo3withextension-modulefeature enabled andsome_binarywill fail to link.This behaviour is entirely valid from
cargo’s standpoint – it dictates that features should be additive and thus there must not be a way to write any single crate in a way that would fail when additional features are enabled in its dependencies.To be honest, I don’t see a good way to fix it, other than spiting
pyo3into two separate crates.