How can I prevent users from compiling or running my crate on Windows?

Let's suppose I want to write a Rust program which may be a great tool for Unix-like systems but there is a risk that running it on Windows would damage the system or users' data or at least, my program wouldn't work properly.

Which is the simplest and effective way to ensure that nobody will never ever compile or run it on Windows?

Perhaps there should be an option in Cargo.toml to impede installation on given operating systems but I can't find it discussed in The Cargo Book.

1 Like

Put all your code in a module #[cfg(not(windows))] ?

2 Likes

You could also add this:

#[cfg(windows)]
compile_error!("This doesn't work on windows.");

That said, using conditional compilation to make your crate empty is often better because it makes it easier for users of your library that want to support windows via some alternate mechanism.

18 Likes

Thank you @erelde and @alice! After pasting #[cfg(not(windows))] to DuckDuckGo I found this: cfg - Rust By Example

Edit: unfortunately, I can't mark both answers as the solution at once. :confused:

1 Like

Note you can use #![cfg(...)] in your lib.rs (note the exclamation mark) to easily exclude everything.

You may also want to use cfg(unix) instead of cfg(not(windows)) - I'm not sure if there are any supported rust platforms (barring bare metal no_std ones) that aren't either Windows or Unix family, but if there were, you'd probably not work on those too. And it's shorter too!

2 Likes

I tend to go with something that runs and outputs a helpful error message...


#[cfg(target_os = "unix")]
mod os {
    pub fn main() -> Result<(), Box<dyn std::error::Error>> {
        // Put your stuff here.
        Ok(())
    }
}

#[cfg(target_os = "windows")]
mod os {
    pub fn main() -> Result<(), Box<dyn std::error::Error>> {
        Err(Box::new(std::io::Error::new(std::io::ErrorKind::Other,
            "Sorry.  This program isn't for you.  But, if you upgrade to Linux, you will be quite pleased.")))
    }
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    os::main()
}
1 Like

It seems that Redox OS is supported and, unofficially, Haiku: Platform Support - The rustc book

By the way, "Unix" is a quite ambiguous term for me, so what is actually enclosed here? Linux is not Unix and Redox OS is neither but Linux is often classified as "Unix-like".

cfg(unix) is shorthand for cfg(target_family = "unix"), and target family is defined by the target. It includes Linux, BSD, MacOS at least, basically vaguely-POSIX based systems.

If you only work on Linux, for example, you should instead use cfg(target_os = "linux")

4 Likes

Me: cries in WebAssembly...

5 Likes

:smile: I would class wasm as a kind of "no_std bare metal" target, though, if that makes you feel better!

2 Likes