Does Ninja outshine GNU Make?

Build systems are indispensable tools in software development. They automate the compilation of code, link libraries and finally generate executable files. GNU Make is probably the most common build system. Nevertheless, Ninja is often mentioned as a better alternative.
What are the differences, advantages and disadvantages of the two build systems?

Ninja

Ninja is a fast and lightweight build system designed for efficient incremental builds. Below are some important features of Ninja:

  1. Speed: Ninja is known for its speed. Especially for incremental builds, Ninja is fast and efficient, making it ideal for large projects with many dependencies.
  2. Simple and efficient: Ninja contains only the functions needed to get incremental builds right. Most complex tasks are outsourced to a build generator.
  3. Clear syntax: Ninja build files use a clear syntax that is easy to read and write. The focus is on simplicity and performance.
  4. Useless on its own: Ninja build files are not meant to be created manually. Therefore, the use of a build generator such as CMake or Meson is mandatory.

GNU Make

GNU Make is a classic build tool that has been around for decades. It uses Makefiles (written in a specific Make syntax) to define build rules. Here are some aspects of GNU Make:

  1. Widely used: GNU Make is used and supported on various platforms. It is the default build system of many projects.
  2. Rich in features: GNU Make has a lot of functionality. Some examples: Conditional statements, functions for text manipulation, suffix rules, built-in rules. This means that Makefiles can be powerful, but also complex.
  3. Cryptic: Makefiles use a special syntax that is often opaque for beginners and occasional users. The combination of variables, rules, dependencies and tabs can be confusing and requires extensive training.
  4. Standalone: GNU Make was originally developed as a standalone tool and was designed with the idea of writing Makefiles manually. Build generators were added later and their use is therefore optional.
gegenueberstellung

Figure 1: Comparison of Ninja build file and Makefile to illustrate the syntax

Experience with Ninja

During the development of a build generator that creates Ninja build files, we have had both positive and negative experiences. Here are the most important findings:

Flat learning curve: thanks to the few features Ninja offers, the Ninja manual is clear and the syntax is quickly understood. Ninja offers a Python module `ninja_syntax.py`, which can be used to generate Ninja build files.

Compilation Database: With `ninja -t compdb` a compilation database can be created. This is a JSON file which describes how individual compilation processes can be repeated independently of the build system. Many tools, e.g. for static code analysis, support this format as an interface. Being able to easily extract the compilation database from the Ninja build files made the integration of these tools much easier.

Absolute and relative paths: Excerpt from the Ninja manual:

“File paths are compared as they are. This means that an absolute path and a relative path that refer to the same file are considered different by Ninja”

This is a challenge, especially in the context of depfiles, where you do not have control over the generated paths. Our conclusion: Mixing absolute and relative paths should be avoided. Which is not always easy (see issue on GitHub - open for over 8 years).

Conclusion

If a build generator such as CMake is used, compiling with Ninja is much more efficient than with GNU Make. It is therefore advisable to use Ninja, as most build generators support the generation of Ninja build files.

If you are developing a build generator, it makes sense to use the modern Ninja. However, writing Ninja files manually is not recommended due to possible errors. GNU Make remains a reliable option for smaller projects, but its limitations become apparent in larger, more complex codebases.

Choose the build system that best suits the requirements of your project and your development workflow. Both Ninja and GNU Make have their strengths.

We at CSA Engineering are happy to support you competently, regardless of which build system you choose.

Pascal Hari

Pascal Hari
BSc BFH in Microtechnology
Embedded Software Engineer

About the author

Pascal Hari has been working as an embedded software engineer at CSA Engineering AG since 6 years. His focus is on the development of firmware in C++ on STM32. However, he also has a great passion for topics such as build environment, toolchain and Docker. In his latest activities he is leading the development of a python-based build system based on Ninja.

Contact us