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 шт):
Решение влоб использовать только простые $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}
;
Да, известная проблема. Решается добавлением заглушки (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 подключит заглушку - и все останутся довольны.