-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Description
If a crate is used both as a normal dependency and a build-dependency, features enabled for the build-dependency are also enabled for the normal dependency. This leads to build failures in the no_std
world, because an use_std
feature that is turned on for the build-dependency is also turned on for the normal dependency.
Minimal example
cargo new bar --lib
cd bar
cargo new foo --lib
In bar/foo/Cargo.toml
:
[features]
default = ["use_std"]
use_std = []
In bar/foo/src/lib.rs
:
#[cfg_attr(not(feature = "use_std"), no_std)]
pub fn return_42() -> u32 { 42 }
#[cfg(feature = "use_std")]
pub fn print_42() {
println!("{}", return_42());
}
In bar/Cargo.toml
:
[dependencies.foo]
path = "foo"
default-features = false
[build-dependencies.foo]
path = "foo"
In bar/src/lib.rs
:
#![no_std]
extern crate foo;
pub fn return_42() -> u32 {
foo::return_42()
}
Compiling with cargo build --verbose
:
Compiling foo v0.1.0 (file:///…/bar/foo)
Running `rustc --crate-name foo foo/src/lib.rs --crate-type lib --emit=dep-info,link
-C debuginfo=2
--cfg 'feature="default"' --cfg 'feature="use_std"'
-C metadata=5cd2c90dafa7c435 -C extra-filename=-5cd2c90dafa7c435
--out-dir /…/bar/target/debug/deps
-C incremental=/…/bar/target/debug/incremental
-L dependency=/…/bar/target/debug/deps`
Compiling bar v0.1.0 (file:///…/bar)
Running `rustc --crate-name bar src/lib.rs --crate-type lib --emit=dep-info,link
-C debuginfo=2 -C metadata=0a475a34b1347c78
-C extra-filename=-0a475a34b1347c78 --out-dir /…/bar/target/debug/deps
-C incremental=/…/bar/target/debug/incremental
-L dependency=/…/bar/target/debug/deps
--extern foo=/…/bar/target/debug/deps/libfoo-5cd2c90dafa7c435.rlib`
We see that --cfg 'feature="default"' --cfg 'feature="use_std"'
is passed, i.e. the use_std
feature is activated even though default-features = false
is used. When we comment out the [build-dependencies.foo]
section, foo
is built without the use_std
feature.
Breaking no_std libs
The problem is that compilation for custom targets using xargo
/cargo-xbuild
fails when the std
feature is activated for the custom target:
cargo xbuild --target some-custom-target.json --verbose
+ "rustc" "--print" "sysroot"
+ "rustc" "--print" "target-list"
+ RUSTFLAGS="--sysroot /…/bar/target/sysroot"
+ "cargo" "build" "--target" "some-custom-target" "--verbose"
Compiling foo v0.1.0 (file:///…/bar/foo)
Running `rustc --crate-name foo foo/src/lib.rs --crate-type lib --emit=dep-info,link
-C debuginfo=2
--cfg 'feature="default"' --cfg 'feature="use_std"'
-C metadata=beb376bcf23896f4
-C extra-filename=-beb376bcf23896f4
--out-dir /…/bar/target/some-custom-target/debug/deps
--target /…/bar/some-custom-target.json
-C incremental=/…/bar/target/some-custom-target/debug/incremental
-L dependency=/…/bar/target/some-custom-target/debug/deps
-L dependency=/…/bar/target/debug/deps
--sysroot /…/bar/target/sysroot`
error[E0463]: can't find crate for `std` ] 0/2: foo
|
= note: the `some-custom-target-6722811146760112169` target may not be installed
error: aborting due to previous error
For more information about this error, try `rustc --explain E0463`.
error: Could not compile `foo`.
We see that the use_std
feature is turned on even though we are compiling for the custom target. So this is definitely not the build dependency getting built because build scripts are compiled for the host target.
Workarounds
There are two ways to work around this, but both have sigificant downsides:
- Use the host dependency in
no_std
mode and don't use any std-dependent features and build scripts. This makes writing build scripts harder. - Use a forked and renamed dependency so that two different libraries are used. This comes with a high maintainance burden and is thus not practical in most cases.
Both workarounds don't really work for build dependencies of dependencies.
Versions
cargo 1.29.0-nightly (af9e40c26 2018-07-05)
release: 1.29.0
commit-hash: af9e40c26b4ea2ebd6f31ee86ee61d5ac1c74eb0
commit-date: 2018-07-05
rustc 1.29.0-nightly (254f8796b 2018-07-13)
binary: rustc
commit-hash: 254f8796b729810846e2b97620032ecaf103db33
commit-date: 2018-07-13
host: x86_64-unknown-linux-gnu
release: 1.29.0-nightly
LLVM version: 7.0