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.
Common errors
-
ninja: error: loading 'build.ninja': No such file or directory
cause This error occurs when the `ninja` executable is run in a directory where the `build.ninja` file, which defines the build rules, does not exist or cannot be found in the specified path.fixEnsure you are running `ninja` from the correct build directory where `build.ninja` was generated (e.g., a `build/` or `out/Default` subdirectory created by CMake or another meta-build system). If the file is missing, you need to run the meta-build system (e.g., `cmake .. -G Ninja`) to generate it first. -
ninja: command not found
cause This error indicates that the `ninja` executable is not in your system's PATH environment variable, or it is not installed. When used with CMake, the error might appear as 'CMake Error: CMake was unable to find a build program corresponding to "Ninja"'.fixInstall Ninja (e.g., `pip install ninja` for the Python package or `sudo apt install ninja-build` on Debian/Ubuntu, `brew install ninja` on macOS) and ensure its installation directory is correctly added to your system's PATH. For CMake, ensure Ninja is installed and discoverable by CMake, or specify its path using `CMAKE_MAKE_PROGRAM`. -
ModuleNotFoundError: No module named 'ninja'
cause This error occurs when a Python script tries to import the `ninja` module (typically `ninja_syntax.py` for generating build files) but the Python interpreter cannot find it. This usually means the Python `ninja` package is not installed in the active Python environment, or there's a conflict with other Python installations.fixInstall the Python `ninja` package using pip: `pip install ninja`. Ensure you are installing it for the correct Python interpreter that your script is using, especially if you have multiple Python versions or virtual environments. -
ninja: build stopped: subcommand failed.
cause This is a generic error from Ninja indicating that one of the underlying commands (e.g., a compiler, linker, or custom script) that Ninja executed as part of the build process returned a non-zero exit code, signifying a failure. The actual, more specific error message from the failed subcommand is usually printed in the console output *before* this 'subcommand failed' line.fixScroll up in your terminal or build log to find the detailed error message from the subcommand that failed. This message will provide the actual cause of the build failure (e.g., compilation error, linker error, missing file, incorrect arguments) which needs to be addressed.
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.
- gotcha The `ninja_syntax` module is a separate Python package and is not bundled with the `ninja` package. Attempting to `import ninja_syntax` without installing it will result in a `ModuleNotFoundError`.
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')