こちらでは、大きなC++プロジェクト開発でビルド時間の短縮に有効な「プリコンパイル済みヘッダー」の意味と、Visual Studioからの設定方法を説明していきます。
あまり設定する頻度は多くないが故に忘れやすい、でも新規プロジェクトを作るときなど使うことは確実にあるので、ここでまとめておきます。
プリコンパイル済みヘッダーの意味
プリコンパイル済みヘッダーはそもそもなんのために使うのかというと、
- 含まれるヘッダーはまとめてコンパイル済み扱いとなり、次のビルドでもコンパイル済みとして利用可能(変更があったら再コンパイル)
- よく使うヘッダーファイルをまとめて半自動的にincludeできる
といったことが目的(メリット)です。
1つめは、その名の通りプリコンパイル済み(事前コンパイル済み)とすることで、再度コンパイルしなくよくなり、コンパイル時間の省略、すなわちビルド時間の短縮が可能、ということです。
2つめは、よく使う#include <vector>
などといったincludeをいちいち書かなくてよくなり、コード記述の省略が可能、ということです。
このメリットをみて短絡的に考えると、なんでもプリコンパイル済みヘッダーに含めたほうがいいんじゃない?なんて思うこともありますが、当然含まれるヘッダーファイルに変更があった場合は、再コンパイルが必要なので、変更が多いと1つめのメリット(再コンパイル不要化)が失われます。
かといって、全く変更が起きないヘッダー(stdライブラリ等)のみを含めるべきか、というとそうでもありません。
独自定義のヘッダーでも、便利関数や、マクロ、using定義など、多くの箇所で使うコードは自動的に使えるようになっていたほうが実装もはかどりますね。
ですので、何をプリコンパイル済みヘッダー煮含めるかは、そのヘッダーの内容がプロジェクト全体にとって利用頻度が高く有益かと、変更頻度が比較的少ないか、のバランスを含めて決める、ということになります。
Visual C++ 空のプロジェクトからの設定
プロジェクト作成ウィザードで空のプロジェクトとして作成した場合の設定方法です。
1.pch.hとpch.cppをプロジェクトに追加
プリコンパイル済みヘッダーの名前は自由ですが、stdafx.h
かpch.h
が多いです。ここではpch.h
で作成していきます。
プリコンパイル済みヘッダーは後述過程でもでてきますが「プリコンパイル済みヘッダー作成」の設定のために、cppファイルも追加します。
pch.hにはプリコンパイル済みに含めるヘッダーを記述、pch.cppは空のままで大丈夫です。
2.プロジェクトにプリコンパイル済みヘッダー利用設定
プロジェクトを右クリックしたプロパティで、
[構成プロパティ]→[C/C++]→[プリコンパイル済みヘッダー]の項目で
- 「プリコンパイル済みヘッダー」を「使用(/Yu)」
- 「プリコンパイル済みヘッダーファイル」を「pch.h」
と設定します。
3.プリコンパイル済みヘッダーを作成する設定
ここで空でなんのためにあるのか謎だったpch.cpp
を使って、プリコンパイル済みヘッダーの作成設定をします。
pch.cppファイルを右クリックしたプロパティで、
[構成プロパティ]→[C/C++]→[プリコンパイル済みヘッダー]の項目で
- 「プリコンパイル済みヘッダー」を「作成(/Yc)」
と設定します。
こうすることで、pch.h
をプリコンパイル済みヘッダーとして作成するという設定になります。
2の「利用設定」では作成に関する設定にはなっておらず、cppファイルから設定する必要がありこのような手順となります。
↓要確認
ちなみにcppファイルであればよいので、pch.cppじゃなくても可能には可能ですが、わかりやすさのために専用のcppファイルを追加するのが通常です。
4.pch.hを自動的にincludeされるようにする
最後に、作成されるようになったプリコンパイル済みヘッダーを自動的に、各ファイルがinclude済みとなるように設定します。
プロジェクトを右クリックしたプロパティで、
[構成プロパティ]→[C/C++]→[詳細設定]の項目で
- 「必ずインクルードされるファイル」にpch.hを追加
と設定します。
これで#include pch.h
と書かずとも各ファイルがpch.hをinclude済みとして実装することが可能です。
ちなみに、この設定は自動的にincludeしてくれるものなので、設定を省略して、必要なファイルにだけに#include pch.h
を記述していっても使えます。
ただ、通常はプリコンパイル済みヘッダーの内容は、多くのファイルで使う変更の少ない内容、であるためどこからでも使えるようになっている前提で実装を進められるよう、自動include設定にします。
プリコンパイル済みヘッダーに含める内容の指針
冒頭で挙げたプリコンパイル済みヘッダーの意味・特徴を踏まえて、プリコンパイル済みヘッダーには何を含めるべきなのでしょう?
プリコンパイル済みヘッダーに記述して間違いないものに、おおよそ以下のようなものが挙げられます。
- よく使うライブラリのヘッダー(std、boost、DirectX等)
- よく使うマクロ
- グローバルに参照する変更が少ない定数、enum
- グローバルに参照するusing、typedef
- よく参照されそうな実装class、structの前方宣言
「よく使うライブラリのヘッダー」は、プリコンパイル済みヘッダーの役割そのもので、多く使われるかつ変更が少ない(外部ライブラリなど)ものは、含めていきたいところ(vectorやmathなど)。
それ以外の4つに関しては、当然「多く使われるかつ変更が少ない」前提でもありますが、加えて「コンパイル時間にほとんど影響を与えない」であろうことも、含める大きな要因です。
classや関数の宣言・定義などのように構文解析や依存関係の解決がほとんどないので、コンパイル時間の負荷が少なく、書いておくだけ書いておいて損はないような項目となります。
特にclass、structの前方宣言などが書いてある前提になると、どこの実装でも前方宣言をすることを気にしなくて良くなり、実装が手軽になったりします。
コメント
[…] Visual StudioでC++プリコンパイル済みヘッダーの設定方法 […]