3.22 Использование предварительно скомпилированных заголовков ¶
Часто в крупных проектах множество файлов заголовков включается в каждый исходный файл. Время, которое занимает компилятор для обработки этих файлов заголовков снова и снова, может составлять почти всё время, необходимое для сборки проекта. Чтобы ускорить сборку, 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
- Случайное расположение адресного пространства (ASLR) может привести к тому, что файлы PCH не будут бинарно идентичны. Если вы полагаетесь на стабильные содержимое файлов PCH, отключите ASLR при создании файлов PCH.
Во всех этих случаях, за исключением последнего, компилятор автоматически игнорирует предварительно скомпилированный заголовок, если эти условия не выполняются. Если вы обнаружите комбинацию параметров, которая не работает и не приводит к игнорированию предварительно скомпилированного заголовка, пожалуйста, рассмотрите возможность отправить отчёт об ошибке, см. Сообщения об ошибках.
Если вы используете различные параметры при создании и использовании предварительно скомпилированного заголовка, фактическое поведение является смесью поведения для этих параметров. Например, если вы используете -g для создания предварительно скомпилированного заголовка, но не при его использовании, вы можете или не можете получить отладочную информацию для процедур в предварительно скомпилированном заголовке.
© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-10.5.0/gcc/Precompiled-Headers.html