Pre/post build script via cargo

So a bit of googling basic questions has lead me to believe this is not possible with cargo.

I need to - as part of the cargo build process execute a command line before a build and/or after a build.

I really do not want to wrap Cargo with a shell script because IDEs that are "cargo friendly" - they won't execute my extra commands.

Examples include:

A) I am cross compiling to a arm64 linux target, I have to push the image to my test board via SSH and execute a command via SSH.

B) I have to create a "package" - ie: The executable needs to be digitally signed, and extra data files, etc - need to be package up.

C) My build process transforms large data files into binary data used by the application. If the source of those data files change - my script is smart enough to rebuild or skip generating the binary data files. But - I need those files updated as part of the build

D) In the embedded world part of the build process is creating a BINARY with extra features required by the boot loader on my board - I do this today with python

I coud list many other things - but doing this inside of 'build.rs' - seems very wrong headed.

To me, it would be as simple as:

    [package] 
    pre_build= "some command line in a quoted string" 
    build = "build.rs"
    post_build="another command line in a quoted string"

The rules would be very simple:

  1. The string must be an executable command as if the user typed it or the string was passed to the standard C library function: "system()"
  2. The command line must exit 0 otherwise processing stops.

All CARGO build environment variables should available to the command
I am interested the "TARGET" and "HOST" variables so myself script can do the right thing.

Maybe this already exists - but RUST lacks the ability to google search for solutions that exist I say that because I can only find things where people learned: "Nope not supported"

Examples of others wanting this:

https://internals.rust-lang.org/t/a-list-of-commands-to-pre-configure-the-project/17492/11

https://stackoverflow.com/questions/66284221/can-i-perform-a-task-after-compilation-is-complete
       https://www.reddit.com/r/rust/comments/zwttsl/run_python_scripts_before_compilation_using_cargo/

You can do this in a build script (build.rs). There is nothing that says a build script has to only “compile code” and not “preprocess data”.

You can set a custom runner in the Cargo configuration which will be executed after build for any cargo test or cargo run command. That custom runner can be a script which performs both of these steps; this way, an IDE’s test or run commands will work for you.

For purposes other than testing (i.e. distribution) it should be not much trouble to have a script that you run yourself.

2 Likes

how do i control when the build script runs?
i need it to do something before and after?

there is a single main function? how does cargo tell me what stage it is at in the build process?

A biild script always runs before compiling the associated crate. @kpreid suggested putting the things that need to run after the build in a custom runner instead.

Yes, sorry, when I said "do this" I meant specifically "do the transformation of data files" and none of the other things.

Yea, so IMHO - it's really stupid that the only thing the BUILD.RS script will do for me is execute a single shell script and nothing more. Almost pure and total boiler plate code to do this too.

Why? Because the underlying c/data library is used for other things, and it works today as is, so what benefit does rewriting that shell script in RUST going to give me? The answer I have is: ZERO nada ZILCH, other than waste time rewriting what I already have that works and then debugging that re-written code.

It's not like rust will give me more security here it is my code, it is me running this code, it is not code that runs for weeks as a service - it is not exposed to the World Wide Web, it is code that runs for about 0.010 seconds. Yea zero benefit nothing more, other then I have to rewrite steps that work.

IMHO - the rust fanatics are not making things easy for others to make use of rust. In fact it seems they are going out of their way to say: "Use RUST and do it the rust wayside or go away" AND IMHO - this is why rust has not taken off as fast as it could or should have. It's called "friction in the development process".

And what runner is executed every time I build as a post build runnerhe

BTW the seems wrong anyway - I am not running anything I am doing more build steps.

I would really like the IDE - to be able to do the complete job - for both the test cases and the normal build steps.

No reasons to be so rude, IMHO.

In virtually every IDE it is possible to define some sort of tasks. So if build.rs doesn't fulfill your requirements, what's wrong with using those facilities?

mroth>> In virtually every IDE it is possible to define some sort of tasks. So if build.rs doesn't fulfill your requirements, what's wrong with using those facilities?

First: And all of those IDE/BUILD systems have a "pre/post" script feature as part of their build system.

Second: Cargo is a build system, but without a GUI - instead it is more like the Eclipse Headless build with the managed make approach which has a pre/post build feature.

So when I'm looking at a build system, I like others expect it to have certain features. This is one of those features one would expect of a build system.

It also means that I cannot create a crate or package that just works. Instead each user of the crate needs to do "IDE customizations" as you describe.

As an example - (not my example, but another persons example) I might have a sound/animation crate that plays a sound and displays something on the screen. That type of thing would often have an accompanying "assets" file that contains these sound and graphic items.

How would you propose I create such a crate? so that if somebody uses my crate - these additional steps get run by cargo when they 'cargo add MYCRATE'?

Does every user of my crate need to manually modify their IDE to make it work correctly? Why should they? Why shouldn't my crate just work?

Or if there are N developers, it has to be done N times correctly by all N developers? Possibly M different ways because there are M different IDEs .. yea simple to make that happen.

My preference is it is done once and only once. This suggestion does not help with that.

Cargo is not a general purpose fully flexible build system. It is designed to only work with Rust and doesn't do anything other than building rust executables and libraries. If you need any extra steps like signing, changing the binary format from ELF to something else or packaging extra assets, you will either have to make a build system that wraps around cargo. For example using the cargo xtask pattern, make, cargo-make Or in the specific case of needing to do this steps only after the executable is built right before running it though a custom runner that does those steps for you before running.

Even if cargo were to get support for running arbitrary commands after a build, I'm pretty sure it would be restricted to only allow the top level crate to specify those as many such commands crates may want to do would compose badly or not at all with each other.

1 Like

I think it's helpful to properly express your expectations, and to understand what Cargo crates are for. Crates are primarily for libraries (which typically don't have assets, and if they do then they need to coordinate that with the caller). They are also for self-contained executables, such as the ones you might publish to crates.io.

If you're expecting Cargo to be an all-in-one build and deploy system, sorry. It does not work that way. Cargo supports build scripts (written in Rust to avoid the controversy, conflict, and dependency hell from integrating a different language). Those are for facilitating tasks such as linking C libraries into an otherwise self-contained library, or compressing and bundling assets into your binary. They are not for deploying your project. They can help with examples C and D. Example A, as previously stated, is best solved with a custom runner. Example B, however, is outside of the scope of Cargo, and rightfully so.

If Cargo doesn't suit your needs, I'm sorry. If you have specific, plausible, and defensible proposals to improve it, please share! We are always looking to improve the ecosystem (though remember that the manpower to make that happen isn't always there). But otherwise, please consider an alternative system designed for packaging and deploying software, of which there are many (I know cargo-xtask is popular, and may help your use case).

3 Likes