Подтвердить что ты не робот

Как определить версию "и вверх" ifdefs в Delphi?

Я работал над тем, чтобы Log4D работал в Delphi XE4 и получал некоторые ошибки компиляции, потому что он не мог найти Contnrs в предложении uses, если только я не переместил его за пределы ifdef, в котором он был определен.

{$IFDEF DELPHI5_UP}
  Contnrs,
{$ENDIF}

Немного разобравшись, выяснилось, что ifdef определен во включенном файле Defines.inc, который имеет блок для каждой поддерживаемой версии delphi, которая останавливает несколько версий:

например:

{$IFDEF VER170}  { Delphi 2005 }
{$DEFINE DELPHI9}
{$DEFINE DELPHI4_UP}
{$DEFINE DELPHI5_UP}
{$DEFINE DELPHI6_UP}
{$DEFINE DELPHI7_UP}
{$ENDIF}

{$IFDEF VER180}  { Delphi 2006 }
{$DEFINE DELPHI10}
{$DEFINE DELPHI4_UP}
{$DEFINE DELPHI5_UP}
{$DEFINE DELPHI6_UP}
{$DEFINE DELPHI7_UP}

Итак, хотя было бы довольно легко пойти и скопировать и вставить ifdef для Delphi 2006 и создать блок Delphi XE4... это похоже на неэлегантное решение. Это определенно не будущее доказательство... каждая новая версия вам нужно обновить этот файл сейчас, поэтому некоторый код, отсутствующий в Delphi 4, не заставит кого-то еще 15 летнего старого кода взорваться.

Итак, мне было интересно, есть ли лучший способ сделать условную компиляцию, чтобы она действительно проверяла, есть ли у вас "Delphi 5 или выше" при компиляции этой строки, а не в этом формате, который требует обновления каждой новой версии delphi это выходит.

4b9b3361

Ответ 1

IIRC, Delphi 6 ввели условные выражения, которые на самом деле были предложены TLama. Чтобы ваш код работал с версиями Delphi ниже этого, вы должны проверить {$IFDEF CONDITIONALEXPRESSIONS }. Если это не определено, вам нужно использовать старую схему VERxxx, чтобы различать версии Delphi.

Для Delphi 6 и выше вы можете использовать встроенные константы CompilerVersion и RTLVersion. Какой из них вы используете, зависит от вашего кода. Всякий раз, когда вы используете новый тест функции компилятора для CompilerVersion. Для всего, что связано с тестом RTL или VCL для RTLVersion.

Всегда полезно прокомментировать предыдущий компилятор и использовать условную часть для совместимости с более старыми версиями. Поэтому вместо написания {$IF CompilerVersion >= 26.0} напишите свой код так, чтобы использовался {$IF CompilerVersion < 26.0}. Таким образом, в будущем гораздо проще отказаться от поддержки старых версий компилятора.

Ответ 2

Если бы я был поставщиком компонентов (TMS, DevEx), я мог бы чувствовать себя вынужденным придерживаться длинного подробного синтаксиса, который когда-либо поддерживал КАЖДЫЙ delphi. Вот почему этот большой беспорядок существует в большинстве кодовых баз компонентов.

Тем не менее, для моих собственных компонентов я не обновляю каждую версию, которая появляется, потому что мой файл ver.inc выглядит так, и я не поддерживаю версии Delphi вообще, которые не поддерживают этот новый синтаксис:

{ver.inc}

{ MYSOFT VERSION DEFINES }


{$IF CompilerVersion >= 22.0}
{$DEFINE RTL220_UP}
{$DEFINE XE_UP}
{$IFEND}

{$IF CompilerVersion >= 23.0}
{$DEFINE RTL230_UP}
{$DEFINE XE2_UP}
{$IFEND}

{$IF CompilerVersion >= 24.0}
{$DEFINE RTL240_UP}
{$DEFINE XE3_UP}
{$IFEND}

{$IF CompilerVersion >= 25.0}
{$DEFINE RTL250_UP}
{$DEFINE XE4_UP}

{$IFEND}

{$IF CompilerVersion >= 26.0}
{$DEFINE RTL250_UP}
{$DEFINE XE5_UP}
{$IFEND}

{$DEFINE OTHER_THING}

Ничего в коде выше не разрывается, когда выходит новая версия delphi. Обратите внимание, что мне НЕ нужно поддерживать Delphi 5 по 2010 с моими кодами. Фактически, я поддерживаю только XE2 и выше.

Несколько более длинная версия вышеуказанной формы может использоваться для поддержки каждой версии Delphi 6 и выше без каких-либо повторяющихся блоков и без прерывания при каждом выпуске новой версии delphi.

Также см. ответ Uwe для метода, в котором вы можете создать один .inc файл, который поддерживает КАЖДУЮ версию, и использовать только старую форму для старых версий delphi.

Ответ 3

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

Чтобы обрабатывать версии до Delphi 6, которые не поддерживают {$IF}, я оставил их как as-is. В лучшем случае у вас будет 5 таких, но в моем случае это было всего 2:

{$IFDEF VER120}  { Delphi 4 }
  {$DEFINE DELPHI4}
  {$DEFINE DELPHI4_UP}
{$ENDIF}

{$IFDEF VER130}  { Delphi 5 }
  {$DEFINE DELPHI4_UP}
  {$DEFINE DELPHI5_UP}
{$ENDIF}

И затем для версий, поддерживающих {$ IF} (Delphi 6+), я завернул их в блок {$IFDEF CONDITIONALEXPRESSIONS }, как это было предложено Uwe. Документация Embarcadero показала хороший пример этого, как только я узнал правильные условия поиска.

Это, в сочетании с предложением Уоррена об использовании блоков IF на большей или равной версии компилятора значительно упростило ситуацию:

{$IFDEF CONDITIONALEXPRESSIONS} { Delphi 6+ }

  {$IF CompilerVersion >= 14.0} { Delphi 6+ }
    {$DEFINE DELPHI4_UP}
    {$DEFINE DELPHI5_UP}
    {$DEFINE DELPHI6_UP}
  {$IFEND}

  {$IF CompilerVersion >= 15.0} { Delphi 7+ }
    {$DEFINE DELPHI7_UP}
  {$IFEND}

{$ENDIF}

Embarcadero имеет полезную целую диаграмму со всеми версиями Delphi и их именованными константами и обычным именем пакета. Между тем и этим ответом на переполнение стека я смог заполнить все константы версии компилятора.

Как только я получил этот блок там, мне даже не нужны блоки Delphi 2005/2006 в моем вопросе вообще, и XE4 счастливо компилируется.

Мне понравилось предлагать кодирование для версии X и ниже, а не Y и выше, когда это возможно, хотя я и не смог сразу использовать это предложение, так как это было бы столько, чтобы переработать IFs и IFDEF, это было бы прежде всего, чтобы вырвать поддержку для Delphi 3; -).

Ответ 4

Ответ проще, чем я думал. Из документации:

Например, чтобы определить версию компилятора и библиотеки времени выполнения, которые использовались для компиляции вашего кода, вы можете использовать {$ IF} с CompilerVersion, RTLVersion и другими константами.

 {$IFDEF CONDITIONALEXPRESSIONS}
    {$IF CompilerVersion >= 23.0}
      ...
    {$IFEND}
 {$ENDIF}

где версия 23.0 означает в данном случае Delphi XE2.

Полный список версий Delphi вы можете найти здесь.