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
.
Let's say cargo smart
.
cargo smart
First, make sure to add the following files:
.
├── .cargo // <--
│ └── config // <--
├── Cargo.toml
├── build.rs // <-- (Optional)
├── smart // <--
│ ├── Cargo.toml // <--
│ └── main.rs // <--
└── src
└── lib.rs
...
-
.cargo/config
[alias] smart = ["r", "-q", "--manifest-path", "smart/Cargo.toml", "--"]
-
smart/Cargo.toml
[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 callcargo
usingsmart
)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 cargo
from a Windows environment, not when compiling to one).