VisualDSP: директивы управления заголовочными файлами Печать
Добавил(а) microsin   

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

[#pragma hdrstop]

Прагма hdrstop pragma используется вместе с ключом командной строки -pch (precompiled header), см. врезку ниже. Опция -pch инструктирует компилятор искать файл предварительной компиляции заголовков (файл с расширением *.pch), и если не получилось его найти, то этот файл будет сгенерирован для использования в последующей компиляции. Файл *.pch содержит снимок всего кода, который был скомпилирован до точки останова предварительной компиляции (header stop point). Эта точка в исходном коде (или в заголовочном файле) задается директивой #pragma hdrstop.

-pch

Опция командной строки -pch (precompiled header) указывает компилятору автоматически генерировать и использовать файлы так называемые файлы предварительной компиляции заголовков (precompiled header files). Результат этой предварительной компиляции сохраняется в файл с расширением *.pch и именем, взятым из основного имени исходного файла. По умолчанию все precompiled headers сохраняются в каталоге с именем PCHRepository.

Следует иметь в виду, что файлы precompiled header занимают дополнительное место на диске (каждый такой файл может занимать несколько мегабайт).

Примечание переводчика: опытным путем выяснил, что опция -pch иногда приводит к ошибке cc0219, которую исправить никак не удается:

cc0219:  Catastrophic error: error while deleting file
          "PCHRepository\somefile.pch"

1 catastrophic error detected in the compilation of ".\somefile.cpp". Compilation terminated. cc3089: fatal error: Compilation failed Tool failed with exit/exception code: 1. Build was unsuccessful.

Ошибка проявлялась на 64-битной системе Windows 7, однако на другом компьютере с Windows XP 32 бита все компилировалось нормально.

По умолчанию точка header stop point (если #pragma hdrstop не используется) - первая не обрабатываемая предварительной компиляцией строка в основном исходном коде. Директива #pragma hdrstop может использоваться установки header stop point в файле исходного кода.

В следующем примере точка останова по умолчанию для предварительной компиляции - начало декларации переменной i.

#include "standard_defs.h"
#include "common_data.h"
#include "frequently_changing_data.h"
  
int i;

Такой вариант выбора точки останова предварительной компиляции может быть плохим выбором, потому что заголовочный файл frequently_changing_data.h может находится на стадии разработки и подвергаться частым модификациям. Это приведет к тому, что файл *.pch будет часто генерироваться заново, и выгода использования precompiled header теряется. Прагма hdrstop может использоваться для того, чтобы выбрать более подходящее место для точки header stop.

В следующем примере файл precompiled header не будет включать frequently_changing_data.h, потому что он подключается после #pragma hdrstop. Поэтому precompiled header не нужно будет создавать заново каждый раз, когда был изменен frequently_changing_data.h.

#include "standard_defs.h"
#include "common_data.h"
 
#pragma hdrstop
#include "frequently_changing_data.h"
 
int i;

[#pragma no_implicit_inclusion]

С помощью опции -c++ (см. врезку ниже) для каждого файла заголовка (с расширением *.h или без расширения), компилятор пытается подключить соответствующий файл *.c или .cpp. Это называется "неявное подключение" (implicit inclusion).

-c++

Эта опция (режим C++) указывает компилятору, что исходные файлы написаны в соответствии со стандартом ANSI/ISO языка C++, с добавлением расширений языка от Analog Devices.

В режиме по умолчанию допускаются все стандартные возможности C++, кроме обработки исключений (exception handling) и идентификаторов типа времени выполнения (run-time type identification), потому что это приводит к слишком большим расходам ресурсов и обычно неприемлемо для встраиваемых приложений. Поддержка этих функций может быть разрешена с помощью опций командной строки -eh и -rtti.

-eh

Опция -eh (разрешить exception handling) указывает компилятору, что в коде C++ разрешены операторы обработки исключений try/catch, и есть возможность выбрасывания исключений (throw exceptions) и другие функции, связанные с ANSI/ISO standard C++ exceptions. Когда этот ключ разрешен, компилятор определяет макрос __EXCEPTIONS как 1.

Если опция -eh используется при компиляции C-программ без опции -c++ (-c++ включает режим языка C++), то -eh указывает компилятору генерировать таблицы исключений, но не менять принятый язык. В этом случае макрос __EXCEPTIONS не определяется.

Опция –eh также заставляет компилятор определить __ADI_LIBEH__ во время стадии линковки, чтобы в ldf-файле [1] могли быть активированы соответствующие секции, и программа могла быть слинкована с библиотекой, собранной с разрешением обработки исключений (exceptions enabled library).

Объектные файлы, созданные с разрешением исключений, могут быть линкованы с объектными файлами, где обработка исключений не включена. Однако исключения могут выброшены и пойманы, и выполнен код очистки, в модулях, скомпилированных с -eh. Если сделана попытка выбрасывания исключения в функции, не скомпилированной с -eh, то будет вызвана функция abort или функция, зарегистрированная с помощью set_terminate. Подробнее см. раздел помощи "Exceptions Tables Pragma" VisualDSP.

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

Опция -eh применяется, когда установлена галочка "C++ exceptions and RTTI" диалога свойств проекта VisualDSP++ (Compile -> Language Settings).

-no-eh

Опция -no-eh (запрет exception handling) указывает компилятору отменить разрешение обработки исключений языка C++ (ANSI/ISO C++ exception handling). Это режим по умолчанию для компилятора.

-rtti

Опция -rtti (разрешение идентификации типов во время выполнения кода, run-time type identification) указывает компилятору разрешить в программе использование выражений dynamic_cast и других функций ANSI/ISO C++ run-time type identification. Этот ключ также заставляет компилятор определить макрос __RTTI как 1.

Опция -rtti применяется, когда установлена галочка "C++ exceptions and RTTI" диалога свойств проекта VisualDSP++ (Compile -> Language Settings).

-no-rtti

Опция -no-rtti (запрет run-time type identification) указывает компилятору отменить разрешение поддержки dynamic_cast и других функций ANSI/ISO C++ run-time type identification. Это режим по умолчанию для компилятора.

Если строка #pragma no_implicit_inclusion помещена в заголовочный файл *.h (или файл без расширения), то компилятор не будет неявно подключать соответствующий файл *.c или .cpp при компиляции с опцией -c++. Это поведение влияет только на файл *.h (или файл без расширения), в котором есть строка #pragma no_implicit_inclusion, и соответствующие файлы *.c или *.cpp.

Например, если есть файл t.c, содержащий

#include "m.h"

и файлы m.h и m.c оба пустые, то командная строка:

ccblkfn -c++ t.c -M

покажет следующие зависимости для t.c:

t.doj: t.c
t.doj: m.h
t.doj: m.c 

Если следующая строка добавлена в m.h:

#pragma no_implicit_inclusion

то запуск компилятора с той же командой (ccblkfn -c++ t.c -M) не покажет m.c в списке зависимостей:

t.doj: t.c
t.doj: m.h

[#pragma no_pch]

Прагма no_pch отменяет ключ -pch (precompiled headers) для определенного файла исходного кода. Она указывает компилятору, что он не должен искать файл *.pch, и не должен генерировать его для указанного файла исходного кода.

[#pragma once]

Прагма once предназначена для замены набора директив #ifndef/#define/#endif. Это просто "синтаксический сахар", используемый для красоты и удобства.

Директива #pragma once должна находиться в начале заголовочного файла. Она говорит компилятору, что этот заголовочный файл написан таким образом, что его однократное подключение дает тот же эффект, как и многократное подключение. Т. е., говоря по-русски, заголовочный файл с #pragma once должен подключаться в проекте только один раз, даже если директива #include этого файла встречается во многих модулях проекта. Например,

#pragma once
// Следующие обрамляющие директивы #ifndef/#define/#endif
// больше не нужны:
#ifndef FILE_H
#define FILE_H
 
... содержимое файла заголовка ...
 
#endif

Примечание: в этом примере директиву #pragma once в действительности указывать необязательно, потому что компилятор увидит директивы #ifndef, #define и #endif, и не будет повторно обрабатывать этот заголовок.

[#pragma system_header]

Прагма system_header pragma идентифицирует файл как файл, предоставленный системой программирования VisualDSP++. Компилятор VisualDSP++ использует эту информацию, чтобы помочь оптимизации использования предоставляемых библиотечных функций и inline-функций, которые определены этими файлами. Не используйте эту прагму в исходном коде пользовательского приложения.

[Ссылки]

1. Linker Description File.
2. Visual Studio: /Yc, /Yu, #pragma hdrstop, stdafx.h.