Speedy Builds with Rust

By

Sep 3, 2021

Contents

Rust is a multi-paradigm, high-level, general-purpose programming language designed for performance and safety, especially safe concurrency. In today’s post we are using Rust nightly. You can also add more targets like stable or beta, but we are going to show you the power or utilizing caching when it comes to building in Rust on Travis.

Rust and Travis

Rust builds are notoriously slow, especially when compiling from a clean slate. This is less true than it once was, but it’s still slow enough to be a significant problem for CI systems. So I thought why not write something that will help future Rust builders using Travis?

Slow down, you’re going too fast

Actually, you’re doing just fine. The good news is, is that we can use cache: cargo, and a few other things up our builders sleeves to help the speed of builds in Rust. For example, take a look at this .travis.yml I wrote:

---
cache: cargo
dist: xenial
language: rust
matrix:
  allow_failures:
    - rust: nightly
  before_cache: 
    - rm -rf ~/.cargo/registry/index/ # Remove cache files 
    - rm -f  ./target/.rustc_info.json # Remove more cache files that are recursively brought back upon a triggered build
    - find ./target/debug -maxdepth 1 -type f -delete # Delete loose files 
  fast_finish: true
os: linux
rust:
  - stable
  - beta
  - nightly
script:
  - "cargo build --verbose --all"
  - "cargo test --verbose --all"

We are testing against 3 Rust channels here, on occassion nightly will fail due to the compiler, but since this post is about speeding up your builds, you’ll notice I put in a conditional, that is, allowing failures from only one Rust channel, and that is nightly:

matrix:
  allow_failures:
    - rust: nightly

You’ll notice stable and beta are not listed along with nightly. Now since speed is the center of this post, you may want to disable Cargo’s incremental compilation, as it doesn’t really give any more verbosity to the build, so let’s try removing it for even faster builds. In order to do this, you’ll need to set the CARGO_INCREMENTAL env var to 0.

Tests

Now, let’s make a test file, here’s some Rust code, you’re free to name it whatever you like, in this case you can see we named our file test_run:

extern crate test_run;

use logic_gates::{and, xor};

pub type Sum = u8;
pub type Carry = u8;

pub fn half_adder_input_output() -> Vec<((u8, u8), (Sum, Carry))> { 
    vec![
        ((0, 0), (0, 0)), 
        ((0, 1), (1, 0)), 
        ((1, 0), (1, 0)), 
        ((1, 1), (0, 1)), 
    ] 
}

fn half_adder(a: u8, b: u8) -> (Sum, Carry) {
    (xor(a, b), and(a, b))
}

#[test]
fn one_bit_adder() {
    for (inn, out) in half_adder_input_output() {
        let (a, b) = inn;
        assert_eq!(half_adder(a, b), out);
    }
}

Looks good builders, now let’s go over what we have:

  • Test file written in Rust
  • .travis.yml file
  • Some tips on setting the env var to 0
  • We ran a matrix build (multiple platforms and Rust versions) to test both stable Rust versions and nightly builds of their respective rust compiler on different platforms. I stated earlier, you’ll find nightly builds can fail, since those compilers aren’t final and may have bugs, so don’t mark these build fails as an overall failure of the build if that’s solely what went wrong

Repopulation of cached files

As the official Travis documentation states, Travis currently checks ~/.cargo and target/ for any changes from the current cache after a build. You must note, there will always be changes in target/ if the source has changed, which it usually does when a Travis build runs. This means new incremental object files, fingerprints, and build script compilation files are being added to the cache every build, and the more you build – the more clutter! You’ll notice there’s a before_cache section I added, in this section I added:

before_cache: 
    - rm -rf ~/.cargo/registry/index/ 
    - rm -f  ./target/.rustc_info.json
    - find ./target/debug -maxdepth 1 -type f -delete

This will help with that subroutine, and speed your builds up whilst using Rust, and now you should have a working build! You can carry over some of the methods you read here today and apply them to larger scale projects, this is just a small sample of implementing various ways of speeding up Rust builds on Travis.

132039334 70e2d953 9e1f 4b14 a9d4 54f3d1922ab1

If you have any questions please email me at [email protected] and I’ll answer any and all questions!

Happy building!

Written By

Reviewed By