GNU make のビルド高速化|サフィックスルール

シェアする

ビルド時間は短ければ短いほどいいのは、エンジニアなら誰しも納得いただけるところと思います。仮にビルド時間を1分短縮できれば、ビルド回数×開発者人数×単価(円)がそのまま経費削減できます。大規模プロジェクトだと、これは結構効いてきますよね。開発者自身にとってもビルド待ちは面倒ですし。

ということで、今回は GNU make 環境下でのビルド高速化についてお伝えします。と言っても、ccache のように劇的な効果をもたらすツールはメジャーかなと思いますので、今回は、そんなに効果はないけど簡単にかつちょっとだけビルドが速くなる、ニッチなローリスクローリターンな方法をご紹介します。規模やMakefileの書き方にもよるかと思いますが、運が良ければ数分の作業で数%のビルド時間削減ができるかも、です。なんにせよほぼデメリットはないのでやって損はないでしょう。

やり方は簡単です。 Makefile の先頭行に下記の1行を追加してください。

 .SUFFIXES:

上記だけでもOKなんですが、 GNU make ver3 の中には上記のコードがうまく働かない場合があるようですので、念押しでに–no-builtin-rulesオプションを指定してください。意味は上記と同じです。

*2016-08-29 修正*
–no-builtin-rules を引数で足すのではなく、Makefile に下記のように書いたほうが楽ですね!

 MAKEFLAGS += --no-builtin-rules

たったこれだけで終わりです。 time コマンドなどで実行時間を計測してみてください。変わらないか、ほんのわずか速くなっているかと思います。

原理を簡単に説明します。別に知らなくても困らない知識ですので、興味のある人だけ読んでいただければ幸いです。
今回の手法は、暗黙のサフィックスルールを無効化するための記述です。例えば main.o を作れ!と指示されると、make は内部に持っているデータベースのデフォルト値を使って、 main.v, main.F, main.web などなどを勝手に探し回ります。下記のようにちゃんとパターンルールを指定していても、なぜか探し回ります。

 %.o : %.c

そのため、今回ご紹介した方法で暗黙のサフィックスルールを抑止してあげます。すると、明示的に指定していないような無駄なルールの探索(.v やら .Fやら)をしなくなるので多少高速化が見込めます。

ちなみに、今回の対応を行うとログの行数が下記のように数割に減りますね。

$ make -d 2> /dev/null  | wc -c 
   63670
$ make -d  2> /dev/null  | wc -c 
    1183

デフォルトのままの時のログを一部抜粋します。よく分からない拡張子まで探索に行きますねぇ。

Trying pattern rule with stem `makefile'.
Rejecting impossible implicit prerequisite `makefile.c'.
Trying pattern rule with stem `makefile'.
Rejecting impossible implicit prerequisite `makefile.cc'.
Trying pattern rule with stem `makefile'.
Rejecting impossible implicit prerequisite `makefile.C'.
Trying pattern rule with stem `makefile'.
Rejecting impossible implicit prerequisite `makefile.cpp'.
Trying pattern rule with stem `makefile'.
Rejecting impossible implicit prerequisite `makefile.p'.
Trying pattern rule with stem `makefile'.
Rejecting impossible implicit prerequisite `makefile.f'.
Trying pattern rule with stem `makefile'.
Rejecting impossible implicit prerequisite `makefile.F'.
Trying pattern rule with stem `makefile'.
Rejecting impossible implicit prerequisite `makefile.m'.
Trying pattern rule with stem `makefile'.
Rejecting impossible implicit prerequisite `makefile.r'.
Trying pattern rule with stem `makefile'.
Rejecting impossible implicit prerequisite `makefile.s'.
Trying pattern rule with stem `makefile'.
Rejecting impossible implicit prerequisite `makefile.S'.
Trying pattern rule with stem `makefile'.
Rejecting impossible implicit prerequisite `makefile.mod'.
Trying pattern rule with stem `makefile'.

以上です。多少でもお役に立てば。
ccache については、リクエストあればそのうち書くかも。