How Every C++ Build System Works (Except for CMake & Premake)
The inspiration for this post comes from a comment that suggested a video series on compilers, toolchains, and build systems. My first thought was: “NO! Learning how to do the same thing over and over with different languages and frameworks is the bane of a software developer’s existence. I’m NOT doing that!"
Besides, all build systems pretty much do the same thing, except for the two oddballs: CMake and PreMake. So, today I’m going to explain how all of those build systems work, and then we can talk about individual build systems…
How Pretty Much Every C/C++ Build System Works
All C/C++ build systems read some sort of script, and then run the compiler for each source file that needs to be built using the parameters given by the script. Once all files are compiled, then it calls the compiler’s linker to link all of the compiled files into a working program. That’s it.
Okay, things can get more complicated. Some scripts have complex configuration rules, and the script might end up running other tools as well (e.g., a code generator). But, at a high level, this is how they work.
Why Shell Scripts are NO Substitute for a Build System
Some of you will be thinking, “why do I need a build system for that?” I can do the same with a shell script. True, you could. However, build systems have a “killer feature” that makes them the right tool for the job: incremental builds and change detection.
You see, your shell script would recompile all files every time. Some programs have huge code-bases with thousands of files. So, that could take a very long time. Huge projects like WebKit have tens of millions of lines of code, and can take over half an hour to build from scratch on a fast machine. Got a slow machine, and you could be waiting hours for a full build.
Imagine having to wait that long every time you wanted to test your code. Ugh! No thanks. Enter code change detection. Build systems check whether a source file (or dependency) has changed since you last compiled it, and will only recompile files that have actually changed. So, if you’ve only changed one file, then it’ll only recompile that one. This is a game changer, because it drastically reduces build time, massively speeding up the code and test cycle.
What about CMake & Premake? How do they work?
They are what we call meta-build-systems. So they read in their own build script, and then generate a build script for your compiler’s native build-system. Then that build system will do the actual build.
The advantage of doing this, is that you can use the best compiler for the job on all platforms. So you can use Visual C++ on Windows, GCC on Linux, Clang on MacOS X, etc.
Comparing Build Systems
Talking about all these compilers and build systems. Remember how I balked at the idea of doing a series on multiple build systems? Well, if I were a beginner then I’d love a series of videos comparing different C++ build systems. There are so many options that it’s hard to know when to start. It doesn’t help that so many C++ tutorials fail to explain how to compile the code to a working program.
Okay, you don’t need to twist my arm any further. I’ll make a video series comparing CMake to other C++ build systems at a practical level. The rules will be simple: I try to build the same code on each build system, and get them to do the same things, within reason. Some things are a lot easier to do on one build system than another.
If you want to see it, then subscribe to the newsletter using the form below this post (or click here).
Final Request
Fellow software developers, please do NOT create yet another build system. I know, I know, they all suck. But you know what would suck even more? YOU adding yet another one to the mix. Don’t do it!
2 Comments
Hans de Ruiter 23/10/2024 1:40am (21 days ago)
Hehe. All the best with your build system. May yours finally be the one that doesn't suck!
dragonblade316 18/10/2024 5:47pm (26 days ago)
Already started and am using this article for reference. lol