Delphi не видит модуль под директивой условной компиляции $IF

Если в Delphi XE2 на форму бросить TImageList, то в uses модуля автоматически добавиться Vcl.ImgList. Если сделать тоже самое на Delphi 11, то дополнительно добавится System.ImageList. Я хочу, чтобы проект мог компилироваться на любой версии. Конкретно сейчас я могу сделать так:

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
  System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs,

  {$IFDEF VER350}
  System.ImageList,
  {$IFEND}

  Vcl.ImgList;

Но тогда я жёстко привязываюсь к Delphi 11. Используя это я исправил на:

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
  System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs,

  {$IF CompilerVersion > 23.0}
  System.ImageList,
  {$IFEND}

  Vcl.ImgList;

(теперь в последствии я могу уточнить, начиная с какой версии мне нужно включить этот модуль в uses)

Но теперь при попытке компиляции Delphi 11 автоматически добавляет мне еще один System.ImageList

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
  System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs,

  {$IF CompilerVersion > 23.0}
  System.ImageList,
  {$IFEND}

  Vcl.ImgList, System.ImageList;

и отказывается компилировать с ошибкой

[dcc32 Error] Unit1.pas(14): E2004 Identifier redeclared: 'System.ImageList'

Причём само условие {$IF CompilerVersion > 23.0} вполне работает в исполняемом коде. Я специально создал отдельный код

procedure TForm1.Button1Click(Sender: TObject);
begin
  {$IF CompilerVersion > 23.0}
  ShowMessage('CompilerVersion > 23.0');
  {$ELSE}
  ShowMessage('CompilerVersion <= 23.0');
  {$IFEND}
end;

и он работает и в XE2

CompilerVersion <= 23.0

и в 11

CompilerVersion > 23.0

Каким образом еще можно создать универсальную условную компиляцию проверяющую версию или как то иначе избавитьтся от данного бага?


Ответы (2 шт):

Автор решения: Kromster

Решение влоб использовать только простые $IFDEF условия:

unit Unit1;
interface
uses
  Forms
  {$IFDEF VER320} {$DEFINE VARIANT_SHORT} {$IFEND}
  {$IFDEF VER330} {$DEFINE VARIANT_SHORT} {$IFEND}
  {$IFDEF VER340} {$DEFINE VARIANT_LONG} {$IFEND}
  {$IFDEF VER350} {$DEFINE VARIANT_LONG} {$IFEND}
  {$IFDEF VARIANT_SHORT}, Classes, Controls, StdCtrls{$IFEND}
  {$IFDEF VARIANT_LONG}, System.Classes, Vcl.Controls, Vcl.StdCtrls{$IFEND}
  ;
→ Ссылка
Автор решения: zed

Да, известная проблема. Решается добавлением заглушки (placeholder):

  • создайте в папке с сорцами проекта папку Placeholders;
  • создайте в этой папке файл ImageList.pas;
  • в настройках проекта для XE2 добавьте папку Placeholders в Search path (Build - Delphi compiler) для всех платформ (x32, x64).

Содержимое заглушки ImageList.pas:

unit ImageList;

interface

implementation

initialization

{$IF (CompilerVersion >= 24)} // XE3 and UP
  {$MESSAGE ERROR 'This unit is placeholder for XE2 and early versions only!'}
{$IFEND}

end.

Ещё, вам скорее всего понадобятся заглушки для UITypes.pas и Actions.pas.

Ну и понятно, что теперь вам не нужно использовать никаких условий компиляции в uses при подключении проблемного модуля. Новая версия Delphi возьмёт актуальный юнит, а XE2 подключит заглушку - и все останутся довольны.

→ Ссылка