Unexpected interaction between dependencies and build-dependencies

I’m sorry for the generic title, but I really don’t know how to phrase it better since I don’t actually understand what’s going on. I have condensed the problem down to a pretty minimal example project consisting of three files:

  • Cargo.toml:

    [package]
    name = "foo"
    version = "0.1.0"
    
    [dependencies]
    cstr_core = "0.1"
    
    [build-dependencies]
    bindgen = "0.42"
    
  • src/lib.rs:

    #![no_std]
    
  • test-target.json:

    {
        "llvm-target": "x86_64-unknown-linux-gnu",
        "data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128",
        "arch": "x86_64",
        "target-endian": "little",
        "target-pointer-width": "64",
        "target-c-int-width": "32",
        "os": "linux",
        "linker-flavor": "gcc"
    }
    

So this is a no_std crate. I use a custom target to ensure that there is no std crate in this example.
Now when I try to build the crate with cargo-xbuild I get:

$ cargo +nightly --version
cargo 1.31.0-nightly (2d0863f65 2018-10-20)
$ rustc +nightly --version
rustc 1.31.0-nightly (4bd4e4130 2018-10-25)

$ cargo +nightly xbuild --target test-target.json
   Compiling core v0.0.0 (/home/jan/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src/libcore)                                                                                                                      
    Finished release [optimized] target(s) in 28.07s                                                                                                                                                                                           
   Compiling compiler_builtins v0.1.0 (/home/jan/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src/libcompiler_builtins)                                                                                            
    Finished release [optimized] target(s) in 1.90s                                                                                                                                                                                            
   Compiling alloc v0.0.0 (/tmp/xargo.FyWlRRJHNQDm)                                                                                                                                                                                            
    Finished release [optimized] target(s) in 4.08s                                                                                                                                                                                            
    Updating crates.io index
   Compiling version_check v0.1.5                                                                                                                                                                                                              
   Compiling libc v0.2.43                                                                                                                                                                                                                      
   Compiling cfg-if v0.1.6                                                                                                                                                                                                                     
   Compiling cty v0.1.5                                                                                                                                                                                                                        
error[E0463]: can't find crate for `std`                                                                                                                                                                                                       
  |                                                                                                                                                                                                                                            
  = note: the `test-target-12673086420766320107` 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 `libc`.                                                                                                                                                                                                               
warning: build failed, waiting for other jobs to finish...
error: build failed     

The error is pretty clear I think. Cargo tries to install libc, libc depends on std which isn’t available, the build fails.

However, I don’t understand why it even tries to install libc. The only dependency of my crate is cstr_core which in turn depends on memchr, but with the use_std feature disabled, so memchr shouldn’t depend on libc. For some reason Cargo tries to install it anyway and I’m pretty sure this is due to the bindgen build-dependency: When I remove the bindgen dependency, everything compiles just fine without libc. So there must be some weird interaction here.

Some further observations:

  • Removing the cstr_core dependency and building only with the bindgen build-dependency also works just fine. In fact, Cargo installs no packages for bindgen, probably because it isn’t used anywhere.
  • This seems to be unrelated to cargo-xbuild. cargo build throws more errors because it also complains about the missing core crate, but the error about the missing std crate is still there. So this seems to be an issue with Cargo actually.

It would be really helpful if someone more knowledgeable than me could chime in an let me know if I’m missing something or if this actually is a bug in Cargo.

It is most likely the fact that crate features are unified for your whole build tree.

Huh, that was fast! And yes that looks exactly like the issue I’m experiencing. Thanks so much!