Conditional Compilation
Conditional Compilation allows to change the way code is generated using 'Preprocessor commands'.
The '`#define`' command allows to define compilation constants, that is constants that describe the parameters of the platform for which the program is compiled.
These constants make it possible to carry out conditional compilations, that is to say to modify the behavior of the program according to parameters defined during its compilation.
The '`#define`' command is also used to replace identifiers of the program with other identifiers, for example to test several versions of the same function without modifying the entire program.
Compilation constants
A clear distinction will be made between compilation constants defined with the '`#define`' directive of the preprocessor and the constants defined with the '`Const`' keyword.
Indeed, the literal constants do not reserve memory. These are immediate values, defined by the compiler.
On the other hand, the '`Const`' can still have a reserved memory space. This is for example the case when manipulating string literals.
A literal constant declared with the '`#define`' directive of the preprocessor will always retain its value (provided that it is not redefined). These literal constants have no type, which can be very annoying and error-prone in code.
Their use will be reserved for compilation constants only, and the '`Const`' keyword will be preferred for all other constants of the program.
The preprocessor sets a number of built-in constants automatically.
These are the 'Intrinsic Defines' (see their list).
Conditional compilation
The definition of identifiers and compilation constants is widely used to perform so-called conditional compilation.
Conditional compilation consists of replacing certain portions of source code with others, depending on the presence or value of compilation constants.
This is achievable using conditional compilation directives.
The most common of which are probably:
`#ifdef symbol`
`' Conditionally included statements`
`#endif`
the text between the `#ifdef` (ie, "if defined") and the `#endif` is left as it is if the identifier `symbol` is known to the preprocessor. Otherwise, it is deleted (the identifier can be declared using just the `#define` command seen previously).
There are other conditional compilation directives like:
- `#ifndef (if not defined ...)`
- `#else` / `#elseif (otherwise ... / otherwise, if ...)`
- `#if (if ...)`
the `#if` directive expects a constant expression as parameter (the text that follows is included in the file if and only if this expression is true).
Another common application of compilation directives is the protection of header files against multiple inclusions:
`#ifndef AlreadyThere`
`#define AlreadyThere`
`' Text to include only once at most.`
`#endif`
This prevents the text from being included multiple times, as a result of multiple `#include` calls.
Indeed, at the first call, `AlreadyThere` is not known to the preprocessor. It is therefore declared and the text is included.
On any subsequent call, `AlreadyThere` exists, and the text is not included.
This kind of writing is found in header files, for which in general we do not want a multiple inclusion to take place.
Example
Example of conditional compilation using the Intrinsic define `__FB_DEBUG__` to debug a recursive function:
`
Function recursiveFactorial (ByVal n As Integer) As Integer
If (n = 0) Then '' end condition
#if __FB_DEBUG__ <> 0
Print "end of recursion and result:";
#endif
Return 1
Else '' recursion loop
#if __FB_DEBUG__ <> 0
Print "multiply by: " & n
#endif
Return n * recursiveFactorial(n - 1) '' recursive call
End If
End Function
Print recursiveFactorial(5)
Sleep
`
Output after compiling without `-g` option:

     120

Output after compiling with `-g` option:

    multiply by: 5
    multiply by: 4
    multiply by: 3
    multiply by: 2
    multiply by: 1
    end of recursion and result: 120

See also

- Preprocessor Overview
- Macros