Введение
Оптимизированный тип файла в компьютерном программировании
В компьютерном программировании предварительно скомпилированный заголовок (PCH) — это (C или C++) заголовочный файл, который компилируется в промежуточное представление, ускоряющее его обработку компилятором. Использование предварительно скомпилированных заголовков может существенно сократить время компиляции, особенно применительно к большим заголовочным файлам, заголовочным файлам, включающим множество других заголовочных файлов, или заголовочным файлам, которые включаются во многие единицы трансляции.
Обоснование
В языках программирования C и C++ заголовочный файл – это файл, текст которого может быть автоматически включен в другой исходный файл препроцессором C с помощью директивы препроцессора в этом исходном файле. Заголовочные файлы иногда могут содержать очень большой объем исходного кода (например, файлы заголовков windows.h и Cocoa/Cocoa.h в Microsoft Windows и OS X соответственно). Это особенно актуально с появлением крупных "заголовочных" библиотек, активно использующих шаблоны, таких как математическая библиотека Eigen и библиотеки Boost C++. Они почти полностью написаны в виде заголовочных файлов, которые пользователь подключает с помощью #include, а не связывает во время выполнения. Таким образом, при каждой компиляции программы пользователь фактически перекомпилирует множество заголовочных библиотек. (В отличие от этого, в обычных библиотеках код предварительно компилируется в разделяемые объекты или динамические библиотеки). Для сокращения времени компиляции некоторые компиляторы позволяют компилировать заголовочные файлы в промежуточную форму, которая быстрее обрабатывается. Эта промежуточная форма называется предварительно скомпилированным заголовком и обычно хранится в файле с расширением pch или аналогичным, например, gch в GNU Compiler Collection.
Использование
Например, если дан исходный файл C++.cpp, включающий header.hpp:
//header.hpp
//source.cpp
#include "header.hpp"
#include "header. hpp"
При компиляции source.cpp в первый раз с включенной функцией предварительно скомпилированных заголовков, компилятор сгенерирует предварительно скомпилированный заголовок header.pch. В следующий раз, если временная метка этого заголовка не изменилась, компилятор может пропустить этап компиляции, относящийся к header.hpp, и вместо этого использовать header.pch напрямую.
Microsoft Visual C и C++
Microsoft Visual C++ (версия 6.0 и более поздняя) может предварительно компилировать любой код, а не только файлы заголовков. Это файл, генерируемый мастером среды разработки Microsoft Visual Studio, который описывает как стандартные системные, так и специфичные для проекта включаемые файлы, которые часто используются, но редко изменяются. Префикс `afx` в `stdafx.h` обозначает расширения фреймворка приложений. `AFX` – это первоначальная аббревиатура для Microsoft Foundation Classes (MFC). Хотя имя `stdafx.h` использовалось по умолчанию в проектах MSVC до версии 2017, любое другое имя может быть указано вручную. Совместимые компиляторы предварительно компилируют этот файл для сокращения общего времени компиляции. Visual C++ не будет компилировать код, расположенный перед `#include "pch.h"` в исходном файле, если не снять флажок с опции компиляции `/Yu'pch.h'` (по умолчанию установлено); компилятор предполагает, что весь код в исходном файле до и включая эту строку уже скомпилирован.
ССК
Предварительно скомпилированные заголовки поддерживаются в GCC (версии 3.4 и новее). Подход GCC аналогичен подходу VC и совместимых компиляторов. GCC сохраняет предварительно скомпилированные версии файлов заголовков с расширением ".gch". При компиляции исходного файла компилятор проверяет, существует ли этот файл в той же директории, и использует его, если это возможно. GCC может использовать предварительно скомпилированную версию только в том случае, если установлены те же параметры компиляции, что и при компиляции заголовка, и может использовать не более одного такого файла. Кроме того, перед включением предварительно скомпилированного заголовка могут располагаться только директивы препроцессора (поскольку он должен быть включен напрямую или косвенно через другой обычный заголовок, перед любым компилируемым кодом). GCC автоматически определяет большинство файлов заголовков по их расширению. Однако, если это не удается (например, из-за нестандартных расширений заголовков), можно использовать опцию -x, чтобы гарантировать, что GCC будет рассматривать файл как заголовок.
Звук
Компилятор Clang добавил поддержку PCH в Clang 2.5 / LLVM 2.5 в 2009 году. Компилятор токенизирует входной исходный код и выполняет синтаксический и семантический анализ заголовков, записывая внутреннее генерируемое им абстрактное синтаксическое дерево (AST) и таблицу символов в предварительно скомпилированный файл заголовка. При возможности, предварительно скомпилированные заголовки используются совместно для всех модулей проекта. Например, при работе с библиотекой визуальных компонентов, обычно первым включается заголовочный файл vcl.h, который содержит большинство часто используемых заголовочных файлов VCL. Таким образом, предварительно скомпилированный заголовок может быть использован во всех модулях проекта, что значительно сокращает время сборки. Кроме того, C++Builder можно настроить на использование определенного заголовочного файла в качестве предварительно скомпилированного заголовка, аналогично механизму, предоставляемому Visual C++. C++Builder 2009 представляет "Мастер предварительной компиляции заголовков", который анализирует все исходные модули проекта на предмет включенных заголовочных файлов, классифицирует их (например, исключает заголовочные файлы, если они являются частью проекта или не имеют защиты от повторного включения) и автоматически генерирует и тестирует предварительно скомпилированный заголовок для указанных файлов.
Претокенный заголовок
Претокенизированный заголовок (PTH) — это файл заголовка, хранящийся в формате, прошедшем лексический анализ, но не подвергнутом семантическим операциям. PTH использовался в Clang до поддержки PCH и также был опробован в одной из веток GCC. По сравнению с полноценным механизмом PCH, PTH обладает преимуществами языковой (и диалектной) независимости, поскольку лексический анализ схож для языков семейства C, и архитектурной независимости, так как один и тот же поток токенов может быть использован при компиляции для различных целевых архитектур.