Switching from Make to Ninja and GN across the board.
A build system is what coordinates the build process of various source files and libraries.
Make is a tried and tested tool, but it does not scale well with large, collaborative projects that often require complicated build rules and maximum parallelism. In an attempt to augment it, GNU Autotools was introduced, but its complicated workflow is little short of intimidating.
Originally, Make has been my choice. It is familiar to most programmers and is
(almost) ubiquitous in every *nix system. As time went by however, things get a
little complicated, warranting a makefile generator. Taking cues from static
HTML template engines, I rolled a custom one in Python, which takes a
description file BUILD.mg
in JSON, and a Makefile template. However, the
generator needs to be constantly maintained to meet my growing demands.
For a while, I considered CMake, as it is the de facto standard used by popular projects in the open source community like LLVM, OpenCV, and PyTorch. However, its syntax is arguably inelegant, and my personal experience with it was painful during grad school.
Ninja is unfamiliar to most programmers. But this is not to say Ninja is any less capable. It began with Chromium, the open source web browser project initiated by Google. In a bid to accelerate the build process, Googlers noted that for a non-trivial project:
- Make was designed in a way that makefiles are writable by hand, so it makes a lot of deductions at runtime, which is slow, and
- The syntax makes it not easy to write rules that get the dependency correct; most of the time programmers add new rules haphazardly just to "make things work".
As a result, the Chromium team built Ninja, a build system that was designed with a focus on speed and dependency correctness.
Writing ninja files by hand is painful by design, because they are meant to be
auto-generated. GN is such a generator, just
like the role CMake plays for Make: it takes *.gn
files and produces ninja
files for the user. Additionally:
- GN has lots of other useful functionalities baked inside.
- Its declarative syntax is much more concise and tasteful than CMake, and arguably makes it easier to make changes.
- It has the right amount of flexibility, but not too much. Writing build rules should not be a creative endeavor; ideally two people should produce the same results given the same requirements.
After the release of GN for Chromium, Google open-sourced Bazel, a distributed, cross-language build system based on its internal one. Though Bazel can replace GN and Ninja all at once and it is the official build system for a number of open source projects like Abseil and Tensorflow, I didn't choose Bazel because:
- Bazel seems too heavy.
- GN's syntax is similar to Bazel's, as GN was designed to mimic the latter.
- GN is actively maintained by Chromium (and V8), and is used by Firefox and Fuschia as well.
- The migration cost outweighs the benefits.
Q: Have you tried other build tools, like XMake, SCons, and Meson?
A: No.
Q: Ahh.. I really do not want YET ANOTHER build tool!
A: ¯\_(ツ)_/¯
.
■
Using
gn check
: https://drive.google.com/file/d/1E3YQVAYKSYmJ3_FW_R6xa6z9upAQhiXW/view?usp=sharing