Vorkompilierte Headerdateien
Wenn Sie ein neues Projekt in Visual Studio erstellen, wird dem Projekt eine vorkompilierte Headerdatei pch.h
hinzugefügt. (In Visual Studio 2017 und früher wurde die Datei als . stdafx.h
) Der Zweck der Datei besteht darin, den Buildprozess zu beschleunigen. Alle stabilen Headerdateien, z. B. Standardbibliotheksheader wie <vector>
, sollten hier eingefügt werden. Der vorkompilierte Header nur kompiliert, wenn er oder jegliche in ihm enthaltene Dateien geändert werden. Wenn Sie Änderungen am Quellcode Ihres Projekts vornehmen, überspringt der Buildprozess die Kompilierung des vorkompilierten Headers.
Die Compileroptionen für vorkompilierte Header sind /Y
. Auf den Projekteigenschaftenseiten befinden sich die Optionen unter Konfigurationseigenschaften>C/C++.> Sie können sich dazu entscheiden, keine vorkompilierten Header zu verwenden, und den Headerdateinamen sowie den Namen und Pfad der Ausgabedatei festlegen.
Benutzerdefinierter vorkompilierter Code
Für große Projekte, deren Buildprozesse einige Zeit beanspruchen, sollten Sie das Erstellen benutzerdefinierter vorkompilierter Dateien in Erwägung ziehen. Die Microsoft C- und C++-Compiler stellen Optionen für das Vorkompilieren von beliebigem C- oder C++-Code bereit, einschließlich Inlinecode. Mithilfe dieses Leistungsfeatures können Sie einen stabilen Codetext kompilieren, den kompilierten Zustand des Codes in einer Datei speichern und bei nachfolgenden Kompilierungen den vorkompilierten Code mit Code kombinieren, der noch in der Entwicklung ist. Jede spätere Kompilierung ist schneller, da der stabile Code nicht neu kompiliert werden muss.
Gründe für die Vorkompilierung des Quellcodes
Vorkompilierter Code ist während des Entwicklungsprozesses nützlich, um die Kompilierungszeit zu reduzieren. Dies gilt insbesondere in folgenden Fällen:
Sie verwenden immer umfangreiche Codeabschnitte, die häufig geändert werden.
Ihr Programm besteht aus mehreren Modulen, die alle eine Standardgruppe von Includedateien und die gleichen Kompilierungsoptionen verwenden. In diesem Fall können alle Dateien in einen vorkompilierten Header vorab kompiliert werden. Weitere Informationen zu neueren Methoden zum Verarbeiten von Dateien finden Sie unter Vergleichen von Headereinheiten, Modulen und vorkompilierten Headern.
Die erste Kompilierung (die die vorkompilierte Headerdatei erstellt) dauert etwas länger als nachfolgende Kompilierungen. Nachfolgende Kompilierungen können schneller fortgesetzt werden, indem der vorkompilierte Code eingefügt wird.
Sie können sowohl C- als auch C++-Programme vorkompilieren. Bei der C++-Programmierung ist es üblich, Klassenschnittstelleninformationen in Headerdateien zu trennen. Diese Headerdateien können später in Programme eingefügt werden, die die Klasse verwenden. Indem Sie diese Header vorkompilieren, können Sie die Zeit reduzieren, die die Kompilierung eines Programms erfordert.
Hinweis
Obwohl Sie pro Quelldatei nur eine vorkompilierte Kopfzeile (.pch
) verwenden können, können Sie mehrere .pch
Dateien in einem Projekt verwenden.
Zwei Optionen für Vorkompilierungscode
Sie können einen beliebigen C- oder C++-Code vorab kompilieren. Sie sind nicht auf das Vorabkompilieren von Headerdateien beschränkt.
Vorkompilierung erfordert Planung, bietet aber viel schnellere Kompilierungen, wenn Sie anderen Quellcode als einfache Headerdateien vorab kompilieren.
Vorkompilierungscode, wenn Sie wissen, dass Ihre Quelldateien allgemeine Gruppen von Headerdateien verwenden oder wenn Sie Quellcode in die Vorkompilierung einschließen möchten.
Die Vorkompilierungsheaderoptionen sind /Yc
(Vorkompilierte Headerdatei erstellen) und /Yu
(Precompiled Header File verwenden). Dient /Yc
zum Erstellen eines vorkompilierten Headers. Bei Verwendung mit dem optionalen hdrstop
Pragma /Yc
können Sie sowohl Headerdateien als auch Quellcode vorab kompilieren. Wählen Sie diese Option /Yu
aus, um einen vorhandenen vorkompilierten Header in der vorhandenen Kompilierung zu verwenden. Sie können auch /Fp
mit den /Yc
Optionen einen /Yu
alternativen Namen für den vorkompilierten Header bereitstellen.
In den Compileroptionsreferenzartikeln /Yu
erfahren Sie /Yc
, wie Sie in der Entwicklungsumgebung auf diese Funktionalität zugreifen können.
Vorkompilierte Headerkonsistenzregeln
Da PCH-Dateien Informationen über die Computerumgebung und Speicheradresseninformationen über das Programm enthalten, sollten Sie nur eine PCH-Datei auf dem Computer verwenden, auf dem sie erstellt wurde.
Konsistenzregeln für die Verwendung von vorkompilierten Headern pro Datei
Mit der /Yu
Compileroption können Sie angeben, welche PCH-Datei verwendet werden soll.
Wenn Sie eine PCH-Datei verwenden, geht der Compiler von derselben Kompilierungsumgebung aus, die beim Erstellen der PCH-Datei wirksam war, sofern Sie nichts anderes angeben. Die Kompilierungsumgebung enthält die Compileroptionen, Pragmen usw. Wenn der Compiler eine Inkonsistenz erkennt, wird eine Warnung ausgegeben und die Inkonsistenz wird identifiziert, wenn möglich. Solche Warnungen weisen nicht unbedingt auf ein Problem mit der PCH-Datei hin. Sie dienen lediglich dazu, Sie vor möglichen Konflikten zu warnen. In den folgenden Abschnitten werden die Konsistenzanforderungen für PCH-Dateien behandelt.
Compileroptionskonsistenz
Die folgenden Compileroptionen können bei Verwendung einer PCH-Datei eine Inkonsistenzwarnung auslösen:
Makros, die mit der Präprozessoroption (
/D
) erstellt wurden, müssen mit der Kompilierung identisch sein, die die PCH-Datei und die aktuelle Kompilierung erstellt hat. Der Status der definierten Konstanten wird nicht überprüft, aber unvorhersehbare Ergebnisse können auftreten, wenn sich diese Makros ändern.PCH-Dateien funktionieren nicht mit den
/E
Optionen/EP
.PCH-Dateien müssen entweder mit der Option "Durchsucheninformationen generieren" (
/FR
) oder der Option "Lokale Variablen ausschließen" (/Fr
) erstellt werden, bevor nachfolgende Kompilierungen, die die PCH-Datei verwenden, diese Optionen verwenden können.
C 7.0-kompatibel (/Z7
)
Wenn diese Option wirksam ist, wenn die PCH-Datei erstellt wird, können spätere Kompilierungen, die die PCH-Datei verwenden, die Debuginformationen verwenden.
Wenn die C 7.0-Kompatible Option (/Z7
) nicht wirksam ist, wenn die PCH-Datei erstellt wird, werden später Kompilierungen, die die PCH-Datei verwenden, kompiliert und /Z7
eine Warnung ausgelöst. Die Debuginformationen werden in der aktuellen .obj
Datei platziert, und lokale Symbole, die in der PCH-Datei definiert sind, sind für den Debugger nicht verfügbar.
Pfadkonsistenz einschließen
Eine PCH-Datei enthält keine Informationen über den Header, einschließlich pfad, der beim Erstellen wirksam war. Wenn Sie eine PCH-Datei verwenden, verwendet der Compiler immer den Header include path specified in the current compilation.
Konsistenz der Quelldatei
Wenn Sie die Option "Vorkompilierte Headerdatei verwenden" (/Yu
) angeben, ignoriert der Compiler alle Präprozessordirektiven (einschließlich Pragmen), die im Quellcode angezeigt werden, der vorkompiliert wird. Die durch solche Präprozessordirektiven angegebene Kompilierung muss mit der Kompilierung übereinstimmen, die für die Option "Vorkompilierte Headerdatei erstellen" (/Yc
) verwendet wird.
Pragma-Konsistenz
Pragmas, die während der Erstellung einer PCH-Datei verarbeitet wurden, wirken sich in der Regel auf die Datei aus, mit der die PCH-Datei später verwendet wird. Die comment
Und message
Pragmen wirken sich nicht auf den Re Standard der der Kompilierung aus.
Diese Pragmen wirken sich nur auf den Code in der PCH-Datei aus. sie wirken sich nicht auf Code aus, der später die PCH-Datei verwendet:
comment
linesize
message
page
pagesize
skip
subtitle
title
Die folgenden Pragmas werden als Teil eines vorkompilierten Headers beibehalten und wirken sich auf die restliche Kompilierung aus, die den vorkompilierten Header verwendet:
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
Konsistenzregeln für /Yc und /Yu
Wenn Sie einen vordefinierten Header verwenden, der mit /Yc
oder /Yu
oder erstellt wurde, vergleicht der Compiler die aktuelle Kompilierungsumgebung mit dem, das beim Erstellen der PCH-Datei vorhanden war. Stellen Sie sicher, dass Sie für die aktuelle Kompilierung eine Umgebung entsprechend der vorherigen festlegen (mithilfe konsistenter Compileroptionen, Pragmas usw.). Wenn der Compiler eine Inkonsistenz erkennt, wird eine Warnung ausgegeben und die Inkonsistenz wird identifiziert, wenn möglich. Solche Warnungen weisen nicht unbedingt auf ein Problem mit der PCH-Datei hin. Sie dienen lediglich dazu, Sie vor möglichen Konflikten zu warnen. In den folgenden Abschnitten werden die Konsistenzanforderungen für vorkompilierte Header erläutert.
Compileroptionskonsistenz
In dieser Tabelle werden die Compileroptionen aufgeführt, die eine Inkonsistenzwarnung auslösen könnten, wenn ein vorkompilierter Header verwendet wird:
Option | Name | Regel |
---|---|---|
/D |
Define constants and macros (Konstanten und Makros definieren) | Diese Option muss in der Kompilierung, in der der vorkompilierte Header erstellt wurde, und der aktuellen Kompilierung übereinstimmen. Der Status der definierten Konstanten wird nicht überprüft. Unvorhersehbare Ergebnisse können jedoch auftreten, wenn Ihre Dateien von den Werten der geänderten Konstanten abhängen. |
/E oder /EP |
Copy preprocessor output to standard output (Präprozessorausgabe in Standardausgabe kopieren) | Vorkompilierte Kopfzeilen funktionieren nicht mit der /E Oder /EP Option. |
/Fr oder /FR |
Generate Microsoft Source Browser information (Microsoft-Quellbrowserinformationen generieren) | Damit die /Fr Optionen /FR mit der /Yu Option gültig sind, müssen sie auch wirksam sein, wenn der vorkompilierte Header erstellt wurde. Nachfolgende Kompilierungen mit dem vorkompilierten Header generieren ebenfalls Quellbrowserinformationen. Browserinformationen werden in einer einzelnen .sbr Datei abgelegt und auf die gleiche Weise wie CodeView-Informationen von anderen Dateien referenziert. Sie können die Platzierung von Quellbrowserinformationen nicht außer Kraft setzen. |
/GA , /GD , /GE , /Gw oder /GW |
Windows protocol options (Windows-Protokolloptionen) | Diese Option muss in der Kompilierung, in der der vorkompilierte Header erstellt wurde, und der aktuellen Kompilierung übereinstimmen. Der Compiler gibt eine Warnung aus, wenn sich diese Optionen unterscheiden. |
/Zi |
Generate complete debugging information (Vollständige Debuginformationen generieren) | Wenn diese Option bei Erstellung des vorkompilierten Headers aktiv ist, können nachfolgende Kompilierungen, die die Vorkompilierung verwenden, die Debuginformationen verwenden. Wenn /Zi der vorkompilierte Header nicht erstellt wird, werden nachfolgende Kompilierungen, die die Vorkompilierung verwenden, und die /Zi Option eine Warnung auslösen. Die Debuginformationen werden in der aktuellen Objektdatei platziert, und lokale Symbole, die im vorkompilierten Header definiert sind, sind für den Debugger nicht verfügbar. |
Hinweis
Vorkompilierte Header sind nur zur Verwendung in C- und C++-Quelldateien vorgesehen.
Verwenden von vorkompilierten Kopfzeilen in einem Projekt
Die obigen Abschnitte veranschaulichen eine Übersicht über vorkompilierte Header: „/Yc“ und „/Yu“, die Option „/Fp“ und das Pragma hdrstop. In diesem Abschnitt wird eine Methode zur Verwendung der manuellen vorkompilierten Headeroptionen in einem Projekt beschrieben. Der Abschnitt endet mit einem Makefilebeispiel und dem Code, der durch dieses verwaltet wird.
Für einen anderen Ansatz zur Verwendung der manuellen Vorkompilierungsheaderoptionen in einem Projekt untersuchen Sie eine der Makefiles, die MFC\SRC
sich im Verzeichnis befinden, das während der Standardeinrichtung von Visual Studio erstellt wird. Diese Makefiles haben einen ähnlichen Ansatz wie in diesem Abschnitt. Sie nutzen microsoft Program Maintenance Utility (NMAKE)-Makros und bieten eine bessere Kontrolle über den Buildprozess.
PCH-Dateien im Buildprozess
Die Codebasis eines Softwareprojekts ist häufig in mehreren C- oder C++-Quelldateien, Objektdateien, Bibliotheken und Headerdateien enthalten. Ein Makefile koordiniert in der Regel die Kombination dieser Elemente in eine ausführbare Datei. Die folgende Abbildung veranschaulicht die Struktur eines Makefile, das eine vorkompilierte Headerdatei verwendet. Die NMAKE-Makronamen und die Dateinamen in diesem Diagramm entsprechen dem Beispielcode in der Beispiel-Makefile für PCH und Beispielcode für PCH.
In der Abbildung werden drei Diagrammelemente zum Veranschaulichen des Ablaufs des Buildprozesses verwendet. Beschriftete Rechtecke stellen einzelne Dateien oder Makros dar. Die drei Makros stellen eine oder mehrere Dateien dar. Schattierte Bereiche stellen Kompilierungs- oder Verknüpfungsaktionen dar. Die Pfeile geben an, welche Dateien und Makros während des Kompilierungs- oder Verknüpfungsprozesses kombiniert werden.
Struktur einer Makefile, die eine vorkompilierte Headerdatei verwendet:
Das Diagramm zeigt "$(STABLEHDRS)" und "$(BOUNDRY)" in CL /c /C /W3 /Yc$(BOUNDRY) applib.cpp myapp.cpp. Die Ausgabe davon ist $(STABLE). PCH). Dann, applib.cpp und $(UNSTABLEHDRS) und $(STABLE). PCH) feed in CL /c /w3 /Yu $(BOUNDRY) applib.cpp, die applib.obj erzeugt. myapp.cpp, $(UNSTABLEHDR) und $(STABLE). PCH) feed in CL /c /w3 /Yu $(BOUNDRY) myapp.cpp, die myapp.obj produziert. Schließlich werden applib.obj und myapp.obj von LINK /NOD ONERROR:NOEXE $(OBJS), myapp, NUL, $(LIBS), NUL kombiniert, um myapp.exe zu produzieren.
Beginnend am oberen Rand des Diagramms sind BOUNDRY
sowohl NMAKE-Makros als auch STABLEHDRS
NMAKE-Makros, in denen Sie Dateien auflisten, die wahrscheinlich nicht neu kompiliert werden müssen. Diese Dateien werden nur von der Befehlszeichenfolge
CL /c /W3 /Yc$(BOUNDRY) applib.cpp myapp.cpp
nur, wenn die vorkompilierte Headerdatei (STABLE.pch
) nicht vorhanden ist oder Wenn Sie Änderungen an den dateien vornehmen, die in den beiden Makros aufgeführt sind. In beiden Fällen enthält die vorkompilierte Headerdatei code nur aus den im STABLEHDRS
Makro aufgeführten Dateien. Listet die letzte Datei auf, die BOUNDRY
im Makro vorkompiliert werden soll.
Bei den Dateien, die Sie in diesen Makros aufführen, kann es sich entweder um Headerdateien oder C- bzw. C++-Quelldateien handeln. (Eine einzelne PCH-Datei kann nicht mit C- und C++-Quellen verwendet werden.) Sie können das Makro verwenden, um die hdrstop
Vorkompilierung an einem bestimmten Punkt in der BOUNDRY
Datei zu beenden. Weitere Informationen finden Sie unter hdrstop
.
Stellt als Nächstes im Diagramm APPLIB.obj
den in Ihrer endgültigen Anwendung verwendeten Supportcode dar. Es wird aus APPLIB.cpp
den dateien erstellt, die im UNSTABLEHDRS
Makro aufgelistet sind, und vorkompiliertem Code aus dem vorkompilierten Header.
MYAPP.obj
stellt Ihre endgültige Anwendung dar. Es wird aus MYAPP.cpp
den dateien erstellt, die im UNSTABLEHDRS
Makro aufgelistet sind, und vorkompiliertem Code aus dem vorkompilierten Header.
Schließlich wird die ausführbare Datei (MYAPP.EXE
) erstellt, indem die im OBJS
Makro (APPLIB.obj
und MYAPP.obj
) aufgeführten Dateien verknüpft werden.
Beispiel-Makefile für PCH
Die folgende Makefile verwendet Makros und eine !IF
!ELSE
Befehlsstruktur !ENDIF
des Flusses der Steuerung, um die Anpassung an Ihr Projekt zu vereinfachen.
# 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
Abgesehen von den makros BOUNDRY
in UNSTABLEHDRS
der Abbildung "Struktur einer Makefile, die eine vorkompilierte Headerdatei verwendet" in PCH-Dateien im Buildprozess, stellt diese Makefile ein CLFLAGS
Makro und ein LINKFLAGS
Makro STABLEHDRS
bereit. Sie müssen diese Makros verwenden, um Compiler- und Linkeroptionen aufzulisten, die unabhängig davon angewendet werden, ob Sie eine Debugversion oder die endgültige Version der ausführbaren Datei erstellen. Es gibt auch ein LIBS
Makro, in dem Sie die Bibliotheken auflisten, die Ihr Projekt benötigt.
Die Makefile verwendet !IF
außerdem , !ELSE
um zu erkennen, !ENDIF
ob Sie ein DEBUG
Symbol in der NMAKE-Befehlszeile definieren:
NMAKE DEBUG=[1|0]
Dieses Feature ermöglicht es Ihnen, die gleiche Makefile während der Entwicklung und für die endgültigen Versionen Ihres Programms zu verwenden. Wird für die endgültigen Versionen verwendet DEBUG=0
. Die folgenden Befehlszeilen sind gleichwertig:
NMAKE
NMAKE DEBUG=0
Weitere Informationen zu Makefiles finden Sie in der NMAKE-Referenz. Siehe auch MSVC-Compileroptionen und die MSVC-Linkeroptionen.
Beispielcode für PCH
Die folgenden Quelldateien werden in der makefile verwendet, die in PCH-Dateien im Buildprozess und Sample Makefile für PCH beschrieben wird. Die Kommentare enthalten wichtige Informationen.
Quelldatei 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
Quelldatei 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
Quelldatei 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
Quelldatei 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";
}
Quelldatei 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();
}
Siehe auch
Vergleichen von Kopfzeileneinheiten, Modulen und vorkompilierten Headern
Referenz zur C/C++-Erstellung
MSVC-Compileroptionen– Übersicht über Module in C++
Lernprogramm: Importieren der C++-Standardbibliothek mithilfe von Modulen
Exemplarische Vorgehensweise: Erstellen und Importieren von Headereinheiten in Ihren Visual C++-Projekten
Exemplarische Vorgehensweise: Importieren von STL-Bibliotheken als Headereinheiten