Difference between revisions of "Conditional compilation"
Windsurferme (talk | contribs) |
Windsurferme (talk | contribs) m |
||
Line 147: | Line 147: | ||
[[Category:Lazarus]] | [[Category:Lazarus]] | ||
[[Category:Compiler directives]] | [[Category:Compiler directives]] | ||
+ | [[Category:Tutorials]] |
Revision as of 12:58, 27 January 2014
Compile-Time Directives $DEFINE and $IFDEF
Why?
If you have an application that needs several variations - say for two customers, or for two operating systems then compile-time defines are just what you need. A practical example is when coding across several platforms. 32 bit Windows only allows 4Gb files because of the maximum size of an integer and other operating systems do not have this limitation. So a filesize definition may be as follows:
var
MyFilesize:
{$ifdef Win32}
Cardinal
{$else}
int64
{$endif}
None of the above is case sensitive.
For another practical example see: http://wiki.freepascal.org/Code_Conversion_Guide#Useful_compiler_variables_.2F_defines_.2F_macros.
Another way of doing the same thing is to use IDE macros. http://wiki.freepascal.org/IDE_Macros_in_paths_and_filenames.
All that remains is to find where the {$DEFINE WIN32} is placed.
How?
There are three ways to do this.
- Unit based {$DEFINE} and {$IFDEF} statements
- Include file
- Project | Project Options | Compiler Options | Other | Custom options
Commands
Nested $IFNDEF, $IFDEF, $ENDIF, $ELSE, $DEFINE, $UNDEF are allowed. See http://wiki.lazarus.freepascal.org/local_compiler_directives#Conditional_compilation for a complete list.
In Custom options
-d is the same as #DEFINE -u is the same as #UNDEF
These entries apply to the whole project.
Examples
Unit based defines and Include (.inc) files must be done individually for each unit. A Custom Option entry applies to every unit.
Unit based {$DEFINE} and {$IFDEF} statements
Create a single form project as below. Comment and uncomment the two {$DEFINE) statements in turn and see what happens. If you add a second form (Form2) which opens when the first form (Form1) is clicked, similar statements will work independently of the {$DEFINE} statements in Form1.
var
Form1: TForm1;
implementation
{$R *.lfm}
{$DEFINE RED}
//{$DEFINE BLUE}
{ TForm1 }
procedure TForm1.FormClick(Sender: TObject);
begin
{$IFDEF RED} Form1.Color := clRed; {$ENDIF}
{$IFDEF BLUE} Form1.Color := clBlue; {$ENDIF}
{$IFDEF BLUE AND $IFDEF RED} Form1.Color := clYellow; {$ENDIF}
{$IFNDEF RED AND $IFNDEF BLUE} Form1.Color := clAqua; {$ENDIF}
end;
Include files
Include files add code into any .pas unit.
Create a file called unit1.inc (It could be called anything.inc.) that contains:
{$DEFINE RED}
//{$DEFINE BLUE}
Create another called unit1a.inc that contains:
{$IFDEF RED} Form1.Color := clRed; {$ENDIF}
{$IFDEF BLUE} Form1.Color := clBlue; {$ENDIF}
{$IFDEF BLUE AND $IFDEF RED} Form1.Color := clYellow; {$ENDIF}
{$IFNDEF RED AND $IFNDEF BLUE} Form1.Color := clAqua; {$ENDIF}
Add them to the project folder. When compiled, these lines will replace the $INCLUDE statements below. Both methods present the same code to the compiler. However, using the include file method makes it easier to handle more complex requirements.
var
Form1: TForm1;
implementation
{$R *.lfm}
{$INCLUDE unit1.inc}
{ TForm1 }
procedure TForm1.FormClick(Sender: TObject);
begin
{$INCLUDE unit1a.inc}
end;
Now, we can get extend to this:
var
Form1: TForm1;
implementation
{$R *.lfm}
{$IFDEF ABC}
{$INCLUDE abc.inc}
{$ELSE}
{$INCLUDE xyz.inc}
{$ENDIF}
{ TForm1 }
procedure TForm1.FormClick(Sender: TObject);
begin
... some code ...
{$IFDEF ABC}
{$INCLUDE abcCode.inc}
{$ELSE}
{$INCLUDE xyzCode.inc}
{$ENDIF}
... some more code ...
end;
Project | Project Options | Compiler Options | Other | Custom options
Comment out the {$DEFINE} statements and add the directives as below. In this case the directives will apply to all units. These are FPC Macro calls. For example -dDEBUG -dVerbose will define the FPC macros DEBUG and Verbose, so you can use {$IFDEF Debug}. See http://wiki.freepascal.org/IDE_Macros_in_paths_and_filenames.
Note the -d prefix.
-dRED -dBLUE
A similar approach can be used when compiling with fpc intead of Lazarus: specify the -d... argument on the command line calling FPC (e.g. in a batch file).