Sdílet prostřednictvím


Návod: Sestavení a import jednotek hlaviček v Microsoft Visual C++

Tento článek se zabývá sestavováním a importem jednotek hlaviček pomocí sady Visual Studio 2022. Informace o importu hlaviček standardní knihovny C++ jako jednotek hlaviček najdete v tématu Návod: Import knihoven STL jako jednotek hlaviček. Ještě rychlejší a robustnější způsob importu standardní knihovny najdete v tématu Kurz: Import standardní knihovny C++ pomocí modulů.

Jednotky hlaviček jsou doporučenou alternativou k předkompilovaným souborům hlaviček (PCH). Jednotky hlaviček se snadněji nastavují a používají, jsou na disku výrazně menší, poskytují podobné výhody výkonu a jsou flexibilnější než sdílené PCH.

Chcete-li porovnat jednotky záhlaví s jinými způsoby zahrnutí funkcí do programů, přečtěte si téma Porovnání jednotek záhlaví, modulů a předkompilovaných hlaviček.

Požadavky

Pokud chcete použít jednotky hlaviček, potřebujete Visual Studio 2019 16.10 nebo novější.

Co je jednotka záhlaví

Jednotka záhlaví je binární reprezentace souboru hlavičky. Jednotka záhlaví končí příponou .ifc . Stejný formát se používá pro pojmenované moduly.

Důležitým rozdílem mezi jednotkou záhlaví a souborem záhlaví je to, že jednotka záhlaví není ovlivněná definicemi maker mimo jednotku záhlaví. To znamená, že nemůžete definovat symbol preprocesoru, který způsobí, že se jednotka záhlaví chová jinak. Po importu jednotky záhlaví je jednotka záhlaví již zkompilována. To se liší od způsobu zacházení se souborem #include . Zahrnutý soubor může být ovlivněn definicí makra mimo soubor záhlaví, protože soubor záhlaví prochází preprocesorem při kompilaci zdrojového souboru, který ho obsahuje.

Jednotky záhlaví je možné importovat v libovolném pořadí, což neplatí pro soubory hlaviček. Pořadí souborů hlaviček záleží, protože definice maker definované v jednom souboru hlaviček můžou mít vliv na následující soubor hlaviček. Definice maker v jedné jednotce záhlaví nemohou ovlivnit jinou jednotku záhlaví.

Všechno viditelné ze souboru záhlaví je viditelné také z jednotky záhlaví, včetně maker definovaných v rámci jednotky záhlaví.

Před importem musí být soubor záhlaví přeložen do jednotky záhlaví. Výhodou jednotek hlaviček oproti předkompilovaným souborům hlaviček (PCH) je, že je lze použít v distribuovaných buildech. Pokud zkompilujete .ifc a program, který ho importuje se stejným kompilátorem, a cílíte na stejnou platformu a architekturu, může být jednotka hlaviček vytvořená na jednom počítači spotřebována na jiném počítači. Na rozdíl od PCH se při změně jednotky záhlaví změní jenom na to, co na ní závisí. Jednotky záhlaví můžou mít velikost až do velikosti menší než .pch.

Jednotky hlaviček omezují méně omezení požadovaných kombinací přepínačů kompilátoru, které se používají k vytvoření jednotky hlavičky a ke kompilaci kódu, který ho využívá, než PCH. Některé kombinace přepínačů a definice maker ale můžou způsobit porušení jednoho pravidla definice (ODR) mezi různými jednotkami překladu.

A konečně, jednotky hlaviček jsou flexibilnější než PCH. S PCH se nemůžete rozhodnout, že do PCH vložíte jenom jednu hlavičku – kompilátor zpracuje všechny. S jednotkami záhlaví, i když je zkompilujete do statické knihovny, přenesete do aplikace jenom obsah jednotky záhlaví, kterou importujete.

Jednotky hlaviček představují krok mezi soubory hlaviček a moduly C++20. Poskytují některé výhody modulů. Jsou robustnější, protože na ně nemají vliv vnější definice maker– takže je můžete importovat v libovolném pořadí. A kompilátor je může zpracovat rychleji než soubory hlaviček. Jednotky záhlaví ale nemají všechny výhody modulů, protože jednotky záhlaví zveřejňují makra definovaná v nich (moduly ne). Na rozdíl odmodulůch K označení privátní implementace se soubory hlaviček se používají různé techniky, jako je přidání úvodních podtržítka k názvům nebo vložení věcí do oboru názvů implementace. Modul nezpřístupňuje privátní implementaci v žádném formuláři, takže to nemusíte dělat.

Zvažte nahrazení předkompilovaných hlaviček jednotkami záhlaví. Získáte stejnou výhodu rychlosti, ale s dalšími výhodami hygieny kódu a flexibility.

Způsoby kompilace jednotky hlaviček

Soubor můžete zkompilovat do jednotky hlaviček několika způsoby:

  • Sestavte projekt sdílené jednotky záhlaví. Tento přístup doporučujeme, protože poskytuje větší kontrolu nad organizací a opětovnou použitím importovaných jednotek hlaviček. Vytvořte projekt statické knihovny, který obsahuje požadované jednotky záhlaví, a pak na něj naimportujte jednotky záhlaví. Návod k tomuto přístupu najdete v tématu Sestavení projektu statické knihovny jednotek hlaviček pro jednotky hlaviček.

  • Zvolte jednotlivé soubory, které se mají přeložit na jednotky záhlaví. Tento přístup vám dává kontrolu nad tím, co se považuje za jednotku hlavičky. Je také užitečné, když musíte zkompilovat soubor jako jednotku hlavičky, protože nemá výchozí příponu (.ixx, .cppm, .h, .hpp), by se normálně nezkompilovala do jednotky hlavičky. Tento přístup je ukázaný v tomto názorném postupu. Pokud chcete začít, přečtěte si téma Přístup 1: Překlad konkrétního souboru do jednotky záhlaví.

  • Automaticky prohledávat a sestavovat jednotky hlaviček. Tento přístup je pohodlný, ale je nejvhodnější pro menší projekty, protože nezaručuje optimální propustnost sestavení. Podrobnosti o tomto přístupu najdete v tématu Přístup 2: Automatická kontrola jednotek hlaviček.

  • Jak je uvedeno v úvodu, můžete vytvářet a importovat soubory hlaviček STL jako jednotky hlaviček a automaticky zacházet #include se záhlavími knihovny STL jako import bez přepsání kódu. Postup najdete v návodu : Import knihoven STL jako jednotek hlaviček.

Přístup 1: Překlad konkrétního souboru do jednotky hlavičky

V této části se dozvíte, jak zvolit konkrétní soubor, který se má přeložit na jednotku záhlaví. Zkompilujte hlavičkový soubor jako jednotku hlaviček pomocí následujících kroků v sadě Visual Studio:

  1. Vytvořte nový projekt konzolové aplikace C++.

  2. Obsah zdrojového souboru nahraďte následujícím způsobem:

    #include "Pythagorean.h"
    
    int main()
    {
        PrintPythagoreanTriple(2,3);
        return 0;
    }
    
  3. Přidejte volaný Pythagorean.h hlavičkový soubor a nahraďte jeho obsah tímto kódem:

    #ifndef PYTHAGOREAN
    #define PYTHAGOREAN
    
    #include <iostream>
    
    inline void PrintPythagoreanTriple(int a, int b)
    {
        std::cout << "Pythagorean triple a:" << a << " b:" << b << " c:" << a*a + b*b << std::endl;
    }
    #endif
    

Nastavení vlastností projektu

Pokud chcete povolit jednotky hlaviček, nejprve nastavte standard jazyka C++ na /std:c++20 nebo novější pomocí následujícího postupu:

  1. V Průzkumník řešení klikněte pravým tlačítkem myši na název projektu a zvolte Vlastnosti.
  2. V levém podokně okna stránek vlastností projektu vyberte Obecné vlastnosti>konfigurace.
  3. V rozevíracím seznamu Standard jazyka C++ vyberte ISO C++20 Standard (/std:c++20) nebo novější. Kliknutím na tlačítko OK zavřete dialogové okno.

Zkompilujte soubor hlaviček jako jednotku záhlaví:

  1. V Průzkumník řešení vyberte soubor, který chcete zkompilovat jako jednotku záhlaví (v tomto případě Pythagorean.h). Klikněte pravým tlačítkem myši na soubor a zvolte Vlastnosti.

  2. Nastavte rozevírací seznam Vlastnosti>konfigurace Obecné>typy položek na kompilátor C/C++ a zvolte OK.

    Screenshot that shows changing the item type to C/C++ compiler.

Když tento projekt sestavíte později v tomto názorném postupu, Pythagorean.h přeloží se do jednotky hlaviček. Přeloží se do jednotky záhlaví, protože typ položky pro tento soubor hlaviček je nastavený na kompilátor C/C++, a protože výchozí akce pro .h soubory a .hpp nastavené tímto způsobem je přeložit soubor do jednotky záhlaví.

Poznámka:

Pro tento názorný postup to není nutné, ale poskytuje se pro vaše informace. Pokud chcete zkompilovat soubor jako jednotku hlaviček, která nemá výchozí příponu souboru jednotky hlaviček, například .cpp nastavit vlastnosti>konfigurace C/C++>Advanced>Compile As to Compile as C++ Header Unit (/exportHeader):Screenshot that shows changing Configuration properties > C/C++ > Advanced > Compile As to Compile as C++ Header Unit (/exportHeader).

Změna kódu pro import jednotky záhlaví

  1. Ve zdrojovém souboru pro ukázkový projekt změňte #include "Pythagorean.h" na import "Pythagorean.h"; Nezapomeňte na koncové středníky. Vyžaduje se pro import příkazy. Protože se jedná o soubor hlaviček v místním adresáři projektu, použili jsme uvozovky s příkazem import : import "file";. Pokud chcete zkompilovat jednotku záhlaví ze systémového záhlaví, použijte ve vlastních projektech úhlové závorky: import <file>;

  2. Řešení sestavíte tak, že v hlavní nabídce vyberete Sestavit>řešení. Spusťte ho, abyste viděli, že vytváří očekávaný výstup: Pythagorean triple a:2 b:3 c:13

Ve vlastních projektech opakujte tento proces a zkompilujte soubory hlaviček, které chcete importovat jako jednotky hlaviček.

Pokud chcete převést jenom několik souborů hlaviček na jednotky hlaviček, je tento přístup dobrý. Pokud ale máte mnoho souborů hlaviček, které chcete zkompilovat, a potenciální ztráta výkonu sestavení se převáží pohodlím automatického zpracování systému sestavení, přečtěte si následující část.

Pokud vás zajímá konkrétně import hlaviček knihovny STL jako jednotek hlaviček, přečtěte si téma Návod: Import knihoven STL jako jednotek hlaviček.

Přístup 2: Automatické prohledávání a sestavení jednotek hlaviček

Vzhledem k tomu, že kontrola všech zdrojových souborů pro jednotky hlaviček a jejich sestavení nějakou dobu trvá, je pro menší projekty nejvhodnější následující přístup. Nezaručuje optimální propustnost sestavení.

Tento přístup kombinuje dvě nastavení projektu sady Visual Studio:

  • Kontrola zdrojů závislostí modulů způsobí, že systém sestavení zavolá kompilátor, aby se před kompilací souborů, které na nich závisí, vytvořily všechny importované moduly a jednotky hlaviček. V kombinaci s příkazem Translate Includes to Imports se všechny soubory hlaviček zahrnuté ve zdroji, které jsou také zadané v header-units.json souboru umístěném ve stejném adresáři jako soubor hlaviček, zkompilují do jednotek hlaviček.
  • Funkce Translate Includes to Imports považuje soubor hlaviček za soubor záhlaví, import pokud #include odkazuje na soubor hlaviček, který lze zkompilovat jako jednotku hlavičky (jak je uvedeno v header-units.json souboru) a zkompilovaná jednotka hlaviček je k dispozici pro soubor hlaviček. V opačném případě se soubor záhlaví považuje za normální #include. Soubor header-units.json se používá k automatickému sestavení jednotek záhlaví pro každou z nich #includebez duplikace symbolů.

Tato nastavení můžete zapnout ve vlastnostech projektu. Uděláte to tak, že kliknete pravým tlačítkem myši na projekt v Průzkumník řešení a zvolíte Vlastnosti. Pak zvolte Vlastnosti>konfigurace C/C++>Obecné.

Screenshot that shows the project properties screen with Configuration highlighted and All Configurations selected. Under C/C++ > General, Scan Sources for Module Dependencies is highlighted and set to yes, and Translate Includes to Imports is highlighted and set to Yes (/translateInclude)

Vyhledat zdroje závislostí modulů lze nastavit pro všechny soubory v projektu ve vlastnostech projektu, jak je znázorněno zde, nebo pro jednotlivé soubory ve vlastnostech souboru. Moduly a jednotky hlaviček se vždy naskenují. Tuto možnost nastavte, pokud máte .cpp soubor, který importuje jednotky záhlaví, které chcete vytvořit automaticky a které ještě nemusí být sestaveny.

Tato nastavení spolupracují na automatickém sestavování a importu jednotek hlaviček za těchto podmínek:

  • Prohledávat zdroje závislostí modulů prohledává zdroje souborů a jejich závislostí, které je možné považovat za jednotky hlaviček. Soubory s příponou .ixxa soubory, které mají vlastnosti> Souboru C/C++>Compile As nastavenou na Compile as C++ Header Unit (/export), se vždy prohledávají bez ohledu na toto nastavení. Kompilátor také hledá import příkazy pro identifikaci závislostí jednotek hlaviček. Pokud /translateInclude je zadán, kompilátor také vyhledá direktivy #include , které jsou také zadány v header-units.json souboru, aby se choval jako jednotky hlaviček. Graf závislostí je sestaven ze všech modulů a jednotek hlaviček v projektu.
  • Translate Includes to Imports When the compiler encounter an #include statement, and a matching header unit file (.ifc) exists for the specified header file, the compiler import the header unit místo zacházet se soubor hlavičky jako s #include. V kombinaci s vyhledáváním závislostí najde kompilátor všechny soubory hlaviček, které lze zkompilovat do jednotek hlaviček. Kompilátor se poraďte s povoleným seznamem, aby se rozhodl, které soubory hlaviček se můžou zkompilovat do jednotek hlaviček. Tento seznam je uložený v header-units.json souboru, který musí být ve stejném adresáři jako zahrnutý soubor. Příklad souboru najdete header-units.json v instalačním adresáři pro Visual Studio. Kompilátor například používá k určení, %ProgramFiles%\Microsoft Visual Studio\2022\Enterprise\VC\Tools\MSVC\14.30.30705\include\header-units.json zda lze hlavičku standardní knihovny šablon zkompilovat do jednotky hlaviček. Tato funkce existuje, aby sloužila jako most se starším kódem, abyste získali některé výhody jednotek hlaviček.

Soubor header-units.json slouží ke dvěma účelům. Kromě určení, které soubory hlaviček je možné zkompilovat do jednotek hlaviček, minimalizuje duplicitní symboly, aby se zvýšila propustnost sestavení. Další informace o duplikaci symbolů najdete v referenčních informacích k jazyku C++ header-units.json.

Tyto přepínače a header-unit.json poskytují některé výhody jednotek záhlaví. Pohodlí vychází z nákladů na propustnost sestavení. Tento přístup nemusí být pro větší projekty nejlepší, protože nezaručuje optimální časy sestavení. Stejné soubory hlaviček se také můžou opakovaně zpracovávat, což zvyšuje čas sestavení. V závislosti na projektu ale může být vhodné ho využít.

Tyto funkce jsou navržené pro starší verze kódu. V případě nového kódu přejděte na moduly místo jednotek hlaviček nebo #include souborů. Kurz použití modulů najdete v kurzu k modulům Name (C++).

Příklad způsobu, jakým se tato technika používá k importu souborů hlaviček STL jako jednotek hlaviček, najdete v tématu Návod: Import knihoven STL jako jednotek hlaviček.

Důsledky preprocesoru

K vytvoření a použití jednotek hlaviček se vyžaduje standardní preprocesor C99/C++11, který vyhovuje. Kompilátor umožňuje, aby nový preprocesor C99/C++11 při kompilaci jednotek hlaviček implicitně přidal /Zc:preprocessor do příkazového /exportHeader řádku při každém použití libovolné formy. Při pokusu o vypnutí dojde k chybě kompilace.

Povolení nového preprocesoru ovlivňuje zpracování variadických maker. Další informace najdete v části Poznámky k makrům Variadic.

Viz také

/translateInclude
/exportHeader
/headerUnit
header-units.json
Porovnání jednotek záhlaví, modulů a předkompilovaných hlaviček
Přehled modulů v jazyce C++
Kurz: Import standardní knihovny C++ pomocí modulů
Návod: Import knihoven STL jako jednotek hlaviček