hdrstop pragma | Microsoft Learn
Twitter LinkedIn Facebook Адрес электронной почты
- Статья
- Чтение занимает 2 мин
Предоставляет более полный контроль над именами файлов с предварительной компиляцией и расположением, в котором сохраняется состояние компиляции.
Синтаксис
#pragma hdrstop[(«имя_файла«)]
Имя файла является именем предкомпилированного файла заголовка для использования или создания (в зависимости от того, указан ли /Yu параметр или /Yc ). Если имя файла не содержит спецификацию пути, предполагается, что предкомпилированный заголовочный файл находится в том же каталоге, что и исходный файл.
Если файл C или C++ содержит объект hdrstoppragma при компиляции с параметром /Yc , компилятор сохраняет состояние компиляции вплоть до расположения pragma . Компилированное состояние любого кода, следующего за, pragma не сохраняется.
Используйте файл filename , чтобы присвоить имя файлу предкомпилированного заголовка, в котором сохраняется компилированное состояние. Пробел между hdrstop и filename является необязательным.
Имя файла, указанное в параметре hdrstoppragma , является строкой и подчиняется ограничениям любой строки C или C++. В частности, необходимо заключить его в кавычки и использовать escape-символ (обратная косая черта), \ чтобы указать имена каталогов. Например:
#pragma hdrstop( "c:\\projects\\include\\myinc.pch" )
Имя предкомпилированного файла заголовка определяется в соответствии со следующим правилам в порядке приоритета.
Аргумент для
/Fpпараметра компилятораАргумент filename для
#pragma hdrstopБазовое имя исходного файла с расширением PCH
Если ни один из /Yc параметров hdrstoppragma и /Yu не указывает имя файла, базовое имя исходного файла используется в качестве базового имени файла предкомпилированного заголовка.![]()
Команды предварительной обработки также можно использовать для выполнения замены макроса.
#define INCLUDE_PATH "c:\\progra~1\\devstsu~1\\vc\\include\\" #define PCH_FNAME "PROG.PCH" . . . #pragma hdrstop( INCLUDE_PATH PCH_FNAME )
Следующие правила управляют тем, hdrstoppragma где можно разместить.
Пример
#include <windows.h> // Include several files
#include "myhdr.h"
__inline Disp( char *szToDisplay ) // Define an inline function
{
// ... // Some code to display string
}
#pragma hdrstop
В этом примере элемент hdrstoppragma появляется после включения двух файлов и определения встроенной функции. Это расположение, на первый взгляд, кажется нечетным pragma . Однако следует учесть, что с помощью параметров /Yc предварительной компиляции вручную и /Yu с hdrstoppragma помощью можно выполнить предварительную компиляцию всех исходных файлов или даже встроенного кода.
Компилятор Майкрософт не ограничивает предварительную компиляцию только объявлений данных.
См. также раздел
Директивы pragma и __pragma Ключевые слова и _Pragma
как ускорить компиляцию с помощью предкомпилированных заголовков
compilation speeds …
С++ Builder Language Guide
Вместо вступления сразу приведу пример. Полная сборка (build) проекта, содержащего около 170 cpp-модулей, при использовании предкомпилированных заголовков происходит за 811 секунд, при этом число обработанных компилятором строк составляет 1,808,780. При компиляции того же проекта без использования предкомпилированных заголовков, время сборки составляет 2399 секунд, а число строк, обработанных компилятором — 45,261,820. Впечатляет, не так ли? Плата за это ускорение, в принципе не велика — предкомпилированный образ, размер которого около 40 Мб.
При компиляции исходных текстов, компилятор должен обработать все *.cpp файлы проекта и все включенные в них *.h — файлы. При этом обрабатываются как пользовательские заголовочные файлы, так и стандартные, такие как vcl.h или Word2k.h. Количество кода, находящегося в стандартных заголовках может быть очень большим, например размер файла Word2k.h превышает 5 Мб, в нем больше 130 000 строк кода.
Принцип действия предкомпилированных заголовков
Для управления предкомпилированными предназначена директива компилятора #pragma hdrstop. Все заголовочные файлы, включенные до этой директивы, помещаются в один образ, например:
#include <vcl.h>
#include <string>
#pragma hdrstop
Такая последовательность создаст образ, содержащий скомпилированные vcl.
Таким образом, для повторного использования предкомпилированного заголовка необходимо выполнение двух условий:
— состав включенных до директивы hdrstop файлов должен быть тем же
— последовательность включения файлов до директивы hdrstop должна быть той же
Сократить затраты на компиляцию стандартных заголовков до минимума можно только в том случае, если скомпилировать один образ, содержащий все стандартные заголовки, необходимые для проекта. Для этого нужно, чтобы:
- — ВСЕ cpp-файлы проекта имели одинаковый блок включений до директивы hdrstop
— в этот блок должны входить ВСЕ стандартные заголовочные файлы, необходимые для проекта
Выполнить эти условия достаточно просто, для этого в начало каждого cpp-файла необходимо поместить следующие строки:
#include <pch.h>
#pragma hdrstop
где pch.h — файл, содержащий включения всех стандартных заголовков:
#ifndef PCH_H
#define PCH_H
#define INC_VCLDB_HEADERS
#define INC_VCLEXT_HEADERS
#include <vcl.h>
#include <sysset.h>
#include <IniFiles.hpp>
#include <AppEvnts.hpp>
#include <ActnMan.hpp>
...
#endif
Полный текст моей версии этого файла приведен в конце статьи. На h-файлы, входящие в предкомпилированный образ, накладывается ограничение — в них не должно быть инициализированных данных, например, в math.hpp есть строки:
рекомендации
static const Extended NaN = 0.0 / 0.0;
static const Extended Infinity = 1.0 / 0.0;
Из-за наличия этих констант включить math.hpp в файл pch.h нельзя.
Кстати, С++ Builder при добавлении новых модулей в проект реализует описанную стратегию управления предкомпилированными заголовками.
Например, при создании нового приложения, файл Unit1.cpp будет таким:
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
....
Если посмотреть на текст vcl.h, то можно увидеть, что он является оболочкой для включения большого числа других стандартных заголовочных файлов.
Как в существующем проекте перейти к использованию предкомпилированных заголовков
Даже в большом проекте перейти к использованию предкомпилированных заголовков достаточно просто.
Первым делом нужно создать сам заголовочный файл pch.h. Его нужно разместить в папке с проектом, содержимое этого файла приведено в конце статьи.
Затем в свойствах проекта нужно включить кэширование предкомпилированных заголовков, рекомендуется также указать «персональный» файл, в котором будет храниться образ предкомпилированных заголовков: Project — Options — закладка Compiler, группа «Pre-compiled headers».

После этого в начало каждого cpp-модуля необходимо вставить 2 строки:
#include "pch.h"
#pragma hdrstop
Все ранее включенные заголовочные файлы остаются на своих местах, их удалять не надо. Например:
#include "pch.h" // включает vcl.h, string и т.д.
#pragma hdrstop
#include <vcl.h>
#include <string>
...
Так как во всех стандартных заголовках применяются стражи повторного включения, то повторное их упоминание не влечет за собой повторного включения.
В принципе, при использовании pch.h, техническая потребность во включении стандартных заголовков исчезает. Однако, полезно все же указывать все необходимые для каждого конкретного модуля заголовки ниже директивы #pragma hdrstop.
Во-первых, это в некоторой степени документирует модуль — по включаемым файлам можно судить, какими возможностями пользуется этот модуль. Во-вторых, это облегчает повторное использование модуля в других проектах, в которых либо не используется pch.h, либо его содержимое может быть другим.
Теоретически можно еще больше повысить эффективность компиляции, если включить в pch.h не только стандартные, но и все пользовательские заголовочные файлы. Практически, так как пользовательские заголовки меняются достаточно часто, это может повлечь за собой частую перекомпиляцию pch.h, что негативно скажется на времени компиляции. Кроме того, пользовательские заголовки обычно не бывают очень большими и компилируются очень быстро. Поэтому включать их pch.h не целесообразно.
Как проверить, что предкомпилированные заголовки используются эффективно
При добавлении в проект новых файлов нужно не забывать включать в них pch.h, иначе для них не будет использован общий предкомпилированный образ.
Такая же ситуация может возникнуть, если в каком-то модуле включаются стандартные заголовки, которые не вошли в pch.h. Для того, чтобы отследить такие файлы, есть несколько способов:
— визуальное наблюдение за процессом компиляции. Обычно, число строк компилируемых в одном файле не должно превышать 10000-15000 строк
— если для проекта выбран индивидуальный файл для хранения образа предкомпилированных заголовков и этот файл называется pch.csm, то нужно обратить внимание на наличие вспомогательных файлов с именами pch.#00, pch.#01 и т.д. Если для всех файлов проекта используется один и тот же предкомпилированный образ, то вспомогательный файл должен быть только один — pch.#00. Если таких файлов больше, это значит что для каких-то cpp-модулей создаются дополнительные образы.
— в свойствах проекта включить опцию Show General Messages (Project -> Options -> закладка Compiler). Тогда в окно Messages будет выводится дополнительная информация в процессе компиляции, в том числе информация о загрузке предкомпилированных заголовков.
Если для файла загружен предкомпилированный образ, то в окне Messages после его имени будет выведено «[C++] Loaded pre-compiled headers». Текст pch.h
#ifndef PCH_H
#define PCH_H
#define INC_VCLDB_HEADERS
#define INC_VCLEXT_HEADERS
#include <vcl.h>
/* Все, что подключается предыдущими 3-мя строчками
// Core (minimal) Delphi RTL headers
#include <System.hpp>
#include <Types.hpp>
#include <Windows.hpp>
#include <Messages.hpp>
#include <SysUtils.hpp>
#include <Classes.hpp>
// Core (minimal) VCL headers
#if defined(INC_VCL)
#include <Controls.hpp>
#include <Graphics.hpp>
#include <Forms.hpp>
#include <Dialogs.hpp>
#include <StdCtrls.hpp>
#include <ExtCtrls.hpp>
// VCL Database related headers
#if defined(INC_VCLDB_HEADERS)
#include <DBCtrls.hpp>
#include <DB.hpp>
#include <DBTables.hpp>
#endif // INC_VCLDB_HEADERS
// Full set of VCL headers
#if defined(INC_VCLEXT_HEADERS)
#include <Buttons.hpp>
#include <ChartFX.hpp>
#include <ComCtrls.hpp>
#include <DBCGrids.hpp>
#include <DBGrids.hpp>
#include <DBLookup.hpp>
#include <DdeMan.hpp>
#include <FileCtrl.hpp>
#include <GraphSvr.hpp>
#include <Grids.hpp>
#include <MPlayer.hpp>
#include <Mask.hpp>
#include <Menus.hpp>
#include <OleCtnrs.hpp>
#include <OleCtrls.hpp>
#include <Outline.hpp>
#include <Tabnotbk.hpp>
#include <Tabs.hpp>
#include <VCFImprs.hpp>
#include <VCFrmla1.hpp>
#include <VCSpell3.hpp>
#endif // INC_VCLEXT_HEADERS
#endif // INC_VCL
*/
#include <sysset.h>
#include <IniFiles.hpp>
#include <AppEvnts.hpp>
#include <ActnMan.hpp>
#include <ActnCtrls.hpp>
#include <BandActn.hpp>
#include <CustomizeDlg.hpp>
#include <ImgList.hpp>
#include <ToolWin.hpp>
#include <ExtDlgs.hpp>
#include <ActnList.hpp>
#include <IBDatabase.hpp>
#include <IBCustomDataSet.hpp>
#include <IBQuery.hpp>
#include <IBTable.hpp>
#include <IBSQL.hpp>
#include <IBServices.hpp>
#include <math.h>
#include <assert.h>
#include <complex.h>
#include <values.h>
#include <map>
#include <list>
#include <set>
#include <vector>
#include <algorithm>
#include <functional>
#include <string>
#include <memory>
#include <fstream>
//нестандартные компоненты RxLib и EhLib
#include "CURREDIT.hpp"
#include "RXSpin.hpp"
#include "RxCalc.hpp"
#include "RxCombos.hpp"
#include "APPUTILS.hpp"
#include "RXDBCtrl.hpp"
#include "Placemnt.hpp"
#include "DBGridEh.hpp"
#endif
О вышеизложенном
Если по поводу изложенного материала есть вопросы и замечания, то я готов их принять — пишите
[email protected] .
P.S.
Мне несколько раз сообщали о проблеме с предкомпилированными заголовками — что Builder начинает выдавать предупреждение «Dialogs.hpp(437): W8058 Cannot create pre-compiled header: initialized data in header» и не создает предкомпилированный заголовок.
Из-за чего это возникает, я так и не понял, но, как написал мне Алеутдинов Сергей Харизович, ему удалось найти обходной путь:
цитата:Проблему удалось решить «обходным манёвром».
Создал файл заголовков AllHeaders.hpp, куда включил все не VCL хёдеры (DevExpress, FIBPlus, собственные редко изменяемые заголовки и т.д. )
В каждый файл проекта вставил три строки:
#include <vcl.h>
#include <AllHeaders.hpp>
#pragma hdrstop
Вроде прошло.
прагма hdrstop | Microsoft Узнайте
Обратная связь Редактировать
Твиттер LinkedIn Фейсбук Эл. адрес
- Статья
- 2 минуты на чтение
Дает вам больше контроля над именами файлов предварительной компиляции и над расположением, в котором сохраняется состояние компиляции.
Синтаксис
#pragma hdrstop[( » имя файла » ) ]
Имя файла — это имя предварительно скомпилированного файла заголовка для использования или создания (в зависимости от того, указано ли /Yu или /Yc ).
Если имя файла не содержит спецификацию пути, предполагается, что предварительно скомпилированный заголовочный файл находится в том же каталоге, что и исходный файл.
Если файл C или C++ содержит hdrstop прагма при компиляции с /Yc компилятор сохраняет состояние компиляции до местоположения прагмы. Скомпилированное состояние любого кода, следующего за прагмой, не сохраняется.
Используйте имя файла , чтобы назвать предварительно скомпилированный файл заголовка, в котором сохраняется скомпилированное состояние. Пробел между hdrstop и имя файла является необязательным. Имя файла, указанное в прагме hdrstop , является строкой и подчиняется ограничениям любой строки C или C++. В частности, вы должны заключить его в кавычки и использовать escape-символ (обратная косая черта, \ ), чтобы указать имена каталогов.
Например:
#pragma hdrstop( "c:\\projects\\include\\myinc.pch" )
Имя предварительно скомпилированного заголовочного файла определяется по следующим правилам в порядке старшинства:
Аргумент опции компилятора
/FpАргумент имени файла для
#pragma hdrstopБазовое имя исходного файла с расширением PCH
Если ни один из параметров /Yc и /Yu или прагма hdrstop не указывает имя файла, базовое имя исходного файла используется в качестве базового имени предварительно скомпилированного заголовка файл.
Вы также можете использовать команды предварительной обработки для замены макроса следующим образом:
#define INCLUDE_PATH "c:\\progra~1\\devstsu~1\\vc\\include\\" #define PCH_FNAME "PROG.PCH" . . . #pragma hdrstop (INCLUDE_PATH PCH_FNAME)
Следующие правила определяют место размещения прагмы hdrstop :
Пример
#includeh> // Включить несколько файлов #include "myhdr.h" __inline Disp( char *szToDisplay ) // Определение встроенной функции { // ... // Какой-то код для отображения строки } # прагма hdrstop
В этом примере прагма hdrstop появляется после включения двух файлов и определения встроенной функции. Поначалу это место может показаться странным для прагмы. Учтите, однако, что при использовании параметров ручной предварительной компиляции /Yc и /Yu с прагмой hdrstop позволяет предварительно скомпилировать целые исходные файлы или даже встроенный код. Компилятор Microsoft не ограничивает вас предварительной компиляцией только объявлений данных.
См. также
Директивы Pragma и ключевые слова __pragma и _Pragma
Обратная связь
Отправить и просмотреть отзыв для
Этот продукт Эта страница
Просмотреть все отзывы о странице
C++ — Что делает #pragma hdrstop без параметра при использовании в нескольких файлах?
спросил
Изменено 4 года, 8 месяцев назад
Просмотрено 8к раз
Какова практическая ценность («что это делает») помещения #pragma hdrstop (без параметра имени файла) в пару исходных (cpp) файлов?
Обратите внимание, что документы MSDN (еще раз) для меня ясны как грязь.
Изменить/Примечание: я спрашиваю об этом, потому что этот ответ и статья, на которую он ссылается, рекомендуют это. Но я не понимаю, какая польза от того, что у него есть отдельный файл pch для каждой единицы компиляции.
- c++
- visual-c++
- precompiled-headers
Ответ на первоначальный вопрос заключается в том, что цель наличия #pragma hdrstop в файле без установленного /Yc или /Yu заключается в том, что он игнорируется, и поэтому вы можно настроить конфигурацию сборки, которая строится без предварительно скомпилированных заголовков, и другие конфигурации сборки, которые создают С предварительно скомпилированными заголовками, и вам не нужно для этого изменять код или заголовки, которые вообще включены.
Подробнее…
В примечаниях к MSDN говорится, что «Прагма hdrstop дает вам дополнительный контроль над именами файлов предварительной компиляции и над расположением, в котором сохраняется состояние компиляции».
что верно, но не совсем очевидно, насколько это может быть полезно…
В двух словах.
- Помещение #pragma hdrstop в исходный файл, который не скомпилирован с параметрами /Yc или /Yu, не имеет никакого эффекта.
- Если вы установили /Yu для файла, то hdrstop сообщает компилятору отбросить все до строки, в которой появляется hdrstop, и вместо этого вставить предварительно скомпилированный заголовок.
- Если для файла задан параметр /Yc, то hdrstop означает сохранение всего скомпилированного состояния для всего до строки, в которой hdrstop появляется в качестве предварительно скомпилированного заголовка.
Хитрость заключается в использовании /Yc и /Yu без дополнительного имени файла заголовка; просто установите переключатель «использовать» или «создать» и оставьте поле редактирования «через заголовок» пустым (или отредактируйте файл проекта…).
Итак, у вас есть 1 файл, возможно с именем PrecompiledHeader.cpp, который включает заголовки, которые вы хотите включить в предварительно скомпилированный заголовок, и который имеет #pragma hdrstop в конце списка включаемых файлов.
Этот ОДИН файл скомпилирован с параметром /Yc.
Затем у вас есть все остальные файлы cpp с #pragma hdrstop после включаемых файлов, которые находятся в предварительно скомпилированном заголовке. Все эти файлы скомпилированы с параметром /Yu.
Это приводит к тому, что PrecompiledHeader.cpp создает ваш (в данном примере) один файл pch и все остальные файлы, используя этот единственный файл pch.
Преимущество этого заключается в том, что НИ ОДИН из ваших файлов не должен включать «глобальный» предварительно скомпилированный заголовочный файл для создания заголовков, поэтому нет stdafx.h или чего-то еще. Это означает, что вы можете настроить конфигурацию сборки, которая строит БЕЗ предварительно скомпилированных заголовков, где все строки #pragma hdrstop просто игнорируются.
Это «хорошо», потому что это означает, что вы можете иметь единую конфигурацию сборки «без предварительного компиляции», которая позволяет вам быстро разрабатывать (вы можете изменить один заголовок и НЕ заставлять мир перестраиваться) и другие «обычные» конфигурации, которые ДЕЙСТВУЮТ.
использовать предварительно скомпилированные заголовки.
2
Весь код до #pragma hdrstop будет частью предварительно скомпилированного заголовка. Если параметр имени файла не указан, именем заголовка будет базовое имя исходного файла с расширением .PCH, как указано в документации:
Имя предварительно скомпилированного заголовочного файла определяется в соответствии с следующие правила, в порядке старшинства:
Аргумент параметра компилятора /Fp
Аргумент имени файла для #pragma hdrstop
Базовое имя исходного файла с расширением .PCH
Итак, если у вас есть это в файле с именем blah.cpp , он создаст файл с именем blah.pch , IFF скомпилирован с /Yc (который должен был быть установлен только в одном файле).
1
Если #pragma hdrstop не используется в вашем проекте C/C++, вы должны иметь специальный файл .
cpp в качестве исходного файла для созданного .pch.
При использовании #pragma hdrstop в файле .cpp, с которым вы хотите создать файл .pch, файл .cpp может иметь другое полезное содержимое после строки #pragma hdrstop . Когда вы впервые скомпилируете этот файл .cpp с параметром компиляции /Yc, вы получите файл .pch и файл .obj. Когда вы изменяете файл .cpp и перекомпилируете его с параметром компиляции /Yu, компилятор заменяет содержимое перед строкой #pragma hdrstop файлом .pch и перекомпилирует часть после строки #pragma hdrstop , создайте новый файл .obj, что экономит время компиляции. Очень полезно, чтобы ваш проект имел только один исходный файл.
Для исходных файлов, использующих только головные файлы предварительной компиляции, #pragma hdrstop является ориентиром для компилятора, какая часть должна быть заменена файлом .pch, поэтому вам не нужно указывать имя файла заголовка с параметром компиляции /Yu.
h>
hpp>
h>
hpp"
д. )