Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Post-build script execution #545

Open
vosen opened this Issue Sep 10, 2014 · 42 comments

Comments

Projects
None yet
@vosen
Copy link

vosen commented Sep 10, 2014

Currently, cargo execute scrips before the build starts with the build field. I propose renaming build to pre_build and adding post_build (which would run after every successful build). It's useful for general postprocessing: running executable packers, zipping files, copying stuff, logging, etc.

@alexcrichton

This comment has been minimized.

Copy link
Member

alexcrichton commented Sep 10, 2014

This will likely happen as part of an implementation of cargo install, but cargo build is not meant to be a general purpose build system for these sorts of applications.

@DiamondLovesYou

This comment has been minimized.

Copy link
Contributor

DiamondLovesYou commented Jan 2, 2015

What about integration tests? For example, PNaCl modules can be run on the host machine, but they have to be translated into a NaCl beforehand and then run with sel_ldr (from the NaCl SDK).

@jan-hudec

This comment has been minimized.

Copy link

jan-hudec commented Mar 12, 2015

@DiamondLovesYou, would #1411 work for the tests?

@caitp

This comment has been minimized.

Copy link

caitp commented Jul 5, 2015

A "post_build" script would be useful for things like creating a MacOS bundle, rather than having a separate script to do that work separately. "install" could do this too, but maybe not as useful for testing there?

@vvanders

This comment has been minimized.

Copy link

vvanders commented Sep 26, 2015

+1 For rust projects that linked dynamically from other languages being able to deploy(move) the .so after a successful build would be nice.

@tbelaire

This comment has been minimized.

Copy link

tbelaire commented Nov 22, 2015

This would be useful for running

arm-none-eabi-objcopy -O binary ${TARGET}.elf ${TARGET}.gba
gbafix ${TARGET}.gba

To fix up the headers and such after building my project.

@Boscop

This comment has been minimized.

Copy link

Boscop commented Jun 16, 2016

+1 for post build scripts

moises-silva added a commit to friends-of-freeswitch/mod_prometheus that referenced this issue Aug 6, 2016

Adjust symbol name for first load into FreeSWITCH
I'd prefer if cargo would generate mod_prometheus.so
instead of libmod_prometheus.so but I did not find
a way to tell cargo or rustc to not prefix the binary
with 'lib'.

A post-build step on cargo would be also an option if
this were implemented: rust-lang/cargo#545
@mkroman

This comment has been minimized.

Copy link
Contributor

mkroman commented Sep 4, 2016

This will likely happen as part of an implementation of cargo install, but cargo build is not meant to be a general purpose build system for these sorts of applications.

It doesn't have to mean that cargo will be a general purpose build system.
An example where a post-build action could be used for cargo is triggering a build of a crate in a sub-directory once the main crate has been built.

Crate B depends on crate A, and is in a sub-directory of crate A, and it automatically gets built every time crate A has been built.

@Boscop

This comment has been minimized.

Copy link

Boscop commented Sep 4, 2016

But what if crate B also depends on sub crates C and D? Shouldn't the build of dependencies be caused by building the crate that depends on them in a "by need" manner?
I would say the post build command should not involve building any related crates or calling cargo (can be easily enforced), only for post processing of the lib/exe that was just built. To keep it compartmentalized / clean.

@JinShil

This comment has been minimized.

Copy link

JinShil commented Oct 29, 2016

This would be useful for embedded systems programming. I often run arm-none-eabi-size to verify my binary size with each build, and occasionally other utilities from binutils to verify symbol tables, etc...

@steveklabnik

This comment has been minimized.

Copy link
Member

steveklabnik commented Oct 29, 2016

Don't forget that there's nothing that says you have to use a non-Rust solution for these kinds of things; any "cargo-foo" executable on your $PATH works as "cargo foo", and can be written in any language, including Rust. Your custom command could invoke "cargo build" as a step first and then do anything.

On Oct 29, 2016, 13:35 -0400, Mike notifications@github.com, wrote:

This would be useful for embedded systems programming. I often run arm-none-eabi-size to verify my binary size with each build, and occasionally other utilities from binutils to verify symbol tables, etc...


You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub (#545 (comment)), or mute the thread (https://github.com/notifications/unsubscribe-auth/AABsimputy3ucYbBxCoVRqmOdAF8GQPnks5q44P0gaJpZM4CgUcP).

@JinShil

This comment has been minimized.

Copy link

JinShil commented Oct 30, 2016

Don't forget that there's nothing that says you have to use a non-Rust solution for these kinds of things; any "cargo-foo" executable on your $PATH works as "cargo foo", and can be written in any language, including Rust. Your custom command could invoke "cargo build" as a step first and then do anything.

Yes, that is what I, and probably others, are already doing. It would just be more convenient to integrate this into the already familiar cargo build.

@ssokolow

This comment has been minimized.

Copy link

ssokolow commented Oct 30, 2016

Not to mention that, in my experience, if you try to enforce your will too strongly, you start to get behaviours similar to what has been standard in the home inkjet printer market for well over a decade now.

(Where the first thing you see when you open the box is a slip that warns you, in big letters, to never plug the printer in until after you've installed the software off their CD, because Microsoft's automated driver installation workflow doesn't allow them to install their fancy, tray-resident, bloated, talking print drivers and their official position is that, if Microsoft's installer has had a chance to run, your OS is now broken and must be repaired first.)

Better to have an official way to run a post-build script than to see everyone and their dog reinventing broken wheels... especially since, as a Stubborn Person™, I can easily foresee these horrors:

  • Crates which bail out early and insist that, even if they're being used as a dependency, you must run their own special cargo mybuild wrapper instead of cargo build (possibly not as an inherent thing, but as a result of depending on something else by the same author which has that build requirement).
  • Developers recognizing the ugliness of the former situation and producing a "better" solution by hacking (subtly buggy) post-builds onto cargo build using pre-build scripts which leave something running in the background to trigger the post-build using inotify or equivalent.

(Also, keep in mind that, as Rust sees more corporate uptake, we'll see more "I'm too busy to learn the 'proper' way, so I'll just hack something in" WTFs. That's just a basic rule of programming in general.)

@Kixunil

This comment has been minimized.

Copy link

Kixunil commented Jan 29, 2017

In embedded development it's useful to run objcopy to produce hex file or something similar. Adding this to post-build script would be much cleaner than reinventing wheel with my own shell script.

@yasammez

This comment has been minimized.

Copy link

yasammez commented Mar 19, 2017

This would be useful for stuff like

SignTool sign /v /s PrivateCertStore /n MyTestCrt /t http://timestamp.verisign.com/scripts/timstamp.dll driver.sys

when developing Windows drivers in Testmode.

@fschutt

This comment has been minimized.

Copy link
Contributor

fschutt commented Apr 2, 2017

This would be useful for packaging debian applications, especially when combined with configuration
Like a configuration deploy which builds the crate in release mode, then creates the folders needed for a package (control files, etc.) and runs dpkg on it.

@kornelski

This comment has been minimized.

Copy link
Contributor

kornelski commented Apr 4, 2017

cargo install touches files outside the current directory, so it doesn't feel like a proper post-build step. If I want to strip the built binary, would I have to work on a binary already copied to /bin?

@Boscop

This comment has been minimized.

Copy link

Boscop commented Apr 20, 2017

Why not do this:
If there is a postbuild.rs file, it gets executed after build. (similar to the build.rs file before.)
It would make sense to execute the script also if the build failed. The build status can be passed to it in an env var.

@Kixunil

This comment has been minimized.

Copy link

Kixunil commented Apr 22, 2017

@Boscop I like that idea but I worry that executing another binary every compilation might slow down iterative development. Maybe using postbuild-success.rs for only success, postbuild-failure.rs for only failure and postbuild.rs for both?

@Boscop

This comment has been minimized.

Copy link

Boscop commented Apr 22, 2017

I think there won't really be a slowdown compared to having different scripts for success/failure because if your postbuid.rs script checks the build status first and then returns if it's not success/failure, it won't really slow things down. The postbuild.rs script won't have to be recompiled every time, only when it changes. So calling it will just incur the cost of starting an executable that immediately returns.
Having one postbuild.rs script follows the KISS principle, most projects won't even have a postbuild.rs script, and for those that will have one, I think having one script fulfills their needs.
If they notice a slowdown, we can always introduce the option to replace the postbuild.rs script by the other two later. But let's first have just the postbuild.rs and see if that's enough.

@Kixunil

This comment has been minimized.

Copy link

Kixunil commented Apr 24, 2017

That sounds reasonable.

@tanis2000

This comment has been minimized.

Copy link

tanis2000 commented Jun 9, 2017

@Boscop idea of the postbuild.rs script sounds like a very good way of managing post build actions. Even though the general opinion seems to be split between this and avoiding to turn cargo into a general purpose make system, I feel that this won't hurt.

@JoeyAcc

This comment has been minimized.

Copy link

JoeyAcc commented Jun 26, 2017

Not that I'm advocating for it per se, but Cargo already is a general purpose build system due to the cargo plugins (e.g. cargo tree) being able to do whatever they want. That that is merely a user-friendly(ish) facade for "random turing-complete script" doesn't diminish that in any way.

So the real question becomes: How ergonomic do we want to make this general-purpose build system?

@Boscop

This comment has been minimized.

Copy link

Boscop commented Jun 26, 2017

Cargo is not a general purpose build system in the sense that e.g. cmake is.
But I see no reason why cargo can't be the best build system for Rust projects, and having post-build script execution would remove the need to wrap cargo build into another build system for projects that have post-build steps, which occurs more often than not.

@JoeyAcc

This comment has been minimized.

Copy link

JoeyAcc commented Jun 26, 2017

Cargo is more restricted than e.g. CMake in the sense that there are assumptions about e.g. where to download dependencies, that each such dependency is a rust crate etc.

That doesn't mean it's not general purpose, since again each cargo "plugin" (AFAIK just some binary that masquerades as a part of Cargo) can do whatever it wants to, including downloading arbitrary projects (including non-rust ones), and mangling them in arbitrary ways, including building them.

That is why I view this as a discussion about ergonomicity rather than capability.

@ssokolow

This comment has been minimized.

Copy link

ssokolow commented Jun 26, 2017

That is why I view this as a discussion about ergonomicity rather than capability.

Agreed. I won't restate my previous comment, but I highly recommend that anyone who hasn't seen/doesn't remember it should scroll up and read it.

There are a couple of ways in which I can very easily imagine people who "just need to get work done" foisting a a monstrosity of a bodge on the rest of us.

@matklad

This comment has been minimized.

Copy link
Member

matklad commented Jul 29, 2017

Just to make sure folks are aware, there are at least two Rust projects which make executing stuff in addition to cargo build simpler:

https://github.com/casey/just
https://sagiegurari.github.io/cargo-make/

@JoeyAcc

This comment has been minimized.

Copy link

JoeyAcc commented Aug 25, 2017

Especially cargo-make seems, at least for now, like the way to go if post-build steps are required.
The utility name is apt, as it looks like a cross-platform version of make with much more intuitive "Makefile" syntax, since makefiles are just TOML files.

While that is certainly a workable solution for a lot of projects, I still have to wonder if long-term we want to incorporate that kind of functionality directly into Cargo.

@ssokolow

This comment has been minimized.

Copy link

ssokolow commented Aug 25, 2017

The problem with cargo-make is that cargo build on a package isn't aware of any cargo-make or just scripting in the dependencies, so it's only a solution for --bin crates, not library crates.

For example, suppose you want to build a Rust binary that depends on a cdylib-based dlopened plugin for one of its other dependencies (or just wants to automate installing some plugins via features) and that cdylib needs to do some post-processing on the generated .so/.dll/.dylib file.

The only solution, currently, is to manually build the cdylib separately, using cargo-make or what have you, and then copy it into the depending project.

@JoeyAcc

This comment has been minimized.

Copy link

JoeyAcc commented Aug 25, 2017

Couldn't a build dependency on cargo-make in the cdylib project (assuming it's a Cargo project) help with that, even when building a binary that depends on that cdylib?

Even though Cargo may not be explicitly aware of cargo-make, it know does know about transitive build dependencies, doesn't it?

@ssokolow

This comment has been minimized.

Copy link

ssokolow commented Aug 25, 2017

How would that help to run something after the dependency is compiled without either forcing all downstream dependencies to also explicitly use/call cargo-make for/in their build automation or resorting to the ugly hackery I worry about where people fire off an inotify-based "watch for build completion" daemon in the pre-build script?

@JoeyAcc

This comment has been minimized.

Copy link

JoeyAcc commented Aug 25, 2017

After the dependency is compiled this solution wouldn't do a thing of course.
But if the dependency is a Cargo project, then Cargo can build it however specified in its Cargo.toml.

So this wouldn't help with e.g. pre-existing native (C/C++) dependencies, but it could help with some Cargo projects I think.

@ssokolow

This comment has been minimized.

Copy link

ssokolow commented Aug 25, 2017

And the whole point I've been trying to make is that, in certain contexts, there are tasks which Cargo.toml doesn't understand which must take place after the build process.

(eg. modifications to the built ELF/Mach-O/PE files where include! and friends aren't applicable because the required format for the modifications is defined by some entity outside the developer's control, such as the operating system's loader.)

To summarize my first comment, if you don't accomodate these enough, you'll get horrendous hacks from people who care more about getting work done than tying themselves in knots to make the perfect codebase. (Such as the example I mentioned of firing off something in build.rs which sits around in the background, waiting for the build artifact to appear so it can manipulate it further.)

@kornelski

This comment has been minimized.

Copy link
Contributor

kornelski commented Sep 2, 2017

RFC for build system integration may be relevant to this.

@Boscop

This comment has been minimized.

Copy link

Boscop commented Dec 2, 2017

What would be the best way to do post build script execution by starting a process that waits in the background; should that process use the notify crate to wait for a write event on target/release/<package name>.exe (for executables on windows)?

Would it make sense to publish a generic post build task runner tool, installable as a cargo binary?

@Kixunil

This comment has been minimized.

Copy link

Kixunil commented Dec 5, 2017

@Boscop sounds very hacky to me. Anyone wanting to implement it would spend their time better by writing PR agains Cargo.

@SoniEx2

This comment has been minimized.

Copy link

SoniEx2 commented Dec 9, 2017

Need to cat a zip to a bin. This would be useful, even if restricted to application/binary builds.

@gnzlbg

This comment has been minimized.

Copy link

gnzlbg commented Feb 23, 2018

I need to do something with my binary after I build it and before it is installed.

Without a post build script cargo install installs the wrong thing.

@FredrikAleksander

This comment has been minimized.

Copy link

FredrikAleksander commented Mar 26, 2018

In one of my projects, I need to generate a symbol map after building, and it is pretty annoying this cannot be done via Cargo. My current solution is using gnu make instead of Cargo, and have make call cargo when it needs to build rust. This is a really hacky solution, and it would be easily solved with a post build script

@dancrossnyc

This comment has been minimized.

Copy link

dancrossnyc commented Jun 18, 2018

+1 on the need for this or something very like it. I need to run objcopy on a binary after build.

@timburks

This comment has been minimized.

Copy link

timburks commented Jul 6, 2018

I'm also using rust to build macOS apps, currently by calling cargo from a shell script.

A suggestion that I haven't seen yet is to name the post-build script final.rs and run it after all builds, perhaps with environment variables to pass build status. This seems very non-disruptive to current usage.

[package]
# ...
build = "build.rs"
final = "final.rs"
@kornelski

This comment has been minimized.

Copy link
Contributor

kornelski commented Mar 15, 2019

cc #3483

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.