Wednesday, September 23, 2015

Conditional Compilation with Features

EDIT: Make sure you read this post to the very end!

Are you developing a code that must work in different Delphi versions? Are you sick of writing code like

{$IF CompilerVersion >= 22}
class function Mapper<T1,T2>:
IMapper<T1,T2>;
{$ENDIF}

as you a) never know when some feature was introduced into Delphi and b) constantly wonder which version of Delphi has CompilerVersion equal to 22?


Then maybe you could use this simple include file.



Features to the rescue!


Instead of writing CompilerVersion defines, you can start thinking in term of features. In the code above I knew that it requires a Delphi that supports generics (quite obvious) and that it needs a Delphi that implements TArray<T> (implementation detail). So I was able to rewrite it as such:

{$I DelphiFeatures.inc}

{$IFDEF F_Generics}{$IFDEF F_TArrayOfT}
class function Mapper<T1,T2>:
IMapper<T1,T2>;
{$ENDIF}{$ENDIF}

This is both easier to write (as I don’t have to remember in which magic version some feature was introduced) and easier to understand.


Initial feature set


Currently, the following features are defined:

{$UNDEF F_AnonymousMethods}       //Anonymous methods.
{$UNDEF F_Helpers}
//Class helpers.
{$UNDEF F_ConditionalExpressions}
//Conditional expressions.
{$UNDEF F_CorrectNativeInt}
//NativeInt/NativeUInt are correctly defined.
{$UNDEF F_EnhancedRecords} /
/Enhanced records (records with methods).
{$UNDEF F_EnhancedRTTI}
//Enhanced RTTI support.
{$UNDEF F_Enumerators}
//For..in statement and GetEnumerator support.
{$UNDEF F_Generics}
//Generics.
{$UNDEF F_Generics_Limited}
//Generics implementation is severely limited.
{$UNDEF F_Inline}
//'inline' directive.
{$UNDEF F_ScopedUnitNames}
//Scoped (dotted) unit names.
{$UNDEF F_StaticClassMethods}
//Static class methods.
{$UNDEF F_StrictVisibility}
//'strict' visibility levels.
{$UNDEF F_TArrayOfT}
//TArray<T> is defined.
{$UNDEF F_TypeHelpers}
//Helpers for simple types.

Unlicense


DelphiFeatures.inc is completely free for any use. You can get it at GitHub.


All suggestions and contributions are welcome!


Poof, and it’s gone!


As friendly people have notified me, JEDI.INC already contains a lot of HAS_XXXXX and SUPPORTS_XXXXX. I don’t plan to support “yet another standard” (thanks, Mason), so I’ll just kill this project and contribute to JEDI.INC.

10 comments:

  1. Anonymous16:28

    https://github.com/project-jedi/jedi/blob/master/jedi.inc

    ReplyDelete
    Replies
    1. Ollivier Sannier also pointed that on FB. I was not aware that JEDI.INC contains HAS_XXXXX and SUPPORTS_XXXXX defines!

      Delete
  2. We use a similar design for our mORMot framework, in Synopse.inc.
    It helps also not only when working with diverse Delphi versions, but also for FPC support.
    One example is {$ifdef HASINLINE}inline;{$endif} which works for Delphi and FPC.

    ReplyDelete
    Replies
    1. Anonymous08:39

      Indy does something similar, in its IdCompilerDefines.inc file.

      Delete
  3. We use a similar design for our mORMot framework, in Synopse.inc.
    It helps also not only when working with diverse Delphi versions, but also for FPC support.
    One example is {$ifdef HASINLINE}inline;{$endif} which works for Delphi and FPC.

    ReplyDelete
  4. Because Jedi.inc already solved this problem, Tommi. :-)

    ReplyDelete
  5. Anonymous14:54

    https://github.com/gabr42/DelphiFeaturesInc
    This repository is not accessible, returns 404 error

    ReplyDelete
    Replies
    1. As I wrote at the beginning - read the post to the very end where I wrote "... I’ll just kill this project ...".

      Delete
    2. Anonymous18:35

      )))
      Funny all that! :-)

      Delete