ninja build tools使い方メモ

Chromeビルドでも使われてるらしい高速なビルドツールninjaのメモ

前置き

デザインデータとかアセット関連の変換環境構築はあまり情報がないのでいろいろ大変。

アセットデータの変換はソースコードと同様に

 入力→出力

の関係なのでソースコードビルドツールが転用できるけど、記述がかなり複雑になりがち。

また、手順も複雑になることが多く多段別ルールで実行させたりしないといけなかったりする。

 

Make, OMake. SCons等様々なビルドツールがあるけど、どれも共通して高機能で重い!

アセットデータの複雑さに対応できるのはいいけど、複雑さに引きずられて設定ファイル解析時間がかなり伸びてしまう。

 ※OMakeだとビルド時間5分のうち半分はOMakefile解析に費していることもある!

 

ninjaの思想はビルドツールアセンブラらしい。

高機能なビルドツールで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 hoge

  command = $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

使えない書式①

windows絶対パス指定は相性が悪いことが多い。

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環境だとファイルパス指定とかで結構怒られる