Using Rust's Cargo as a build system
Around the beginning of 2020, I started using Rust’s
cargo as my build system for a large repo. The repo has a couple
In the past I’ve used Maven, NPM, Pants, Bazel, and Make, but they all required a lot fo setup and maintenance for multi-language targets. Maven is java focused, and since I’m not using java at the moment, extending it is pretty awkward. NPM is upsetting because it’s just a proxy to scripts and commands - not much structure. Pants and Bazel both have pretty full features, but seem to be focused on large organizations. Make has always been great - but I’ve found Cargo to be even better.
Why not use the one that I’m already using to build Rust binaries? Cargo has a lot of good features that Make has, but with the benefit of being in a full-featured programming language I already know and use. Here’s a rough list of the benefits:
- Checks dependency graph - bash and NPM can’t easily do this.
- Extensible using
build.rs. Can easily run pre-build tasks, or if need be, use the build file that to call into shell scripts.
- Already using cargo to manage dependencies, don’t need to install something else.
- Can extend development tooling beyond build with
cargo xby creating custom cargo commands.
- Watch specific files through the use of
cargo:rerun-if-changed- equally flexible to Make, if not more so.
- Depend on non-rust languages and targets by just making them a dependency.
All of these taken together allow me to run
cargo build -p x and build a package once, watching dependencies to see if
It’s nice to be able to build frontend targets by calling shell scripts from
build.rs. For example, since all my
frontend code is built with esbuild, the cargo build script runs
esbuild.sh, which does
some building and
cp-ing of files.
If you’re already using Rust, give it a try. It’s simpler, easier, and far less time-consuming than almost all the other options.