O(1) Build File

Rule of thumb: the size of build or CI configuration should be mostly independent of the project size. In other words, adding, say, a new test should not require adding a new line to the build file to build the test, and a new line to .yml to run it on CI.

Lines in CI config are costly each line is typically a new entry point, and a bit of required knowledge to be able to run the project locally. That is, every time you add something to CI, you need to explain that to your colleagues, so that they know that they need to run more things locally.

Lines in build config are usually a little cheaper, but are still far from free. Often a new build config also implies a new entry point. At other times, its just a new build artifact tied to an existing entry point, for example, a new integration test binary. Build artifacts are costly in terms of compile time as your project is linked with every build artifact, the total linking time is quadratic.

What to do instead?

Minimize the number of entry points and artifacts. Enumerate O(1) of project entry points explicitly. You probably need:

This is a point of contention, but consider if you can avoid separate lint and fmt entry points, as those are a form of automated tests.

Of course, an entry point can allow filters to run a subset of things: run --test-filter=tidy. Its much easier to discover how to filter out things you dont need, than to realize that theres something you need to opt into.

Minimize the number of build artifacts, Delete Cargo Integration Tests. You probably need separate production and test builds, to avoid linking in test code with the production binaries. But chances are, these two binaries are all you need. Avoid building a set of related binaries, use subcommands or BusyBox-style multicall binaries instead. Not only does this improve compile times, it also helps with putting out fires in the field, as the binary you have in production also contains all the debug tools.


On rules of thumb in general: for me, the term doesnt mean that what follows is the correct way to do things, better than alternatives. Rather: