Shave Some Time From Your Travis Builds
A lot of projects in the Rustoshpere use travis for their continuous integration (CI) builds. The idea behind this is that you let them build on every PR and thus can see if something fails before merging, theoretically allowing you to keep a working master at all times (I say theoretically, because even that may fail in the face of changing dependencies, but they’re rare for normal projects unlike unstable compiler plugins like clippy).
Travis is a Berlin/Germany-based company that thrives by selling their CI build
superpowers to companies and giving open source projects free access to their
build platforms. Having used their services for most of my projects, I can
attest to their general awesomeness. The way you setup their build is to
register with their service and add a travis.yml
file into your project
containing the setup. For Rust projects, the minimum file will be:
language: Rust
That is enough to get you a plain build+test cycle. Travis can also be configured to upload docs (see Huon Wilson’s travis-cargo), or do whatever you would do in a shell. Good stuff.
However, all that awesome power for free can make one forget that they have to burn cycles to build our stuff, and also the less time it takes to build the faster we can merge new features into our projects. So there’s some motivation to make the builds perform as fast as possible. Here are three general hints to make the builds fast:
1. Use container-based builds if possible
Unless you need to be root (and if you do, you may want to stop and think if
you can change your build to remove that requirement) you can add sudo: false
to your .travis.yml
. This will speed up your build considerably (although I
don’t have numbers, I remember noticing the speedup when making the switch for
optional).
2. Cache cargo dependencies
With the line cache: cargo
in your .travis.yml
, travis
will remember the contents of $HOME/.cargo
and
$TRAVIS_BUILD_DIR/target
, so that you only need to recompile dependencies
if they or the compiler were upgraded. For some dependency-heavy projects, this
can make quite the difference.
3. Only build what you need
If you just want to test, you don’t need a release build (unless your tests are
so massive that running them from a debug build is slower than building a
release build + running them there). If you want to benchmark, you don’t need a
debug build (you can cargo test --release
to stop building two separate
builds). Know what compiler/cargo flags change build behavior. For example, -C
debug-assertions=on
enables debug assertions (including integer overflow
checking) even on release builds. To reliably do this with cargo, you can call
cargo * --verbose
(where *
is any of the other commands, usually build
,
test
or doc
) and copy the respective rustc
commands into your build. You
can then use cargo rustc -- ..
to add the same flags to your build when using
cargo.