Conditionally compile units for FMX or VCL

2020-07-08 07:25发布

问题:

I want to have a different list of units in the uses clause depending on compiling for FMX or VCL. In the code below I try to test FireMonkeyVersion which works in an FMX project (label1.Text is 'FMX'). When I move the $IF statement into the uses clause I get an error message ([dcc32 Error] fmx_text.pas(7): E2026 Constant expression expected). Is there any way to get the desired conditional compilation?

unit fmx_text;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Rtti, System.Classes,
  System.Variants, FMX.Controls, FMX.Forms, FMX.Dialogs, FMX.Types;
{$IF FireMonkeyVersion >= 16}
   {$DEFINE HAS_FMX}
{$ELSE}
   {$DEFINE HAS_VCL}
{$IFEND}

type

  TForm2 = class(TForm)
    Label1: TLabel;
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form2: TForm2;

implementation

{$R *.fmx}

procedure TForm2.FormCreate(Sender: TObject);
begin
   label1.Text := 'Undefined';
{$IFDEF HAS_FMX}
   label1.Text := 'FMX';
{$ENDIF}
{$IFDEF HAS_VCL}
   label1.Text := 'VCL';
{$ENDIF}
end;

end.

回答1:

FireMonkeyVersion is not a compiler-defined value. It is a named constant declared in the FMX.Types unit instead. Try using {$IF DECLARED(FireMonkeyVersion)}, eg:

{$DEFINE HAS_VCL}
{$IF DECLARED(FireMonkeyVersion) AND (FireMonkeyVersion >= 16)}
  {$UNDEF HAS_VCL}
  {$DEFINE HAS_FMX}
{$IFEND}

But I don't see a reason to check its numeric value. You either have FireMonkey or you do not:

{$IF DECLARED(FireMonkeyVersion)}
  {$DEFINE HAS_FMX}
{$ELSE}
  {$DEFINE HAS_VCL}
{$IFEND}

With that said, do keep in mind that it is possible (though not officially supported) to mix FireMonkey and VCL together in the same project. So you might need to re-think whatever you are trying to accomplish by differentiating the frameworks.