Ninja
Ninja is a small build system focused on speed, typically used with higher-level build systems like CMake to manage large projects. The Python package `ninja` provides the `ninja` executable and the `ninja_syntax.py` module for generating `.ninja` build files programmatically. It is currently at version 1.13.0 and actively maintained by scikit-build.
Warnings
- breaking Versions of the `ninja` Python package after 1.13 no longer support Python 3.7. Similarly, versions after 1.11.1.1 dropped support for Python 2-3.6.
- breaking The `pipes` module, which `ninja` relies on, was deprecated and removed in Python 3.13. This causes build failures when `ninja` is used with Python 3.13 or newer.
- gotcha Ninja is designed as a low-level build system. Its `.ninja` input files are intended to be generated by a higher-level build system (like CMake or Meson), not written or maintained by hand for complex projects. Attempting to manage complex build logic directly within `.ninja` files is an anti-pattern.
- gotcha Building the `ninja` Python package from source using `--no-binary=ninja` can fail if CMake is not already installed on the system, as `ninja`'s build process sometimes requires CMake.
- gotcha Incorrectly generated dependency files (`dep-files`) by certain compilers can lead to `ninja` always triggering full re-builds even when no changes have occurred.
Install
-
pip install ninja
Imports
- ninja_syntax
from ninja_syntax import Writer
Quickstart
import subprocess
from ninja_syntax import Writer
import os
# Create a simple build.ninja file
with open('build.ninja', 'w') as f:
writer = Writer(f)
writer.variable('cflags', '-Wall -Wextra')
writer.rule('cc', 'gcc $cflags -c $in -o $out')
writer.rule('link', 'gcc $in -o $out')
writer.build('hello.o', 'cc', 'hello.c')
writer.build('hello', 'link', 'hello.o')
writer.default('hello')
# Create a dummy source file
with open('hello.c', 'w') as f:
f.write("""
#include <stdio.h>
int main() {
printf("Hello, Ninja!\n");
return 0;
}
""")
print("Generated build.ninja and hello.c. Running ninja...")
try:
# Run ninja
result = subprocess.run(['ninja'], capture_output=True, text=True, check=True)
print("Ninja build successful!")
print("\nStdout:\n", result.stdout)
if result.stderr:
print("\nStderr:\n", result.stderr)
# Optionally, run the built executable
print("\nRunning built executable...")
exec_result = subprocess.run(['./hello'], capture_output=True, text=True, check=True)
print("Executable output:\n", exec_result.stdout)
except subprocess.CalledProcessError as e:
print(f"Ninja build failed with error: {e}")
print("\nStdout:\n", e.stdout)
print("\nStderr:\n", e.stderr)
except FileNotFoundError:
print("Error: 'ninja' command not found. Please ensure Ninja is installed and in your PATH.")
# Clean up generated files (optional)
# os.remove('build.ninja')
# os.remove('hello.c')
# if os.path.exists('hello.o'):
# os.remove('hello.o')
# if os.path.exists('hello'):
# os.remove('hello')