Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to define version "and up" ifdefs in Delphi?

I was working on getting Log4D working in Delphi XE4, and was getting some compile errors because it couldn't find Contnrs in the uses clause, unless I moved it outside the ifdef it was defined in.

{$IFDEF DELPHI5_UP}
  Contnrs,
{$ENDIF}

A little bit of investigating uncovered that the ifdef is defined in an included file Defines.inc which has a block for each "supported" version of delphi which stops a few versions back:

eg:

{$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}

So while it would be easy enough to go ahead and copy and paste the ifdef for Delphi 2006 and create a Delphi XE4 block... this seems like an inelegant solution. It's definitely not future proof...every new version you have to go update this file now so some code that wasn't present in Delphi 4 doesn't make someone else's 15+ year old legacy code explode.

So I was wondering if there's a better way to do conditional compilation such that it really does just check whether you have "Delphi 5 or above" when compiling that line, rather than this format that requires updating every single new version of delphi that comes out.

like image 286
Jessica Brown Avatar asked May 16 '14 20:05

Jessica Brown


Video Answer


2 Answers

IIRC, Delphi 6 introduced conditional expressions, which are actually what TLama suggested. To make your code work with Delphi versions below that, you have to check for {$IFDEF CONDITIONALEXPRESSIONS }. If this is not defined, you have to use the old VERxxx scheme to distinguish between the Delphi versions.

For Delphi 6 and higher you can use the built-in constants CompilerVersion and RTLVersion. Which of these you use depends on your code. Whenever you use a new compiler feature test for CompilerVersion. For anything related to the RTL or VCL test for RTLVersion.

It is always a good idea to code against the newest compiler and only use the conditional part for compatibility to older versions. So instead of writing {$IF CompilerVersion >= 26.0} write your code in a way that {$IF CompilerVersion < 26.0} is used. Thus in the future it is much easier to drop support for older compiler versions.

like image 139
Uwe Raabe Avatar answered Sep 19 '22 01:09

Uwe Raabe


If I was a component vendor (TMS, DevEx) I might feel compelled to stick with the long, verbose syntax that EVERY delphi version ever supports. That's why that big mess is there in most component codebases.

Yet, for my own in-house components, I do not update with every version that comes out because my ver.inc file looks like this, and I do not support Delphi versions at all that do not support this newer syntax:

{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}

Nothing in the code above breaks when a new delphi version comes out. Note that I DO NOT have to support Delphi 5 through 2010 with my codebases. In fact, I only support XE2 and up.

A slightly longer version of the above form could be used to support every version from Delphi 6 and up, without any repeated blocks, and without breaking each time a new delphi version releases.

Also, see Uwe's answer for a technique where you can build one .inc file that supports EVERY version, and only use the old form for the old delphi versions.

like image 20
Warren P Avatar answered Sep 20 '22 01:09

Warren P