I'm again at a framework where files may be contributed to the app's installation directory.
The debug_assertions
constant may be used to detect cargo build --release
, but I wanted some consensus on what is best to do here.
In my framework the user could do this at the Cargo manifest:
[package.metadata.fl]
files = [
{ from = "assets/**/*.webp", to = "img" }
]
This would make it so the source path ~/assets/flowers/red.webp
may be read during runtime using the app://img/flowers/red.webp
URL (and the actual file will be exported at that path as well).
When debugging (e.g. cargo run
ning an app), I want to avoid exporting these files, therefore bootstrapping the application with the (from, to) entries so I do some magic when resolving app:
URLs for the user. (In the HTML5 target, app:
is resolved via HTTP requests, while in native targets I'd use std::fs
and the executable path).
What leaves me confused is whether I detect cargo run
solely through debug_assertions
or if there's something more reliable to use (because, then, even a simple cargo build
can't be used correctly as I'd not export files when debugging with the debug_assertions
approach).
I suppose using an explicit feature is the only way to detect cargo run
.
[features]
run_flag = []
Then:
#[cfg(feature = "run_flag")]
I forgot about that, but I'd really want something more built-in.
Regarding the title question in general: The user expectation should always be that cargo run
will do precisely the same thing as cargo build
, followed by executing the compiled binary. In fact, running cargo run
after cargo build
is usually expected not to re-do any building steps, and running cargo build
after cargo run
is usually a no-op; that is, if no source files changed in the meantime.
The choice of profiles is orthogonal, in particular, either command has a default (debug) variant, and a --release
variant.
As you noted, crate feature flags can be one way to provide customization of the build process, however crate features do interact with the dependency solver in ways that could influence their usefulness for fully “custom” ways of influencing the built process, in case the crate in question is just a "library crate". In this case, possibly environment variables may be more fitting; those can be read & tracked in build scripts as described here.
Your question sounds more like this is a "framework" in the sense of involving a particular format of overall project structure, so we can consider more flexible approaches when controlling the crate that starts the compilation.
If I understand the question correctly, and the desired behavior of what you call cargo run
is something that will only be sensible if run in (otherwise surprisingly) specific ways directly from the source directory… one possibility could be to let the user not use cargo run
to begin with. The local cargo
config files can define (conveniently) custom subcommands (via aliases)… while you cannot change the meaning of cargo run
itself, you could follow e.g. more or less precisely the "cargo xtask
" design pattern, and have it called anything from cargo xtask run
to cargo debugrun
or whichever naming scheme you like. That alias can then call cargo run
for you while setting a fitting environment variable (or compiler flag?), that controls the build process as desired, while ensuring everything runs from the right place.
1 Like
That idea of using environment variables isn't bad (seems more convenient than a feature), butenv!
requires a known environment variable at compile-time.
My issue with env!
isn't an issue at all, because, as you've shown, I can have custom commands for my framework (I'm thinking of a CLI though) so they are always passed, but....
What about when running cargo publish
? How do I prevent that env!
lookup error during crate verification?