Pliki prekompilowanego nagłówka
Podczas tworzenia nowego projektu w programie Visual Studio do projektu jest dodawany wstępnie skompilowany plik nagłówkowy o nazwie pch.h
. (W programie Visual Studio 2017 i starszych plik został nazwany stdafx.h
.) Celem pliku jest przyspieszenie procesu kompilacji. Wszystkie stabilne pliki nagłówków, na przykład nagłówki biblioteki standardowej, takie jak <vector>
, powinny być dołączone tutaj. Prekompilowany nagłówek jest kompilowany tylko wtedy, gdy zostanie zmodyfikowany lub wszystkie pliki, które zawiera. Jeśli wprowadzisz tylko zmiany w kodzie źródłowym projektu, kompilacja pominie kompilację prekompilowanego nagłówka.
Opcje kompilatora dla wstępnie skompilowanych nagłówków to /Y
. Na stronach właściwości projektu opcje znajdują się w obszarze Właściwości>konfiguracji C/C++>Prekompilowane nagłówki. Możesz nie używać wstępnie skompilowanych nagłówków i określić nazwę pliku nagłówka oraz nazwę i ścieżkę pliku wyjściowego.
Niestandardowy wstępnie skompilowany kod
W przypadku dużych projektów wymagających znacznego czasu na skompilowanie warto rozważyć utworzenie niestandardowych wstępnie skompilowanych plików. Kompilatory języka Microsoft C i C++ udostępniają opcje wstępnego kompilowania dowolnego kodu C lub C++, w tym kodu wbudowanego. Korzystając z tej funkcji wydajności, można skompilować stabilną treść kodu, zapisać skompilowany stan kodu w pliku, a podczas kolejnych kompilacji połączyć wstępnie skompilowany kod z kodem, który jest nadal opracowywany. Każda późniejsza kompilacja jest szybsza, ponieważ stabilny kod nie musi być ponownie skompilowany.
Kiedy należy wstępnie skompilować kod źródłowy
Wstępnie skompilowany kod jest przydatny podczas cyklu programowania, aby skrócić czas kompilacji, zwłaszcza jeśli:
Zawsze używasz dużej treści kodu, który zmienia się rzadko.
Program składa się z wielu modułów, z których wszystkie korzystają ze standardowego zestawu plików dołączanych i tych samych opcji kompilacji. W takim przypadku wszystkie pliki dołączania można wstępnie skompilować do jednego prekompilowanego nagłówka. Aby uzyskać więcej informacji na temat nowszych sposobów obsługi dołączania plików, zobacz Porównanie jednostek nagłówka, modułów i wstępnie skompilowanych nagłówków.
Pierwsza kompilacja (ta, która tworzy wstępnie skompilowany plik nagłówka) trwa nieco dłużej niż kolejne kompilacje. Kolejne kompilacje mogą być wykonywane szybciej, dołączając wstępnie skompilowany kod.
Można wstępnie skompilować zarówno programy C, jak i C++. W programowaniu w języku C++ typowym rozwiązaniem jest oddzielenie informacji o interfejsie klasy do plików nagłówkowych. Te pliki nagłówkowe można później uwzględnić w programach korzystających z klasy . Dzięki wstępnej kompilacji tych nagłówków można skrócić czas kompilowania programu.
Uwaga
Chociaż można użyć tylko jednego wstępnie skompilowanego pliku nagłówka (.pch
) na plik źródłowy, można użyć wielu .pch
plików w projekcie.
Dwie opcje prekompilowania kodu
Możesz wstępnie skompilować dowolny kod C lub C++; Nie ograniczasz się do wstępnej kompilacji tylko plików nagłówkowych.
Wstępne kompilowanie wymaga planowania, ale oferuje znacznie szybsze kompilacje, jeśli prekompilujesz kod źródłowy inny niż proste pliki nagłówkowe.
Prekompiluj kod, gdy wiesz, że pliki źródłowe używają typowych zestawów plików nagłówkowych lub gdy chcesz dołączyć kod źródłowy do prekompilacji.
Opcje prekompilowanego nagłówka to (Utwórz wstępnie skompilowany plik nagłówka) i /Yu
(Użyj prekompilowanego pliku nagłówka)./Yc
Użyj /Yc
polecenia , aby utworzyć wstępnie skompilowany nagłówek. W przypadku użycia z opcjonalną hdrstop
pragma /Yc
umożliwia wstępne kompilowanie plików nagłówków i kodu źródłowego. Wybierz /Yu
, aby użyć istniejącego prekompilowanego nagłówka w istniejącej kompilacji. Można również użyć /Fp
z opcjami /Yc
i /Yu
, aby podać alternatywną nazwę prekompilowanego nagłówka.
Artykuły /Yu
referencyjne dotyczące opcji kompilatora i /Yc
omówienie sposobu uzyskiwania dostępu do tych funkcji w środowisku deweloperów.
Reguły spójności prekompilowanego nagłówka
Ponieważ pliki PCH zawierają informacje o środowisku maszyny i adresie pamięci o programie, należy użyć tylko pliku PCH na maszynie, na której został utworzony.
Reguły spójności dla użycia wstępnie skompilowanych nagłówków dla poszczególnych plików
Opcja kompilatora /Yu
umożliwia określenie, który plik PCH ma być używany.
W przypadku korzystania z pliku PCH kompilator zakłada to samo środowisko kompilacji, które zostało zastosowane podczas tworzenia pliku PCH, chyba że określono inaczej. Środowisko kompilacji zawiera opcje kompilatora, pragma i tak dalej. Jeśli kompilator wykryje niespójność, wyświetla ostrzeżenie i identyfikuje niespójność tam, gdzie to możliwe. Takie ostrzeżenia nie muszą wskazywać problemu z plikiem PCH; po prostu ostrzegają o możliwych konfliktach. Wymagania dotyczące spójności plików PCH opisano w poniższych sekcjach.
Spójność opcji kompilatora
Następujące opcje kompilatora mogą wyzwalać ostrzeżenie o niespójności podczas korzystania z pliku PCH:
Makra utworzone przy użyciu opcji Preprocesor (
/D
) muszą być takie same między kompilacją, która utworzyła plik PCH i bieżącą kompilację. Stan zdefiniowanych stałych nie jest sprawdzany, ale nieprzewidywalne wyniki mogą wystąpić w przypadku zmiany tych makr.Pliki PCH nie działają z opcjami
/E
i ./EP
Pliki PCH należy utworzyć przy użyciu opcji Generuj informacje przeglądania (
/FR
) lub opcji Wyklucz zmienne lokalne (/Fr
) przed kolejnymi kompilacjami używającymi pliku PCH mogą korzystać z tych opcji.
Zgodny z językiem C 7.0 (/Z7
)
Jeśli ta opcja jest w mocy podczas tworzenia pliku PCH, późniejsze kompilacje korzystające z pliku PCH mogą używać informacji debugowania.
Jeśli opcja Zgodna z językiem C 7.0 (/Z7
) nie działa po utworzeniu pliku PCH, późniejsze kompilacje, które używają pliku PCH i /Z7
wyzwalają ostrzeżenie. Informacje o debugowaniu są umieszczane w bieżącym .obj
pliku, a symbole lokalne zdefiniowane w pliku PCH nie są dostępne dla debugera.
Uwzględnij spójność ścieżki
Plik PCH nie zawiera informacji o nagłówku dołączanej ścieżki, która obowiązywała podczas jego tworzenia. W przypadku korzystania z pliku PCH kompilator zawsze używa ścieżki dołączania nagłówka określonej w bieżącej kompilacji.
Spójność pliku źródłowego
Po określeniu opcji Użyj prekompilowanego pliku nagłówka (/Yu
) kompilator ignoruje wszystkie dyrektywy preprocesora (w tym pragma), które będą wyświetlane w kodzie źródłowym, który zostanie wstępnie skompilowany. Kompilacja określona przez takie dyrektywy preprocesora musi być taka sama jak kompilacja używana dla opcji Utwórz wstępnie skompilowany plik nagłówka (/Yc
).
Spójność pragma
Pragmas przetwarzane podczas tworzenia pliku PCH zwykle wpływają na plik, z którym plik PCH jest później używany. message
Pragmas comment
i nie mają wpływu na pozostałą część kompilacji.
Te pragma mają wpływ tylko na kod w pliku PCH; nie mają wpływu na kod, który później używa pliku PCH:
comment
linesize
message
page
pagesize
skip
subtitle
title
Te pragmas są zachowywane jako część prekompilowanego nagłówka i wpływają na pozostałą część kompilacji, która używa prekompilowanego nagłówka:
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
Reguły spójności dla /Yc i /Yu
Jeśli używasz wstępnie skompilowanego nagłówka utworzonego przy użyciu polecenia /Yc
lub /Yu
, kompilator porównuje bieżące środowisko kompilacji z tym, które istniało podczas tworzenia pliku PCH. Pamiętaj, aby określić środowisko zgodne z poprzednim (przy użyciu spójnych opcji kompilatora, pragmas itd.) dla bieżącej kompilacji. Jeśli kompilator wykryje niespójność, wyświetla ostrzeżenie i identyfikuje niespójność tam, gdzie to możliwe. Takie ostrzeżenia nie muszą wskazywać problemu z plikiem PCH; po prostu ostrzegają o możliwych konfliktach. W poniższych sekcjach opisano wymagania dotyczące spójności prekompilowanych nagłówków.
Spójność opcji kompilatora
W tej tabeli wymieniono opcje kompilatora, które mogą wyzwolić ostrzeżenie o niespójności podczas używania prekompilowanego nagłówka:
Opcja | Nazwisko | Reguła |
---|---|---|
/D |
Definiowanie stałych i makr | Musi być taka sama między kompilacją, która utworzyła prekompilowany nagłówek i bieżącą kompilację. Stan zdefiniowanych stałych nie jest sprawdzany. Jednak nieprzewidywalne wyniki mogą wystąpić, jeśli pliki zależą od wartości zmienionych stałych. |
/E lub /EP |
Kopiowanie danych wyjściowych preprocesora do standardowych danych wyjściowych | Prekompilowane nagłówki nie działają z opcją /E lub /EP . |
/Fr lub /FR |
Generowanie informacji o przeglądarce źródłowej firmy Microsoft | /Fr Aby opcje i /FR były prawidłowe z opcją/Yu , muszą one również obowiązywać po utworzeniu wstępnie skompilowanego nagłówka. Kolejne kompilacje korzystające ze wstępnie skompilowanego nagłówka również generują informacje o przeglądarce źródłowej. Informacje o przeglądarce są umieszczane w jednym .sbr pliku i odwołują się do innych plików w taki sam sposób jak informacje o kodzieView. Nie można zastąpić umieszczania informacji o przeglądarce źródłowej. |
/GA , , /GD , /GE , /Gw lub /GW |
Opcje protokołu systemu Windows | Musi być taka sama między kompilacją, która utworzyła prekompilowany nagłówek i bieżącą kompilację. Kompilator emituje ostrzeżenie, jeśli te opcje się różnią. |
/Zi |
Generowanie pełnych informacji o debugowaniu | Jeśli ta opcja jest w mocy po utworzeniu wstępnie skompilowanego nagłówka, kolejne kompilacje korzystające ze wstępnego kompilowania mogą używać tych informacji debugowania. Jeśli /Zi nie ma zastosowania podczas tworzenia prekompilowanego nagłówka, kolejne kompilacje używające prekompilacji i /Zi opcja wyzwalają ostrzeżenie. Informacje debugowania są umieszczane w bieżącym pliku obiektu, a symbole lokalne zdefiniowane w nagłówku prekompilowanego nie są dostępne dla debugera. |
Uwaga
Wstępnie skompilowana funkcja nagłówka jest przeznaczona do użytku tylko w plikach źródłowych C i C++.
Używanie wstępnie skompilowanych nagłówków w projekcie
W poprzednich sekcjach przedstawiono omówienie wstępnie skompilowanych nagłówków: /Yc i /Yu, /Fp opcji i hdrstop pragma. W tej sekcji opisano metodę używania opcji prekompilowanego nagłówka ręcznego w projekcie; kończy się przykładowym plikiem makefile i kodem, który zarządza.
W przypadku innego podejścia do korzystania z opcji prekompilowanego nagłówka ręcznego w projekcie zapoznaj się z jednym z plików make znajdujących się w MFC\SRC
katalogu utworzonym podczas domyślnej konfiguracji programu Visual Studio. Te pliki makefile przyjmują podobne podejście do tego przedstawionego w tej sekcji. Zapewniają one większe wykorzystanie makr programu Microsoft Program Maintenance Utility (NMAKE) i zapewniają większą kontrolę nad procesem kompilacji.
Pliki PCH w procesie kompilacji
Baza kodu projektu oprogramowania jest często zawarta w wielu plikach źródłowych C lub C++, plikach obiektów, bibliotekach i plikach nagłówkowych. Zazwyczaj plik make koordynuje kombinację tych elementów w pliku wykonywalnym. Na poniższej ilustracji przedstawiono strukturę pliku make, który używa wstępnie skompilowanego pliku nagłówka. Nazwy makr NMAKE i nazwy plików na tym diagramie są zgodne z przykładowym kodem znajdującym się w przykładowym pliku makefile dla PCH i przykładowego kodu PCH.
Na rysunku przedstawiono przepływ procesu kompilacji przy użyciu trzech urządzeń diagramowych. Nazwane prostokąty reprezentują każdy plik lub makro; trzy makra reprezentują jeden lub więcej plików. Zacienione obszary reprezentują każdą akcję kompilowania lub łączenia. Strzałki pokazują, które pliki i makra są łączone podczas procesu kompilacji lub łączenia.
Struktura pliku make korzystającego ze wstępnie skompilowanego pliku nagłówka:
Na diagramie przedstawiono wartości "$(STABLEHDRS)" i "$(BOUNDRY)" przekazujące do środowiska CL /c /W3 /Yc$(BOUNDRY) applib.cpp myapp.cpp. Dane wyjściowe tego polecenia to $(STABLE. PCH). Następnie applib.cpp i $(UNSTABLEHDRS) i $(STABLE. Źródło danych PCH) do CL /c /w3 /Yu $(BOUNDRY) applib.cpp, który generuje applib.obj. myapp.cpp, $(UNSTABLEHDR) i $(STABLE. Źródło PCH) do cl /c /w3 /Yu $(BOUNDRY) myapp.cpp, który generuje myapp.obj. Na koniec applib.obj i myapp.obj są łączone przez LINK /NOD ONERROR:NOEXE $(OBJS), myapp, NUL, $(LIBS), NUL w celu utworzenia myapp.exe.
Począwszy od góry diagramu, zarówno STABLEHDRS
w makrach NMAKE, jak i BOUNDRY
w których na liście plików prawdopodobnie nie trzeba ponownie komkompilować. Te pliki są kompilowane przez ciąg polecenia
CL /c /W3 /Yc$(BOUNDRY) applib.cpp myapp.cpp
tylko wtedy, gdy wstępnie skompilowany plik nagłówka (STABLE.pch
) nie istnieje lub jeśli wprowadzisz zmiany w plikach wymienionych w dwóch makrach. W obu przypadkach wstępnie skompilowany plik nagłówkowy będzie zawierać kod tylko z plików wymienionych w makrze STABLEHDRS
. Wyświetl ostatni plik, który ma zostać wstępnie skompilowany w makrze BOUNDRY
.
Pliki wymienione w tych makrach mogą być plikami nagłówkowymi lub plikami źródłowymi C lub C++. (Pojedynczy plik PCH nie może być używany zarówno ze źródłami C, jak i C++). Możesz użyć makra hdrstop
, aby zatrzymać wstępne komplikowanie w pewnym momencie w BOUNDRY
pliku. Aby uzyskać więcej informacji, zobacz hdrstop
.
Następnie na diagramie APPLIB.obj
reprezentuje kod pomocy technicznej używany w ostatecznej aplikacji. Jest on tworzony na podstawie APPLIB.cpp
pliku , plików wymienionych w makrze UNSTABLEHDRS
i wstępnie skompilowanego kodu z prekompilowanego nagłówka.
MYAPP.obj
reprezentuje ostateczną aplikację. Jest on tworzony na podstawie MYAPP.cpp
pliku , plików wymienionych w makrze UNSTABLEHDRS
i wstępnie skompilowanego kodu z prekompilowanego nagłówka.
Na koniec plik wykonywalny (MYAPP.EXE
) jest tworzony przez połączenie plików wymienionych w makrze OBJS
(APPLIB.obj
i MYAPP.obj
).
Przykładowy plik make dla PCH
Poniższy plik makefile używa makr i !IF
struktury poleceń , !ELSE
, !ENDIF
flow-of-control, aby uprościć jego adaptację do projektu.
# 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
STABLEHDRS
Oprócz makr , BOUNDRY
i UNSTABLEHDRS
pokazanych na rysunku "Struktura pliku programu Make, który używa wstępnie skompilowanego pliku nagłówka" w plikach PCH w procesie kompilacji, ten plik make udostępnia CLFLAGS
makro i LINKFLAGS
makro. Te makra należy używać do wyświetlania listy opcji kompilatora i konsolidatora, które mają zastosowanie niezależnie od tego, czy tworzysz debugowanie, czy ostateczną wersję pliku wykonywalnego aplikacji. Istnieje również makro, LIBS
w którym znajduje się lista bibliotek, których wymaga projekt.
Plik makefile używa również , !IF
!ELSE
!ENDIF
, aby wykryć, czy definiujesz DEBUG
symbol w wierszu polecenia NMAKE:
NMAKE DEBUG=[1|0]
Ta funkcja umożliwia używanie tego samego pliku make podczas programowania i dla końcowych wersji programu. Użyj dla DEBUG=0
wersji końcowych. Następujące wiersze polecenia są równoważne:
NMAKE
NMAKE DEBUG=0
Aby uzyskać więcej informacji na temat plików make, zobacz Dokumentacja narzędzia NMAKE. Zobacz również opcje kompilatora MSVC i opcje konsolidatora MSVC.
Przykładowy kod PCH
Następujące pliki źródłowe są używane w pliku make opisanym w plikach PCH w procesie kompilacji i Przykładowy plik makefile dla PCH. Komentarze zawierają ważne informacje.
Plik ANOTHER.H
źródłowy:
// 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
Plik STABLE.H
źródłowy:
// 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
Plik UNSTABLE.H
źródłowy:
// 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
Plik APPLIB.CPP
źródłowy:
// 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";
}
Plik MYAPP.CPP
źródłowy:
// 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();
}
Zobacz też
Porównanie jednostek nagłówka, modułów i wstępnie skompilowanych nagłówków
Dokumentacja kompilowania języka C/C++
Opcjekompilatora MSVC — omówienie modułów w języku C++
Samouczek: importowanie standardowej biblioteki języka C++ przy użyciu modułów
Przewodnik: kompilowanie i importowanie jednostek nagłówków w projektach Visual C++
Przewodnik: importowanie bibliotek STL jako jednostek nagłówka