Поделиться через


Файлы предкомпилированных заголовков

При создании проекта в Visual Studio в pch.h проект добавляется предварительно скомпилируемый файл заголовка. (В Visual Studio 2017 и более ранних версиях файл был вызван stdafx.h.) Цель файла — ускорить процесс сборки. Здесь следует включить любые стабильные файлы заголовков, например заголовки стандартной библиотеки, такие как <vector>. Предкомпилированный заголовок компилируется только в том случае, если он или какие-либо содержащиеся в нем файлы были изменены. Если изменения вносятся только в исходный код проекта, при сборке будет пропущена компиляция для предкомпилированного заголовка.

Параметры компилятора для предварительно скомпилированных заголовков./Y На страницах свойств проекта параметры находятся в разделе "Свойства>конфигурации C/C++>Precompiled Headers". Можно не использовать предкомпилированные заголовки, а также указать имя файла заголовка и путь к выходному файлу.

Настраиваемый предварительно скомпилированный код

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

Когда следует предварительно компилировать исходный код

Предварительно скомпилированный код полезен во время цикла разработки, чтобы сократить время компиляции, особенно если:

  • Всегда используется большой текст кода, в который редко вносятся изменения.

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

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

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

Примечание.

Хотя для каждого исходного файла можно использовать только один предварительно скомпилируемый заголовок (.pch), можно использовать несколько .pch файлов в проекте.

Два варианта для предварительной компиляции кода

Вы можете предварительно компилировать любой код C или C++; Вы не ограничиваетесь предварительной компиляцией только файлов заголовков.

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

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

Параметры предварительно скомпилированного заголовка: /Yc (создание предварительно скомпилированного файла заголовка) и /Yu (использование предварительно скомпилированного файла заголовка). Используется /Yc для создания предварительно скомпилированного заголовка. При использовании с необязательным hdrstop pragma /Yc позволяет предварительно компилировать файлы заголовков и исходный код. Выберите /Yu для использования существующего предварительно скомпилированного заголовка в существующей компиляции. Можно также использовать /Fp с /Yc параметрами и /Yu для предоставления альтернативного имени предварительно скомпилированного заголовка.

Справочные статьи о параметрах /Yu компилятора и /Yc о том, как получить доступ к этой функции в среде разработки.

Предкомпилированные правила согласованности заголовков

Так как PCH-файлы содержат сведения о среде компьютера и адресе памяти о программе, следует использовать только PCH-файл на компьютере, где он был создан.

Правила согласованности для использования предварительно скомпилированных заголовков для каждого файла

Параметр /Yu компилятора позволяет указать, какой PCH-файл следует использовать.

При использовании PCH-файла компилятор предполагает ту же среду компиляции, которая действует при создании PCH-файла, если не указано в противном случае. Среда компиляции включает параметры компилятора, pragmas и т. д. Если компилятор обнаруживает несогласованность, он выдает предупреждение и по возможности определяет несогласованность. Такие предупреждения не обязательно указывают на проблему с файлом PCH. Они просто предупреждают о возможных конфликтах. Требования к согласованности для файлов PCH описаны в следующих разделах.

Согласованность параметров компилятора

Следующие параметры компилятора могут вызвать предупреждение о несогласованности при использовании файла PCH:

  • Макросы, созданные с помощью параметра препроцессора (/D), должны совпадать между компиляцией, созданной PCH-файлом и текущей компиляцией. Состояние определенных констант не проверяется, но непредсказуемые результаты могут возникать при изменении этих макросов.

  • PCH-файлы не работают с параметрами и /EP параметрами/E.

  • PCH-файлы должны создаваться с помощью параметра "Создать сведения о обзоре" или параметра "Исключить локальные переменные" (/FR/Fr) перед последующими компиляциями, которые используют PCH-файл, могут использовать эти параметры.

Совместимая с C 7.0 (/Z7)

Если этот параметр действует при создании PCH-файла, последующие компиляции, использующие PCH-файл, могут использовать сведения об отладке.

Если параметр C 7.0-Совместимый (/Z7) не действует при создании PCH-файла, последующие компиляции, использующие PCH-файл и /Z7 запускающие предупреждение. Сведения об отладке помещаются в текущий .obj файл, а локальные символы, определенные в PCH-файле, недоступны для отладчика.

Включение согласованности путей

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

Согласованность исходного файла

При указании параметра Use Precompiled Header File (/Yu) компилятор игнорирует все директивы препроцессора (включая pragmas), которые отображаются в исходном коде, который будет предварительно компилирован. Компиляция, указанная такими директивами препроцессора, должна совпадать с компиляцией, используемой для параметра Create Precompiled Header File () (/Yc).

Согласованность pragma

Pragmas, обработанный во время создания PCH-файла, обычно влияет на файл, с которым PCH-файл будет использоваться позже. message И comment pragmas не влияют на оставшуюся часть компиляции.

Эти прагмы влияют только на код в PCH-файле; Они не влияют на код, который позже использует PCH-файл:

comment
linesize

message
page

pagesize
skip

subtitle
title

Эти прагмы сохраняются как часть предкомпилированного заголовка и влияют на оставшуюся часть компиляции, использующую предкомпилированный заголовок:

alloc_text
auto_inline
check_stack
code_seg
data_seg

function
include_alias
init_seg
inline_depth

inline_recursion
intrinsic
optimize
pack

pointers_to_members
setlocale
vtordisp
warning

Правила согласованности для /Yc и /Yu

При использовании предварительно скомпилированного заголовка, созданного с помощью или /Yc /Yu, компилятор сравнивает текущую среду компиляции с той, которая существовала при создании PCH-файла. Не забудьте указать среду, соответствующую предыдущей (с помощью параметров компилятора, прагм и т. д.) для текущей компиляции. Если компилятор обнаруживает несогласованность, он выдает предупреждение и по возможности определяет несогласованность. Такие предупреждения не обязательно указывают на проблему с файлом PCH. Они просто предупреждают о возможных конфликтах. В следующих разделах объясняются требования к согласованности для предкомпилированных заголовков.

Согласованность параметров компилятора

В таблице ниже перечислены параметры компилятора, которые могут вызвать предупреждение о несогласованности при использовании предкомпилированного заголовка.

Вариант Имя. Правило
/D Определение констант и макросов Должны быть одинаковыми в компиляции, создавшей предкомпилированный заголовок, и в текущей компиляции. Состояние определенных констант не проверяется. Однако непредсказуемые результаты могут возникать, если файлы зависят от значений измененных констант.
/E или /EP Копирование выходных данных препроцессора в стандартный вывод Предварительно скомпилированные заголовки не работают с параметром или /EP параметром/E.
/Fr или /FR Создание сведений о браузере исходного кода Майкрософт /Fr /FR Чтобы параметры были допустимыми с параметром/Yu, они также должны быть в действии при создании предварительно скомпилированного заголовка. При последующих компиляциях, использующих предкомпилированный заголовок, также создаются сведения о браузере исходного кода. Сведения браузера помещаются в один .sbr файл и ссылаются на другие файлы таким же образом, как и сведения CodeView. Невозможно переопределить размещение сведений о исходном браузере.
/GA, /GD, /GE, /Gw или /GW Параметры протокола Windows Должны быть одинаковыми в компиляции, создавшей предкомпилированный заголовок, и в текущей компиляции. Компилятор выдает предупреждение, если эти параметры отличаются.
/Zi Создание полной отладочной информации Если при создании предкомпилированного заголовка этот параметр включен, последующие компиляции, использующие предварительную компиляцию, могут использовать отладочную информацию. Если /Zi он не действует при создании предварительно скомпилированного заголовка, последующие компиляции, использующие предварительную компиляцию, и /Zi параметр активирует предупреждение. Сведения об отладке помещаются в текущий файл объекта, а локальные символы, определенные в предварительно компилированного заголовка, недоступны для отладчика.

Примечание.

Средство предварительно откомпилированных заголовков предназначено для использования только в исходных файлах C и C++.

Использование предварительно скомпилированных заголовков в проекте

В предыдущих разделах представлен обзор предкомпилированных заголовков: /Yc и /Yu, параметра /FP и прагмы hdrstop. В этом разделе описывается метод использования в проекте параметров заголовков, предкомпилированных вручную. В конце раздела приводится пример файла makefile и кода, который управляет им.

Для другого подхода к использованию параметров предварительно скомпилированного заголовка вручную в проекте изучите один из файлов makefile, расположенных в MFC\SRC каталоге, созданном во время настройки Visual Studio по умолчанию. Эти файлы makefile принимают аналогичный подход к тому, который представлен в этом разделе. Они обеспечивают более широкий доступ к макросам программы обслуживания (NMAKE) и обеспечивают более широкий контроль над процессом сборки.

PCH-файлы в процессе сборки

База кода проекта программного обеспечения часто содержится в нескольких исходных файлах C или C++, файлах объектов, библиотеках и файлах заголовков. Как правило, файл makefile координирует объединение этих элементов в исполняемый файл. На следующем рисунке показана структура файла makefile, использующего файл предкомпилированного заголовка. Имена макросов NMAKE и имена файлов на этой схеме согласованы с примером кода, найденного в примере файла makefile для PCH и примера кода для PCH.

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

 Схема описана в тексте ниже схемы.
Структура файла makefile, использующего предварительно скомпилированные файл заголовка:

На схеме показан пример входных и выходных данных файла makefile, который использует файл предкомпилированного заголовка.

На схеме показаны данные "$(STABLEHDRS)" и "$(BOUNDRY)" в cl /c /W3 /Yc$(BOUNDRY) applib.cpp myapp.cpp. Выходные данные этого значения — $(STABLE. PCH). Затем applib.cpp и $(UNSTABLEHDRS) и $(STABLE). Канал PCH) в CL /c /w3 /Yu $(BOUNDRY) applib.cpp, который создает applib.obj. myapp.cpp, $(UNSTABLEHDR) и $(STABLE. PCH) в канал CL /c /w3 /Yu $(BOUNDRY) myapp.cpp, который создает myapp.obj. Наконец, applib.obj и myapp.obj объединяются link /NOD ONERROR:NOEXE $(OBJS), myapp, NUL, $(LIBS), NUL для производства myapp.exe.

Начиная с верхней части схемы, оба STABLEHDRS и BOUNDRY являются макросами NMAKE, в которых не требуется перекомпиляция файлов. Эти файлы компилируются с помощью командной строки

CL /c /W3 /Yc$(BOUNDRY) applib.cpp myapp.cpp

только в том случае, если предварительно скомпилированные файлы заголовков (STABLE.pch) не существуют или если вы вносите изменения в файлы, перечисленные в двух макросах. В любом случае предварительно скомпилированные файлы заголовков будут содержать код только из файлов, перечисленных в макросе STABLEHDRS . Перечислите последний файл, который необходимо предварительно скомпилировать в макросе BOUNDRY .

Файлы, перечисленные в этих макросах, могут быть файлами заголовков или файлами исходного кода C или C++. (Один PCH-файл нельзя использовать как с источниками C, так и с C++.) Макрос можно использовать hdrstop для остановки предварительной компиляции в какой-то момент в BOUNDRY файле. Дополнительные сведения см. в разделе hdrstop.

Далее на схеме представлен код поддержки, APPLIB.obj используемый в последнем приложении. Он создается из APPLIB.cppфайлов, перечисленных в UNSTABLEHDRS макросе, и предварительно скомпилированного кода из предварительно скомпилированного заголовка.

MYAPP.obj представляет окончательное приложение. Он создается из MYAPP.cppфайлов, перечисленных в UNSTABLEHDRS макросе, и предварительно скомпилированного кода из предварительно скомпилированного заголовка.

Наконец, исполняемый файл (MYAPP.EXE) создается путем связывания файлов, перечисленных в OBJS макросе (APPLIB.obj и MYAPP.obj).

Пример файла makefile для PCH

В следующем файле makefile используются макросы и !IF!ELSEструктура команд управления , !ENDIF которая упрощает адаптацию проекта.

# Makefile : Illustrates the effective use of precompiled
#            headers in a project
# Usage:     NMAKE option
# option:    DEBUG=[0|1]
#            (DEBUG not defined is equivalent to DEBUG=0)
#
OBJS = myapp.obj applib.obj
# List all stable header files in the STABLEHDRS macro.
STABLEHDRS = stable.h another.h
# List the final header file to be precompiled here:
BOUNDRY = stable.h
# List header files under development here:
UNSTABLEHDRS = unstable.h
# List all compiler options common to both debug and final
# versions of your code here:
CLFLAGS = /c /W3
# List all linker options common to both debug and final
# versions of your code here:
LINKFLAGS = /nologo
!IF "$(DEBUG)" == "1"
CLFLAGS   = /D_DEBUG $(CLFLAGS) /Od /Zi
LINKFLAGS = $(LINKFLAGS) /COD
LIBS      = slibce
!ELSE
CLFLAGS   = $(CLFLAGS) /Oselg /Gs
LINKFLAGS = $(LINKFLAGS)
LIBS      = slibce
!ENDIF
myapp.exe: $(OBJS)
    link $(LINKFLAGS) @<<
$(OBJS), myapp, NUL, $(LIBS), NUL;
<<
# Compile myapp
myapp.obj  : myapp.cpp $(UNSTABLEHDRS)  stable.pch
    $(CPP) $(CLFLAGS) /Yu$(BOUNDRY)    myapp.cpp
# Compile applib
applib.obj : applib.cpp $(UNSTABLEHDRS) stable.pch
    $(CPP) $(CLFLAGS) /Yu$(BOUNDRY)    applib.cpp
# Compile headers
stable.pch : $(STABLEHDRS)
    $(CPP) $(CLFLAGS) /Yc$(BOUNDRY)    applib.cpp myapp.cpp

STABLEHDRSBOUNDRYПомимо макросов, UNSTABLEHDRS показанных на рисунке "Структура файла Makefile, использующего предварительно скомпилированные файл заголовка" в PCH-файлах в процессе сборки, этот файл makefile предоставляет CLFLAGS макрос и LINKFLAGS макрос. Эти макросы необходимо использовать для перечисления параметров компилятора и компоновщика, которые применяются при сборке отладочной или финальной версии исполняемого файла приложения. Существует также LIBS макрос, в котором перечислены библиотеки, необходимые для проекта.

Файл makefile также использует !IF!ELSE, !ENDIF чтобы определить, определен ли символ в командной DEBUG строке NMAKE:

NMAKE DEBUG=[1|0]

Эта функция позволяет использовать тот же файл makefile во время разработки и для окончательных версий программы. Используется DEBUG=0 для окончательных версий. Следующие строки команды являются эквивалентными.

NMAKE
NMAKE DEBUG=0

Дополнительные сведения о файлах makefile см . в справочнике ПО NMAKE. Также см . параметры компилятора MSVC и параметры компоновщика MSVC.

Пример кода для PCH

Следующие исходные файлы используются в файле makefile, описанном в PCH-файлах в процессе сборки и образце файла makefile для PCH. Комментарии содержат важные сведения.

Исходный файл ANOTHER.H:

// ANOTHER.H : Contains the interface to code that is not
//             likely to change.
//
#ifndef __ANOTHER_H
#define __ANOTHER_H
#include<iostream>
void savemoretime( void );
#endif // __ANOTHER_H

Исходный файл STABLE.H:

// STABLE.H : Contains the interface to code that is not likely
//            to change. List code that is likely to change
//            in the makefile's STABLEHDRS macro.
//
#ifndef __STABLE_H
#define __STABLE_H
#include<iostream>
void savetime( void );
#endif // __STABLE_H

Исходный файл UNSTABLE.H:

// UNSTABLE.H : Contains the interface to code that is
//              likely to change. As the code in a header
//              file becomes stable, remove the header file
//              from the makefile's UNSTABLEHDR macro and list
//              it in the STABLEHDRS macro.
//
#ifndef __UNSTABLE_H
#define __UNSTABLE_H
#include<iostream>
void notstable( void );
#endif // __UNSTABLE_H

Исходный файл APPLIB.CPP:

// APPLIB.CPP : This file contains the code that implements
//              the interface code declared in the header
//              files STABLE.H, ANOTHER.H, and UNSTABLE.H.
//
#include"another.h"
#include"stable.h"
#include"unstable.h"
using namespace std;
// The following code represents code that is deemed stable and
// not likely to change. The associated interface code is
// precompiled. In this example, the header files STABLE.H and
// ANOTHER.H are precompiled.
void savetime( void )
    { cout << "Why recompile stable code?\n"; }
void savemoretime( void )
    { cout << "Why, indeed?\n\n"; }
// The following code represents code that is still under
// development. The associated header file is not precompiled.
void notstable( void )
    { cout << "Unstable code requires"
            << " frequent recompilation.\n";
    }

Исходный файл MYAPP.CPP:

// MYAPP.CPP : Sample application
//             All precompiled code other than the file listed
//             in the makefile's BOUNDRY macro (stable.h in
//             this example) must be included before the file
//             listed in the BOUNDRY macro. Unstable code must
//             be included after the precompiled code.
//
#include"another.h"
#include"stable.h"
#include"unstable.h"
int main( void )
{
    savetime();
    savemoretime();
    notstable();
}

См. также

Сравнение единиц заголовков, модулей и предварительно скомпилированных заголовков
Справочные сведения о сборке C/C++
Обзор параметровкомпилятора MSVC в C++
Руководство. Импорт стандартной библиотеки C++ с помощью модулей
Создание и импорт блоков заголовков в проектах Visual C++
Пошаговое руководство. Импорт библиотек STL в качестве блоков заголовков