ninja build tools使い方メモ
Chromeビルドでも使われてるらしい高速なビルドツールninjaのメモ
前置き
デザインデータとかアセット関連の変換環境構築はあまり情報がないのでいろいろ大変。
アセットデータの変換はソースコードと同様に
入力→出力
の関係なのでソースコードビルドツールが転用できるけど、記述がかなり複雑になりがち。
また、手順も複雑になることが多く多段別ルールで実行させたりしないといけなかったりする。
Make, OMake. SCons等様々なビルドツールがあるけど、どれも共通して高機能で重い!
アセットデータの複雑さに対応できるのはいいけど、複雑さに引きずられて設定ファイル解析時間がかなり伸びてしまう。
※OMakeだとビルド時間5分のうち半分はOMakefile解析に費していることもある!
高機能なビルドツールでninja設定ファイルを生成し、リビルドはninjaで高速に行う、という手順と相性がよさげ。
ということで、アセットデータの複雑さを高機能ビルドツールで解析して、解析結果はninjaに吐くという流れが良く見える。
セットアップ
ninjaの導入はとても簡単
https://github.com/martine/ninja/releases
で各環境向けに公開されているので、好きなのをとってくればすぐ動く
実行
デフォルトではbuild.ninjaがあればビルドできる。
$ ./ninja.exe
設定ファイルを指定したい場合は
$ ./ninja.exe -f hoge.ninja
と-fオプションで指定する。
書式
#コメントは接頭辞#をつければよい
#変数定義
cmd1 = touch
cmd2 = cp
#入力に応じたルール記述 rule ルール名
rule test1
#ルール実行時に出力されるルール説明(無くてもよい
description = touch $out
#ルールに応じて実行されるコマンド
command = $cmd1 $out
rule test2
description = cp from $in to $out
command = $cmd2 $in $out
#依存関係記述 build 出力: 実行したいルール名 入力
build hoge.txt: test1
build fuga.txt: test2 hoge.txt
#ルール指定がない場合に処理されるデフォルトルールの指定
default fuga.txt
初回実行結果は以下のとおり
$ tools/ninja.exe
[1/2] touch hoge.txt
[2/2] cp from hoge.txt to fuga.txt
二回目実行結果は以下のとおり
$ tools/ninja.exe
ninja: no work to do.
依存関係解析速い。超速い。0.1秒で依存解析解決して実行に移ってしまう。
もうちょっと細かい書式
複数ある入力ファイル、出力ファイルの依存記述方法
rule hogecommand = $cmd $in $out
build output1 output2: hoge input1 input2
単純にbuild行出力/入力ファイル欄に複数ファイルを羅列すれば良い。
$output = output1 output2
$in = input1 input2
のように扱われる
子ディレクトリもまとめてビルド
他のninja設定ファイルを読み込むにはsubninja, includeで指定する
subninja sub/build.ninja
#もしくは
include sub/build.ninja
subninjaはスコープが分かれるので、subninjaしたbuild.ninjaのスコープに影響を与えない。includeはincludeしたスコープに影響を与えるので注意!
subninjaしたときはsub1/build.ninja, sub2/build.ninjaとそれぞれに同名ルール、同名変数があったとしても干渉しないので基本subninjaしたほうがよいかも。
includeはグローバルな設定読み込みなどに使うとよいかも。
サブディレクトリのファイルを読み込むことができるが、subninjaされたbuild.ninja内のカレントディレクトリがどこなのかは調べ中。多分実行ディレクトリのまま?
ファイルパスは基本的に絶対パスで記述したほうがよさげっぽい
手元の実験ではOMakeで.SUBDIRSしながら.ninjaファイルを生成し、
別途各.ninjaをsubninjaするファイルを生成してみた。
$cat OMakefile
#各OMakefileで.ninjaを生成
.SUBDIR: subdir
#生成された.buildを収集して呼び出し元build.ninja生成
ninja = $(file build.ninja)
echo $"###" > $(ninja)
foreach(f, $(find . -name *.ninja))
echo $"subninja $f" >> $(ninja)
細かいninjaに分けるよりは1ファイルにまとめてしまったほうが楽な気がする
ruleで実行されるコマンドにパラメータを渡す
rule内のcommadには変数を使うことができる。
rule hoge
command = $cmd $infile $outfile
であれば以下のように変数を渡すことができる
cmd = cp
rule hoge
command = $cmd $infile $outfile
build test.txt: hoge in.txt
#buildスコープの中で変数指定が可能
infile = in.txt
outfile = test.txt
複数コマンドを実行
1ファイルを生成する際、複数コマンド実行したいことがある
ninjaのbuild.ninjaを見た感じ、bashのコマンド連結&&を使って
複数コマンド実行できるように見えるがWindows環境では怒られてしまった
rule hoge
command = $cmd1 && $cmd2
複雑なコマンドになるなら別batファイルに分けたほうが幸せになれそう
$ cat cmd.bat
> cmd1.exe
> cmd2.exe
$cat build.ninja
> rule hoge
> command = cmd.bat
使えない書式①
build c:\hoge\sample: ruleName input.txt
だと:でエラーになる。
dir = c:\huga
build $dir\sample: ruleName input.txt
だと怒られない。
使えない書式②
build行の入力ファイルを1行に多数並べるとエラーになる
$で行結合ができるのでなるべく1行1ファイルで書くほうがよい
build out.txt: hoge in1.txt $
in2.txt $
in3.txt
infile = fuga.txt
細かい書式の例はgithubからninjaをもらって
python configure.py
してbuild.ninjaを参照するといい感じ
Linux環境で動かすほうがいろいろ楽っぽい
Windows環境だとファイルパス指定とかで結構怒られる