$Define — Директива компилятора Delphi


Директивы компилятора — Версии Delphi

У меня есть блок, который я написал в Delphi 7 некоторое время назад, и просто получил удовольствие (боль) от преобразования в Delphi XE (Unicode).

Устройства работают отлично после некоторых проблем, теперь я пытаюсь сделать этот модуль совместимым с разными версиями Delphi, если мне когда-либо понадобится переключить IDE обратно в Delphi 7, обновляя какой-то другой код.

У меня только Delphi 7 и Delphi XE, но из того, что я собираю, код, написанный в Delphi 1, Delphi 2007 будет компилироваться, но код из Delphi 2009 и выше будет Unicode.

. В любом случае, в модуле я разделяю un-unicode и unicode так:

Как изменить директиву компилятора, чтобы правила применялись к нескольким версиям? Например, что-то вроде:

Затем это будет охватывать все версии Delphi, если я буду распространять источник или блок .dcu.

Интересно, является ли самый простой подход в этом случае переключать поведение на UNICODE условном. Это условие определено тогда и только тогда, когда вы используете Unicode-версию Delphi, то есть в Delphi 2009 и более поздних версиях. Большим преимуществом этого является то, что это будущее доказательство — вам не нужно обновлять свой код каждый раз, когда выпускается новый Delphi. Более того, условный переключатель будет гораздо читабельнее, поскольку он четко выражает намерение.

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

$Define — Директива компилятора Delphi

директивы условной компиляции

<$C+>и <$C->— директивы проверки утверждений
<$I+>и <$I->— директивы контроля ввода/вывода
<$M>и <$S>— директивы, определяющие размер стека
<$M+>и <$M->— директивы информации времени выполнения о типах
<$Q+>и <$Q->— директивы проверки переполнения целочисленных операций
<$R>— директива связывания ресурсов
<$R+>и <$R->— директивы проверки диапазона
<$APPTYPE CONSOLE>— директива создания консольного приложения

1) Директивы компилятора, разрешающие или запрещающие проверку утверждений

По умолчанию <$C+>или

Область действия локальная

Директивы компилятора $C разрешают или запрещают проверку утверждений. Они влияют на работу процедуры Assert,используемой при отладке программ. По умолчанию действует

директива <$C+>и процедура Assert генерирует исключение EAssertionFailed, если проверяемое утверждение ложно.

Так как эти проверки используются только в процессе отладки программы, то перед ее окончательной компиляцией следует указать директиву <$C->. При этом работа процедур Assert будет блокировано и генерация исключений EassertionFailed производиться не будет.

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

2) Директивы компилятора, включающие и выключающие контроль файлового ввода-вывода

По умолчанию <$I+>или

Область действия локальная

Директивы компилятора $I включают или выключают автоматический контроль результата вызова процедур ввода-вывода Object Pascal. Если действует директива <$I+>, то при возвращении процедурой ввода-вывода ненулевого значения генерируется исключение EInOutError и в его свойство errorcode заносится код ошибки. Таким образом, при действующей директиве <$I+>операции ввода-вывода располагаются в блоке try. except, имеющем обработчик исключения EInOutError. Если такого блока нет, то обработка производится методом TApplication.HandleException.

Если действует директива <$I->, то исключение не генерируется. В этом случае проверить, была ли ошибка, или ее не было, можно, обратившись к функции IOResult. Эта функция очищает ошибку и возвращает ее код, который затем можно анализировать. Типичное применение директивы <$I->и функции IOResult демонстрирует следующий пример:

В этом примере на время открытия файла отключается проверка ошибок ввода вывода, затем она опять включается, переменной i присваивается значение, возвращаемое функцией IOResult и, если это значение не равно нулю (есть ошибка), то предпринимаются какие-то действия в зависимости от кода ошибки. Подобный стиль программирования был типичен до введения в Object Pascal механизма обработки исключений. Однако сейчас, по-видимому, подобный стиль устарел и применение директив $I потеряло былое значение.

3) Директивы компилятора, определяющие размер стека

Область действия глобальная

Локальные переменные в процедурах и функциях размещаются в стеке приложения. При каждом вызове процедуры или функции ее локальные переменные помещаются в стек. При выходе из процедуры или функции эти локальные процедуры удаляются из стека. Директивы компилятора $M задают параметры стека приложения: его минимальный и максимальный размеры. Приложение всегда гарантированно имеет размер стека, равный его минимальной величине. Если при запуске приложения Windows обнаруживает, что не может выделить этот минимальный объем памяти, то выдается сообщение об этой ошибке.

Если во время работы выясняется, что минимального размера стека не хватает, то размер увеличивается на 4 K, но не более, чем до установленного директивой максимального размера. Если увеличение размера стека невозможно из-за нехватки памяти или из-за достижения его максимальной величины, генерируется исключение EStackOverflow. Минимальный размер стека по умолчанию равен 16384 (16K). Этот размер может изменяться параметром minstacksize директивы <$M>или параметром number директивы <$MINSTACKSIZE>.

Максимальный размер стека по умолчанию равен 1,048,576 (1M). Этот размер может изменяться параметром maxstacksize директивы <$M>или параметром number директивы <$MAXSTACKSIZE number>. Значение минимального размера стека может задаваться целым числом в диапазоне между1024 и 2147483647. Значение максимального размера стека должно быть не менее минимального размера и не более 2147483647. Директивы задания размера стека могут включаться только в программу и не должны использоваться в библиотеках и модулях.

В Delphi 1 имеется процедура компилятора <$S>, осуществляющая переключение контроля переполнения стека. Теперь этот процесс полностью автоматизирован и директива <$S>оставлена только для обратной совместимости.

4) Директивы компилятора, включающие и выключающие генерацию информации времени выполнения о типах (runtime type information — RTTI)

По умолчанию <$M->или

Область действия локальная

Директивы компилятора $I включают или выключают генерацию информации времени выполнения о типах (runtime type information — RTTI). Если класс объявляется в состоянии <$M+>или является производным от класса объявленного в этом состоянии, то компилятор генерирует RTTI о его полях, методах и свойствах, объявленных в разделе published. В противном случае раздел published в классе не допускается. Класс TPersistent, являющийся предшественником большинства классов Delphi и все классов компонентов, объявлен в модуле Classes в состоянии <$M+>. Так что для всех классов, производных от него, заботиться о директиве <$M+>не приходится.

5) Директивы компилятора, включающие и выключающие проверку переполнения при целочисленных операциях

По умолчанию <$Q->или

Область действия локальная

Директивы компилятора $Q включают или выключают проверку переполнения при целочисленных операциях. Под переполнением понимается получение результата, который не может сохраняться в регистре компьютера. При включенной директиве <$Q+>проверяется переполнение при целочисленных операциях +, -, *, Abs, Sqr, Succ, Pred, Inc и Dec. После каждой из этих операций размещается код, осуществляющий соответствующую проверку. Если обнаружено переполнение, то генерируется исключение EIntOverflow. Если это исключение не может быть обработано, выполнение программы завершается.

Директивы $Q проверяют только результат арифметических операций. Обычно они используются совместно с директивами <$R>, проверяющими диапазон значений при присваивании. Директива <$Q+>замедляет выполнение программы и увеличивает ее размер. Поэтому обычно она используется только во время отладки программы. Однако, надо отдавать себе отчет, что отключение этой директивы приведет к появлению ошибочных результатов расчета в случаях, если переполнение действительно произойдет во время выполнении программы. Причем сообщений о подобных ошибках не будет.

6) Директива компилятора, связывающая с выполняемым модулем файлы ресурсов

Область действия локальная

Директива компилятора <$R>указывает файлы ресурсов (.DFM, .RES), которые должны быть включены в выполняемый модуль или в библиотеку. Указанный файл должен быть файлом ресурсов Windows. По умолчанию расширение файлов ресурсов — .RES. В процессе компоновки компилированной программы или библиотеки файлы, указанные в директивах <$R>, копируются в выполняемый модуль. Компоновщик Delphi ищет эти файлы сначала в том каталоге, в котором расположен модуль, содержащий директиву <$R>, а затем в каталогах, указанных при выполнении команды главного меню Project | Options на странице Directories/Conditionals диалогового окна в опции Search path или в опции /R командной строки DCC32.

При генерации кода модуля, содержащего форму, Delphi автоматически включает в файл .pas директиву <$R *.DFM>, обеспечивающую компоновку файлов ресурсов форм. Эту директиву нельзя удалять из текста модуля, так как в противном случае загрузочный модуль не будет создан и сгенерируется исключение EResNotFound.

7) Директивы компилятора, включающие и выключающие проверку диапазона целочисленных значений и индексов

По умолчанию <$R->или

Область действия локальная

Директивы компилятора $R включают или выключают проверку диапазона целочисленных значений и индексов. Если включена директива <$R+>, то все индексы массивов и строк и все присваивания скалярным переменным и переменным с ограниченным диапазоном значений проверяются на соответствие значения допустимому диапазону. Если требования диапазона нарушены или присваиваемое значение слишком велико, генерируется исключение ERangeError. Если оно не может быть перехвачено, выполнение программы завершается.

Проверка диапазона длинных строк типа Long strings не производится. Директива <$R+>замедляет работу приложения и увеличивает его размер. Поэтому она обычно используется только во время отладки.

8) Директива компилятора, связывающая с выполняемым модулем файлы ресурсов

Область действия локальная

Директива компилятора <$R>указывает файлы ресурсов (.DFM, .RES), которые должны быть включены в выполняемый модуль или в библиотеку. Указанный файл должен быть файлом ресурсов Windows. По умолчанию расширение файлов ресурсов — .RES. В процессе компоновки компилированной программы или библиотеки файлы, указанные в директивах <$R>, копируются в выполняемый модуль. Компоновщик Delphi ищет эти файлы сначала в том каталоге, в котором расположен модуль, содержащий директиву <$R>, а затем в каталогах, указанных при выполнении команды главного меню Project | Options на странице Directories/Conditionals диалогового окна в опции Search path или в опции /R командной строки DCC32.

При генерации кода модуля, содержащего форму, Delphi автоматически включает в файл .pas директиву <$R *.DFM>, обеспечивающую компоновку файлов ресурсов форм. Эту директиву нельзя удалять из текста модуля, так как в противном случае загрузочный модуль не будет создан и сгенерируется исключение EResNotFound.

Директивы компилятора — Delphi версии

У меня есть блок, который я написал в Delphi 7 некоторое время назад, и только было весело (боль) преобразования в Delphi XE (Unicode).

Группа работает отлично после того, как некоторые проблемы, я сейчас пытаюсь сделать это устройство совместимо с различными версиями Delphi я должен когда-нибудь понадобится, чтобы переключиться обратно в IDE Delphi 7 в то время как обновление какой-либо другой код.

У меня только Delphi 7 и Delphi XE, но от того, что я собираю код, написанный на Delphi 1 в Delphi 2007 будет компилировать, но код с Delphi 2009 и выше будет Unicode.

. Во всяком случае, в блоке я отделяя не-Юникод и Юникод, как так:

Как изменить директиву компилятора поэтому правила применяются к Многоязычным версиям? Например, что-то вроде:

Это позволило бы охватить все версии Delphi я должен распространять исходный или .dcu блок.

Интересно , если самый простой подход в данном случае является переключение поведения на UNICODE условный. Это условное определяется тогда и только тогда , когда вы используете версию Unicode в Delphi, то есть в Delphi 2009 и более поздних версий. Большим преимуществом является то , что это будущее доказательство вам не нужно обновить код каждый раз , когда новый Delphi отпускается. Более того, условный переключатель будет гораздо более удобным для чтения , так как он будет четко выражать намерение.

Документация Delphi имеет отличную тему со списком всех предварительно определенными условными. Полный список версии условных также связан оттуда.

Условная компиляция модулей

Столкнулся с немного странным поведением Delphi 2010. Исходная проблема такова: допустим проект в зависимости от настроек может иметь некоторый модуль а может и нет. Под модулем будем понимать дата-модуль. Т.е. хочется в некотором конфиге при компиляции определить некоторую константу — использовать или не использовать указанный модуль. И вот в результате столкнулся с проблемой.

Комментарии

Это во всех версиях так.
D5,D6,D7,D2005,D2006,D2007,D2010,DXE

Не выявил закономерностей.
Регулярно проверяю *.DPR
Держу в большом коментарии шаблон, как должно быть.
После обширных правок проверяю.

Поступаю именно так же. Ну и конечно, при коммите в систему контроля версий всегда проверяю dpr-файл проекта.

common.inc «выпадает» из проекта, т.к не перечислен в USES в dpr-файле (не подключен к проекту; и наверное, вообще, не модуль — unit), он просто там включается (include), что совсем разные вещи.

TestDM «выпадает» от того, что директива компилятора не в настройках проекта задана, а в include-файле. Попробуйте вписать USE_MODULE в настройки проекта, вдруг получится.

Без пахнущего идиотизмом IFDEF при каждом обращении к полю записи тоже вряд ли удасться обойтись.

Как сказано выше — это проблема любой версии Delphi.
Беда в том, что раздел uses drp-файла среда полностью создаёт заново при добалвении/исключении модулей проекта.

Я эту проблему решил следующим образом: создал юнит, например под таким названием:
MyAdditions.pas
В котором директивами включаю (или не включаю) доп. модули в uses этого файла (у меня там FastMM/FastCode/EurekaLog etc.)

А в dpr-файле в разделе uses модуль MyAdditions идёт первым.

>> Что же делать, как же быть? кто сталкивался с подобным поведением, >> или если у вас были подобные ситуации, то как вы их разрешали?
>> Поделитесь опытом, товарищи!

How to define compiler directive for a project group in Delphi 7?

For example we have 2 project groups — ProjectGroupA.bpg и ProjectGroupB.bpg . Each group consists of EXE and BPL modules.

In each project group there are same projects Project1.bpl , Project2.bpl , Project3.bpl and different projects appA.exe , Project5.bpl and appB.exe , Project6.bpl , like so: ProjectGroupA.bpg (projects exeA-1-2-3-5) and ProjectGroupB.bpg (projects exeB-1-2-3-6).

In the same projects (1, 2, 3) there are minor differences in functionality for application A and B, which are best resolved by using conditional defines (e.g. including certain lines within bpl or uses sections).

Question is — How to set up compiler defines for the project group, so that when application A is built, all modules within it would have directive DEFINE_PROJECT_A , and when building application B — directive DEFINE_PROJECT_B ?

In case this can’t be done, what are possible workarounds for having conditional compilation in a project group? Usage scenario is to be able to change some code on developers machine, hit F9 and see the working application immediately.

$Define — Директива компилятора Delphi

<$I+>и <$I->— директивы контроля ввода/вывода <$M>и <$S>— директивы, определяющие размер стека <$M+>и <$M->— директивы информации времени выполнения о типах <$Q+>и <$Q->— директивы проверки переполнения целочисленных операций <$R>— директива связывания ресурсов <$R+>и <$R->— директивы проверки диапазона <$APPTYPE CONSOLE>— директива создания консольного приложения 1) Директивы компилятора, разрешающие или запрещающие проверку утверждений. По умолчанию <$C+>или <$ASSERTIONS ON>Область действия локальная Директивы компилятора $C разрешают или запрещают проверку утверждений. Они влияют на работу процедуры Assert,используемой при отладке программ. По умолчанию действует директива <$C+>и процедура Assert генерирует исключение EAssertionFailed, если проверяемое утверждение ложно. Так как эти проверки используются только в процессе отладки программы, то перед ее окончательной компиляцией следует указать директиву <$C->.

mirsovetov.net

Андрощук Александр, ИТ решения, советы, заметки…

Delphi — <$IFDEF>более одной директивы

Задача: Каким образом можно определить более одного условного оператора в одной проверке <$IFDEF>?
Инструментарий: Delphi
Решение:
Для того чтобы выполнить проверку нескольких условных операторов в одной проверке <$IFDEF>— нужно воспользоваться директивой .

Пример использования:

Другие варианты применения, с использованием констант:

Условная компиляция в Delphi 7

Иногда программисту нужно управлять дерективами процессора и компиляцией программного кода. Для этого в Delphi реализована условная компиляция. Существуют два пути построения условной компиляции.

В ней реализован метод проверки некоторого условия. Как мы видим, она начинается с условной директивы и заканчивается . Если условие в конструкции после $IF не выполняется, то конструкция не компилируется. Можно сделать вывод о второй конструкции на основании $IF. Значит можно поставить .

Условная компиляция во втором случае ведет себя также как и полный условный оператор в теле программы. Соответственно если истина, то после не компилируется. Иначе все наоборот.

Условные директивы. Задаем само условие идентификатора: . Сама условная директива будет иметь вид: . Она проверяет, был определен указанный в ней условный идентификатор в конструкции вида .

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

Условные идентификаторы должны начинаться с буквы и может быть любой длины. Предопределены некоторые идентификаторы: VER150, MSWINDOWS, WIN32, LINUX, CPU386, CONSOLE, CONDITIONAL EXPRESSIONS. По названимям можно понять, что они способствуют настройке приложения на различные платформы.

возвращает истину, если включена указанная опция. Опции вы можете посмотреть на этой странице. Конструкция вида

дает возможность вводить в процессе отладки различные отладочные печати.

$Define — Директива компилятора Delphi

разбираюсь с чужим проектом. В нем часто используется директива
<$IFDEF LOGXML>
.

но вот я не могу найти определения <$Define LOGXML>
Где может определяться символ LOGXML?? Подскажите.

Медвешонок Порошок ( 25.10.13 16:39 ) [1]

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

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

Andrey_Pl ( 25.10.13 16:47 ) [3]

где он может задаваться? так как я вижу что программа заходит в область
<$IFDEF LOGXML>
.

Andrey_Pl ( 25.10.13 16:52 ) [4]

> sniknik © (25.10.13 16:46) [2]
спасибо, так и есть! Нашел в опциях)

Германн © ( 26.10.13 01:19 ) [5]

> sniknik © (25.10.13 16:46) [2]
>
> в опциях проекта удобнее. там дефайн на все модули проекта
> распространяется.

Не только на все модули проекта. Но и вообще на все модули, чей код при сборке включается в исполняемый код. Лишь бы исходники этих модулей были бы доступны компилятору. Тот же эффект можно получить прописав явно эти дефайны (как и любые опции компилятора) в файл проекта.

jack128_ ( 14.11.13 16:21 ) [6]

> Тот же эффект можно получить прописав явно эти дефайны (как
> и любые опции компилятора) в файл проекта

если под «файлом проэкта» ты имеешь в виду dpr-файл, то дефайны заданные в нем не влияют на unit’ы. Только на сам dpr файл.

Германн © ( 14.11.13 17:11 ) [7]

> jack128_ (14.11.13 16:21) [6]

Твоя правда.

Директивы по версиям компилятора Delphi: <$ IFDEF VER180>— 2020

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

Если вы планируете писать код Delphi, который должен работать с несколькими версиями компилятора Delphi, вам необходимо знать, в каких версиях компилируется ваш код.

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

Если они попытаются перекомпилировать код компонента (ваш код) — у них могут быть проблемы! Что если вы использовали параметры по умолчанию в ваших функциях, а у пользователя Delphi 3?

Директива компилятора: $ IfDef

Директивы компилятора — это специальные синтаксические комментарии, которые мы можем использовать для управления функциями компилятора Delphi. Компилятор Delphi имеет три типа директив: переключение директив, директивы параметров а также условные директивы, Условная компиляция позволяет нам выборочно компилировать части исходного кода в зависимости от того, какие условия установлены.

Директива компилятора $ IfDef запускает секцию условной компиляции.

Синтаксис выглядит так:

DefName представляет так называемый условный символ. Delphi определяет несколько стандартных условных символов. В приведенном выше «коде», если определено DefName, код выше $ Else компилируется.

Delphi Version Symbols

Распространенным применением директивы $ IfDef является тестирование версии компилятора Delphi.

В следующем списке указаны символы, которые необходимо проверить при условной компиляции для конкретной версии компилятора Delphi:

  • УСЛОВНОЕ ОБОЗНАЧЕНИЕ — Компиляционная версия
  • VER80 — Delphi 1
  • VER90 — Delphi 2
  • VER100 — Delphi 3
  • VER120 — Delphi 4
  • VER130 — Delphi 5
  • VER140 — Delphi 6
  • VER150 — Delphi 7
  • VER160 — Delphi 8
  • VER170 — Delphi 2005
  • VER180 — Delphi 2006
  • VER180 — Delphi 2007
  • VER185 — Delphi 2007
  • VER200 — Delphi 2009
  • VER210 — Delphi 2010
  • VER220 — Delphi XE
  • VER230 — Delphi XE2
  • WIN32 — Указывает, что операционной средой является Win32 API.
  • LINUX — Указывает, что операционной средой является Linux
  • MSWindows — Указывает, что операционной средой является MS Windows / li]
  • ПРИСТАВКА — Указывает, что приложение компилируется как консольное приложение.

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

Примечание: символ VER185, например, используется для обозначения компилятора Delphi 2007 или более ранней версии.

Использование символов «VER»

Обычно (и желательно) для каждой новой версии Delphi добавлять несколько новых подпрограмм RTL к языку.

Например, функция IncludeTrailingBackslash, представленная в Delphi 5, добавляет «» в конец строки, если ее там еще нет. В проекте Delphi MP3 я использовал эту функцию, и несколько читателей пожаловались, что не могут скомпилировать проект — у них есть какая-то версия Delphi до Delphi 5.

Одним из способов решения этой проблемы является создание собственной версии этой подпрограммы — функции AddLastBackSlash.

Если проект должен быть скомпилирован на Delphi 5, вызывается IncludeTrailingBackslash. Если используются некоторые из предыдущих версий Delphi, мы моделируем функцию IncludeTrailingBackslash.

Это может выглядеть примерно так:

функция AddLastBackSlash (ул: строка) : строка; начать Результат: = IncludeTrailingBackslash (str); если Copy (str, Length (str), 1) = «» затем Результат: = ул еще Результат: = str + «»; конец;

При вызове функции AddLastBackSlash Delphi выясняет, какая часть функции должна использоваться, а другая часть просто пропускается.

Delphi 2008?

Delphi 2007 использует VER180 для обеспечения неразрывной совместимости с Delphi 2006, а затем добавляет VER185 для разработки, которая по каким-либо причинам должна быть нацелена на Delphi 2007.

Примечание. Каждый раз, когда интерфейс модуля изменяет код, использующий этот модуль, его необходимо перекомпилировать.Delphi 2007 — выпуск без прерываний, означающий, что файлы DCU из Delphi 2006 будут работать как есть.

Илон Маск рекомендует:  Что такое код hw_getparents
Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL