詳細
phonyルール
特別なルール名phonyは、他のターゲットのエイリアスを作成するために使用することができます。例えば
build foo: phony some/file/in/a/faraway/subdir/foo
これにより、ninja foo はより長いパスを構築するようになります。意味的には、phonyのルールはコマンドが何もしないプレーンなルールと同等ですが、phonyのルールは、実行時に表示されない、ログに記録されない (下記参照)、ビルド処理の一部として表示されるコマンド数に貢献しない、という点で特別に扱われます。
phonyのターゲットが他のビルドルールの入力として使われる場合、他のビルドルールは意味的に、phonyのルールの入力を自分のものとして考えることになる。したがって、phonyのルールは、ヘッダーファイルなどの入力をグループ化するために使用することができます。
phonyは、ビルド時に存在しない可能性のあるファイルに対してダミーターゲットを作成するためにも使用することができます。phony build文が依存関係なしに書かれている場合、ターゲットが存在しなければ、古いものとみなされます。phonyのビルド文がない場合、Ninjaはビルドに必要なファイルが存在しないとエラーを報告します。
決して再構築しないルールを作成するには、何も入力しないビルドルールを使用します。
rule touch
command = touch $out
build file_that_always_exists.dummy: touch
build dummy_target_to_follow_a_pattern: phony file_that_always_exists.dummy
デフォルトのターゲットステートメント
デフォルトでは、コマンドラインでターゲットが指定されていない場合、Ninjaは他の場所で入力として指定されていないすべての出力をビルドします。この動作を上書きするには、default target文を使用します。デフォルトのターゲット文は、コマンドラインで何も指定されなかった場合に、指定された出力ファイルのサブセットのみをビルドするようにします。
デフォルトターゲット文は、default キーワードで始まり、default targets という形式を持ちます。デフォルト ターゲット ステートメントは、ターゲットを出力ファイルとして宣言する build ステートメントの後に記述する必要があります。この文は累積的であるため、複数の文を使用してデフォルト ターゲットのリストを拡張することができます。たとえば、次のようになります。
default foo bar
default baz
これにより、Ninjaはデフォルトでfoo, bar, bazターゲットをビルドするようになります。
Ninjaログ
Ninjaは、ビルドされた各ファイルに対して、ビルドに使用されたコマンドのログを記録しています。このログを利用することで、Ninjaは既存の出力がビルドファイルの指定と異なるコマンドラインでビルドされた(コマンドラインが変更された)ことを知り、そのファイルをリビルドすることを知ることができる。
ログファイルはビルドルートにある.ninja_logというファイルに保存されます。最外部のスコープでbuilddirという変数を指定すると、.ninja_logはそのディレクトリに代わりに保存される。
バージョン互換性
Available since Ninja 1.2.
Ninja のバージョンラベルは標準の major.minor.patch 形式で、後方互換性のない構文や動作の変更にはメジャーバージョンが、新しい動作にはマイナーバージョンが増加します。build.ninjaではninja_required_versionという変数を宣言し、生成されたファイルを使用するために必要な最小限のNinjaのバージョンを表明することができます。例えば
ninja_required_version = 1.1
ビルドファイルがNinja 1.1で導入された機能(おそらくプールシンタックス)に依存しており、ビルドにはNinja 1.1以上を使用しなければならないことを宣言しています。他のNinja変数と異なり、このバージョン要件はパース時に即座にチェックされるため、ビルドファイルの先頭に記述することが望ましい。
Ninjaのメジャーバージョンとninja_required_versionが一致しない場合は必ず警告を出す。メジャーバージョン変更はまだ出ていないので、どのような動作が要求されるかは予測しにくい。
C/C++のヘッダー依存性
C/C++のヘッダ依存関係(あるいは同様の動作をする他のビルド依存関係)を正しく取得するために、Ninjaはいくつかの特別な機能を備えています。
ヘッダの問題は、あるソースファイルが依存するファイルの完全なリストが、コンパイラによってのみ発見されることです。プリプロセッサの定義やインクルードパスが異なると、異なるファイルが使用されます。コンパイラの中には、ビルド中にこの情報を出すものがあり、Ninjaはそれを使って依存関係を完璧にすることができる。
考えてみてください。ファイルが一度もコンパイルされていない場合、とにかくビルドする必要があり、副次的にヘッダーの依存関係を生成します。もしファイルが後で変更された場合(どのヘッダに依存するかを変更するような場合でも)、その変更によって再構築が行われ、依存関係が最新に保たれます。
これらの特別な依存関係をロードする際、Ninjaはリストされた依存関係が欠落していてもエラーにならないように、暗黙のうちにビルドエッジを追加しています。これにより、ヘッダファイルを削除して再構築しても、入力の欠落でビルドが中断されることはない。
depファイル
gcc (および clang などの他のコンパイラ) は、Makefile の構文で依存性情報を出力することをサポートしています。(gccに限らず、この形式で依存関係を書けるコマンドなら何でも使えます)。
この情報をNinjaに取り込むには、協力が必要である。Ninja側では、ビルドのdepfile属性に、このデータが書き込まれるパスを指定する必要があります。(Ninjaは、コンパイラが出力するMakefile構文の限られたサブセットのみをサポートしています)。そして、コマンドは依存関係をdepfileのパスに書き込むことを知っていなければなりません。次の例のように使う。
rule cc
depfile = $out.d
command = gcc -MD -MF $out.d [other gcc flags here]
gccの-MDフラグはヘッダの依存性を出力するように指示し、-MFフラグはそれをどこに書くかを指示します。
deps
(Available since Ninja 1.3.)
大規模なプロジェクトでは(特にファイルシステムの遅いWindowsでは)、起動時にこれらの依存ファイルを読み込むと時間がかかることが判明しました。
Ninja 1.3では、依存関係を生成直後に処理し、同じ情報をコンパクトにしたものをNinja内部のデータベースに保存することができる。
Ninjaはこの処理を2つの形でサポートしています。
- deps = gcc は、gcc形式の依存関係をMakefileの形で出力することを指定します。上記の例にこれを追加すると、Ninjaはコンパイル終了後直ちにdepfileを処理し、.dファイル(これは一時的なものとしてしか使われない)を削除するようになります。
- deps = msvc は、Visual Studioのコンパイラの/showIncludesフラグによって生成される形式で、ツールがヘッダの依存性を出力することを指定します。簡単に言うと、このツールは特別にフォーマットされた行を標準出力に出力することを意味する。そして、Ninjaは表示された出力からこれらの行をフィルタリングします。depfile属性は必要ありませんが、ヘッダーファイルのパスの前にローカライズされた文字列を指定します。例えば msvc_deps_prefix = Note: including file: は英語のVisual Studioの場合です(デフォルト)。グローバルに定義する必要があります。
msvc_deps_prefix = Note: including file:
rule cc
deps = msvc
command = cl /showIncludes -c $in /Fo$out
include ディレクトリディレクティブが絶対パスを使用している場合、あなたの depfile は相対パスと絶対パスが混在した結果になることがあります。他のビルドルールによって使用されるパスは、正確に一致する必要があります。したがって、このような場合は相対パスを使用することが推奨されます。
プール
Available since Ninja 1.1.
プールでは、1つまたは複数のルールまたはエッジを割り当て、デフォルトの並列処理よりも厳しく制限された有限数の同時実行ジョブを実現できます。
これは、例えば、特定の高価なルール(巨大な実行ファイルのリンクステップなど)を制限したり、同時に実行するとパフォーマンスが低下することがわかっている特定のビルドステートメントを制限したりするのに便利です。
各プールは、ビルドファイルで指定される深さ変数を持っています。プールは、ルールまたはビルド文のいずれかでプール変数を使用して参照されます。
どのようなプールを指定しても、ninja はデフォルトの並列度やコマンドライン (-j) で指定されたジョブ数以上の同時ジョブを実行することはありません。
# No more than 4 links at a time.
pool link_pool
depth = 4
# No more than 1 heavy object at a time.
pool heavy_object_pool
depth = 1
rule link
...
pool = link_pool
rule cc
...
# The link_pool is used here. Only 4 links will run concurrently.
build foo.exe: link input.obj
# A build statement can be exempted from its rule's pool by setting an
# empty pool. This effectively puts the build statement back into the default
# pool, which has infinite depth.
build other.exe: link input.obj
pool =
# A build statement can specify a pool directly.
# Only one of these builds will run at a time.
build heavy_object1.obj: cc heavy_obj1.cc
pool = heavy_object_pool
build heavy_object2.obj: cc heavy_obj2.cc
pool = heavy_object_pool
コンソールプール
Available since Ninja 1.5.
このプールは、Ninjaに提供された標準入力、出力、エラーストリームに直接アクセスできるという特殊な性質を持っています。これは対話的なタスクや、テスト・スイートなどのコンソール上でステータスを更新するような長時間実行のタスクに有効であろう。
コンソールプール内のタスクが実行されている間、Ninjaの通常の出力(進捗状況や同時実行タスクからの出力など)は、そのタスクが完了するまでバッファリングされる。