Předkompilované soubory hlaviček

Když v sadě Visual Studio vytvoříte nový projekt, přidá se do projektu předkompilovaný hlavičkový soubor s názvem pch.h . Ve verzi Visual Studio 2017 a starších byl soubor nazýván stdafx.h. Účelem souboru je urychlit proces sestavení. Zde by měly být zahrnuty všechny stabilní soubory hlaviček, například hlavičky standardní knihovny, například <vector>hlavičky standardní knihovny. Předkompilovaná hlavička se zkompiluje pouze tehdy, když se upraví ona sama nebo některý z souborů, které obsahuje. Pokud ve zdrojovém kódu projektu provedete změny, sestavení přeskočí kompilaci pro předkompilovanou hlavičku.

Možnosti kompilátoru pro předkompilované hlavičky jsou /Y. Na stránkách vlastností projektu se možnosti nacházejí pod Vlastnosti konfigurace>C/C++>Předkompilované záhlaví. Můžete zvolit, že nebudete používat předkompilovaná záhlaví a můžete zadat název souboru záhlaví a název a cestu výstupního souboru.

Vlastní předkompilovaný kód

U velkých projektů, které zabírají značné množství času sestavení, můžete zvážit vytvoření vlastních předkompilovaných souborů. Kompilátory jazyka Microsoft C a C++ poskytují možnosti pro předkompilování libovolného kódu jazyka C nebo C++, včetně vloženého kódu. Pomocí této funkce výkonu můžete zkompilovat stabilní tělo kódu, uložit zkompilovaný stav kódu do souboru a během následných kompilací zkombinovat předkompilovaný kód s kódem, který je stále ve vývoji. Každá pozdější kompilace je rychlejší, protože stabilní kód nemusí být rekompilován.

Kdy předkompilovat zdrojový kód

Předkompilovaný kód je užitečný během vývojového cyklu, aby se zkrátila doba kompilace, zejména pokud:

  • Vždy používáte velké tělo kódu, které se mění zřídka.

  • Program obsahuje více modulů, z nichž všechny používají standardní sadu souborů include a stejné možnosti kompilace. V tomto případě je možné všechny zahrnuté soubory předkompilovat do jedné předkompilované hlavičky. Pro více informací o novějších způsobech zpracování záhlaví souborů naleznete v tématu Porovnání jednotek záhlaví, modulů a předkompilovaných hlaviček.

První kompilace (ta, která vytvoří předkompilovaný soubor hlaviček) trvá o něco déle než následné kompilace. Následné kompilace můžou pokračovat rychleji zahrnutím předkompilovaného kódu.

Můžete předkompilovat programy jazyka C i C++. V programování V jazyce C++ je běžné oddělit informace o rozhraní třídy do souborů hlaviček. Tyto hlavičkové soubory lze později zahrnout do programů, které používají třídu. Předkompilováním těchto hlaviček můžete zkrátit dobu potřebnou ke kompilaci programu.

Poznámka:

I když pro každý zdrojový soubor můžete použít pouze jeden předkompilovaný soubor záhlaví (.pch), můžete v projektu použít více .pch souborů.

Dvě volby pro předkompilování kódu

Můžete předkompilovat jakýkoli kód jazyka C nebo C++; Nejste omezeni pouze na předkompilování pouze souborů hlaviček.

Předkompilování vyžaduje plánování, ale nabízí mnohem rychlejší kompilace, pokud předkompilujete jiný zdrojový kód než jednoduché hlavičkové soubory.

Předkompilní kód, když víte, že zdrojové soubory používají běžné sady hlaviček souborů nebo když chcete do předkompilace zahrnout zdrojový kód.

Možnosti předkompilovaného záhlaví jsou /Yc (vytvořit předkompilovaný hlavičkový soubor) a /Yu (použít předkompilovaný hlavičkový soubor).) Slouží /Yc k vytvoření předkompilované hlavičky. Při použití s volitelnou hdrstop direktivou pragma můžete předkompilovat jak soubory hlaviček, /Yc tak zdrojový kód. Vyberte /Yu , pokud chcete použít existující předkompilovanou hlavičku v existující kompilaci. Můžete také použít /Fp s možnostmi /Yc a /Yu zadat alternativní název předkompilované hlavičky.

Referenční články o možnostech kompilátoru pro /Yu a /Yc popisují, jak získat přístup k této funkcionalitě ve vývojovém prostředí.

Předkompilovaná pravidla konzistence hlaviček

Protože soubory PCH obsahují informace o prostředí počítače a informace o adrese paměti o programu, měli byste použít pouze soubor PCH na počítači, ve kterém byl vytvořen.

Pravidla konzistence pro použití předkompilovaných hlaviček pro jednotlivé soubory

Možnost /Yu kompilátoru umožňuje určit, který soubor PCH se má použít.

Při použití souboru PCH kompilátor předpokládá stejné prostředí kompilace, které se projevilo při vytváření souboru PCH, pokud nezadáte jinak. Prostředí kompilace zahrnuje možnosti kompilátoru, pragmy atd. Pokud kompilátor zjistí nekonzistence, vydá upozornění a zjistí nekonzistence, pokud je to možné. Taková upozornění nemusí nutně znamenat problém se souborem PCH; prostě vás varují před možnými konflikty. Požadavky na konzistenci pro soubory PCH jsou popsány v následujících částech.

Konzistence možností kompilátoru

Následující možnosti kompilátoru můžou aktivovat upozornění na konzistenci při použití souboru PCH:

  • Makra vytvořená pomocí možnosti Preprocesor (/D) musí být stejná mezi kompilací, která vytvořila soubor PCH a aktuální kompilaci. Stav definovaných konstant se nekontroluje, ale pokud se tato makra změní, může dojít k nepředvídatelným výsledkům.

  • Soubory PCH nefungují s možnostmi /E a /EP.

  • Soubory PCH musí být vytvořeny pomocí možnosti Generovat informace o procházení (/FR) nebo Vyloučit místní proměnné (/Fr), aby je následné kompilace, které používají soubor PCH, mohly použít.

Kompatibilní s C 7.0 (/Z7)

Pokud se tato možnost projeví při vytvoření souboru PCH, mohou později kompilace, které používají soubor PCH, použít informace o ladění.

Pokud při vytvoření souboru PCH není možnost kompatibilní s C 7.0 (/Z7), pozdější kompilace, které používají soubor PCH, a /Z7 aktivují upozornění. Informace o ladění se umístí do aktuálního .obj souboru a místní symboly definované v souboru PCH nejsou pro ladicí program k dispozici.

Zahrnout konzistenci cesty

Soubor PCH neobsahuje informace o cestě k zahrnutí hlavičky, která byla v platnosti při jeho vytvoření. Pokud používáte soubor PCH, kompilátor vždy používá cestu k zahrnutí hlavičky zadanou v aktuální kompilaci.

Konzistence zdrojového souboru

Když zadáte možnost Use Precompiled Header File (/Yu), kompilátor ignoruje všechny direktivy preprocesoru (včetně pragmas), které se zobrazí ve zdrojovém kódu, které budou předkompilovány. Kompilace určená těmito direktivami preprocesoru musí být stejná jako kompilace použitá pro možnost Create Precompiled Header File (/Yc).

Konzistence direktivy Pragma

Pragmas zpracované během vytváření souboru PCH obvykle ovlivňují soubor, se kterým je později použit soubor PCH. Od comment a message direktivy pragma nemají vliv na zbytek kompilace.

Tyto direktivy mají vliv pouze na kód v souboru PCH; nemají vliv na kód, který později používá soubor PCH:

comment
linesize

message
page

pagesize
skip

subtitle
title

Tyto pragmas se zachovají jako součást předkompilované hlavičky a ovlivňují zbytek kompilace, která používá předkompilovanou hlavičku:

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

Pravidla konzistence pro /Yc a /Yu

Při použití předkompilované hlavičky vytvořené pomocí /Yc nebo /Yukompilátor porovná aktuální prostředí kompilace s prostředím, které existovalo při vytváření souboru PCH. Pro aktuální kompilaci nezapomeňte určit prostředí konzistentní s předchozím prostředím (pomocí konzistentních možností kompilátoru, pragmas atd.). Pokud kompilátor zjistí nekonzistence, vydá upozornění a zjistí nekonzistence, pokud je to možné. Taková upozornění nemusí nutně znamenat problém se souborem PCH; prostě vás varují před možnými konflikty. Následující části popisují požadavky na konzistenci pro předkompilované hlavičky.

Konzistence možností kompilátoru

Tato tabulka uvádí možnosti kompilátoru, které můžou aktivovat upozornění na konzistenci při použití předkompilované hlavičky:

Možnost Název Pravidlo
/D Definujte konstanty a makra Musí být stejná mezi kompilací, která vytvořila předkompilovanou hlavičku a aktuální kompilaci. Stav definovaných konstant se nekontroluje. Nepředvídatelné výsledky ale mohou nastat, pokud vaše soubory závisí na hodnotách změněných konstant.
/E nebo /EP Kopírování výstupu preprocesoru do standardního výstupu Předkompilované hlavičky nefungují s možností /E ani /EP.
/Fr nebo /FR Generování informací o prohlížeči zdrojového kódu Microsoftu /Fr a /FR možnosti, aby byly platné s /Yu možností, musely také platit již při vytváření předkompilované hlavičky. Následné kompilace, které používají předkompilovanou hlavičku, také generují informace o zdrojovém prohlížeči. Informace o prohlížeči jsou umístěny do jednoho .sbr souboru a jsou odkazovány jinými soubory stejným způsobem jako CodeView informace. Umístění informací o zdrojovém prohlížeči nejde přepsat.
/GA, /GD, /GE, /Gwnebo /GW Možnosti protokolu Systému Windows Musí být stejná mezi kompilací, která vytvořila předkompilovanou hlavičku a aktuální kompilaci. Kompilátor vygeneruje upozornění, pokud se tyto možnosti liší.
/Zi Generujte kompletní informace pro ladění Pokud se tato možnost projeví při vytvoření předkompilované hlavičky, můžou následné kompilace, které používají předkompilace, použít tyto informace o ladění. Pokud /Zi není v platnosti při vytvoření předkompilované hlavičky, následné kompilace, které používají předkompilaci, a možnost /Zi vyvolá upozornění. Informace o ladění se umístí do aktuálního souboru objektu a místní symboly definované v předkompilované hlavičce nejsou pro ladicí program k dispozici.

Poznámka:

Předkompilovaná hlavička je určena pouze pro použití ve zdrojových souborech C a C++.

Použití předkompilovaných hlaviček v projektu

Předchozí části představují přehled předkompilovaných hlaviček: /Yc a /Yu, možnost /Fp a pragma hdrstop . Tato část popisuje metodu použití možností ručního předkompilovaného záhlaví v projektu; končí ukázkovým souborem pravidel a kódem, který spravuje.

Další způsob, jak používat možnosti ručního předkompilovaného záhlaví v projektu, je prostudovat si jeden z makefilů umístěných v MFC\SRC adresáři vytvořeném během výchozího nastavení sady Visual Studio. Tyto makefiles používají podobný přístup jako ten uvedený v této sekci. Využívají více maker programu Microsoft Program Maintenance Utility (NMAKE) a nabízejí větší kontrolu nad procesem sestavení.

Soubory PCH v procesu sestavení

Základ kódu softwarového projektu je často obsažen v několika zdrojových souborech C nebo C++, souborech objektů, knihovnách a hlavičkových souborech. Obvykle makefile koordinuje kombinaci těchto prvků do spustitelného souboru. Následující obrázek znázorňuje strukturu makefile, který používá předkompilovanou hlavičku. Názvy maker NMAKE a názvy souborů v tomto diagramu jsou konzistentní s ukázkovým kódem nalezeným v Ukázkovém souboru pravidel pro PCH a ukázkovém kódu pro PCH.

Na obrázku jsou použity tři diagramové prvky k zobrazení toku procesu kompilace. Pojmenované obdélníky představují každý soubor nebo makro; tři makra představují jeden nebo více souborů. Stínované oblasti představují každou akci kompilace nebo propojení. Šipky ukazují, které soubory a makra se během procesu kompilace nebo propojení zkombinují.

Struktura Makefile, který používá předkompilovaný hlavičkový soubor:

Diagram znázorňující ukázkové vstupy a výstupy souboru pravidel, který používá předkompilovaný hlavičkový soubor

Diagram znázorňuje "$(STABLEHDRS)" a "$(BOUNDRY)", které se používají v CL /c /W3 /Yc$(BOUNDRY) applib.cpp myapp.cpp. Výstupem je $(STABLE.PCH). Pak applib.cpp a $(UNSTABLEHDRS) a $(STABLE.PCH) se podávají do CL /c /w3 /Yu $(BOUNDRY) applib.cpp, což produkuje applib.obj. myapp.cpp, $(UNSTABLEHDR), a $(STABLE.PCH) se podávají do CL /c /w3 /Yu $(BOUNDRY) myapp.cpp, což produkuje myapp.obj. Nakonec jsou apllib.obj a myapp.obj kombinovány pomocí LINK /NOD ONERROR:NOEXE $(OBJS), myapp, NUL, $(LIBS), NUL k výrobě myapp.exe.

Počínaje horní částí diagramu jsou STABLEHDRS a BOUNDRY makra NMAKE, ve kterých uvedete soubory, které pravděpodobně nebudou vyžadovat překompilaci. Tyto soubory jsou kompilovány pomocí příkazového řetězce.

CL /c /W3 /Yc$(BOUNDRY) applib.cpp myapp.cpp

Pouze pokud předkompilovaný hlavičkový soubor (STABLE.pch) neexistuje nebo provedete změny souborů uvedených v těchto dvou makrech. V obou případech bude předkompilovaný soubor hlaviček obsahovat kód pouze ze souborů uvedených v STABLEHDRS makrech. Vypište poslední soubor, který chcete předkompilovat v BOUNDRY makrech.

Soubory, které v těchto makrech uvádíte, mohou být buď soubory hlaviček, nebo zdrojové soubory jazyka C nebo C++. (Jeden soubor PCH nelze použít se zdroji jazyka C i C++.) Můžete použít makro hdrstop k zastavení předkompilace v určitém okamžiku v souboru BOUNDRY. Další informace najdete na webu hdrstop.

Dále v diagramu APPLIB.obj představuje kód podpory použitý v konečné aplikaci. Vytvoří se z APPLIB.cpp, souborů uvedených v UNSTABLEHDRS makru a z předkompilovaného kódu z předkompilované hlavičky.

MYAPP.obj představuje konečnou aplikaci. Vytvoří se z MYAPP.cpp, souborů uvedených v UNSTABLEHDRS makru a předkompilovaného kódu z předkompilovaného headeru.

Nakonec se vytvoří spustitelný soubor (MYAPP.EXE) propojením souborů uvedených v OBJS makrech (APPLIB.obj a MYAPP.obj).

Ukázkový makefile pro PCH

Následující makefile používá makra a !IF!ELSE!ENDIF strukturu příkazů řízení toku pro snadnější přizpůsobení vašemu 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

Kromě makra STABLEHDRS, BOUNDRY a UNSTABLEHDRS zobrazených na obrázku "Struktura souboru pravidel, který používá předkompilovaný hlavičkový soubor" v sekci PCH soubory v procesu sestavení tento soubor pravidel poskytuje makro CLFLAGS a makro LINKFLAGS. Tato makra musíte použít k výpisu možností kompilátoru a linkeru, které se použijí bez ohledu na to, jestli sestavíte ladicí nebo konečnou verzi spustitelného souboru aplikace. K dispozici je také LIBS makro, ve kterém zobrazíte seznam knihoven, které projekt vyžaduje.

Soubor makefile také používá !IF, !ELSE, !ENDIF k detekci, zda definujete symbol na příkazovém řádku NMAKE.

NMAKE DEBUG=[1|0]

Tato funkce umožňuje použít stejný soubor makefile během vývoje a pro konečné verze programu. Používá se DEBUG=0 pro konečné verze. Následující příkazové řádky jsou ekvivalentní:

NMAKE
NMAKE DEBUG=0

Pro další informace o souborech viz referenci NMAKE. Viz také možnosti kompilátoru MSVC a možnosti linkeru MSVC.

Příklad kódu pro PCH

Následující zdrojové soubory se používají v souboru pravidel popsaném v souborech PCH v procesu sestavení a ukázkový soubor pravidel pro PCH. Komentáře obsahují důležité informace.

Zdrojový soubor 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

Zdrojový soubor 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

Zdrojový soubor 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

Zdrojový soubor 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";
    }

Zdrojový soubor 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();
}

Viz také

Porovnání jednotek záhlaví, modulů a předkompilovaných hlaviček
Příručka pro kompilaci jazyka C/C++
Možnosti kompilátoru MSVC
Přehled modulů v jazyce C++
Kurz: Import standardní knihovny C++ pomocí modulů
Návod: Vytváření a import jednotek hlaviček v projektech Microsoft C++
Návod: Import knihoven STL jako jednotek hlaviček