Предварительно скомпилированный заголовок - Precompiled header

В компьютерное программирование, а предварительно скомпилированный заголовок это (C или C ++ ) заголовочный файл это собрано в промежуточная форма это быстрее для обработки компилятор. Использование предварительно скомпилированных заголовков может значительно сократить время компиляции, особенно когда применяется к большим файлам заголовков, файлам заголовков, которые включают много других файлов заголовков, или файлам заголовков, которые включены во многих единицы перевода.

Обоснование

в C и C ++ языки программирования, а заголовочный файл это файл, текст которого может быть автоматически включен в другой исходный файл посредством Препроцессор C с помощью директива препроцессора в исходном файле.

Заголовочные файлы иногда могут содержать очень большие объемы исходного кода (например, заголовочные файлы windows.h и Какао / Какао.h на Майкрософт Виндоус и OS X соответственно). Это особенно верно с появлением больших библиотек "заголовков", которые широко используют шаблоны, словно Математическая библиотека Eigen и Библиотеки Boost C ++. Они почти полностью записываются как файлы заголовков, которые пользователь #включаютs, а не связываться во время выполнения. Таким образом, каждый раз, когда пользователь компилирует свою программу, он, по сути, также перекомпилирует многочисленные библиотеки заголовков. (Они будут предварительно скомпилированы в общие объекты или библиотеки динамической компоновки в библиотеках без "заголовков".)

Чтобы сократить время компиляции, некоторые компиляторы позволяют компилировать файлы заголовков в форму, которая быстрее обрабатывается компилятором. Эта промежуточная форма известна как предварительно скомпилированный заголовок, и обычно хранится в файле с расширением .pch или подобное, например .gch под Коллекция компиляторов GNU.

Применение

Например, учитывая файл C ++ source.cpp это включает header.hpp:

//header.hpp...
//source.cpp#включают "header.hpp"...

При компиляции source.cpp впервые с включенной функцией предварительно скомпилированного заголовка компилятор сгенерирует предварительно скомпилированный заголовок, header.pch. В следующий раз, если метка времени этого заголовка не изменилась, компилятор может пропустить этап компиляции, относящийся к header.hpp и вместо этого используйте header.pch прямо.

Общие реализации

Microsoft Visual C и C ++

Microsoft Visual C ++ (версия 6.0 и новее[нужна цитата ]) может предварительно скомпилировать любой код, а не только заголовки.[1]Это можно сделать двумя способами: либо предварительно скомпилировать весь код до файла, имя которого соответствует / Ycимя файла вариант или (когда / Yc указывается без каких-либо имя файла) предварительная компиляция всего кода до первого появления #pragma hdrstop в коде[2][3]Предварительно скомпилированный вывод сохраняется в файле, названном в честь имя файла дано / Yc вариант, с .pch расширение, или в файле, названном в соответствии с именем, предоставленным / Fpимя файла вариант.[3]В / Yu вариант, подчиненный / Yc опция, если используется вместе, заставляет компилятор использовать уже предварительно скомпилированный код из такого файла.[3]

pch.h (назван stdafx.h до Visual Studio 2017[4]) - это файл, созданный Microsoft Visual Studio IDE волшебник, который описывает как стандартную систему, так и конкретный проект включать файлы которые используются часто, но почти никогда не меняются.

В afx в stdafx.h означает расширения платформы приложений. AFX было оригинальным сокращением для Классы Microsoft Foundation (MFC). Хотя имя stdafx.h использовалось по умолчанию в проектах MSVC до версии 2017, любое альтернативное имя можно указать вручную.

Совместимые компиляторы предварительно скомпилируют этот файл, чтобы сократить общее время компиляции. Visual C ++ не будет ничего компилировать до #include "pch.h" в исходном файле, если только опция компиляции /Ю'пч.х ' не отмечен (по умолчанию); предполагается, что весь код в исходном коде до этой строки включительно уже скомпилирован.

лязгать

В лязгать компилятор имеет два механизма.

Первоначальный, более простой и менее мощный механизм был предварительно токенизированные заголовки где поток лексических токенов в одном или нескольких исходных файлах хранится в том, что по сути является кеш токенов, из которого их можно быстрее получить при последующих компиляциях, чем при выполнении лексический анализ снова на исходных исходных файлах.[5]

По сравнению с механизмом полностью предварительно скомпилированного заголовка, у этого есть преимущества независимости от языка, поскольку лексический анализ одинаков для языков C, C ++, Objective C и Objective C ++, а также независимость от архитектуры, поскольку может использоваться один и тот же поток токенов. при компиляции для разных целевых архитектур.[5]Однако у него есть недостаток: в дальнейшем чем простой лексический анализ, требующий синтаксический и семантический анализ потока токенов выполняться при каждой компиляции; и время компиляции, линейно масштабирующееся в зависимости от размера в лексических токенах предварительно токенизированного файла, что не обязательно в случае полноценного механизма предварительной компиляции.[5]

Механизм предварительной токенизации включает несколько второстепенных механизмов для помощи препроцессору: кэширование информации о существовании файла и метки даты, а также запись защита включения чтобы можно было быстро пропустить защищенный код.[5]

Позднее развитие clang представило полноценный механизм предварительно скомпилированных заголовков.[6]Это как токенизирует входной исходный код, так и выполняет его синтаксический и семантический анализ, записывая внутреннюю сгенерированную компилятором абстрактное синтаксическое дерево (Стенд таблица символов в предварительно скомпилированный заголовочный файл.[6]

По сравнению с механизмом предварительно токенизированного заголовка, он масштабируется намного лучше, поскольку чтение предварительно скомпилированного файла заголовка обратно в компилятор не ограничивается тем фактом, что входные данные представляют собой поток (лексических токенов) для линейного чтения файла с использованием последовательного ввода / вывода. О.[6]AST записывается в предварительно скомпилированный заголовочный файл таким образом, что компилятор может прочитать его, используя ввод-вывод с произвольным доступом, в частности не чтение в частях предварительно скомпилированного AST, на которые последующий код фактически не ссылается, что является обычным явлением с заголовками, которые предоставляют большие библиотеки шаблонов.[6]Это устраняет проблему чтения файла кэша, линейно масштабируемого с размером предварительно скомпилированного ввода.[6]

Обратной стороной, однако, является потеря универсальности по сравнению с механизмом предварительной токенизации.[5][6]Предварительно скомпилированный заголовок должен хранить информацию об используемом диалекте языка, вплоть до уровня того, могут ли такие вещи, как стиль C ++ // комментарии включены в языках, отличных от C ++, целевой архитектуре, версии компилятора (точнее, версии внутренней структуры данных AST, которую использует компилятор) и списке предопределенных макросов препроцессора; так что при повторном чтении предварительно скомпилированного файла заголовка компилятор может убедиться, что он использует предварительно скомпилированный заголовок, действительный для данной компиляции.[6]

Схема предварительно скомпилированного заголовка clang с некоторыми улучшениями, такими как возможность для одного предварительно скомпилированного заголовка ссылаться на другой, предварительно скомпилированный заголовок внутреннего использования, также формирует основу для механизма его модулей.[6]Он использует тот же битовый код формат файла, который используется LLVM, инкапсулированные в специфичные для clang разделы внутри Общий формат объектного файла или Расширяемый формат ссылок файлы.[6]

GCC

Предварительно скомпилированные заголовки поддерживаются в GCC (3.4 и новее). Подход GCC аналогичен подходу VC и совместимых компиляторов. GCC сохраняет предварительно скомпилированные версии файлов заголовков с помощью символа ".gch"суффикс. При компиляции исходного файла компилятор проверяет, присутствует ли этот файл в том же каталоге, и по возможности использует его.

GCC может использовать предварительно скомпилированную версию только в том случае, если установлены те же параметры компилятора, что и при компиляции заголовка, и он может использовать не более одного. Кроме того, только инструкции препроцессора могут быть помещены перед предварительно скомпилированным заголовком (потому что он должен быть прямо или косвенно включен через другой нормальный заголовок перед любым компилируемым кодом).

GCC автоматически определяет большинство файлов заголовков по их расширению. Однако, если это не удается (например, из-за нестандартных расширений заголовков), -Икс можно использовать переключатель, чтобы гарантировать, что GCC рассматривает файл как заголовок.

C ++ Builder

В конфигурации проекта по умолчанию C ++ Builder компилятор неявно генерирует предварительно скомпилированные заголовки для всех заголовков, включенных исходным модулем, до строки #pragma hdrstop найден.[7] Предварительно скомпилированные заголовки по возможности используются для всех модулей проекта. Например, при работе с Библиотека визуальных компонентов, обычно включают vcl.h сначала заголовок, который содержит большинство часто используемых файлов заголовков VCL. Таким образом, предварительно скомпилированный заголовок может использоваться всеми модулями проекта, что значительно сокращает время сборки.

Кроме того, C ++ Builder можно настроить на использование определенного файла заголовка в качестве предварительно скомпилированного заголовка, аналогично механизму, предоставляемому Visual C ++.

C ++ Builder 2009 представляет «Мастер предварительно скомпилированных заголовков», который анализирует все исходные модули проекта на предмет включенных файлов заголовков, классифицирует их (т.е. исключает файлы заголовков, если они являются частью проекта или не имеют Включить охрану ) и автоматически генерирует и проверяет предварительно скомпилированный заголовок для указанных файлов.

Смотрите также

использованная литература

  1. ^ MSDN 2015a.
  2. ^ MSDN 2015b.
  3. ^ а б c MSDN 2015c.
  4. ^ "Могу ли я использовать #include" pch.h "вместо #include" stdafx.h "в качестве заголовка предварительной компиляции в Visual Studio C ++?". Переполнение стека.
  5. ^ а б c d е лязг 2018a.
  6. ^ а б c d е ж г час я лязг 2018b.
  7. ^ Сварт 2003, п. 76

Источники

внешние ссылки