What Is A Build System? A Gentle Introduction To Over-Thinking.

2021/09/19

Considering code as code. Maven doesn’t suck that much: the rest does too. Setting the stage.

Out of the blue, I sometimes need to improvise a mini explanation about build systems, usually as a pre-requirement for having a constructive discussion on topics that build on that notion.

This is pretty much a personal definition: it’s likely incomplete. Also, it’s an attempt at explaining stuff, if not from first principles, at least in a bottom up fashion, and will hopefully be part of a series of posts on subjects related to building and shipping software.

Note: if you’re more of the visual kind, you may want to directly head to what is a build system, illustrated.

What’s a Build System?

First, let’s take a step back and ask another question:

What’s a Program?

For our purpose, a program is something, anything, really, that:

Hold that thought for a moment.

The Traditional Introduction

I learnt about build systems in an unpleasant way at my first job: during a conversation with a more senior colleague from another team, I realised there were aspects of our profession I literally knew nothing about1.

It went like this:

– So, what build system are you using?

– ???

–You know, what’s the program you run to build your code into something executable

I’ve since enjoyed the (admittedly guilty) pleasure of asking juniors about their favourite build system during interviews. When, exactly like I did, they have no clue what I’m talking about, I explain it as:

The thing that makes something useful out of your code.

To their relief (which echoes my own, back in the good old days), we discover that we’ve essentially all been using build systems since we started coding.

First Inception Attempt

Usually, the whatever you are using to turn your code into something useful is a program as well. Hence, a build system can generally be seen as:

A program that spits out programs based on some input

Some Add-Ons

In general, build systems will come with additional tools to help with:

This gets us to what most people understand (consciously or not) under the term “Build System”: Maven, webpack, sbt, graddle, make, as well as many others, all fit the above definition.

Second Attempt

Now, at this point most people are like yeah I got it, I can get back to work, not sure the time was worth it m’kay? Programs spitting out programs whatever, gotta ship that new feature…

But that’s actually where the fun starts: to those who are still around, we ask the simple question:

So what about using the output of a build system as the input to another build system?

Or, more prosaically:

What about using the output of a program as the input to another one?

Yeah, right, pretty pedestrian: That’s the most obvious thing ever, why are you waisting my time? Ever heard about piping with your shell? Lol that’s like how everything works already no?

Indeed, it’s not new. But it’s not trivial either.

Discovering The Pain

To illustrate, consider how annoying it generally is to mix together multiple programming languages: I may well build some Typescript and some Go along with my Java using Maven, so that for example I cook up a jar containing a Go binary as well as a web app to be served.

However, the whole setup will likely be slow and brittle. Furthermore, what if I suddenly need to use a Python script to generate multiple variants of the web application? What if I need to replace Python with Rust?

All this is possible using your standard tools, but it’s increasingly hard and unflexible with each new program you add to the setup. Plus, the result is likely to be extremely specific to your situation, failing to generalise in any meaningful way to other situations.

Later, we’ll look into how the above example is not as convoluted as it first seems, and why revisiting the way we usually think about building software can yield surprising results.

A (short) Definition

So, what’s a build system? Here goes:

A Build System orchestrates multiples programs along with their respective inputs and outputs. Build Systems commonly use the output of a program as the input to other programs.

Sounds awfully generic? Head over to my latest post on the subject that also includes some build-system illustrations!


  1. My past self always seems so clueless to my present self, while my present self always feels so confident. Please don’t think through to the logical conclusion… ↩︎