Difference between revisions of "Conditional compilation"

From Lazarus wiki
Jump to navigationJump to search
(Using the correct syntax of $ELSEIF)
m (Fixed syntax highlighting; typos and wiki markup)
Line 1: Line 1:
 +
{{Template:Directives, Defines and Conditionals}}
 
{{Conditional_compilation}}
 
{{Conditional_compilation}}
  
== What is conditional compilation? ==
+
= What is conditional compilation? =
Conditional compilation is compiling or omitting part of the sourcecode based on if a condition exists or not.<br>
+
 
The features that make this possible in most compiled languages are called compile time directives.
+
Conditional compilation is compiling or omitting part of the source code based on if a condition exists or not.
Compile time directives make it possible to compile a block of code based on the presence or absense of a condition at compile time.
+
 
 +
The features that make this possible in most compiled languages are called compile time directives. Compile time directives make it possible to compile a block of code based on the presence or absence of a condition at compile time.
 +
 
 
They can be used for a variety of purposes like:
 
They can be used for a variety of purposes like:
 +
 
* Platform specific code isolation
 
* Platform specific code isolation
 
* Natural language selection  
 
* Natural language selection  
Line 14: Line 18:
 
* etc, etc.
 
* etc, etc.
  
FreePascal supports four different styles of conditional compilation:
+
Free Pascal supports four different styles of conditional compilation:
* TurboPascal and early Delphi style directives
+
 
 +
* Turbo Pascal and early Delphi style directives
 
* Mac Pascal style directives
 
* Mac Pascal style directives
* Modern Freepascal and Delphi style directives
+
* Modern Free Pascal and Delphi style directives
* Compile time Macro's
+
* Compile time Macros
 +
 
 
Note the syntax here is not case sensitive as conforms to all Pascal syntax. We will use both lowercase and uppercase examples.
 
Note the syntax here is not case sensitive as conforms to all Pascal syntax. We will use both lowercase and uppercase examples.
 
We will show you the difference between the modes and how to efficiently use them.
 
We will show you the difference between the modes and how to efficiently use them.
== TurboPascal style directives ==
+
 
The TurboPascal style directives are {$DEFINE}, {$IFDEF}, {$ENDIF}, {$IFNDEF}, {$IFOPT}, {$ELSE}, {$ELSEIF} and {$UNDEF}.<br>
+
= Turbo Pascal style directives =
We will describe the directives in the context of the style. Some defines have an extended meaning in another style.<br>
+
 
That means later on we may expand the meaning of certain directives like e.g. {$DEFINE} in the context of Macro's.
+
The Turbo Pascal style directives are {$DEFINE}, {$IFDEF}, {$ENDIF}, {$IFNDEF}, {$IFOPT}, {$ELSE}, {$ELSEIF} and {$UNDEF}.<br>
===== $define =====
+
We will describe the directives in the context of the style. Some defines have an extended meaning in another style.
 +
 
 +
That means later on we may expand the meaning of certain directives like e.g. {$DEFINE} in the context of Macros.
 +
 
 +
== $define ==
 +
 
 
The {$DEFINE} directive simply declares a symbol that we later can use for conditional compilation:
 
The {$DEFINE} directive simply declares a symbol that we later can use for conditional compilation:
<syntaxhighlight>{$DEFINE name} // This defines a symbol called "name"</syntaxhighlight>
+
 
  Note you can also define a symbol from the command line or the IDE <b>-dDEBUG</b> for example is the command line equivalent of {$DEFINE DEBUG} in the sourcecode.
+
<syntaxhighlight lang="pascal">{$DEFINE name} // This defines a symbol called "name"</syntaxhighlight>
===== $undef =====
+
 
 +
Note you can also define a symbol from the command line or the IDE <b>-dDEBUG</b> for example is the command line equivalent of {$DEFINE DEBUG} in the source code.
 +
 
 +
== $undef ==
 +
 
 
The {$UNDEF} directive undefines a previously defined symbol. Here is an example that the author uses in practice:
 
The {$UNDEF} directive undefines a previously defined symbol. Here is an example that the author uses in practice:
<syntaxhighlight>
+
 
// Some older sourcecode is polluted with {$IFDEF FPC}'s that are no  
+
<syntaxhighlight lang="pascal">
 +
// Some older source code is polluted with {$IFDEF FPC} that are no  
 
// longer necessary depending on the Delphi version to which it it should be compatible.
 
// longer necessary depending on the Delphi version to which it it should be compatible.
 
// I always test this by trying this on top of the program or unit:
 
// I always test this by trying this on top of the program or unit:
Line 39: Line 55:
 
   {$UNDEF FPC}
 
   {$UNDEF FPC}
 
   {$DEFINE VER150}  
 
   {$DEFINE VER150}  
   // code will now compile as if it was Delphi 7, provided the original Delphi sourcecode was indeed written for Delphi 7 and up.
+
   // code will now compile as if it was Delphi 7, provided the original Delphi source code was indeed written for Delphi 7 and up.
{$ENDIF}</syntaxhighlight>
+
{$ENDIF}
 +
</syntaxhighlight>
 +
 
 +
== $ifdef and $endif ==
  
===== $ifdef and $endif =====
 
 
The simplest way to define a block of conditional code is like this:
 
The simplest way to define a block of conditional code is like this:
<syntaxhighlight>unit cross;
+
 
{$IFDEF FPC}{$MODE DELPHI}{$ENDIF}</syntaxhighlight>
+
<syntaxhighlight lang="pascal">
The above example is quite common for sourcecode that has to compile in both Delphi and Freepascal</br>
+
unit cross;
If the compiler is Delphi then nothing is done, but if the compiler is FreePascal it will switch Freepascal to compile and use Delphi syntax mode.<br>
+
{$IFDEF FPC}{$MODE DELPHI}{$ENDIF}
 +
</syntaxhighlight>
 +
 
 +
The above example is quite common for source code that has to compile in both Delphi and Free Pascal
 +
 
 +
If the compiler is Delphi then nothing is done, but if the compiler is Free Pascal it will switch Free Pascal to compile and use Delphi syntax mode.
 +
 
 
This "FPC" conditional symbol is defined in system - there is a long list of those.
 
This "FPC" conditional symbol is defined in system - there is a long list of those.
The {$IFDEF} and {$ENDIF} block syntax is symmetrical: every {$IFDEF} has its own {$ENDIF}.<br> To help you recognize the corresponding blocks you can use e.g. indentation, but you can also use the comment feature:
+
The {$IFDEF} and {$ENDIF} block syntax is symmetrical: every {$IFDEF} has its own {$ENDIF}.
<syntaxhighlight>{$IFDEF FPC this part is Freepascal specific}
+
 
// some Freepascal specific code
+
To help you recognize the corresponding blocks you can use e.g. indentation, but you can also use the comment feature:
{$ENDIF Freepascal specific code}</syntaxhighlight>  
+
 
 +
<syntaxhighlight lang="pascal">
 +
{$IFDEF FPC this part is Free Pascal specific}
 +
// some Free Pascal specific code
 +
{$ENDIF Free Pascal specific code}
 +
</syntaxhighlight>  
  
<b>warning</b><br>
+
{{Warning| This comment feature is often not well understood.  Some people - as on an older version of this wiki entry - assumed you could nest {$IFDEF} because the compiler seems to accept the syntax.  But the former is false and the latter is true: Yes the compiler accepts the syntax below, but it is not a nested {$IFDEF} but a single {$IFDEF} condition and the rest is a comment!"  
This comment feature is often not well understood.  
+
<br/>
  Some people - as on an older version of this wiki entry - assumed you could nest {$IFDEF}'s because the compiler seems to accept the syntax.
+
The code below executes the writeln <b>if and only if red is defined.</b> In this example {$ifdef blue} is a comment! Even if the {$define blue} is valid.}}
  But the former is false and the latter is true:
+
 
Yes the compiler accepts the syntax below, but it is not a nested {$IFDEF} but a single {$IFDEF} condition and the rest is a comment!"
+
<syntaxhighlight lang="pascal">
The code below executes the writeln <b>if and only if red is defined.</b><br>In this example {$ifdef blue} is a comment! Even if the {$define blue} is valid.
+
// program completely wrong;
<syntaxhighlight>program completelywrong;
 
 
{$define blue}   
 
{$define blue}   
 
begin
 
begin
Line 67: Line 95:
 
{$endif red or blue}      // everything after $endif is a comment.
 
{$endif red or blue}      // everything after $endif is a comment.
 
end.</syntaxhighlight>
 
end.</syntaxhighlight>
===== $ifndef =====
 
This is the opposite of {$IFDEF} and code will be included of a certain condition is <b>not</b> defined.<br>
 
A simple example is:<syntaxhighlight>{$IFNDEF FPC this part not for Freepascal}
 
// some specific code that Freepascal should not compile
 
{$ENDIF code for other compilers than Freepascal}</syntaxhighlight>
 
  
===== $else and $elseif =====
+
== $ifndef ==
{$ELSE} is used to compile code that does not belong to the codeblock that is defined by the corresponding {$IFDEF}. It is also valid in the context {$IFOPT}, {$IF} or {$IFC} that we will discuss later.
+
 
<syntaxhighlight>
+
This is the opposite of {$IFDEF} and code will be included of a certain condition is <b>not</b> defined. A simple example is:
 +
 
 +
<syntaxhighlight lang="pascal">
 +
{$IFNDEF FPC this part not for Free Pascal}
 +
// some specific code that Free Pascal should not compile
 +
{$ENDIF code for other compilers than Free Pascal}
 +
</syntaxhighlight>
 +
 
 +
== $else and $elseif ==
 +
 
 +
{$ELSE} is used to compile code that does not belong to the code block that is defined by the corresponding {$IFDEF}. It is also valid in the context {$IFOPT}, {$IF} or {$IFC} that we will discuss later.
 +
 
 +
<syntaxhighlight lang="pascal">
 
{$IFDEF red}   
 
{$IFDEF red}   
 
   writeln('Red is defined');   
 
   writeln('Red is defined');   
Line 84: Line 119:
 
   writeln('Neither red nor blue is defined');  
 
   writeln('Neither red nor blue is defined');  
 
   {$ENDIF blue}   
 
   {$ENDIF blue}   
{$ENDIF red}</syntaxhighlight>
+
{$ENDIF red}
 +
</syntaxhighlight>
 +
 
 
Such nested conditional written in the above syntax can get very messy and unreadable. Luckily we can simplify it a lot by using {$ELSEIF}. The code below is an expanded equivalent of the first example:
 
Such nested conditional written in the above syntax can get very messy and unreadable. Luckily we can simplify it a lot by using {$ELSEIF}. The code below is an expanded equivalent of the first example:
<syntaxhighlight>
+
 
 +
<syntaxhighlight lang="pascal">
 
{$IF Defined(red)}   
 
{$IF Defined(red)}   
 
   writeln('Red is defined');   
 
   writeln('Red is defined');   
Line 95: Line 133:
 
{$ELSE}
 
{$ELSE}
 
   writeln('Neither red, blue or green. Must be black...or something else...');
 
   writeln('Neither red, blue or green. Must be black...or something else...');
{$ENDIF}</syntaxhighlight>
+
{$ENDIF}
 +
</syntaxhighlight>
 +
 
 
As you can see this is a lot more readable.
 
As you can see this is a lot more readable.
===== $ifopt =====
+
 
 +
== $ifopt ==
 +
 
 
With {$IFOPT} we can check if a certain compile option is defined.
 
With {$IFOPT} we can check if a certain compile option is defined.
 +
 
From the programmers manual:
 
From the programmers manual:
The {$IFOPT switch} will compile the text that follows it if the switch switch is currently in the specified state. If it isn’t in the specified state, then compilation continues after the corresponding {$ELSE}  
+
 
or {$ENDIF} directive.
+
  The {$IFOPT switch} will compile the text that follows it if the switch switch is currently in the specified state. If it isn’t in    
As an example:
+
  the specified state, then compilation continues after the corresponding {$ELSE} or {$ENDIF} directive.
<syntaxhighlight>
+
 
 +
As an example:
 +
 
 +
<syntaxhighlight lang="pascal">
 
  {$IFOPT M+}   
 
  {$IFOPT M+}   
 
   Writeln(’Compiled with type information’);   
 
   Writeln(’Compiled with type information’);   
  {$ENDIF}</syntaxhighlight>
+
  {$ENDIF}
Will compile the Writeln statement only if generation of type information is on.
+
</syntaxhighlight>
Remark:The {$IFOPT} directive accepts only short options, i.e. {$IFOPT TYPEINFO} will not be accepted.
+
 
 +
Will compile the Writeln statement only if generation of type information is on. Remark: The {$IFOPT} directive accepts only short options, ie {$IFOPT TYPEINFO} will not be accepted.
 +
 
 +
A common use is this example to test if DEBUG mode is defined:
 +
 
 +
<syntaxhighlight lang="pascal">{$IFOPT D+}{$NOTE debug mode is active}{$ENDIF}</syntaxhighlight>
  
A common use is this example to test if DEBUG mode is defined:<syntaxhighlight>{$IFOPT D+}{$NOTE debug mode is active}{$ENDIF}</syntaxhighlight>
 
 
Such defines can also reside in configuration files like fpc.cfg which also contains a full explanation on how to use:
 
Such defines can also reside in configuration files like fpc.cfg which also contains a full explanation on how to use:
 
  # ----------------------
 
  # ----------------------
Line 122: Line 172:
 
  #
 
  #
 
  #
 
  #
  # Some examples (for switches see below, and the -? helppages)
+
  # Some examples (for switches see below, and the -? help pages)
 
  #
 
  #
  # Try compiling with the -dRELEASE or -dDEBUG on the commandline
+
  # Try compiling with the -dRELEASE or -dDEBUG on the command line
 
  #
 
  #
  # For a release compile with optimizes and strip debuginfo
+
  # For a release compile with optimizes and strip debug info
 
  #IFDEF RELEASE
 
  #IFDEF RELEASE
 
   -O2
 
   -O2
Line 132: Line 182:
 
   #WRITE Compiling Release Version
 
   #WRITE Compiling Release Version
 
  #ENDIF
 
  #ENDIF
== Examples of bad use of conditional compilation: What not to do ==
+
 
What is wrong with this code? Can you spot it?<syntaxhighlight>
+
= What not to do =
 +
 
 +
What is wrong with this code? Can you spot it?
 +
 
 +
<syntaxhighlight lang="pascal">
 
var
 
var
 
   MyFilesize:
 
   MyFilesize:
Line 140: Line 194:
 
   {$else}
 
   {$else}
 
     int64
 
     int64
   {$endif}</syntaxhighlight>
+
   {$endif}
 +
</syntaxhighlight>
  
 
The answer is:
 
The answer is:
* that Freepascal compiles for more CPU types than 32 an 64 bit, also for e.g. 8 and 16 bit.
+
 
 +
* that Free Pascal compiles for more CPU types than 32 an 64 bit, also for e.g. 8 and 16 bit.
 
* on most 64 bit platforms the maximum file size is a qword, not an int64.
 
* on most 64 bit platforms the maximum file size is a qword, not an int64.
That programmer fell into a trap that is common: if you use a define, make sure your logic is solid. Otherwise such code can easily cause accidents.
+
 
The compiler will not catch your logic errors!<br>
+
That programmer fell into a trap that is common: if you use a define, make sure your logic is solid. Otherwise such code can easily cause accidents. The compiler will not catch your logic errors!
 +
 
 
It is always good to realize such things especially that such things can easily be fixed.
 
It is always good to realize such things especially that such things can easily be fixed.
<syntaxhighlight>
+
 
 +
<syntaxhighlight lang="pascal">
 
var
 
var
 
   MyFilesize:
 
   MyFilesize:
Line 157: Line 215:
 
   {$else}
 
   {$else}
 
     {$error this code is written for win32 or win64}
 
     {$error this code is written for win32 or win64}
   {$endif}</syntaxhighlight>
+
   {$endif}
 +
</syntaxhighlight>
 +
 
 
As an aside of course there is a solution for this particular example that does not use conditionals at all:
 
As an aside of course there is a solution for this particular example that does not use conditionals at all:
<syntaxhighlight>
+
 
 +
<syntaxhighlight lang="pascal">
 
var
 
var
   MyFilesize:NativeUint; </syntaxhighlight>
+
   MyFilesize:NativeUint;  
 +
</syntaxhighlight>
 +
 
 +
What is wrong with this code? Can you spot it?
  
 +
<syntaxhighlight lang="pascal"> 
 +
{$IFDEF BLUE AND $IFDEF RED} Form1.Color := clYellow; {$ENDIF}
 +
{$IFNDEF RED AND $IFNDEF BLUE} Form1.Color := clAqua; {$ENDIF}
 +
</syntaxhighlight>
  
What is wrong with this code? Can you spot it?<syntaxhighlight>  {$IFDEF BLUE AND $IFDEF RED} Form1.Color := clYellow; {$ENDIF}
 
  {$IFNDEF RED AND $IFNDEF BLUE} Form1.Color := clAqua; {$ENDIF}</syntaxhighlight>
 
 
The Answer is:
 
The Answer is:
 +
 
* Well, I have already wrote a '''comment''' that warned you.. so look at the warning.... You should be able to spot it...
 
* Well, I have already wrote a '''comment''' that warned you.. so look at the warning.... You should be able to spot it...
 
* Compiler directives override the compiler... be careful with that axe Eugene.
 
* Compiler directives override the compiler... be careful with that axe Eugene.
 
{{Template:Directives, Defines and Conditionals}}
 

Revision as of 13:20, 4 July 2019

Directives, definitions and conditionals definitions
global compiler directives • local compiler directives

Conditional Compiler Options • Conditional compilation • Macros and Conditionals • Platform defines
$IF


Deutsch (de) English (en) suomi (fi) français (fr) русский (ru)

What is conditional compilation?

Conditional compilation is compiling or omitting part of the source code based on if a condition exists or not.

The features that make this possible in most compiled languages are called compile time directives. Compile time directives make it possible to compile a block of code based on the presence or absence of a condition at compile time.

They can be used for a variety of purposes like:

  • Platform specific code isolation
  • Natural language selection
  • Licensing opensource and closed source parts
  • Isolating experimental code
  • Compiler version
  • Library version
  • etc, etc.

Free Pascal supports four different styles of conditional compilation:

  • Turbo Pascal and early Delphi style directives
  • Mac Pascal style directives
  • Modern Free Pascal and Delphi style directives
  • Compile time Macros

Note the syntax here is not case sensitive as conforms to all Pascal syntax. We will use both lowercase and uppercase examples. We will show you the difference between the modes and how to efficiently use them.

Turbo Pascal style directives

The Turbo Pascal style directives are {$DEFINE}, {$IFDEF}, {$ENDIF}, {$IFNDEF}, {$IFOPT}, {$ELSE}, {$ELSEIF} and {$UNDEF}.
We will describe the directives in the context of the style. Some defines have an extended meaning in another style.

That means later on we may expand the meaning of certain directives like e.g. {$DEFINE} in the context of Macros.

$define

The {$DEFINE} directive simply declares a symbol that we later can use for conditional compilation:

{$DEFINE name} // This defines a symbol called "name"

Note you can also define a symbol from the command line or the IDE -dDEBUG for example is the command line equivalent of {$DEFINE DEBUG} in the source code.

$undef

The {$UNDEF} directive undefines a previously defined symbol. Here is an example that the author uses in practice:

// Some older source code is polluted with {$IFDEF FPC} that are no 
// longer necessary depending on the Delphi version to which it it should be compatible.
// I always test this by trying this on top of the program or unit:
{$IFDEF FPC}
  {$MODE DELPHI}
  {$UNDEF FPC}
  {$DEFINE VER150} 
  // code will now compile as if it was Delphi 7, provided the original Delphi source code was indeed written for Delphi 7 and up.
{$ENDIF}

$ifdef and $endif

The simplest way to define a block of conditional code is like this:

unit cross;
{$IFDEF FPC}{$MODE DELPHI}{$ENDIF}

The above example is quite common for source code that has to compile in both Delphi and Free Pascal

If the compiler is Delphi then nothing is done, but if the compiler is Free Pascal it will switch Free Pascal to compile and use Delphi syntax mode.

This "FPC" conditional symbol is defined in system - there is a long list of those. The {$IFDEF} and {$ENDIF} block syntax is symmetrical: every {$IFDEF} has its own {$ENDIF}.

To help you recognize the corresponding blocks you can use e.g. indentation, but you can also use the comment feature:

{$IFDEF FPC this part is Free Pascal specific}
// some Free Pascal specific code
{$ENDIF Free Pascal specific code}
Warning-icon.png

Warning: This comment feature is often not well understood. Some people - as on an older version of this wiki entry - assumed you could nest {$IFDEF} because the compiler seems to accept the syntax. But the former is false and the latter is true: Yes the compiler accepts the syntax below, but it is not a nested {$IFDEF} but a single {$IFDEF} condition and the rest is a comment!"
The code below executes the writeln if and only if red is defined. In this example {$ifdef blue} is a comment! Even if the {$define blue} is valid.

// program completely wrong;
{$define blue}  
begin
{$ifdef red or $ifdef blue}// everything after red is a comment
  writeln ('red or blue'); // this code is never reached
{$endif red or blue}       // everything after $endif is a comment.
end.

$ifndef

This is the opposite of {$IFDEF} and code will be included of a certain condition is not defined. A simple example is:

{$IFNDEF FPC this part not for Free Pascal}
// some specific code that Free Pascal should not compile
{$ENDIF code for other compilers than Free Pascal}

$else and $elseif

{$ELSE} is used to compile code that does not belong to the code block that is defined by the corresponding {$IFDEF}. It is also valid in the context {$IFOPT}, {$IF} or {$IFC} that we will discuss later.

{$IFDEF red}  
   writeln('Red is defined');  
{$ELSE  no red}  
  {$IFDEF blue}  
   writeln('Blue is defined, but red is not defined');  
  {$ELSE no blue}  
  writeln('Neither red nor blue is defined'); 
  {$ENDIF blue}  
{$ENDIF red}

Such nested conditional written in the above syntax can get very messy and unreadable. Luckily we can simplify it a lot by using {$ELSEIF}. The code below is an expanded equivalent of the first example:

{$IF Defined(red)}  
  writeln('Red is defined');  
{$ELSEIF Defined(blue)}  
  writeln('Blue is defined');  
{$ELSEIF Defined(green)}  
  writeln('Green is defined');   
{$ELSE}
  writeln('Neither red, blue or green. Must be black...or something else...');
{$ENDIF}

As you can see this is a lot more readable.

$ifopt

With {$IFOPT} we can check if a certain compile option is defined.

From the programmers manual:

 The {$IFOPT switch} will compile the text that follows it if the switch switch is currently in the specified state. If it isn’t in      
 the specified state, then compilation continues after the corresponding {$ELSE} or {$ENDIF} directive.

As an example:

 {$IFOPT M+}  
   Writeln(Compiled with type information);  
 {$ENDIF}

Will compile the Writeln statement only if generation of type information is on. Remark: The {$IFOPT} directive accepts only short options, ie {$IFOPT TYPEINFO} will not be accepted.

A common use is this example to test if DEBUG mode is defined:

{$IFOPT D+}{$NOTE debug mode is active}{$ENDIF}

Such defines can also reside in configuration files like fpc.cfg which also contains a full explanation on how to use:

# ----------------------
# Defines (preprocessor)
# ----------------------
#
# nested #IFNDEF, #IFDEF, #ENDIF, #ELSE, #DEFINE, #UNDEF are allowed
#
# -d is the same as #DEFINE
# -u is the same as #UNDEF
#
#
# Some examples (for switches see below, and the -? help pages)
#
# Try compiling with the -dRELEASE or -dDEBUG on the command line
#
# For a release compile with optimizes and strip debug info
#IFDEF RELEASE
  -O2
  -Xs
  #WRITE Compiling Release Version
#ENDIF

What not to do

What is wrong with this code? Can you spot it?

var
  MyFilesize:
  {$ifdef Win32} 
    Cardinal 
  {$else}
    int64
  {$endif}

The answer is:

  • that Free Pascal compiles for more CPU types than 32 an 64 bit, also for e.g. 8 and 16 bit.
  • on most 64 bit platforms the maximum file size is a qword, not an int64.

That programmer fell into a trap that is common: if you use a define, make sure your logic is solid. Otherwise such code can easily cause accidents. The compiler will not catch your logic errors!

It is always good to realize such things especially that such things can easily be fixed.

var
  MyFilesize:
  {$if defined(Win32)} 
    Cardinal 
  {$elseif defined(Win64)}
    Qword;
  {$else}
     {$error this code is written for win32 or win64}
  {$endif}

As an aside of course there is a solution for this particular example that does not use conditionals at all:

var
  MyFilesize:NativeUint;

What is wrong with this code? Can you spot it?

  
{$IFDEF BLUE AND $IFDEF RED} Form1.Color := clYellow; {$ENDIF}
{$IFNDEF RED AND $IFNDEF BLUE} Form1.Color := clAqua; {$ENDIF}

The Answer is:

  • Well, I have already wrote a comment that warned you.. so look at the warning.... You should be able to spot it...
  • Compiler directives override the compiler... be careful with that axe Eugene.