gccのプリコンパイル済みヘッダ

昨日の続き。

gccのプリコンパイル済みヘッダ(PCH)がかなり速いことに気づいたけど、日本語の資料が少ないので本家のマニュアルを読んだ。結構複雑だったから下にメモしておく。

作り方

foo.hのプリコンパイル済みヘッダを作る場合、普通にコンパイルするように

$ gcc foo.h

とするとfoo.h.gchができる。完成。ヘッダを認識しない場合は-xオプションで指定すると良いみたい。

使い方

PCHを使いたいコードからfoo.hをインクルードするとき、条件が満たされた場合、自動的にPCHが使用される。条件は以下の通り。

foo.h.gchがサーチされること

gccは#include "foo.h"を発見すると、サーチパスのディレクトリごとにfoo.h.gchを探した後でfoo.hを探す。foo.h.gchとfoo.hは同じディレクトリに無くてもかまわない。また、"foo.h.gchディレクトリ"を見つけた場合、その中の全てのファイルの中から使用可能なもの使う。このとき、ディレクトリの中の探す順番は決まっていない。

基本的な制限
  • コンパイル単位に付きPCHは1つまで。
  • PCHのインクルード前にCのトークンが表れてはならない。プリプロセッサは使えるので、インクルードした先でPCHのインクルードをすることも可能。
  • PCHと使用側のプログラムは同じ言語であること。CとC++でもダメ。
  • 同様に、コンパイラは同じバイナリであること。
  • PCHのインクルード前に定義されたマクロは、PCHのコンパイル時にも同じ方法で定義されているか、PCHに何の影響も与えないものであること。-Dオプションと#includeだけでなく、-Oや-Wdeprecatedなどもマクロを定義することに注意。
コンパイラオプションについて

基本的に、PCHと使用側で違うオプションが指定された場合、それらが混ざった動作になる。

  • PCHが-gや類似のデバッグオプション付きでコンパイルされている場合、それら無しで使用側のコードをコンパイルできる。その逆はできない。
  • -mオプションは通常同じでなければならない。
  • その他にいくつか同じでなければならないオプションがあるが、どのオプションを変えても大丈夫かは今のところはっきりしていない。

まとめ

foo.h.gchディレクトリの中にコンパイラオプションだけを変えたPCHを入れておけば、使用側のオプションによって自動的にマッチするものを選んでくれるので便利。ただし、-gや-pgの有無だけが違うものを置いてしまうとどっちが使われるか分からないので、「-g -pgと-DNDEBUG」みたいに片方しかマッチしないように工夫すると良いかも。