Issue in conditional compilation of extern crates


#1

I’m writing a rust program (App) which uses an extern crate (VM). The VM crate itself uses another extern crate (GC). My development host is Linux, and the target is x86_64-rumprun-netbsd.

I build App using the following command:
‘cargo build --target=x86_64-rumprun-netbsd’

But the target is not automatically passed to extern crates. So, to import VM in my app, I use the following in Cargo.toml:

[dependencies.VM]
path = "../../../VM"
target = "x86_64-rumprun-netbsd"

And then in VM, I use the following to pass the target to GC:

[target.x86_64-rumprun-netbsd.dependencies]
gc = { path = "src/gc", target = "x86_64-rumprun-netbsd"}

However the result is not completely as I expected. For the following code in build.rs of VM:

#[cfg(target_os = "linux")]
#[cfg(target_arch = "x86_64")]
fn main() {
    println!("detected linux");
...

#[cfg(all(target_os = "netbsd", target_vendor = "rumprun"))]
#[cfg(target_arch = "x86_64")]
fn main() {
    use std::path::Path;
    println!("detected rumprun-netbsd");

I receive this output:

detected linux
TARGET = Some("x86_64-rumprun-netbsd")
OPT_LEVEL = Some("0")
TARGET = Some("x86_64-rumprun-netbsd")
HOST = Some("x86_64-unknown-linux-gnu")
TARGET = Some("x86_64-rumprun-netbsd")
TARGET = Some("x86_64-rumprun-netbsd")
HOST = Some("x86_64-unknown-linux-gnu")
CC_x86_64-rumprun-netbsd = None
CC_x86_64_rumprun_netbsd = None
TARGET_CC = None
CC = Some(" gcc")
TARGET = Some("x86_64-rumprun-netbsd")
HOST = Some("x86_64-unknown-linux-gnu")
CFLAGS_x86_64-rumprun-netbsd = None
CFLAGS_x86_64_rumprun_netbsd = None
TARGET_CFLAGS = None
CFLAGS = Some("")
PROFILE = Some("debug")

It seems that the target is correctly passed to build.rs, but the conditional comilation does something esle.

Do you have any opinions?


#2

The build.rs script is compiled for the host, which means any #[cfg] within matches the host itself as the target. Then when the build script runs, it will see the cross-compilation TARGET in its environment.


#3

I changed the source code to:

fn main() {
    println!("detected linux");
    if cfg!(target_os = "linux"){
        println!("Linux");
    }
    else if cfg!(target_os = "netbsd") {
        println!("netbsd");
    }

But it prints:
detected linux
Again Linux
TARGET = Some(“x86_64-rumprun-netbsd”)

So, the TARGET for build.rs is Linux, both at compile-time and runtime.


#4

cfg! works the same way as #[cfg]. You need to use env::var to read the TARGET dynamically.