Skip to content

Features of dependencies are enabled if they're enabled in build-dependencies; breaks no_std libs #5730

@phil-opp

Description

@phil-opp

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:

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

Metadata

Metadata

Assignees

Labels

A-featuresArea: features — conditional compilation

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions