2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

.a ファイルのビルドを makefile と build.ninja で比較。 make から ninja への移行検討メモ

Posted at

これは何

GNU make から ninja に移行を検討中のメモです。

想定読者

makefile を自分でかける人
.PHONY: clean を毎回書くのに飽き飽きした人
素の make の動作が遅いなぁと思う人
ninja 向けのメタビルドツールを作りたい人

ninja って何?

https://mattn.kaoriya.net/software/ninja/20140121141906.htm こことか読んでください。

libfoo.a のビルドを比較

a.c, b.c, c.c の3ファイルから構成される libfoo.a をビルドする例を makefilebuild.ninja で示します。
実行ファイルのビルドについては 前回を見てください。

今回は、ソースファイルの置き場と、ビルドの作業領域が別ディレクトリとしています。下記のようなファイル配置です。

./
|-- src/a.c
|-- src/b.c
|-- src/c.c
|-- build/makefile
`-- build/build.ninja

make する場合は、 make -C build を行います。 ninja する場合は ninja -C build となります。

makefile の場合

makefile の例を示します。デフォルトルールを全力で利用した場合、下記のようになると思います。
並列ビルドを行うと、 libfoo.a が破壊されるので実用性は皆無です。デフォルトルールを使わない方が良いでしょう。

makefile
CFLAGS = -Wall -Os -MMD -MP
CPPFLAGS = -DNDEBUG

vpath %.c ../src

.PHONY:clean
libfoo.a: libfoo.a(a.o) libfoo.a(b.o) libfoo.a(c.o)
libfoo.a(a.o):
libfoo.a(b.o):
libfoo.a(c.o):

clean:
	$(RM) libfoo.a a.o a.d b.o b.d c.o c.d
-include a.d
-include b.d
-include c.d

相変わらず、clean ルールの記述が面倒くさい。
初回 make は、中間ファイルが削除されるので、ちょっと気持ちがいい。
しかし、このルール記述だと毎度 ar が走るので、イマイチです。

ninja.build for gcc の場合

上記 makefile と同等の build.ninja を示します。 ninja は、暗黙のルールや変数を持ちません。
そのため、すべて明示的に定義しています。

build.ninja
cc = cc
cflags = -Wall -Os
cppflags = -DNDEBUG
ar = ar
arflags = rv

rule compile
     deps    = gcc
     depfile = $out.d
     command = $cc -MMD -MP -MF $out.d $cflags $cppflags $target_arch -c -o $out $in

rule archive
     command = $ar $arflags $out $in

build libfoo.a: archive a.o b.o c.o
build a.o: compile ../src/a.c
build b.o: compile ../src/b.c
build c.o: compile ../src/c.c

今回は、makefile と記述量があまり変わりません。変わらない理由は、makefile で変数展開を駆使していないからですが。。。
rule文とbuild文を明確に分けて記述するだけなので、読む側からは理解しやすいです。
makefile だと、サフィックスルールの記述方法が2種類あって、どっちがどうだったとか、ライブラリ用の書き方がどうだったかとかで混乱します。
そして、clean がビルトインされているのがうれしい。

感想

make は暗黙ルールを使わないと負けた気がして、無理矢理使ってしまいがちです。私だけかもしれませんが。
とは言え、暗黙ルールと暗黙の変数を使用しておかないと、環境変数で CLFAGSCC をオーバーライドしたりできなくなってしまうので、使わないとダサい makefile になっちゃいます。
暗黙ルールに従った makefile であれば、 gcc から clang に変えたければ export CC=clang してから make すれば良いので便利。クロスコンパイルしたければ、export CC=arm-linux-gcc してから make すれば OK だったりして便利。
といっても、こんな簡単にいかないから autotools や cmake が流行っている訳で。

思い返すと、 makefile を初めて書いたとき、build.ninja のように全てのルールと依存関係を記述していた。慣れてきて、暗黙ルールを駆使して記述量が減ることに喜んでいました。しかしなぁ、全部書くのと機能に違いが無いんだから、書きゃいいよなぁ。昔と違って、エディタもPCリソースも豊かなんだし。ということで、ninja がいいと思います。

参考リンク

The Ninja build system
Static library built-in rule in GNU make

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?