3.21 Использование предварительно скомпилированных заголовков
В больших проектах часто используется множество файлов заголовков, которые включаются в каждый исходный файл. Время, затрачиваемое компилятором на обработку этих файлов заголовков снова и снова, может составлять почти всё время, необходимое для сборки проекта. Чтобы ускорить сборку, GCC позволяет вам предварительно скомпилировать файл заголовка.
Чтобы создать файл предварительно скомпилированного заголовка, просто скомпилируйте его, как любой другой файл, при необходимости, используя опцию -x, чтобы заставить драйвер обрабатывать его как файл заголовка C или C++ . Возможно, вам понадобится инструмент, подобный make, чтобы поддерживать актуальность предварительно скомпилированного заголовка, когда изменяются содержащиеся в нём заголовки.
Файл предварительно скомпилированного заголовка ищется, когда в процессе компиляции встречается #include. При поиске включённого файла (см. Пути поиска в Препроцессоре C), компилятор ищет предварительно скомпилированный заголовок в каждой директории, перед тем, как искать файл включения в этой директории. Искомое имя — это имя, указанное в #include, с добавленным к нему ‘.gch’. Если файл предварительно скомпилированного заголовка не может быть использован, он игнорируется.
Например, если у вас #include "all.h", и у вас all.h.gch находится в той же директории, что и all.h, то предварительно скомпилированный файл заголовка используется, если это возможно, в противном случае используется исходный заголовок.
В качестве альтернативы, вы можете поместить файл предварительно скомпилированного заголовка в директорию и использовать -I, чтобы убедиться, что эта директория будет просматриваться перед (или вместо) директорией, содержащей исходный заголовок. Затем, если вы хотите убедиться, что файл предварительно скомпилированного заголовка всегда используется, вы можете поместить в эту директорию файл с тем же именем, что и исходный заголовок, содержащий команду #error.
Это также работает с -include. Таким образом, ещё один способ использования предварительно скомпилированных заголовков, подходящий для проектов, не задуманных с учётом предварительно скомпилированных заголовков, заключается в том, чтобы взять большинство файлов заголовков, используемых проектом, включить их из другого файла заголовков, предварительно скомпилировать этот файл заголовков и использовать -include для предварительно скомпилированного заголовка. Если файлы заголовков имеют защиту от многократного включения, они пропускаются, поскольку уже были включены (в предварительно скомпилированный заголовок).
Если вам нужно предварительно скомпилировать один и тот же файл заголовка для разных языков, целевых платформ или опций компилятора, вы можете вместо этого создать директорию с именем, подобным all.h.gch, и поместить каждый предварительно скомпилированный заголовок в эту директорию, возможно, используя -o. Не имеет значения, как вы назовёте файлы в директории; каждый предварительно скомпилированный заголовок в директории рассматривается. Первый встреченный предварительно скомпилированный заголовок в директории, который подходит для этой компиляции, используется; они ищутся без какой-либо определённой последовательности.
Существует множество других возможностей, ограниченных только вашей фантазией, здравым смыслом и ограничениями вашей системы сборки.
Файл предварительно скомпилированного заголовка может быть использован только при соблюдении этих условий:
- В одной конкретной компиляции может быть использован только один предварительно скомпилированный заголовок.
- Предварительно скомпилированный заголовок не может быть использован после появления первого токена C. Вы можете иметь директивы препроцессора перед предварительно скомпилированным заголовком; вы не можете включить предварительно скомпилированный заголовок изнутри другого заголовка.
- Файл предварительно скомпилированного заголовка должен быть создан для того же языка, что и текущая компиляция. Вы не можете использовать предварительно скомпилированный заголовок C для компиляции C++.
- Файл предварительно скомпилированного заголовка должен быть создан той же бинарной программой-компилятором, что и текущая компиляция.
- Любые макросы, определённые до включения предварительно скомпилированного заголовка, должны быть определены точно так же, как и при генерации предварительно скомпилированного заголовка, или не должны влиять на предварительно скомпилированный заголовок, что обычно означает, что они вообще не появляются в нём.
Опция -D — это один из способов определения макроса перед включением предварительно скомпилированного заголовка; использование
#defineтакже может это сделать. Также существуют некоторые опции, которые неявно определяют макросы, такие как -O и -Wdeprecated; то же правило применяется к макросам, определённым таким образом. - Если при использовании предварительно скомпилированного заголовка выводятся данные отладки (с помощью -g или аналогичных опций), то тот же вид данных отладки должен был выводиться при построении предварительно скомпилированного заголовка. Однако предварительно скомпилированный заголовок, построенный с использованием -g, может быть использован в компиляции, когда данные отладки не выводятся.
- В целом должны использоваться те же опции -m при построении и использовании предварительно скомпилированного заголовка. См. Опции субмодели для случаев, когда это правило ослаблено.
- Каждая из следующих опций должна быть одинаковой при построении и использовании предварительно скомпилированного заголовка:
-fexceptions
- Некоторые другие опции командной строки, начинающиеся с -f, -p или -O, должны быть определены так же, как и при генерации предварительно скомпилированного заголовка. В настоящее время неясно, какие опции можно менять, а какие нельзя; самый безопасный выбор — использовать точно такие же опции при генерации и использовании предварительно скомпилированного заголовка. Известно, что следующие опции безопасны:
-fmessage-length= -fpreprocessed -fsched-interblock -fsched-spec -fsched-spec-load -fsched-spec-load-dangerous -fsched-verbose=number -fschedule-insns -fvisibility= -pedantic-errors
Во всех этих случаях, за исключением последнего, компилятор автоматически игнорирует предварительно скомпилированный заголовок, если эти условия не выполнены. Если вы обнаружите комбинацию опций, которая не работает и не приводит к игнорированию предварительно скомпилированного заголовка, пожалуйста, рассмотрите возможность отправки отчёта об ошибке, см. Ошибки.
Если вы используете различные опции при генерации и использовании предварительно скомпилированного заголовка, фактическое поведение будет смесью поведения опций. Например, если вы используете -g для генерации предварительно скомпилированного заголовка, но не при его использовании, вы можете или не можете получить данные отладки для процедур в предварительно скомпилированном заголовке.
Предыдущий: Переменные окружения, Вверх: Вызов GCC [Оглавление][Индекс]
© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-8.5.0/gcc/Precompiled-Headers.html