Get target_os as &str or String?

I found I can use if cfg!(target_os = "android") { ... } and similar lines to get boolean information about the compile target.

I would like to instead get it directly as Strings, without having to build an exhaustive list of possible values.

I found https://crates.io/crates/cargo-rustc-cfg which looks like it would provide those Strings, but it doesn't seem to play well together with a project setup as recommended by flutter_rust_bridge | Dart Package (which I'm using because I want to do my UI with Flutter):

error: could not find Cargo.toml in /home/thomas/Development/git/flutter_rust_bridge_template or any parent directory
The terminal process "cargo 'test', '--doc', '--', 'Cfg::rustc_target', '--nocapture'" failed to launch (exit code: 101).

And even if it worked - Since it seems to run a separate cargo process to get the info it probably wouldn't be able to pick up on the cross-compiling settings used by the flutter_rust_bridge - Which would make the whole thing kind of pointless.

Is there any more elegant way than an exhaustive list of all possible targets in which I define a String manually, like this:

let mut val = String::new();
if cfg!(windows) {
    val.push_str("Windows");
} else if cfg!(target_os = "android") {
    val.push_str("Android");
} else if cfg!(target_os = "ios") {
    val.push_str("iOS");
} else if cfg!(target_arch = "aarch64-apple-darwin") {
    val.push_str("MacOS Darwin");
} else if cfg!(target_os = "macos") {
    val.push_str("MacOS Intel");
} else if cfg!(target_family = "wasm") {
    val.push_str("WebAsembly");
} else if cfg!(target_os = "linux") {
    val.push_str("Linux")
} else if cfg!(unix) {
    val.push_str("other Unix");
} else {
    val.push_str("unknown OS");
}

Is std::env::consts::OS sufficient?

7 Likes

you could use a build script to generate a constant with the target os


build.rs

use std::{env, fs::File, io::Write, path::Path};

fn main() {
    let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap();
    let out_dir = env::var_os("OUT_DIR").unwrap();
    let mut out_file = File::create(Path::new(&out_dir).join("targt_os.rs")).unwrap();
    writeln!(out_file, r#"pub const TARGET_OS: &str = "{}";"#, target_os).unwrap();
}

main.rs

include!(concat!(env!("OUT_DIR"), "/target_os.rs"));

fn main() {
    println!("{}", TARGET_OS);
}

Nice! That's exactly what I was looking for! Thank you!

@juggle-tux also thanks to you, but since @quinedot 's solution is much simpler I'll stick with that for now, thanks to both of you! :smiley:

UPDATE: I now ended with this snippet for collecting an info string about the rust runtime target:

format!("OS: {}\nFamily: {}\nCPU: {}\nDebug: {}"
    ,std::env::consts::OS
    ,std::env::consts::FAMILY
    ,std::env::consts::ARCH
    ,cfg!(debug_assertions).to_string())

Not surprising if std::env::consts has every thing you need the advantage of the build script is that is has access to all cfg variables.

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.