プリコンパイル済みヘッダー ファイル
Visual Studio で新しいプロジェクトを作成すると、pch.h
という名前の "プリコンパイル済みヘッダー ファイル" がプロジェクトに追加されます。 (Visual Studio 2017 以前では、ファイルは stdafx.h
と呼ばれます)。ファイルの目的は、ビルド プロセスを高速化することです。 安定したヘッダー ファイル (たとえば <vector>
などの、標準ライブラリのヘッダー) はここに含まれています。 プリコンパイル済みヘッダーは、そのヘッダーまたはそこに含まれるファイルが変更された場合にのみコンパイルされます。 プロジェクトのソース コードにだけ変更を加えた場合、ビルド時にプリコンパイル済みヘッダーのコンパイルはスキップされます。
プリコンパイル済みヘッダーのコンパイラ オプションは /Y
。 プロジェクトのプロパティ ページでは、オプションは [構成プロパティ]>[C/C++]>[プリコンパイル済みヘッダー] にあります。 プリコンパイル済みヘッダーを使用しないことも選択でき、ヘッダー ファイル名と、出力ファイルの名前とパスを指定できます。
ビルドに長時間かかる大規模なプロジェクトの場合、カスタムのプリコンパイル済みファイルの作成を検討することをお勧めします。 Microsoft C および C++ コンパイラは、インライン コードを含む、C または C++ コードをプリコンパイルするためのオプションを提供します。 このパフォーマンス機能を使用して、安定したコードの本体をコンパイルし、コードのコンパイル済みの状態をファイルに格納します。さらに、後続のコンパイル中に、プリコンパイルされたコードと開発中のコードを結合できます。 安定したコードは再コンパイルの必要がないため、後の各コンパイルが高速化します。
プリコンパイル済みのコードは、特に次の場合、開発サイクル中のコンパイル時間の短縮に役立ちます。
頻繁には変更されない大規模なコード本体を常に使用している。
プログラムが複数のモジュールで構成され、そのすべてで、標準セットのインクルード ファイルと、同じコンパイル オプションを使用している。 この場合、すべてのインクルード ファイルを 1 つのプリコンパイル済みヘッダーにプリコンパイルできます。 インクルード ファイルを処理する新しい方法の詳細については、「 Compare ヘッダー ユニット、モジュール、プリコンパイル済みヘッダーを参照してください。
最初のコンパイル (プリコンパイル済みヘッダー ファイルが作成されるとき) では、後続のコンパイルより少し長く時間がかかります。 後続のコンパイルは、プリコンパイル済みコードを含めることで、より迅速に進めることができます。
C と C++ プログラムのどちらもプリコンパイルできます。 C++ プログラミングでは、クラス インターフェイス情報をヘッダー ファイルに分離するのが一般的です。 これらのヘッダー ファイルは、そのクラスを使用するプログラムに後で含めることができます。 これらのヘッダーをプリコンパイルすると、プログラムのコンパイルにかかる時間を短縮できます。
注意
各ソース ファイルで使用できるプリコンパイル済みヘッダー (.pch
) ファイルは 1 つだけですが、プロジェクトでは複数の .pch
ファイルを使用できます。
どのような C コードまたは C++ コードでもプリコンパイルできます。プリコンパイルするのはヘッダー ファイルだけに限定されません。
プリコンパイルには計画が必要ですが、単純なヘッダー ファイル以外のソース コードをプリコンパイルすると、はるかに高速なコンパイルが提供されます。
ソース ファイルで共通のヘッダー ファイル セットが使用されていることがわかっている場合、またはプリコンパイルにソース コードを含める場合は、コードをプリコンパイルします。
プリコンパイル済みヘッダーのオプションは、/Yc
(プリコンパイル済みヘッダー ファイルの作成) と /Yu
(プリコンパイル済みヘッダー ファイルの使用) です。 /Yc
は、プリコンパイル済みヘッダーを作成する場合に使用します。 省略可能な hdrstop
プラグマと共に使用すると、 /Yc
ヘッダー ファイルとソース コードの両方をプリコンパイルできます。 既存のコンパイルで既存のプリコンパイル済みヘッダーを使用するには、 /Yu
を選択します。 /Yc
オプションと/Yu
オプションで/Fp
を使用して、プリコンパイル済みヘッダーの別名を指定することもできます。
/Yu
および /Yc
のコンパイラ オプションのリファレンス記事では、開発環境でこの機能にアクセスする方法について説明します。
PCH ファイルには、コンピューター環境に関する情報とプログラムに関するメモリ アドレス情報が含まれているため、PCH ファイルは、それが作成されたコンピューター上でのみ使用してください。
/Yu
コンパイラ オプションを使用すると、使用する PCH ファイルを指定できます。
PCH ファイルを使用する場合、特に指定しない限り、コンパイラは PCH ファイルの作成時に有効であったのと同じコンパイル環境を想定します。 コンパイル環境には、コンパイラ オプション、プラグマなどが含まれます。 コンパイラでは、不整合が検出されると警告が発行され、可能な場合はその不整合が特定されます。 このような警告は、必ずしも PCH ファイルに問題があることを示しているわけではありません。競合が発生する可能性があることを警告するだけです。 PCH ファイルの一貫性の要件については、この後のセクションで説明します。
PCH ファイルを使用する場合、次のコンパイラ オプションによって不整合の警告がトリガーされることがあります。
プリプロセッサ (
/D
) オプションを使用して作成されたマクロは、PCH ファイルを作成したコンパイルと現在のコンパイルの間で同じでなければなりません。 定義された定数の状態はチェックされませんが、これらのマクロが変更されると、予測できない結果が生じる可能性があります。PCH ファイルは
/E
オプションおよび/EP
オプションでは機能しません。ブラウザー情報の生成 (
/FR
) オプションまたはローカル変数の除外 (/Fr
) オプションを使用して PCH ファイルを作成してからでないと、その PCH ファイルを使用する後続のコンパイルでこれらのオプションを使用できません。
PCH ファイルの作成時にこのオプションが有効になっている場合、その PCH ファイルを使用する後のコンパイルでデバッグ情報を使用できます。
PCH ファイルの作成時に C 7.0 互換 (/Z7
) オプションが有効になっていない場合、PCH ファイルと /Z7
を使用する後続のコンパイルで警告がトリガーされます。 デバッグ情報は現在の .obj
ファイルに配置され、PCH ファイルで定義されているローカル シンボルはデバッガーでは使用できません。
PCH ファイルには、その作成時に有効だったヘッダー インクルード パスに関する情報は含まれません。 PCH ファイルを使用する場合、コンパイラでは常に現在のコンパイルで指定されたヘッダー インクルード パスが使用されます。
プリコンパイル済みヘッダー ファイルの使用 (/Yu
) オプションを指定すると、コンパイラでは、プリコンパイルされるソース コードに現れるすべてのプリプロセッサ ディレクティブ (プラグマを含む) は無視されます。 このプリプロセッサ ディレクティブによって指定されるコンパイルは、プリコンパイル済みヘッダー ファイルの作成 (/Yc
) オプションで使用されるコンパイルと同じでなければなりません。
PCH ファイルの作成中に処理されるプラグマは、通常、後でその PCH ファイルと一緒に使用されるファイルに作用します。 comment
プラグマと message
プラグマは、コンパイルの残りの部分には作用しません。
次のプラグマは、PCH ファイル内のコードにのみ作用し、後で PCH ファイルを使用するコードには作用しません。
comment
linesize
message
page
pagesize
skip
subtitle
title
次のプラグマは、プリコンパイル済みヘッダーの一部として保持され、プリコンパイル済みヘッダーを使用するコンパイルの残りの部分に作用します。
alloc_text
auto_inline
check_stack
code_seg
data_seg
function
include_alias
init_seg
inline_depth
inline_recursion
intrinsic
optimize
pack
pointers_to_members
setlocale
vtordisp
warning
/Yc
または /Yu
を使用して作成されたプリコンパイル済みヘッダーを使用する場合、コンパイラでは、現在のコンパイル環境と PCH ファイルの作成時に存在していた環境が比較されます。 現在のコンパイルには必ず、(一貫性のあるコンパイラ オプション、プラグマなどを使用して) 前の環境と一致する環境を指定してください。 コンパイラでは、不整合が検出されると警告が発行され、可能な場合はその不整合が特定されます。 このような警告は、必ずしも PCH ファイルに問題があることを示しているわけではありません。競合が発生する可能性があることを警告するだけです。 この後のセクションでは、プリコンパイル済みヘッダーの一貫性の要件について説明します。
次の表に、プリコンパイル済みヘッダーを使用するときに不整合の警告がトリガーされる可能性のあるコンパイラ オプションを示します。
オプション | Name | Rule |
---|---|---|
/D |
定数とマクロの定義 | プリコンパイル済みヘッダーを作成したコンパイルと現在のコンパイルの間で同じでなければなりません。 定義済みの定数の状態はチェックされません。 ただし、変更された定数の値にファイルが依存している場合は予測できない結果が生じる可能性があります。 |
/E または /EP |
標準出力へのプリプロセッサ出力のコピー | プリコンパイル済みヘッダーは /E オプションまたは /EP オプションでは機能しません。 |
/Fr または /FR |
Microsoft ソース ブラウザー情報の生成 | /Fr オプションおよび /FR オプションを /Yu オプションで有効にするには、プリコンパイル済みヘッダーが作成されたときにもこれらが有効になっている必要があります。 プリコンパイル済みヘッダーを使用する後続のコンパイルでも、ソース ブラウザー情報が生成されます。 ブラウザー情報は 1 つの .sbr ファイルに配置され、CodeView 情報と同じ方法で他のファイルから参照されます。 ソース ブラウザー情報の配置をオーバーライドすることはできません。 |
/GA 、/GD 、/GE 、/Gw 、または /GW |
Windows プロトコル オプション | プリコンパイル済みヘッダーを作成したコンパイルと現在のコンパイルの間で同じでなければなりません。 これらのオプションが異なる場合、コンパイラは警告を出力します。 |
/Zi |
詳細なデバッグ情報の生成 | プリコンパイル済みヘッダーの作成時にこのオプションが有効になっている場合、プリコンパイルを使用する後続のコンパイルでそのデバッグ情報を使用できます。 プリコンパイル済みヘッダーの作成時に /Zi が有効になっていない場合、プリコンパイルおよび /Zi オプションを使用する後続のコンパイルで警告がトリガーされます。 デバッグ情報は現在のオブジェクト ファイルに配置され、プリコンパイル済みヘッダーで定義されているローカル シンボルはデバッガーでは使用できません。 |
注意
プリコンパイル済みヘッダー機能は、C および C++ ソース ファイルでの使用のみを目的としています。
前のセクションでは、プリコンパイル済みヘッダーの概要 (/Yc と /Yu、/Fp オプション、hdrstop プラグマ) を紹介しています。 このセクションでは、プロジェクトで手動プリコンパイル済みヘッダーのオプションを使用する方法について説明します。説明の最後に、サンプルのメイクファイルとそれによって管理されるコードを示します。
プロジェクトで手動プリコンパイル済みヘッダーのオプションを使用する別の方法として、Visual Studio の既定のセットアップ時に作成される MFC\SRC
ディレクトリにあるいずれかのメイクファイルを調べます。 これらのメイクファイルは、このセクションで説明する方法と同様のアプローチを取っています。 ここでは Microsoft Program Maintenance Utility (NMAKE) マクロがより活用され、ビルド プロセスをよりよく制御できます。
多くの場合、ソフトウェア プロジェクトのコード ベースは、複数の C または C++ ソース ファイル、オブジェクト ファイル、ライブラリ、ヘッダー ファイルに含まれています。 一般に、メイクファイルは、これらの要素の組み合わせを調整して 1 つの実行可能ファイルにします。 次の図は、プリコンパイル済みヘッダー ファイルを使用するメイクファイルの構造を示しています。 この図の NMAKE マクロ名とファイル名は、PCH 用の Sample makefile および PCH 用の Example コードで見つかったコード例と一致しています。
この図は、3 つの図式デバイスを使用して、ビルド プロセスのフローを示しています。 名前付きの四角形は、各ファイルまたはマクロを表します。3 つのマクロは、1 つ以上のファイルを表します。 網掛け領域は、各コンパイルまたはリンク アクションを表します。 矢印は、コンパイルまたはリンク プロセス中に結合されるファイルとマクロを示します。
プリコンパイル済みヘッダー ファイルを使用するメイクファイルの構造:
図は、CL /c /W3 /Yc$(BOUNDRY) applib.cpp myapp.cppへの '$(STABLEHDRS)' と '$(BOUNDRY)' のフィードを示しています。 その出力は $(STABLE です。PCH)。 次に、applib.cppと $(UNSTABLEHDRS) と $(STABLE)。PCH) は CL /c /w3 /Yu $(BOUNDRY) applib.cppにフィードされ、applib.objが生成されます。myapp.cpp、$(UNSTABLEHDR)、および $(STABLE)。PCH) は CL /c /w3 /Yu $(BOUNDRY) myapp.cppにフィードし、myapp.objを生成します。最後に、applib.objとmyapp.objは LINK /NOD ONERROR:NOEXE $(OBJS)、myapp、NUL、$(LIBS)、NUL によって結合され、myapp.exeが生成されます。
図を上から見ていくと、STABLEHDRS
と BOUNDRY
はいずれも NMAKE マクロであり、ここで、再コンパイルが必要でないと思われるファイルを一覧表示します。 これらのファイルが次のコマンド文字列によってコンパイルされるのは、
CL /c /W3 /Yc$(BOUNDRY) applib.cpp myapp.cpp
プリコンパイル済みヘッダー ファイル (STABLE.pch
) が存在しない場合、または 2 つのマクロに一覧表示されているファイルに変更を加えた場合のみです。 どちらの場合も、プリコンパイル済みヘッダー ファイルには、STABLEHDRS
マクロに一覧表示されているファイルのコードのみが含まれます。 BOUNDRY
マクロには、プリコンパイルする最後のファイルを示します。
これらのマクロに一覧表示するファイルは、ヘッダー ファイルか C または C++ ソース ファイルのいずれかです。 (1 つの PCH ファイルを C と C++ の両方のソースで使用することはできません)。 hdrstop
マクロを使用して、 BOUNDRY
ファイル内のある時点でプリコンパイルを停止できます。 詳細については、hdrstop
を参照してください。
図の次では、APPLIB.obj
は、最終的なアプリケーションで使用されるサポート コードを表します。 これは、APPLIB.cpp
、UNSTABLEHDRS
マクロに一覧表示されているファイル、プリコンパイル済みヘッダーのプリコンパイル済みコードから作成されます。
MYAPP.obj
は、最終的なアプリケーションを表します。 これは、MYAPP.cpp
、UNSTABLEHDRS
マクロに一覧表示されているファイル、プリコンパイル済みヘッダーのプリコンパイル済みコードから作成されます。
最後に、OBJS
マクロ (APPLIB.obj
と MYAPP.obj
) に一覧表示されるファイルをリンクして実行可能ファイル (MYAPP.EXE
) が作成されます。
次のメイクファイルでは、マクロと !IF
、!ELSE
、!ENDIF
制御フロー コマンド構造を使用して、プロジェクトへの適応を単純化します。
# Makefile : Illustrates the effective use of precompiled
# headers in a project
# Usage: NMAKE option
# option: DEBUG=[0|1]
# (DEBUG not defined is equivalent to DEBUG=0)
#
OBJS = myapp.obj applib.obj
# List all stable header files in the STABLEHDRS macro.
STABLEHDRS = stable.h another.h
# List the final header file to be precompiled here:
BOUNDRY = stable.h
# List header files under development here:
UNSTABLEHDRS = unstable.h
# List all compiler options common to both debug and final
# versions of your code here:
CLFLAGS = /c /W3
# List all linker options common to both debug and final
# versions of your code here:
LINKFLAGS = /nologo
!IF "$(DEBUG)" == "1"
CLFLAGS = /D_DEBUG $(CLFLAGS) /Od /Zi
LINKFLAGS = $(LINKFLAGS) /COD
LIBS = slibce
!ELSE
CLFLAGS = $(CLFLAGS) /Oselg /Gs
LINKFLAGS = $(LINKFLAGS)
LIBS = slibce
!ENDIF
myapp.exe: $(OBJS)
link $(LINKFLAGS) @<<
$(OBJS), myapp, NUL, $(LIBS), NUL;
<<
# Compile myapp
myapp.obj : myapp.cpp $(UNSTABLEHDRS) stable.pch
$(CPP) $(CLFLAGS) /Yu$(BOUNDRY) myapp.cpp
# Compile applib
applib.obj : applib.cpp $(UNSTABLEHDRS) stable.pch
$(CPP) $(CLFLAGS) /Yu$(BOUNDRY) applib.cpp
# Compile headers
stable.pch : $(STABLEHDRS)
$(CPP) $(CLFLAGS) /Yc$(BOUNDRY) applib.cpp myapp.cpp
「ビルド プロセスでの PCH ファイル」の図「プリコンパイル済みヘッダー ファイルを使用するメイクファイルの構造」に示されている STABLEHDRS
、BOUNDRY
、UNSTABLEHDRS
マクロとは別に、このメイクファイルには CLFLAGS
マクロと LINKFLAGS
マクロが用意されています。 これらのマクロを使用して、アプリケーションの実行可能ファイルのデバッグ バージョンと最終バージョンのどちらをビルドする場合でも適用される、コンパイラとリンカーのオプションを一覧表示する必要があります。 また、プロジェクトに必要なライブラリを一覧表示する LIBS
マクロもあります。
さらに、このメイクファイルでは、!IF
、!ELSE
、!ENDIF
を使用して、NMAKE コマンド ラインで DEBUG
シンボルを定義するかどうかも検出されます。
NMAKE DEBUG=[1|0]
この機能により、プログラムの開発中バージョンと最終バージョンで同じメイクファイルを使用できます。 最終バージョンでは DEBUG=0
を使用します。 次のコマンド ラインは同等のものです。
NMAKE
NMAKE DEBUG=0
メイクファイルの詳細については、「NMAKE リファレンス」を参照してください。 また、「MSVC コンパイラ オプション」と「MSVC リンカー オプション」も参照してください。
次のソース ファイルは、「ビルド プロセスでの PCH ファイル」と「PCH のサンプル メイクファイル」で説明されているメイクファイルで使用されます。 コメントには重要な情報が含まれています。
ソース ファイル ANOTHER.H
:
// ANOTHER.H : Contains the interface to code that is not
// likely to change.
//
#ifndef __ANOTHER_H
#define __ANOTHER_H
#include<iostream>
void savemoretime( void );
#endif // __ANOTHER_H
ソース ファイル STABLE.H
:
// STABLE.H : Contains the interface to code that is not likely
// to change. List code that is likely to change
// in the makefile's STABLEHDRS macro.
//
#ifndef __STABLE_H
#define __STABLE_H
#include<iostream>
void savetime( void );
#endif // __STABLE_H
ソース ファイル UNSTABLE.H
:
// UNSTABLE.H : Contains the interface to code that is
// likely to change. As the code in a header
// file becomes stable, remove the header file
// from the makefile's UNSTABLEHDR macro and list
// it in the STABLEHDRS macro.
//
#ifndef __UNSTABLE_H
#define __UNSTABLE_H
#include<iostream>
void notstable( void );
#endif // __UNSTABLE_H
ソース ファイル APPLIB.CPP
:
// APPLIB.CPP : This file contains the code that implements
// the interface code declared in the header
// files STABLE.H, ANOTHER.H, and UNSTABLE.H.
//
#include"another.h"
#include"stable.h"
#include"unstable.h"
using namespace std;
// The following code represents code that is deemed stable and
// not likely to change. The associated interface code is
// precompiled. In this example, the header files STABLE.H and
// ANOTHER.H are precompiled.
void savetime( void )
{ cout << "Why recompile stable code?\n"; }
void savemoretime( void )
{ cout << "Why, indeed?\n\n"; }
// The following code represents code that is still under
// development. The associated header file is not precompiled.
void notstable( void )
{ cout << "Unstable code requires"
<< " frequent recompilation.\n";
}
ソース ファイル MYAPP.CPP
:
// MYAPP.CPP : Sample application
// All precompiled code other than the file listed
// in the makefile's BOUNDRY macro (stable.h in
// this example) must be included before the file
// listed in the BOUNDRY macro. Unstable code must
// be included after the precompiled code.
//
#include"another.h"
#include"stable.h"
#include"unstable.h"
int main( void )
{
savetime();
savemoretime();
notstable();
}
ヘッダー ユニット、モジュール、プリコンパイル済みヘッダーを比較する
C/C++ ビルドのリファレンス
MSVC コンパイラ オプション C++ でのモジュールのオーバービュー
チュートリアル: モジュールを使用して C++ 標準ライブラリ (STL) をインポートする
チュートリアル: Visual C++ プロジェクトでヘッダー ユニットをビルドしてインポートする
チュートリアル: STL ライブラリをヘッダ ーユニットとしてインポートする