'How can we detect the host OS type (not the target OS) in Rust?

There are many ways to detect the target OS, e.g. #[cfg(windows)], #[cfg(unix)], std::env::consts::OS. For cross-compilation, how can we detect the OS that our Rust program gets compiled on?



Solution 1:[1]

Since build.rs is run on the workstation (not the target), I guess it can detect some workstation related properties then generate features (cfg) that can be tested in the target related code.

For example, here is a build.rs script that detects a specific file on your workstation.

fn main() {
    // detected on the workstation (not the target)
    if let Ok(_attr) = std::fs::metadata("dummy_file.txt") {
        println!("cargo:rustc-cfg=detected");
    }
    if cfg!(windows) {
        println!("cargo:rustc-cfg=from_windows");
    }
    if cfg!(unix) {
        println!("cargo:rustc-cfg=from_unix");
    }
}

Then, src/main.rs can test the detected feature.

#[cfg(detected)]
fn hello() {
    if cfg!(from_windows) {
        println!("hello from windows with detected file");
    }
    if cfg!(from_unix) {
        println!("hello from unix with detected file");
    }
}

#[cfg(not(detected))]
fn hello() {
    if cfg!(from_windows) {
        println!("hello from windows");
    }
    if cfg!(from_unix) {
        println!("hello from unix");
    }
}

fn main() {
    // run on the target (not the workstation)
    hello();
}

Depending on whether dummy_file.txt exists or not on the workstation when building the project, the resulting binary for the target will use one version or the other of hello(). Each of these two functions can adapt their behaviour depending on the OS the workstation.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1