Features enabled through build scripts should have an effect on dependencies
Closed this issue · 7 comments
I've been using build scripts to enable features based on rust versions automatically, such that if you build with a version that added a new feature to the language or libstd, users of the crate can automatically get those without having to manually enable features.
But sometimes, the feature needs another crate as dependency. In that case, what you really want is an optional dependency, and for the feature to enable it. But the only way to enable a feature from a build script only enables the feature from rustc perspective, not cargo's.
So, say you have a Cargo.toml
with something like:
[dependencies]
foo = { version = "0.1", optional = true }
or
[features]
foo = ["bar"]
[dependencies]
bar = { version = "0.1", optional = true }
A build script that does:
fn main() {
println!("cargo:rustc-cfg=feature=\"foo\"");
}
won't make the optional dependency built in either case, which makes sense because it's all about rustc, but should, IMHO, be supported.
This is currently expected behavior in that Cargo doesn't allow activating features at build-script-time but rather they must be activated manually by the user (as they affect crate graph resolution). We may wish to provide a warning, here, however, or something like tha.t
I just learned from the Cargo IRC channel that this is the expected behavior. It'd definitely be nice to at least mention it in the docs.
However, I'd agree with @glandium that it would be ideal if there was a build-script-time setting that could activate conditional dependencies. It doesn't have to be based on features, it could be based on other configs, such as "cargo:rustc-cfg=mycfg"
. Maybe something like "cargo:cargo-cfg=XYZ"
that affects cargo dependencies too.
Oh, I just unconfused myself, they do have influence over the current crate being built, not the dependencies, disregard me.
With Cargos current architecture, this is technically not possible. The build script is run (once) after the dependencies are built, so without time travel it can not add dependencies.
Leaving open as better docs and better error messages is reasonable.
Could you theoretically make a prebuild script, or a setting that enables it depending on what a function returns?
something like
[features.enable]
foo = "src/build::enable_foo"
bar = "src/build::enable_bar"
fn enable_foo() -> bool{
true
}
fn enable_bar() -> bool{
false
}
would this be possible?