Bazel: Fast, Correct, Usable – choose two

March 14, 2018

Tools Rant 

Originally posted at https://tech.labs.oliverwyman.com/blog/2018/03/14/bazel-fast-correct-usable-choose-two/

I’d recently gotten reminded about Bazel, Google’s ‘boil the ocean‘ build system, and decided to give it a proper go. TL;DR – it’s not ready yet, and might not ever be, unless you’re willing to throw away everything else.

I’m generally on the lookout for good build systems. Some of my colleagues are perfectly happy with make but I’m of the opinion that trying to build a proper modern system out of make and random bits of shell code is a bad idea. I want an actual programming language to work with! Bazel seemed like it was actually what I wanted, and the repeatable builds stuff was just the icing on the cake. So, I need a use case. I decided to start with Sked and Potboiler, and see if I could convert their existing work into using Bazel. Both use Docker, Sked uses Python 3 and Django, and Potboiler uses Rust. I felt that between those two I had enough that if Bazel was happy with those it’d be happy with most things I use.

First problem: Python 3 isn’t fully supported. Apparently if your dependency isn’t available on Python 2 (e.g. Django 2.0), Bazel can’t install it, because it uses Python 2 under the hood, and apparently making it use Python 3 as well is pretty hard. Along the way I also find out the CI system they’re using doesn’t allow for public build log access, which is kinda sucky for an open source project.

Second problem: If you want to build Docker images in Bazel (and it’s claims of deterministic Docker builds was one of the major reasons I tried this out), RUN lines won’t work. If you’re using them to install Debian packages, you might be able to use the Debian package rules to do things, but if you’re using Alpine or want something else, good luck! It’s entire model of building Docker images is radically different to Docker’s standard Dockerfiles, and you’d need a complete rewrite from ground up to do the equivalent of any non-trivial Dockerfile.

Third problem: the Rust support doesn’t support target autodetection, git dependencies, or Cargo workspaces and has a different interpretation of versions to Cargo. I hit all of those trying to build Potboiler…

So there’s one or two issues. That’s before I get to the ergonomics of the sprawl that your WORKSPACE and BUILD files end up being and I haven’t yet found a good way to split them up into multiple files (certainly not one in general use). At this point it’s good to remember that You Are Not Google.

Bazel is in certain ways a really good system – it does actually seem to get close to being able to support at least most languages in major use at the moment, and in the sense of “without writing mountains of shell script or shelling out to the existing tool” which is more than I could say for most other build systems out there, which I’m deeply impressed by. OTOH, it does this by discarding all of the language/framework-specific tooling and telling you to do everything in Bazel, which is probably doable, but it’s a heck of a lot of work. Also, it’s support for things tends to be at the most superficial levels – it’ll support the basic package management and basic building of stuff for language X, but any of the more advanced features (which sadly most non-trivial projects use) just won’t work. If you’re lucky they can be easily rewritten as Bazel code, but the return on things starts to drop a lot.

If you did things with Bazel from the start, in some ways it might be easier, but lots of things (like the Rust generator support) assume you’re using the language specific things, and you do need a weird hybrid of Bazel and other build systems for a reasonable workflow, and at that point Bazel starts to look less attractive. Better Bazel macros could be written (e.g. to declare a package dependency in one line as opposed to having to manually write out exactly how you could download it, which is what the generators do), and that might make it possible to use Bazel as your initial build system. In general, some combination of generators plus easier macros would probably improve things, so might be worth another go in a year or two, which should hopefully help the other issues here.

Previously: Wharf: Dokku Web frontend Next: On Mocking Rust