Indeed, there is no clean / direct way to achieve this. There is a hacky-ish way though: do not directly call cargo build, but call something that will perform some platform detection setting to only then tweak profile.release.
[package]
name = "smart"
version = "0.0.0"
edition = "2018"
[[bin]]
name = "smart"
path = "main.rs"
[workspace]
smart/main.rs
use ::std::{env, ops::Not, process};
fn main ()
{
let mut cmd = process::Command::new(::std::env::var("CARGO").unwrap());
cmd.env("CARGO_SMART", "1"); // Optional, if used with the `build.rs`
let ref args = env::args().skip(1).collect::<Vec<_>>();
// dbg!(args); cmd.arg("-vv"); /* Uncomment when debugging this hack */
cmd.args(args);
// if args...contains... "--target" "...windows..." ...
if cfg!(windows) {
// See https://doc.rust-lang.org/cargo/reference/environment-variables.html#configuration-environment-variables
cmd.env("CARGO_PROFILE_RELEASE_OPT_LEVEL", "0");
}
if cmd.status().ok().map_or(false, |it| it.success()).not() {
process::exit(-1);
}
}
build.rs (Optional, to make sure we don't forget to call cargo using smart)
use ::std::{env, ops::Not};
fn main ()
{
if env::var("CARGO_SMART").ok().map_or(false, |s| s == "1").not() {
panic!("Do not run `cargo ...`, run `cargo smart ...` instead")
}
}
With these changes, cargo smart <usual command>ought to work, such as cargo smart build --release
Feel free to rename smart to something else, and of course to tweak smart/main.rs to correctly handle things like the windows case if cross-compiling (since cfg!(windows) on a build script will only be enabled when running cargofrom a Windows environment, not when compiling to one).
Sadly such config vars do not seem to have an associated env var, so in order for it to work, a an ephemeral .cargo/config override would need to be required, which surpasses my personal threshold for hacky things