Что делает #pragma hdrstop
If a C or C++ file contains a hdrstop pragma when compiled with either /YX or /Yc, the compiler saves the state of the compilation up to the location of the pragma. The compiled state of any code that follows the pragma is not saved.
Всё равно неясно для чего это нужно и нужно ли вообще.
Прошло более 5 лет
#1
20:14, 2 сен 2010
Собственно тоже сталкнулся с этим, Быдлер постоянно сует ее в чистых проектах, что делает сия директива? Я ее просто удаляю, но может она зачем-то нужна?
#2
20:27, 2 сен 2010
Типа PCH, тока не понятно, для чего так, если есть нормальные средства для этого.
#3
20:27, 2 сен 2010
MAMONT-92 [REBORN]
А ты загугли.
#4
20:28, 2 сен 2010
Ну на мсдне вроде все понятно написано, сохраняет все состояние компиляции до этой прагмы, если файл откомпилированного заголовка указан то он вступает в силу с только после этой прагмы, если не указан то берется дефолтный, опять же таки только после этой прагмы
#5
20:29, 2 сен 2010
кароче можно просто удалять и не волнует, так?
#6
20:29, 2 сен 2010
Wraith
> А ты загугли.
а я через гуголь и попал сюда.
#7
20:29, 2 сен 2010
MAMONT-92 [REBORN]
> кароче можно просто удалять и не волнует, так?
если стоит вначале, и выше только #include «. /precompiled.h» — Да
#8
10:57, 3 сен 2010
#pragma hdrstop — своеобразный аналог PCH — все заинклуденные хидеры до #pragma hdrstop будут прекомпилированы и закешены, если где еще в C/CPP файлах компилятор встретит ту же последовательность хидеров до #pragma hdrstop — то заюзается уже скомпиленый кеш.
- Sbtrn. Devil
- Постоялец
#9
12:20, 3 сен 2010
А в небыдлер-м$ $тудии с этой же целью заставляют инклудить stdafx.h, причём принудительно. Так-то!
#10
12:33, 3 сен 2010
Sbtrn. Devil
это был один из агрументов, почему ушел со студии, там без этой хрени ничего не компилилось.
#11
12:41, 3 сен 2010
MAMONT-92 [REBORN]
> это был один из агрументов, почему ушел со студии, там без этой хрени ничего не
> компилилось.
Бедняжка. Хоть не на линукс перешел?
Если тебя бесит то, что проект собирается быстрее, то можно отключить «юзинг прекомпаилед хиадерc» в настройках.
#12
12:43, 3 сен 2010
entryway
> Бедняжка. Хоть не на линукс перешел?
Линукс — это поделка собранная на коленке в туалете полная всевозможных костылей.
#13
12:52, 3 сен 2010
MAMONT-92 [REBORN]
> Sbtrn. Devil
> > А в небыдлер-м$ $тудии с этой же целью заставляют инклудить stdafx.h, причём принудительно. Так-то!
> это был один из агрументов, почему ушел со студии, там без этой хрени ничего не компилилось.
пф-пф-пф.
#14
12:59, 3 сен 2010
Sbtrn. Devil
> А в небыдлер-м$ $тудии с этой же целью заставляют инклудить stdafx.h, причём принудительно. Так-то!
Ну что за бред. Никто никого не заставляет, в чистом проекте вообще нет никаких stdafx.h. Я в каждом новом проекте сам создаю stdafx.h такой, какой мне нужен.
А если уж так хочется создать проект визардом и при этом убрать stdafx.h и при этом не хочется убирать галочку ответственную за это (нафига тока не ясно), то при желании парой кликов PCH отключается.
MAMONT-92 [REBORN]
> это был один из агрументов, почему ушел со студии, там без этой хрени ничего не компилилось.
Лол. Можно это просто не использовать.
Но так как эта вещь очень полезна, то не вижу смысла её не использовать.
С++ Builder: как ускорить компиляцию с помощью предкомпилированных заголовков
Вместо вступления сразу приведу пример. Полная сборка (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 #include #pragma hdrstop
Такая последовательность создаст образ, содержащий скомпилированные vcl.h и string. Этот образ будет использован для другого cpp-файла, если в нем до директивы hdrstop будут включены те же файлы, в том же порядке. Обращу внимание, что важен не только состав, но и порядок следования заголовков — даже если следующий cpp-файл включает те же заголовки, но сначала указан string, а потом vcl.h, то для этого cpp-файла будет создан новый образ.
Таким образом, для повторного использования предкомпилированного заголовка необходимо выполнение двух условий:
- состав включенный файлов до директивы hdrstop должен быть тем же
- последовательность включения файлов до директивы hdrstop должна быть той же
Сократить затраты на компиляцию стандартных заголовков до минимума можно только в том случае, если скомпилировать один образ, содержащий все стандартные заголовки, необходимые для проекта. Для этого нужно, чтобы:
- ВСЕ cpp-файлы проекта имели одинаковый блок включений до директивы hdrstop
- в этот блок должны входить ВСЕ стандартные заголовочные файлы, необходимые для проекта
Выполнить эти условия достаточно просто, для этого в начало каждого cpp-файла необходимо поместить следующие строки:
#include #pragma hdrstop
где pch.h — файл, содержащий включения всех стандартных заголовков:
#ifndef PCH_H #define PCH_H #define INC_VCLDB_HEADERS #define INC_VCLEXT_HEADERS #include #include #include #include #include . #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 #pragma hdrstop #include "Unit1.h" .
Если посмотреть на текст vcl.h, то можно увидеть, что он является оболочкой для включения большого числа других стандартных заголовочных файлов.
Управлять составом включаемых в vcl.h заголовков можно с помощью специальных символов (INC_VCLDB_HEADERS, INC_VCLEXT_HEADERS и др.). В моей версии pch.h эти символы определяются с помощью #define до включения vcl.h, что приводит к увеличению числа включаемых файлов.
Как в существующем проекте перейти к использованию предкомпилированных заголовков
Даже в большом проекте перейти к использованию предкомпилированных заголовков достаточно просто.
В свойствах проекта нужно включить кэширование предкомпилированных заголовков и рекомендуется указать «персональный» файл, в котором будет храниться образ предкомпилированных заголовков: Project — Options — закладка Compiler, группа «Pre-compiled headers». Тут должно быть выбрано «Cache pre-compiled headers», а в поле «File Name» нужно ввести «pch.csm». При такой настройке образ с предкомпилированными заголовками будет находится в папке с проектом, в файле pch.csm.
После этого в начало каждого cpp-модуля необходимо вставить 2 строки:
#include "pch.h" #pragma hdrstop
Все ранее включенные заголовочные файлы остаются на своих местах, их удалять не надо. Например:
#include "pch.h" // включает vcl.h, string и т.д. #pragma hdrstop #include #include .
Так как во всех стандартных заголовках применяются стражи повторного включения, то повторное их упоминание не влечет за собой повторного включения.
В принципе, при использовании 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-модулей создаются дополнительные образы.
#ifndef PCH_H #define PCH_H #define INC_VCLDB_HEADERS #define INC_VCLEXT_HEADERS #include /* Все, что подключается предыдущими 3-мя строчками // Core (minimal) Delphi RTL headers #include #include #include #include #include #include // Core (minimal) VCL headers #if defined(INC_VCL) #include #include #include #include #include #include // VCL Database related headers #if defined(INC_VCLDB_HEADERS) #include #include #include #endif // INC_VCLDB_HEADERS // Full set of VCL headers #if defined(INC_VCLEXT_HEADERS) #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #endif // INC_VCLEXT_HEADERS #endif // INC_VCL */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //нестандартные компоненты 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
О вышеизложенном
Если по поводу изложенного материала есть вопросы и замечания, то я готов их принять — пишите seb.goo@gmail.com.
hdrstop pragma
Обеспечивает больше контроля над именами файлов предварительной компиляции и расположением, в котором сохраняется состояние компиляции.
Синтаксис
Замечания
Имя файла — это имя предварительно скомпилированного файла заголовка для использования или создания (в зависимости от того, задано /Yu или /Yc указано). Если имя файла не содержит спецификацию пути, предполагается, что предварительно скомпилированные файл заголовка будут находиться в том же каталоге, что и исходный файл.
Если файл C или C++ содержит hdrstop pragma файл, скомпилированный с /Yc помощью, компилятор сохраняет состояние компиляции до расположения pragma. Скомпилированное состояние любого кода, следующего за pragma ней, не сохраняется.
Используйте имя файла для имени предварительно скомпилированного файла заголовка, в котором сохраняется скомпилированное состояние. Пространство между hdrstop файлом и именем файла является необязательным. Имя файла, указанное hdrstop pragma в строке, и подлежит ограничениям любой строки C или C++. В частности, необходимо заключить его в кавычки и использовать escape-символ (обратная косая черта, \ ) для указания имен каталогов. Например:
#pragma hdrstop( "c:\\projects\\include\\myinc.pch" )
Имя предкомпилированного файла заголовка определяется в соответствии со следующим правилам в порядке приоритета.
- Аргумент параметра компилятора /Fp
- Аргумент имени файла #pragma hdrstop
- Базовое имя исходного файла с расширением PCH
Если ни один из /Yc параметров или /Yu hdrstop pragma имя файла не указан, базовое имя исходного файла используется в качестве базового имени предварительно скомпилированного файла заголовка.
Команды предварительной обработки также можно использовать для выполнения замены макроса.
#define INCLUDE_PATH "c:\\progra~1\\devstsu~1\\vc\\include\\" #define PCH_FNAME "PROG.PCH" . . . #pragma hdrstop( INCLUDE_PATH PCH_FNAME )
Следующие правила управляют размещением: hdrstop pragma
- Она должна находится за пределами любых объявлений или определений данных или функций.
- Она должна задаваться в файле исходного кода, а не заголовка.
Пример
#include // Include several files #include "myhdr.h" __inline Disp( char *szToDisplay ) // Define an inline function < // . // Some code to display string >#pragma hdrstop
В этом примере hdrstop pragma отображается после включения двух файлов и определена встроенная функция. Сначала это расположение может показаться нечетным размещением pragmaдля . Однако учитывайте, что использование параметров предварительной компиляции вручную и /Yc /Yu с hdrstop pragma помощью этого средства позволяет предварительно компилировать все исходные файлы или даже встроенный код. Компилятор Майкрософт не ограничивает предварительное компиляцию только объявлений данных.
#pragma
Директива #pragma определяется стандартом ANSI С для реализации директив, предоставляющих компилятору различные инструкции. Стандартный вид #pragma следующий:
где имя — это имя директивы #pragma. Borland определяет 14 директив #pragma:
argused
anon_struct
codeseg
comment
exit
hdrfile
hdrstop
inline
intrinsic
message
option
saveregs
startup
warn
Директива argused должна стоять перед функцией. Она используется для устранения предупреждений, если аргумент функции, перед которой стоит #pragma, не используется в теле функции.
Чтобы разрешить использовать анонимные структуры, укажите директиву anon_struct. С помощью директивы codeseg можно указать сегмент, класс или группу, используемую функцией.
Используя директиву comment, в выходной файл, например, в файл с расширением obj или ехе можно поместить комментарии.
Директива exit определяет одну или несколько функций, вызываемых при завершении программы. Директива startup определяет одну или несколько функций, вызываемых при запуске программы. Они имеют следующий вид:
#pragma exit имя_функции приоритет
#pragma startup имя_функции приоритет
Приоритет — это значение от 64 до 255 (значения от 0 до 63 зарезервированы). Приоритет определяет порядок вызова функций. Если приоритет не указан, то по умолчанию предполагается значение 100. Все функции, выполняющиеся в начале или конце программы, должны объявляться следующим образом:
void f(void);
Следующий пример определяет функцию start(), выполняющуюся в начале программы.
#include
void start(void);
#pragma startup start 65
int main(void)
printf(«In main\n»);
return 0;
>
void start (void)
printf(«In start\n»);
>
В результате работы программы на экране появится:
In start
In main
Как показывает данный пример, необходимо предоставить прототип функции до использования директивы #pragma.
С помощью директивы hdrfile можно определить имя файла, используемого для хранения пред- компилированных заголовочных файлов. Он имеет вид
#pragma hdrfile «имя_файла. csm»
где имя_файла — это имя файла (с расширением csm).
Директива hdrstop сообщает Borland С++ о необходимости остановить предкомпиляцию заголовочных файлов.
Также имеется директива inline, имеющая следующий вид:
Она сообщает компилятору, что программа содержит внутренний ассемблерный код. При создании самого быстрого кода компилятор должен знать, что в программе содержится ассемблерный код.
Используя директиву intrinsic, можно указать компилятору на необходимость подстановки кода функции вместо ее вызова. Директива имеет вид:
#pragma intrinsic имя_функции
где имя_функции — это имя функции, которую необходимо сделать внутренней.
Если выбрать опцию Inline Intrinsic Function в ИСР (интегрированной среде разработчика) или воспользоваться опцией -Oi при компиляции с помощью строчного компилятора, то Borland автоматически сделает внутренними следующие функции:
alloca memcpy stpcpy strcpy strncpy
fabs memset strcat strlen strnset
memchr rotl strchr strncat strrchr
memcmp rotr strcmp strncmp
Воспользовавшись директивой intrinsic, можно отменить функции, которые станут внутренними: #pragma intrinsic имя_функции
Директива message позволяет определить сообщение, выводимое в качестве предупреждения при компиляции программы. Например:
#include
#pragma message This will be displayed as a warning.
int main(void)
int i=10;
printf («This is i: %d\n», i);
#pragma message This is also displayed as a warning.
return 0;
>
При компиляции появятся два сообщения #pragma, выводящиеся в качестве предупреждений. При использовании ИСР они появятся в стандартном окне сообщений.
Директива option позволяет определить опции командной строки вместо того, чтобы данные опции явно указывать в командной строке. Она имеет следующий вид:
#pragma option список_опций
Например, следующая директива приводит к тому, что содержащая ее программа будет компилироваться в модели large:
#pragma option -ml
Следующие опции не могут использоваться с директивой option:
-В -с -D -е -Е -F -h
-l -М -о -Р -Q -S -Т
-U -V -X -Y
Для использования некоторых опций директива option должна стоять перед любыми объявлениями, включая прототипы функций. Поэтому имеет смысл помещать данную директиву самой первой.
Директива saveregs запрещает функции, объявленной как huge, изменять какие-либо регистры. Данная директива должна стоять перед функцией, и она влияет только на функцию, перед которой стоит.
Директива warn позволяет запретить или разрешить различные предупреждения. Она имеет вид:
#pragma warn установки
где установки — это опции для определения предупреждений.