Předkompilované hlavičky ve Visual C++

Máte velký projekt a zdá se vám, že se kompiluje příliš dlouho a mohlo by to být i rychlejší ? Tento článek poradí s použitím předkompilovaných hlaviček při programování v prostředí MS Visual Studia.

Předkompilované hlavičky ? Nerozumím.

V praxi obsahuje každý zdrojový soubor v C/C++ někde na začátku direktivu #include, která vkládá do zdrojového textu jiný soubor, většinou s příponou .H, .HPP nebo .HXX. Je samozřejmě možné takto vložit i soubor .CPP, ale není to obvyklé. Důvodem použití této direktivy namísto skutečného vložení obsahu souboru je možnost opakovaného použití různých hlavičkových souborů (angl. header files) pro více zdrojových souborů.

Na rozdíl od jazyka Pascal použitého v prostředí Delphi (kde je obdobnou technikou vkládání zkompilovaných souborů - unitů) jsou hlavičkové soubory v C/C++ vkládány ve zdrojovém tvaru. To znamená, že při kompilaci zdrojového souboru je nutné zkompilovat i soubory hlavičkové. Jejich velikost (a tím pádem i doba kompilace) nejen že není zanedbatelná, naopak tvoří podstatnou část z doby kompilace zdrojového souboru. Např. když vložíte do zdrojového souboru

#include <windows.h>

znamená to vložení dalších až několika MB zdrojových textů. Ačkoliv velikost samotného souboru Windows.h je méně než 10 KB (přesná velikost závisí na verzi SDK, kterou máte), tento soubor inkluduje další a další, které opět vkládají další a další ...

Většina projektů větších než klasický Hello, world !!! se skládá z více modulů a každý z nich obsahuje jednu nebo více direktiv #include. Při kompilaci celého projektu pak dochází k několikanásobné kompilaci všech hlavičkových souborů, což samozřejmě prodlužuje dobu kompilace. Ze své praxe pamatuji projekty, jejichž kompletní překlad trval několik hodin nebo dokonce přes celou noc. Ale i když překlad trvá "jen" čtvrt hodiny, je to velice otravné a snižuje to produktivitu práce.

Pokud nebereme v úvahu koupi nového počítače s co největší pamětí a nejrychlejšími SCSI disky, je jedním z možných řešení pro zkrácení doby kompilace projektu použití tzv. předkompilovaných hlaviček (angl. Precompiled headers). Finta spočívá v tom, že při kompilaci jednoho ze zdrojových souborů se zkompilované hlavičkové soubory uloží do samostatného souboru, který je pak načten při kompilaci ostatních zdrojových souborů. Tato metoda zefektivňuje kompilaci projektů tím více, čím větší počet zdrojových souborů projekt obsahuje a čím větší počet hlavičkových souborů se kompiluje.

Jak to udělat, aby to fungovalo ?

K tomu, aby překompilované hlavičky dobře fungovaly, musejí všechny soubory v projektu inkludnout stejný hlavičkový soubor. Pro projekty psané ve Win API je to většinou soubor windows.h, pro projekty psané v MFC je to většinou StdAfx.h. Je samozřejmě možné vytvořit hlavičkový soubor "vše v jednom", který inkluduje všechny hlavičkové soubory nutné pro kompilaci všech souborů projektu. Pokud v nějakém modulu potřebujeme vložit nějaký hlavičkový soubor navíc, můžeme jej pak dát přímo za společnou hlavičku, nebo jej můžeme vložit do společné hlavičky.

Nastavení projektu ve Visual C++

Nastavení prvního zdrojového souboru Nastavení dalších zdrojových souborů

Jestliže všechny (nebo alespoň většina) zdrojových souborů splňuje podmínky popsanou v předchozím odstavci, můžeme nastavit předkompilované hlavičky pro projekt. V nastaveních projektu (Menu "Project\Settings", karta "C/C++", kategorie "Precompiled headers" nastavte pro celý projekt "Use precompiled header file (.pch)" a do pole "Through header" zadejte jméno společného hlavičkového souboru. Pro zvolený (libovolný) zdrojový modul nastavte "Create precompiled header file (.pch)" a do pole "Through header" zadejte jméno společného hlavičkového souboru.

Nezapomeňte stejným způsobem nastavit předkompilované hlavičky i pro verzi Release (a pokud máte více sestavovacích konfigurací, tak i pro ty ostatní).

Pokud jste vytvořili projekt pomocí App Wizardu v MFC, tak je projekt takto již nastaven. Soubor StdAfx.cpp slouží k vytvoření předkompilované hlavičky, ostatní soubory tuto hlavičku používají.

Některé chyby hlášené překladačem

V souvislosti s předkompilovanými hlavičkami může překladač nahlásit některé chyby:

error C2143: syntax error : missing ';' before 'PCH creation point'

Tato chyba znamená že v jednom z hlavičkových souborů, které jsou zahrnuté do tvorby předkompilovaných hlaviček, chybí středník. Mě osobně se to stává když zapomenu středník za definicí struktury nebo třídy v hlavičkovém souboru.

fatal error C1010: unexpected end of file while looking for precompiled header directive

Soubor při jehož kompilaci tato chyba vznikla, nemá požadované pořadí vložených hlavičkových souborů jako ten, který byl použit k vytvoření předkompilovaných hlaviček. Např.

// StdAfx.cpp
#define _UNICODE
#define UNICODE
#include <tchar.h>
#include <string.h>
#include <windows.h>
a
// WinMain.cpp
#define _UNICODE
#define UNICODE
#include <tchar.h>
#include <windows.h>

Zde vidíme, že v souboru WinMain.cpp je jiné pořadí vkládání hlavičkových souborů než ve StdAfx.cpp. Tato chyba se často stává tehdy, když do projektu vložíte zdrojový text z jiného projektu. Buďto tento soubor odstraňte ze seznamu předkompilovaných hlaviček (Zvolte volbu "Not using precompiled headers" pro tento soubor) nebo upravte inkludy tak, aby souhlasily se souborem, který byl určen k vytvoření předkompilovaných hlaviček.