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

概要

各 C++ コンパイラの 「プリコンパイル済みヘッダ」の考え方について簡単に説明します。 引き合いに出すコンパイラは次のものです。

なお記事中で各コンパイラを略記する時は、 列挙した順に VC6、VC7、GCC、DMC とします。

プリコンパイル済みヘッダとは

大規模なプロジェクトや既存の巨大なライブラリを使う場合、 各ソースファイルには大量のヘッダファイルがインクルードされます。 プリコンパイル済みヘッダとは、 このインクルードする大量の「ヘッダファイル」を文字通り先にコンパイルしておき ソースのコンパイル時間を減らすために作るものです。

コンパイラごとの考え方

Visual C++ 6.0 / .NET 2003

Visual C++ はプリコンパイル済みヘッダを コンパイル単位(ソースファイル)を基準に考えます。 やや難解な仕組みになっていますので順を追って使い方を説明します。

まずコンパイラにはプリコンパイル済みヘッダとして使うヘッダファイル名 (仮に bighead.h とする)を指定します。 するとコンパイラは、 各ソースファイルを先頭から bighead.h をインクルードする行までコンパイルして拡張子 .pch のファイルに保存します。 これが「プリコンパイル済みヘッダ」ファイルです。 この後コンパイラは 各ソースファイル中の bighead.h をインクルードする行までを「無視」します。 そしてその行より後だけコンパイルし、プリコンパイル済みヘッダとリンクします。 こうすると全ソースファイルの bighead.h をインクルードする行までの部分に関して bighead.pch を使い回しできます。 したがって、コンパイル時間を短縮できます。

この方式では基本的に、 各ソースファイル(の頭の方)には必ず プリコンパイル済みヘッダに指定したファイルがインクルードされている 必要があります。オプションを与えれば色々と細かい設定ができるのですが、 Application Wizard で作った MFC プロジェクトに 外部のソースファイルを追加すると次のようなエラーが発生するのは有名な話です。

fatal error C1010: プリコンパイル済みヘッダーの検索中に予期しない EOF を検出しました。

有名なエラーですね(苦笑)。 これは、Visual C++ のプリコンパイル済みヘッダ機能が こういう考えでできているために発生するものなんですね。

GNU C++

GCC のプリコンパイル済みヘッダの考え方は非常にシンプルで、 文字通りヘッダファイルを「あらかじめコンパイルしておく」というものです。

例として非常に大きな bighead.h (言語はC++)というヘッダファイルがあった場合、 次のようなコマンドを実行します。

g++ bighead.h

すると bighead.h.gch というファイルが生成されます。 これが GCC のプリコンパイル済みヘッダファイルです。 この .gch ファイルを生成した状態で、 bighead.h をインクルードするソースファイルをコンパイルすると、 bighead.h の部分を再び解釈せずに解釈済みの bighead.h.gch を使います。 この結果、コンパイル時間を短縮できます。

Digital Mars C++

DMC のプリコンパイル済みヘッダの考え方は GCC のそれと同じです。

例として非常に大きな bighead.h (言語はC++)というヘッダファイルがあった場合、 次のようなコマンドを実行します。

dmc -cpp -HF bighead.h

DMC の場合、標準で生成されるプリコンパイル済みヘッダファイルは bighead.sym という名前になります。 基本的にその他は GCC と同じだと思います。 ・・・細かく検証したわけではありませんので憶測ですが(苦笑)。

後書き

GCC や DMC の方式はシンプルで自然で分かりやすく扱いやすいと思います。 一方 Visual C++ のプリコンパイル済みヘッダの考え方は 柔軟に使おうとするとオプションが非常に複雑になり、 分かりにくく扱いにくいと思います。