Comparison of C build systems
Expectations
- as little dependencies as possible (from best to worst)
- only C compiler and libc would be optimal
- Ok, written in assembly with only an assembler as dependency would also be fine
- written in a compiled language, so you can just drop in the binary is also acceptable
- if written in an interpreted language or a language which needs a VM, it should be wildly available and installed by default on many systems (no JVM)
- easy out-of-source builds
- easy to pass custom flags
- use any C compiler you want
- fast
- simple
To achieve this, we probably need to split to build tools into to different programs.
One for the actual building and one for generating the build files.
Build Systems
Make / GNU Make
Pros
- universally available
- easy to use different compilers
- easy to use own flags
Cons
- OS detection is a GNU Make extension
- out-of-source build Makefiles tend to get complicated
- you have to define the number of threads manually (some people would say it’s a PRO)
- cannot generate compile_commands.json, you need something like bear for this
Ninja
Pros
- fast
- automagically use a reasonable number of threads
Cons
- very low level, you need a build file generator for complex projects
- written in C++, so you need a C++ environment when you just want to build C projects
Samurai
Pros
- fast
- automagically use a reasonable number of threads
- more or less drop-in for ninja
- written in C, only POSIX dependencies
Cons
- same syntax as ninja, which means: very low level, you need a build file generator for complex projects
Meta Build Systems
CMake
Pros
- can generate build files for many build systems (make, ninja, …)
- not to difficult to do out-of-source builds (
mkdir build && cd build && cmake ..
)
- can generate compile_commands.json
Cons
- written in C++
- weird / complicated syntax for CMakeLists.txt
Meson
Pros
- generates build files for ninja
- default out-of-source build
- easy to generate different builds (debug, release, …)
- easy to add custom flags
- generates compile_commands.json, by default
Cons
- written in Python, so you need a Python environment to build C projects
- difficult to use custom compilers (e.g. tcc), but the big ones are supported (gcc, clang)
- problems finding ncurses on the BSDs
GN
Bad documentation.
I couldn’t build a “Hello, World!” project after half an hour trying.
Honestly this should be possible.
You shouldn’t need to read the whole documentation just to build a damn “Hello, World!”.
Premake
Can’t generate ninja build files, so I haven’t look deeper in it.
All the Java build systems
Ant, Maven, Gradle, Bazel, … You name it.
Many sound pretty interesting,
but I don’t want to have a JVM installed just for a build system.
I can live with build systems written in C++,
as I can drop in a binary for bootstrapping.
Python is also acceptable, as it is installed on most of my systems,
but a JVM, seriously?
Additional build system, which I haven’t looked into now
- tup, seems to be on the level with ninja, I’m already happy with samurai
- scons, written in Python, seems to do everything, like make, said to be slow
- gyp, succeeded by gn
- waf
- redo, by djb, will definitly take a look into it
Further reading