9

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.
RRUZ
  • 134,889
  • 20
  • 356
  • 483
Arnold
  • 4,578
  • 6
  • 52
  • 91

1 Answers1

12

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.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • This works! Thanks a lot for your help. The second form is sufficient. As for why I need it: I have several non-visual libraries. While updating them for FMX I noticed that a TBitmap is declared in FMX.Types and VCL.Graphics. So I am trying to make these libraries platform-independent. The example is completely platform dependent but I needed a visual test. I am open for better approaches. I have a lot to convert and will have to live some time with libraries being used by both FMX and VCL. – Arnold Oct 09 '12 at 19:08
  • FireMonkey's `TBitmap` is a very different beast than VCL's `TBitmap`. It is unlikely that you are going to be able to write platform-independant code that can work with both of them without using `IFDEF`s all over the place. – Remy Lebeau Oct 09 '12 at 20:55
  • Aha, so the basis message is: just convert everything. Pity, but I'll start doing that. – Arnold Oct 10 '12 at 15:06
  • 1
    I don't understand this. When I include FMX.Types, the constant is declared, otherwise not. So how does this help to determine if my unit is used by a FMX or VCL project? Let's say my unit uses Vcl.Graphics, but should not if running under FMX... – maf-soft Mar 03 '18 at 20:02
  • 2
    @maf-soft I would recommend defining a custom conditional in each project's options and then `{$IFDEF}` on that instead. – Remy Lebeau Mar 03 '18 at 22:09
  • Note that ">= 16" needs to be ">= 16.0" in Tokyo 10.2.x – Lars Fosdal Aug 08 '18 at 13:31
  • @LarsFosdal no, it doesn't. Whether you use `.0` or not doesn't matter, comparing `16` and `16.0` are identical as far as `$IF` is concerned, and always has been. You can use a decimal to check for updates, but you don't need `.0` to check for the base RTM version – Remy Lebeau Aug 08 '18 at 15:12
  • It seems that I missed the actual root cause of the error, but I do get an error with the example you gave: `{$DEFINE HAS_VCL}` `{$IF DECLARED(FireMonkeyVersion)}` ` {$IF FireMonkeyVersion >= 16} <-- "[dcc32 Error]: E2026 Constant expression expected"` ` {$UNDEF HAS_VCL}` ` {$DEFINE HAS_FMX}` ` {$IFEND}` `{$ENDIF}` while this works `{$DEFINE HAS_VCL}` `{$IFDEF CONDITIONALEXPRESSIONS}` ` {$IF DECLARED(FireMonkeyVersion) and (FireMonkeyVersion >= 16)}` ` {$UNDEF HAS_VCL}` ` {$DEFINE HAS_FMX}` ` {$IFEND}` `{$ENDIF}` – Lars Fosdal Aug 10 '18 at 08:15
  • @LarsFosdal that is a different issue, not related to using `.0` in the comparison. Also, you don't need the `CONDITIONALEXPRESSIONS` check unless you need to support old Delphi compiler versions prior to Delphi 6. – Remy Lebeau Aug 10 '18 at 16:14