Est. 2011 Intermediate

Ninja

A small, deliberately minimal build system focused on speed, designed to have its build files generated by higher-level tools rather than written by hand.

Created by Evan Martin

Paradigm Declarative build specification
Typing Not applicable (declarative build DSL)
First Appeared 2011
Latest Version Ninja 1.13.2 (2025)

Ninja is a small build system built around a single overriding goal: run incremental builds as fast as possible. Created by Evan Martin while he was working on Google’s Chromium browser, Ninja occupies an unusual niche in the build-tooling landscape. It is intentionally not a full-featured, human-friendly build description language like Make or SCons. Instead, it is designed to be a low-level executor — what Martin called an “assembler” for builds — whose input files are generated by a higher-level meta-build system such as CMake, Meson, GN, or the original GYP. The .ninja files Ninja consumes are explicitly not meant to be written by hand.

That narrow focus is the whole point. By refusing to take on configuration logic, conditionals, or platform detection, Ninja keeps its parser trivial and its dependency graph cheap to load, which is intended to let it begin a build of a project with tens of thousands of files with minimal startup delay.

History & Origins

Ninja grew out of a concrete frustration. When Chromium was being ported beyond Windows, the team initially planned to use SCons, but Evan Martin reported that simply deciding what to build could take a substantial amount of time before any compilation started — a significant tax on the rapid edit-compile-test loop that browser development demands. Beginning around 2010, Martin started building a minimal tool that would do almost nothing except figure out, as quickly as possible, which commands needed to run and then run them.

He open-sourced the result in February 2011, hosting it on GitHub and explaining the design in a now well-known blog post. The name Ninja reflected the tool’s intended character: it strikes quickly. Within a few years Ninja had spread far past its origins at Google, becoming a backend for general-purpose build systems and a fixture of large C and C++ projects.

Martin stepped back from active development and handed maintainership to Nico Weber around 2014; maintenance later passed to Jan Niklas Hasse, under whom the project continues to receive regular releases. In 2020, Martin published a candid retrospective, The Success and Failure of Ninja, reflecting on which of his original bets had paid off. He later (around 2022) began n2, a Ninja-compatible reimplementation in Rust used to revisit some of the original design choices.

Design Philosophy

Ninja’s philosophy can be summed up as “do one thing, and do it fast.” Several deliberate constraints flow from that:

  • It is a backend, not a frontend. Ninja assumes that some other tool has already done the hard work of resolving configuration, so its own files can be flat, explicit, and fast to parse.
  • Minimal feature set by design. There is no built-in concept of a compiler, library, or platform. Ninja knows only about rules (command templates) and build statements (which inputs produce which outputs).
  • Speed as the primary metric. Everything from the file format to the dependency-tracking implementation is optimized to make the no-op “nothing changed” build and the small incremental build as quick as possible.

This division of labor — a high-level generator producing low-level Ninja files — is now a common pattern, and Ninja popularized it.

Key Features

The .ninja format is small enough to describe in a few concepts:

  • Rules declare a reusable command, typically parameterized with variables. For example, a cc rule might describe how to invoke a compiler.
  • Build statements connect specific inputs to outputs using a rule, forming the dependency graph.
  • Variables allow simple textual substitution (such as compiler flags), but there is intentionally no general-purpose scripting.
  • Implicit and order-only dependencies give generators fine-grained control over rebuild behavior without complicating the common case.
  • Header dependency tracking integrates with compiler-emitted dependency information (for example, the depfile/deps mechanisms) so that changes to included headers correctly trigger rebuilds.

A minimal Ninja file looks like this:

cflags = -Wall

rule cc
  command = gcc $cflags -c $in -o $out

build hello.o: cc hello.c

rule link
  command = gcc $in -o $out

build hello: link hello.o

Even though such a file can be written by hand for illustration, in practice a generator emits it.

Evolution

Ninja’s evolution has been characterized by restraint — new features are added cautiously, and only when they serve the speed-and-simplicity mission. Over time the project has added niceties such as richer console output, the ninja -t toolset for inspecting and cleaning builds, and improvements to dependency handling. A more recent example is Ninja 1.13.0 (June 2025), which added support for the GNU Make jobserver protocol, allowing Ninja to coordinate parallelism with parent build processes. The latest release in this lineage, Ninja 1.13.2, arrived in November 2025.

The broader Ninja ecosystem has also expanded through compatible implementations: samurai, a compact reimplementation in C, and n2, Evan Martin’s own Rust-based experiment, both consume the same .ninja format.

Current Relevance

Ninja is, by most measures, a quiet success. It rarely receives attention from end users because it is almost always hidden behind a meta-build system — but that invisibility is itself a sign of how thoroughly it has been adopted. Choosing the Ninja backend in CMake or using Meson means using Ninja, often without realizing it. It underpins the builds of some of the most heavily engineered software in existence, including Chromium, LLVM, and Android, and remains under active maintenance.

Why It Matters

Ninja’s lasting contribution is conceptual as much as technical: it demonstrated that build description and build execution are separable concerns, and that separating them yields large, real performance wins. By doing deliberately less than Make, Ninja did the part it kept far better. That insight — pair a smart, slow-to-run generator with a dumb, fast-to-run executor — has become a standard architecture in modern build tooling, and it is the reason a tool created as a side project to speed up one browser is now executing builds across a huge swath of the software world.

Timeline

2010
Evan Martin, an engineer at Google, begins developing Ninja as a side project to speed up the edit-compile cycle while building the Chromium browser
2011
Ninja is open-sourced in February under the Apache License 2.0 and hosted on GitHub, introduced via Evan Martin's blog post describing it as an 'assembler' for build systems
2012
CMake adds a Ninja generator (CMake 2.8.8), letting any CMake project emit .ninja files and broadening Ninja's reach well beyond Chromium
2013
The Meson build system has its first public releases and adopts Ninja as its default backend, further popularizing the tool in the open-source C/C++ world
2014
Evan Martin steps back from day-to-day development and hands maintainership of the project to Nico Weber
2020
Evan Martin publishes 'The Success and Failure of Ninja', a widely read retrospective reflecting on the project's design decisions and impact
2022
Evan Martin begins work on n2, a Ninja-compatible reimplementation written in Rust that explores alternative scheduling and parsing approaches
2025
Ninja 1.13.0 (June) adds support for the GNU Make jobserver protocol, improving coordination of parallel jobs across nested build invocations
2025
Ninja 1.13.2 is released in November, continuing steady maintenance under Jan Niklas Hasse

Notable Uses & Legacy

Google Chrome / Chromium

The project that motivated Ninja's creation. Chromium's build, originally driven by the GYP and later the GN meta-build systems, generates .ninja files, with Ninja designed to keep the startup cost of incremental rebuilds across its large codebase low.

LLVM and Clang

The LLVM project documents Ninja as the recommended build backend; developers typically configure LLVM/Clang with CMake using the Ninja generator to get faster incremental builds than the default Make-based setup.

Android Open Source Project

Android's build system translates its Android.mk/Blueprint definitions into Ninja files (via Kati and Soong), using Ninja as the low-level engine that actually executes the platform build.

Meson-based projects

Meson uses Ninja as its default backend, so major projects built with Meson — including GNOME components, systemd, GStreamer, and Mesa — rely on Ninja to run their builds.

CMake-based C and C++ projects

Because CMake ships a Ninja generator, a large share of modern C/C++ projects can opt into Ninja simply by selecting it at configure time, making it a common default in CI pipelines and IDE toolchains.

Language Influence

Influenced By

Influenced

n2 samurai

Running Today

Run examples using the official Docker image:

docker pull
Last updated: