Target.'cfg(target_os="android") or IOS doesn't work

I had two projects for IOS and Android, that shared same logic, I decided yo merge them with cfg
macro, but it doesn't seem to be working.

In toll: (doesn't work)

[target.'cfg(target_os="android")'.dependencies]
[target.'cfg(target_os="ios")'.build-dependencies]
[target.'cfg(target_os="android")'.build-dependencies]

in build.rs: (doesn't work)

//IOS
#[cfg(target_os = "ios")]
use cbindgen::Language::C;
//Android
#[cfg(target_os = "android")]
use rust_swig::{JavaConfig, LanguageConfig};

And methods like this:

//We have custom setup for IOS and Android, otherwise do nothing.
#[cfg(any(not(target_os = "android"), not(target_os = "ios")))] (doesn't work)
fn setup() {
    println!("Build: default setup");
}

#[cfg(target_os = "ios")]
fn setup() {
    println!("Build: IOS setup");
}

#[cfg(target_os = "android")]
fn setup() {
    println!("Build: Android setup");
}

I build Android with:

CC=aarch64-linux-android21-clang cargo build --target aarch64-linux-android --release
CC=armv7a-linux-androideabi21-clang cargo build --target armv7-linux-androideabi --release
CC=i686-linux-android21-clang cargo build --target i686-linux-android --release

IOS:

cargo lipo --release

Reference:
https://doc.rust-lang.org/reference/conditional-compilation.html

I think you need the default to be all(not(x), not(y)) or not(any(x, y)).

I tried to add print in build.rs ;

fn main() {
    println!("cargo:warning=Build started");
    let target_os = env::var("CARGO_CFG_TARGET_OS");
    match target_os.as_ref().map(|x| &**x) {
        Ok(tos) => println!("cargo:warning=target os {:?}", tos),
        Err(err)=> println!("cargo:warning=os not defined {:?}!", err)
    }
    setup();
}

I changed default setup to:

//#[cfg(all(not(target_os = "android"), not(target_os = "ios")))]
#[cfg(target_os = "macos")]
fn setup() {
    println!("cargo:warning=Build: default setup");
}

And still, when I execute, I see next:

warning: Build started
warning: target os "android"!
warning: Build: default setup

This method is not executed:

#[cfg(target_os = "android")]
fn setup() {
    println!("cargo:warning=Build: Android setup");
}

I tired to move one dependency in cargo.toml to "macos" target and now build for android is failing.

[target.'cfg(target_os = "macos")'.dependencies]
serde = { version = "*", features = ["derive"] } 

Seems cfg(target_os = "android") is not recognized at all?

As well when I added configuration for different lib types:

[target.'cfg(target_os = "android")'.lib]
name = "swapi_core"
crate-type = ["dylib"]

[target.'cfg(target_os = "ios")'.lib]
name = "swapi_core"
crate-type = ["staticlib", "cdylib"]

I got warning in logs:

warning: unused manifest key: target.cfg(target_os = "android").lib
warning: unused manifest key: target.cfg(target_os = "ios").lib

Your build.rs is built and executed for the host, thus target_os in there is your host system, not the target you're building your crate for.

target.lib can't be configured per target, as the warnings indicate.

So target is only host not a target of the build? I totally misunderstood it...
If there a way to implement what I want, for a target of build?

In toml. it also target host or build target?

It's the target the program is being build for. As the build.rs is a program that needs to run on your current running machine during the build process of the whole thing it is your host's system, yes.

You've already shown yourself the answer: branch on the environment variable CARGO_CFG_TARGET_OS if you need to know it in your build script.

For normal dependencies it picks the target of your final program.

1 Like

Got it. But I have some build dependencies that I need only for a specific platform, example:

About toml I think there is a problem with android and ios keyword then.
Because if I put macos and run on my laptop - I see my dependencies are compiled, when I change it to android and build for it - it is not compiled

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.