上記事でCMakeの使い方について話しました。
CMakeでは様々なビルドツールを選択することができますが、そのうちのNinjaというものについて今回は解説します。
Ninjaとは?
Ninjaは、高速性に特化した小規模なビルドシステムです。Googleのエンジニア、Evan Martinによって開発され、Chrome、Android、LLVMなどの大規模プロジェクトで採用されています。
Ninjaの特徴
- 圧倒的な速度: Make比で最大10倍以上高速なビルドが可能
- シンプルな設計: ビルドファイルは人間が書くものではなく、他のツール(CMakeなど)が生成する前提
- 効率的な並列処理: 依存関係を最適に解析し、CPUコアを最大限活用
- インクリメンタルビルドの最適化: 変更されたファイルのみを最小限で再ビルド(Makeなどと同様)
なぜNinjaは速いのか?
- 依存関係グラフの最適化: Ninjaは依存関係を有向非巡回グラフ(DAG)として管理し、並列実行可能なタスクを瞬時に判断
- 最小限のオーバーヘッド: Makeのような複雑な機能(関数、変数展開など)を持たず、純粋なビルド実行に特化
MakeとNinjaの比較
| 項目 | Make | Ninja |
|---|---|---|
| 速度 | 標準的 | 非常に高速(2-10倍) |
| 設計思想 | 人間が書く | ツールが生成 |
| 並列処理 |
-jオプションで指定 |
自動で最適化 |
| 記述の複雑さ(文法の種類の多さ) | 複雑(変数、関数など) | シンプル(基本的な命令のみ) |
| デバッグ | しやすい | build.ninjaは複雑 |
| 採用プロジェクト | 伝統的なUnixツール | Chrome, LLVM, Android |
Ninjaのインストール
Linux (Ubuntu/Debian)
sudo apt update
sudo apt install ninja-build
インストール確認
ninja --version
出力例:
1.11.1
CMakeでNinjaビルドファイルを生成する
基本的な使い方
CMakeは「ジェネレーター」という仕組みで、様々なビルドシステム用のファイルを生成できます。Ninjaはその一つです。
ステップ1: プロジェクトの準備
まず、CMakeプロジェクトがあることを確認します。簡単な例:
CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(MyProject)
set(CMAKE_CXX_STANDARD 14)
add_executable(myapp main.cpp)
ステップ2: Ninjaビルドファイルの生成
# ビルドディレクトリを作成
mkdir build
cd build
# Ninjaジェネレーターを指定してCMakeを実行
cmake -G Ninja ..
-G Ninjaオプションが、Ninjaビルドファイル(build.ninja)を生成するよう指示します。
ステップ3: Ninjaでビルド
# ビルド実行
ninja
# または、CMakeの統一コマンドを使用
cmake --build .
CMakeとNinjaの実践的な使い方
現代的な記法(推奨)
CMake 3.13以降では、より明確な記法が使えます:
# -S: ソースディレクトリ
# -B: ビルドディレクトリ
# -G: ジェネレーター
cmake -S . -B build -G Ninja
# ビルド
cmake --build build
# または直接Ninjaを使用
cd build
ninja
並列ビルド
Ninjaは自動的に並列ビルドを行いますが、制御も可能です:
# デフォルト(全CPUコアを使用)
ninja
# 並列ジョブ数を指定
ninja -j 4
# 進捗を詳細表示
ninja -v
クリーンビルド
# ビルド成果物を削除
ninja clean
# 完全にやり直す場合
rm -rf build
cmake -S . -B build -G Ninja
cmake --build build
Ninjaの便利なコマンド
ターゲット一覧の表示
ninja -t targets
出力例:
myapp: CXX_EXECUTABLE_LINKER__myapp_Debug
clean: phony
help: phony
all: phony
特定ターゲットのみビルド
# 実行ファイルのみ
ninja myapp
# ライブラリのみ
ninja mylib
実践例: CMakeプロジェクトでNinjaを使う
プロジェクト構成
my_project/
├── CMakeLists.txt
├── include/
│ └── calculator.h
└── src/
├── CMakeLists.txt
├── calculator.cpp
└── main.cpp
Ninjaを使うべき場面
✅ Ninjaが適している場合
- 大規模プロジェクト: ファイル数が多い
- 頻繁なビルド: インクリメンタルビルドを何度も実行
- CI/CD環境: ビルド時間の短縮が重要
- マルチコアマシン: 並列処理のメリットが大きい
❌ Makeでも十分な場合
- 小規模プロジェクト: ファイル数が少ない
- カスタムビルドルール: Makefileを直接編集したい
- デバッグ重視: ビルドプロセスを詳細に理解したい
まとめ
Ninjaは大規模プロジェクトに向いているビルドツールです。
自分もいつかその恩恵に預かるようなものを作ることができると良いなと思っています。