Having spent several tens of minutes goggling the problem, I am unfortunately not surprised by your assessment. (I had posted in the hope that someone would surprise me, but confirmation is helpful as well.)
I can set up the multiple compilation (not the first time I've decided to make 'make' a driver of Cargo), was hoping there'd be a solution that didn't look like pulling a car with a horse!
Thanks for this. I was hoping not to have a file-per-case; there are a couple of variables, so I'd end up with several files. I should probably have mentioned in the first place: it's about comparing performance options, so 3 algo's for each of 3 aspects makes for a lot of source files. They could be autogenerated I guess, so that might reduce the manual code.
You could change behavior at runtime by examining args_os().next() (argument 0, usually the path to the executable), and then symlink or hard link the "alternative binaries" to the one true executable.[1]
Or make it command argument or environment based and write a tiny shell script wrapper.
With that many options, I'd do the same thing but use command-line arguments or environment variables to pick which one to use. But if you're just comparing performance and don't actually need them to coexist, you can conditionally compile them with the env! macro, and in a shell script use something like:
Thanks for looking and suggesting! This is part of a 'learn me a Rust' project --- knowing that something isn't possible is useful!
If it ends up as shellscripts, I'll probably just use make/bash/perl/rust-include to bruteforce generate the sources, then 'rustc yadayada" the binaries.
I am interested in a 'pure Rust ecosystem' solution; I've had a response that seems to confirm my suspicion that there is none.
So then, 'make targets' would get me my 27 (or whatever) executables. One source, one makefile. Ok, yes, 3 * 3 * 3 targets, and a rollup target to bind them all.
Key thing is, I'm looking for a Cargo-native solution for this. I'm getting from you that this isn't an option, that's fine, that's something I want to learn!
In general, if you compare Cargo directly to make, you may be disappointed. Cargo largely does a very specific job only: for a given build configuration, it produces Rust binaries or libraries. Build scripts can customize what happens on input, but there are no post-build steps. Therefore, there are a lot of jobs that cannot be done with only Cargo.
So for your case where you want multiple builds with different features, you may find the best option is in fact to use make, or whatever tool you like, to sequence that. If you'd like to do it with “pure Rust”, check out the xtask pattern: you can have Cargo build and run your own custom tooling with a single command.
Also, for the step of actually giving the binaries distinct names rather than overwriting each other in target/, you can use cargo install to ask Cargo to copy the built binary to a particular directory, which might simplify the work — or might complicate it due to cargo install being a bit inflexible about the output path.
I use cargo test with different feature flags, it seems it does distinct builds (generating multiple executable files) so after everything is built the tests can be re-run testing various features without further compilation/linking.
My script:
cargo test %1 --quiet --release -- --nocapture --test-threads 1
cargo test %1 --quiet --release --features unsafe-optim -- --nocapture --test-threads 1
Thanks to all who replied. The initial question ("can I create multiple binary versions using different '#[cfg(...)] options purely in Cargo") has been answered (in the negative).
I've gone with a makefile based solution that runs 'cargo rustc ..." (per kpreid):
I confess that I'm disappointed with this, in that
a) it seems as if Cargo should/could handle this, but does not, and
b) the doc isn't at all clear about that (OTOH, ok, it doesn't support it, why should it be?).
Agreed, too, that this is something I could try to contribute further on. I'm trying to figure out what the initial "gripping point" would be: I'd need to understand a lot more about Cargo/ecosystem in order to make a useful change.