インクリメンタルビルドのための依存解析 #25

公開日: 2012-02-23


前回に続きビルドの話。C/C++のプログラムをインクリメンタルビルド(差分ビルド)するためにはヘッダファイルに基づいた依存解析が必要だ。foo.h を変更したらそれを #include しているすべての .c/cc/cpp ファイルをビルドし直す必要がある。foo.h で宣言、定義されている関数や構造体が変わったら、そのクライアントコードがすべて影響を受けるからだ。

で、この依存性を手で書くのは手間だし間違いやすい。そこで、自動生成しようという話になるのだが、ヘッダファイルは別のヘッダファイルから間接的に読み込まれることがってこれが意外と難しい。

こういうことは、プリプロセッサにやってもらうのがいいんじゃないだろうか。ということで、gcc には -M, -MM, -MMD などといったオプションがあり、これを指定すると foo.o を作るには foo.cc, foo.h, bar.h が必要だよという依存情報をMakefile のフォーマットで出力してくれる。この情報があれば、インクリメンタルビルドができる。

が、この依存解析をいつやればいいかは自明ではない。一番単純なのは、ファイルを追加削除したときに、手動で依存解析を走らせる方法だ。前回紹介した GYPはこの方法を採用している。

automakeはこれを自動化していて Makefile.am を変更すると、次に make を実行したときに依存解析が自動的に走る。SCons も自動で、その上 gcc -Mなどを使わず自力で依存解析をする。が、これが遅くて、規模の大きいソフトウェアでは問題になる。[1]

自動の方がいいような気がするが、ファイルの追加削除はそれほど多く無いし、下手に自動化してビルドの複雑性が増える(はまりポイントが増える)より、手動でやった方がいい、というのはひとつの見識だと思う。

試しに、Chromium の中で一番依存が多いファイルを調べてみたら WebKit の中の third_party/WebKit/Source/WebKit/chromium/src/WebViewImpl.cpp がそれで、852個のヘッダファイルに依存していた。ブラウザというのはやはり複雑なソフトウェアだ。

[1] http://www.electric-cloud.com/blog/2010/07/21/a-second-look-at-scons-performance/

Satoru Takabayashi