уважаемые посетители блога, если Вам понравилась, то, пожалуйста, помогите автору с лечением. Подробности тут.

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

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

Для начала, рассмотрим очень простой код, который вы можете повторить в Delphi за несколько секунд:

procedure TForm2.FormCreate(Sender: TObject);
begin
  {$IFDEF DEBUG}
    OutputDebugString(PChar('DEBUG IS ON!'));
  {$ENDIF}
end;

Теперь нажмите F9 и проверьте, что написано в отладчике в «Events»:

Разберемся с тем, что мы только что написали.

Первая строка:

{$IFDEF DEBUG}

$IFDEF — это директива компилятора;

DEBUG — условное определение или символ условной компиляции. Символ обязательно должен начинаться с буквы за которой может следовать любое количество букв, цифр и знаков подчеркивания, однако использоваться будут лишь первые 255 символов.

Вторая строка:

OutputDebugString(PChar('DEBUG IS ON!'));

Процедура отправляет строку в отладчик для отображения.

Третья строка:

{$ENDIF}

Завершает условную компиляцию, инициированную последней директивой {$IFxxx} (почему не {$IFDEF} — смотрим далее).

Таким образом, используя директивы {$IFDEF} и {$ENDIF} мы указали компилятору дословно следующее: если где-либо по ходу компиляции был встречено условное определение DEBUG, то надо выполнить OutputDebugString.

Где определено условное определение DEBUG? Конкретно в этом случае, символ DEBUG можно найти, если зайти в настройки проекта: Project -> Options ->Delphi Compiler :

 Здесь же можно определить и свои собственные символы. Давайте, например, добавим свой символ условной компиляции TEST. Для этого открываем диалоговое окно редактирования символов условной компиляции (жмем кнопку «…» в строке «Conditional defines») и заносим наш символ в список:

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

procedure TForm2.FormCreate(Sender: TObject);
begin
  {$IFDEF TEST}
    OutputDebugString(PChar('TEST IS ON!'));
  {$ENDIF}
end;

Теперь можете снова запустить приложения в режиме отладки и посмотреть, что в Events появится строка «TEST IS ON».

Сейчас мы с вами рассмотрели самый простой способ использования условной компиляции в Delphi — использование директив {$IFDEF} и {$ENDIF}, а также определение собственного символа условной компиляции через свойства проекта. Вместе с этим, определить (включить) свой символ условной компиляции можно и в коде программы. Для этого используется директива компилятора {$DEFINE}. Воспользуемся этой директивой:

{$DEFINE MyTestSymbol}
 
procedure TForm2.FormCreate(Sender: TObject);
begin
  {$IFDEF MyTestSymbol}
    OutputDebugString(PChar('Символ MyTestSymbol определен'));
  {$ENDIF}
end;

Соответственно, если есть директива определения нового символа, то должна быть и директива, которая отключает символы условной компиляции — она называется {$UNDEF}. Можете написать, например, вот такой код:

{$UNDEF DEBUG}
procedure TForm2.FormCreate(Sender: TObject);
begin
  {$IFDEF DEBUG}
    OutputDebugString(PChar('debug is on'));
  {$ENDIF}
end;

и убедиться, что символ DEBUG выключен, а в окне Events не появится строка «debug is on».

Двигаемся далее. Что делать, если нам необходимо вывести строку не когда символ включен, а именно тогда, когда он выключен? Здесь, опять же, есть варианты. Короткий вариант — воспользоваться директивой противоположной {$IFDEF} — она называется {$IFNDEF} и код между {$IFNDEF} и {$ENDIF} выполняется, если символ выключен:

{Пример использования директивы IFNDEF}
 
{$DEFINE MyTestSymbol}
{$UNDEF DEBUG}
 
procedure TForm2.FormCreate(Sender: TObject);
begin
  {$IFNDEF DEBUG}
    //строка выведется в Events
    OutputDebugString(PChar('debug is off'));
  {$ENDIF}
  {$IFNDEF MyTestSymbol}
    //а эта строка - нет, т.к. символ MyTestSymbol включен
    OutputDebugString(PChar('MyTestSymbol is off'));
  {$ENDIF}
end;

Второй вариант — использование директивы {$ELSE}, если в зависимости от состояния символа условной компиляции вам надо выполнять различные участки кода:

  {$IFDEF DEBUG}
    //эта строка не выведется в Events,
    OutputDebugString(PChar('debug is ON'));
  {$ELSE}
    // а эта - выведется
    OutputDebugString(PChar('debug is OFF'));
  {$ENDIF}

Соответственно, нет необходимости далее повторять этот же участок кода с использованием {$IFNDEF} — работать будет, но прямо противоположно.

Также следует обратить внимание на то, что все условные символы оцениваются в Delphi, когда вы выполняете Build проекта. Справка Delphi рекомендует для надежности пользоваться командой Project -> Build All Projects, чтобы быть уверенным, что все символы условной компиляции определены верно.

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

Например, символ условной компиляции VER330 определен для Delphi 10.3 Rio и с его помощью можно определить какой код должен или не должен выполняться, в случае, если версия компилятора Delphi — 33. Например, воспользуемся фичей Delphi 10.3 Rio под названием Inline Variable Declaration:

procedure TForm2.FormCreate(Sender: TObject);
begin
//этот код сработает только в Delphi 10.3 Rio
  {$IFDEF VER330}
    var s: string;
    S:='Inline Variable';
    ShowMessage(S);
  {$ENDIF}
end;

Сразу может возникнуть вопрос: как сделать так, чтобы приведенный выше код сработал не только в Delphi 10.3 Rio, но и в последующих версиях?
Это можно сделать воспользовавшись, например, такой конструкцией:

 {$IF CompilerVersion >= 33.0}
      var s: string;
      S:='Inline Variable';
      ShowMessage(S);
    {$IFEND}

Здесь мы уже воспользовались директивой {$IF} с помощью которой проверили значение константы CompilerVersion, которая находится в модуле System.

Все версии компилятора вы можете узнать на специальной странице справки по Delphi

Здесь же стоит обратить внимание и на окончание блока — мы использовали директиву {$IFEND}, как того требовала Delphi до версии Delphi XE4:

  • для директивы $IFDEF должна быть определена директива $ENDIF
  • для директивы $IF должна быть определена директива $IFEND

В XE4 нам разрешили использовать {$ENDIF} для закрытия блоков {$IF}, {$IFDEF} и {$IFOPT}. Однако, если у вас возникают проблемы при использовании связки {$IF} и {$ENDIF}, то вы можете использовать специальную директиву {$LEGACYIFEND}, чтобы потребовать использовать для {$IF} именно {$IFEND}:

{$LEGACYIFEND ON} //закрываем IF по-старинке, используя IFEND
 
    {$IF CompilerVersion >= 33.0}
      {$IF Version=1}
        var s: string;
        S:='Inline Variable';
        ShowMessage(S);
      {$ELSE}
        var d: TDateTime;
        d:=Now;
        ShowMessage('DateTime = '+DateTimeToStr(d));
      {$IFEND}
    {$IFEND}

Теперь, если в коде выше использовать директиву $ENDIF, то получим сообщение об ошибке:

[dcc32 Error] Unit2.pas(44): E2029 $IFEND expected but $ENDIF found

Директиву {$IF}, кстати, можно использовать и с другими константами проекта, например, так:

//определим собственную константу
const
  Version = 2;
 
procedure TForm2.FormCreate(Sender: TObject);
begin
//сначала проверяем версию компилятора
    {$IF CompilerVersion >= 33.0}
      {$IF Version=1} //теперь проверяем версию нашей программы
        var s: string;
        S:='Inline Variable';
        ShowMessage(S);
      {$ELSE} 
        //если версия программы не равна 1, то сработает код ниже
        var d: TDateTime;
        d:=Now;
        ShowMessage('DateTime = '+DateTimeToStr(d));
      {$IFEND}
    {$IFEND}
end;

Так как наша константа Version содержит значение 2, то выполнится участок кода расположенный после {$ELSE}. Можете сменить значение константы Version на 1, чтобы убедиться, что выполнится участок кода, где определена переменная s.

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

Резюмируем.

  1. Использование условной компиляции позволяет нам выполнять тот или иной код, в зависимости от того, какие константы и символы условной компиляции определены или не определены в проекте.
  2. Используя предопредленные символы условной компиляции можно указывать Delphi какой код необходимо выполнить, например, если программа собирается под Android, или, если поддерживается архитектура x64 и т.д.
  3. Директива $IF может использоваться с различными константами, в том числе и определенными самим разработчиком.

При подготовке статьи использовалась следующая информация официальной справки по Delphi:

  1. Conditional compilation (Delphi)
  2. Legacy IFEND (Delphi)
  3. Compiler Versions

Книжная полка

Описание: Рассмотрены малоосвещенные вопросы программирования в Delphi. Описаны методы интеграции VCL и API. Показаны внутренние механизмы VCL и приведены примеры вмешательства в эти механизмы. Рассмотрено использование сокетов в Delphi: различные режимы их работы, особенности для протоколов TCP и UDP и др.
купить книгу delphi на ЛитРес
Описание: Книга рассчитана на подготовленного пользователя ПК, желающего самостоятельно научиться программировать и разрабатывать приложения и базы данных в среде Delphi. Опытные программисты смогут использовать издание как справочник. В тексте подробно описаны более 80 компонентов VCL, функции Object Pascal и Win32 API.
купить книгу delphi на ЛитРес


 

5 1 голос
Рейтинг статьи
уважаемые посетители блога, если Вам понравилась, то, пожалуйста, помогите автору с лечением. Подробности тут.
Подписаться
Уведомить о
0 Комментарий
Межтекстовые Отзывы
Посмотреть все комментарии