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

Visual Studio で新しいプロジェクトを作成すると、pch.h という名前の "プリコンパイル済みヘッダー ファイル" がプロジェクトに追加されます。 (Visual Studio 2017 以前では、ファイルは .) と呼ばれます stdafx.h。ファイルの目的は、ビルド プロセスを高速化することです。 安定したヘッダー ファイル (たとえば <vector> などの、標準ライブラリのヘッダー) はここに含まれています。 プリコンパイル済みヘッダーは、そのヘッダーまたはそこに含まれるファイルが変更された場合にのみコンパイルされます。 プロジェクトのソース コードにだけ変更を加えた場合、ビルド時にプリコンパイル済みヘッダーのコンパイルはスキップされます。

プリコンパイル済みヘッダーのコンパイラ オプションは次のとおりです /Y。 プロジェクトのプロパティ ページでは、オプションは [構成プロパティ]>[C/C++]>[プリコンパイル済みヘッダー] にあります。 プリコンパイル済みヘッダーを使用しないことも選択でき、ヘッダー ファイル名と、出力ファイルの名前とパスを指定できます。

カスタムのプリコンパイル済みコード

ビルドに長時間かかる大規模なプロジェクトの場合、カスタムのプリコンパイル済みファイルの作成を検討することをお勧めします。 Microsoft C および C++ コンパイラは、インライン コードを含む、C または C++ コードをプリコンパイルするためのオプションを提供します。 このパフォーマンス機能を使用して、安定したコードの本体をコンパイルし、コードのコンパイル済みの状態をファイルに格納します。さらに、後続のコンパイル中に、プリコンパイルされたコードと開発中のコードを結合できます。 安定したコードは再コンパイルの必要がないため、後の各コンパイルが高速化します。

ソース コードをプリコンパイルする時期

プリコンパイル済みのコードは、特に次の場合、開発サイクル中のコンパイル時間の短縮に役立ちます。

  • 頻繁には変更されない大規模なコード本体を常に使用している。

  • プログラムが複数のモジュールで構成され、そのすべてで、標準セットのインクルード ファイルと、同じコンパイル オプションを使用している。 この場合、すべてのインクルード ファイルを 1 つのプリコンパイル済みヘッダーにプリコンパイルできます。 インクルード ファイルを処理する新しい方法の詳細については、「ヘッダー ユニット、モジュール、プリコンパイル済みヘッダーの比較」を参照してください

最初のコンパイル (プリコンパイル済みヘッダー ファイルが作成されるとき) では、後続のコンパイルより少し長く時間がかかります。 後続のコンパイルは、プリコンパイル済みコードを含めることで、より迅速に進めることができます。

C と C++ プログラムのどちらもプリコンパイルできます。 C++ プログラミングでは、クラス インターフェイス情報をヘッダー ファイルに分離するのが一般的です。 これらのヘッダー ファイルは、そのクラスを使用するプログラムに後で含めることができます。 これらのヘッダーをプリコンパイルすると、プログラムのコンパイルにかかる時間を短縮できます。

Note

各ソース ファイルで使用できるプリコンパイル済みヘッダー (.pch) ファイルは 1 つだけですが、プロジェクトでは複数の .pch ファイルを使用できます。

コードをプリコンパイルする 2 つの方法

どのような 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 ファイルを使用する後続のコンパイルでこれらのオプションを使用できません。

C 7.0 互換 (/Z7)

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 の一貫性規則

/Yc または /Yu を使用して作成されたプリコンパイル済みヘッダーを使用する場合、コンパイラでは、現在のコンパイル環境と PCH ファイルの作成時に存在していた環境が比較されます。 現在のコンパイルには必ず、(一貫性のあるコンパイラ オプション、プラグマなどを使用して) 前の環境と一致する環境を指定してください。 コンパイラでは、不整合が検出されると警告が発行され、可能な場合はその不整合が特定されます。 このような警告は、必ずしも PCH ファイルに問題があることを示しているわけではありません。競合が発生する可能性があることを警告するだけです。 この後のセクションでは、プリコンパイル済みヘッダーの一貫性の要件について説明します。

コンパイラ オプションの一貫性

次の表に、プリコンパイル済みヘッダーを使用するときに不整合の警告がトリガーされる可能性のあるコンパイラ オプションを示します。

オプション 名前 Rule
/D 定数とマクロの定義 プリコンパイル済みヘッダーを作成したコンパイルと現在のコンパイルの間で同じでなければなりません。 定義済みの定数の状態はチェックされません。 ただし、変更された定数の値にファイルが依存している場合は予測できない結果が生じる可能性があります。
/E または /EP 標準出力へのプリプロセッサ出力のコピー プリコンパイル済みヘッダーは /E オプションまたは /EP オプションでは機能しません。
/Fr または /FR Microsoft ソース ブラウザー情報の生成 /Fr オプションおよび /FR オプションを /Yu オプションで有効にするには、プリコンパイル済みヘッダーが作成されたときにもこれらが有効になっている必要があります。 プリコンパイル済みヘッダーを使用する後続のコンパイルでも、ソース ブラウザー情報が生成されます。 ブラウザー情報は 1 つの .sbr ファイルに配置され、CodeView 情報と同じ方法で他のファイルから参照されます。 ソース ブラウザー情報の配置をオーバーライドすることはできません。
/GA/GD/GE/Gw、または /GW Windows プロトコル オプション プリコンパイル済みヘッダーを作成したコンパイルと現在のコンパイルの間で同じでなければなりません。 これらのオプションが異なる場合、コンパイラは警告を出力します。
/Zi 詳細なデバッグ情報の生成 プリコンパイル済みヘッダーの作成時にこのオプションが有効になっている場合、プリコンパイルを使用する後続のコンパイルでそのデバッグ情報を使用できます。 プリコンパイル済みヘッダーの作成時に /Zi が有効になっていない場合、プリコンパイルおよび /Zi オプションを使用する後続のコンパイルで警告がトリガーされます。 デバッグ情報は現在のオブジェクト ファイルに配置され、プリコンパイル済みヘッダーで定義されているローカル シンボルはデバッガーでは使用できません。

Note

プリコンパイル済みヘッダー機能は、C および C++ ソース ファイルでの使用のみを目的としています。

プロジェクトでのプリコンパイル済みヘッダーの使用

前のセクションでは、プリコンパイル済みヘッダーの概要 (/Yc と /Yu、/Fp オプション、hdrstop プラグマ) を紹介しています。 このセクションでは、プロジェクトで手動プリコンパイル済みヘッダーのオプションを使用する方法について説明します。説明の最後に、サンプルのメイクファイルとそれによって管理されるコードを示します。

プロジェクトで手動プリコンパイル済みヘッダーのオプションを使用する別の方法として、Visual Studio の既定のセットアップ時に作成される MFC\SRC ディレクトリにあるいずれかのメイクファイルを調べます。 これらのメイクファイルは、このセクションで説明する方法と同様のアプローチを取っています。 ここでは Microsoft Program Maintenance Utility (NMAKE) マクロがより活用され、ビルド プロセスをよりよく制御できます。

ビルド プロセスでの PCH ファイル

多くの場合、ソフトウェア プロジェクトのコード ベースは、複数の C または C++ ソース ファイル、オブジェクト ファイル、ライブラリ、ヘッダー ファイルに含まれています。 一般に、メイクファイルは、これらの要素の組み合わせを調整して 1 つの実行可能ファイルにします。 次の図は、プリコンパイル済みヘッダー ファイルを使用するメイクファイルの構造を示しています。 この図の NMAKE マクロ名とファイル名は、PCH 用のサンプル メイクファイルと PCH のサンプル コードのコード例と一致しています。

この図は、3 つの図式デバイスを使用して、ビルド プロセスのフローを示しています。 名前付きの四角形は、各ファイルまたはマクロを表します。3 つのマクロは、1 つ以上のファイルを表します。 網掛け領域は、各コンパイルまたはリンク アクションを表します。 矢印は、コンパイルまたはリンク プロセス中に結合されるファイルとマクロを示します。

 The diagram is described in the text following the diagram.
プリコンパイル済みヘッダー ファイルを使用するメイクファイルの構造:

Diagram showing example inputs and outputs of a makefile that uses a precompiled header file.

この図は、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 を生成します。

図を上から見ていくと、STABLEHDRSBOUNDRY はいずれも 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.cppUNSTABLEHDRS マクロに一覧表示されているファイル、プリコンパイル済みヘッダーのプリコンパイル済みコードから作成されます。

MYAPP.obj は、最終的なアプリケーションを表します。 これは、MYAPP.cppUNSTABLEHDRS マクロに一覧表示されているファイル、プリコンパイル済みヘッダーのプリコンパイル済みコードから作成されます。

最後に、OBJS マクロ (APPLIB.objMYAPP.obj) に一覧表示されるファイルをリンクして実行可能ファイル (MYAPP.EXE) が作成されます。

PCH のサンプル メイクファイル

次のメイクファイルでは、マクロと !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 ファイル」の図「プリコンパイル済みヘッダー ファイルを使用するメイクファイルの構造」に示されている STABLEHDRSBOUNDRYUNSTABLEHDRS マクロとは別に、このメイクファイルには CLFLAGS マクロと LINKFLAGS マクロが用意されています。 これらのマクロを使用して、アプリケーションの実行可能ファイルのデバッグ バージョンと最終バージョンのどちらをビルドする場合でも適用される、コンパイラとリンカーのオプションを一覧表示する必要があります。 また、プロジェクトに必要なライブラリを一覧表示する LIBS マクロもあります。

さらに、このメイクファイルでは、!IF!ELSE!ENDIF を使用して、NMAKE コマンド ラインで DEBUG シンボルを定義するかどうかも検出されます。

NMAKE DEBUG=[1|0]

この機能により、プログラムの開発中バージョンと最終バージョンで同じメイクファイルを使用できます。 最終バージョンでは DEBUG=0 を使用します。 次のコマンド ラインは同等のものです。

NMAKE
NMAKE DEBUG=0

メイクファイルの詳細については、「NMAKE リファレンス」を参照してください。 また、「MSVC コンパイラ オプション」と「MSVC リンカー オプション」も参照してください。

PCH のサンプル コード

次のソース ファイルは、「ビルド プロセスでの 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++ 標準ライブラリをインポートする
チュートリアル: Visual C++ プロジェクトでヘッダー ユニットをビルドしてインポートする
チュートリアル: STL ライブラリをヘッダ ーユニットとしてインポートする