Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
APPLIES TO: Business Central 2020 release wave 2 and later
In AL, like in other programming languages, preprocessor directives can be used to make code conditional, to suppress warnings, or to enable the ability to expand and collapse in code. Preprocessor directives can be divided into the following groups. For more information about each type, use the links provided in the following section.
Any code can be made conditional, including table fields, and checked using a conditional directive. To check code using a conditional directive, you must define a symbol to check. A symbol returns a boolean value: true or false. Symbols can be defined at the beginning of a source file, where the scope of the specific symbol is in the file in which it is defined. You can also define symbols in the app.json file, and then the scope is global for the extension.
Note
Built-in symbols are currently not supported in AL. Symbols must be defined in a specific file or in the app.json file.
Note
User personalization and profile configuration (including profile copy) are not meant to work with directives, which means that they are ignored by the platform in the cases of #pragma, #region, #endregion and fail with an error when they are not supported for #if, #elif, #define, etc.
Conditional directives
The following conditional preprocessor directives are supported in AL.
| Conditional preprocessor directive | Description |
|---|---|
| #if | Specifies the beginning of a conditional clause. The #endif clause ends it. Compiles the code between the directives if the specified symbol being checked is defined. Inside the #if directive, you can use logical operators to create complex conditions. The supported logical operators are shown in the next section. |
| #else | Specifies a compound conditional clause. If none of the preceding clauses evaluate to true, the compiler will evaluate code between #else and #endif. |
| #elif | Combines else and if. If #elif is true the compiler evaluates all code between #elif and the next conditional directive. |
| #endif | Specifies the end of a conditional clause that begins with #if. |
| #define | Defines a symbol that can be used to specify conditions for a compilation. For example, #define DEBUG. The scope of the symbol is the file that it was defined in. |
| #undef | Undefines a symbol. |
Logical operators in conditional directives
The operators and, or, and not are supported in conditional directives. and evaluates to true if both operands are true, or evaluates to true if at least one of the operands is true, and not negates the value of the operand.
Defining and using preprocessor symbols
Preprocessor symbols in AL are boolean flags that are either defined (evaluating to true) or undefined (evaluating to false). Unlike some other languages, you can't assign specific values to symbols - they're simply on or off.
Defining symbols globally in app.json
Symbols can be defined globally in the app.json file, making them available throughout your extension. The following example defines DEBUG and PROD as global symbols:
{
"preprocessorSymbols": [ "DEBUG", "PROD" ]
}
When symbols are defined in app.json, they're automatically set to true for the entire extension.
Defining symbols in code
You can also define symbols locally within a specific file using the #define directive. The symbol will only be available in that file:
#define TESTING
#define FEATURE_ENABLED
codeunit 50100 MyCodeunit
{
trigger OnRun()
begin
#if TESTING
Message('This code runs when TESTING is defined');
#endif
end;
}
Undefining symbols
You can undefine a symbol using #undef, which sets it to false from that point forward in the file:
#define DEBUG
// DEBUG is true here
#undef DEBUG
// DEBUG is now false here
How symbols evaluate
- A defined symbol (either in
app.jsonor via#define) evaluates totrue - An undefined symbol (never defined, or after
#undef) evaluates tofalse - Use
notto check if a symbol is undefined:#if not DEBUG
Learn more in JSON Files.
Examples
Example 1: Simple conditional compilation
#define DEBUG
codeunit 50100 MyCodeunit
{
trigger OnRun()
begin
#if DEBUG
Message('Only in debug versions');
#endif
end;
}
Example 2: Using symbols from app.json
If you define symbols in app.json:
{
"preprocessorSymbols": [ "PREMIUM_FEATURES" ]
}
You can then use them throughout your code:
table 50100 MyTable
{
fields
{
field(1; "Basic Field"; Code[20]) { }
#if PREMIUM_FEATURES
field(2; "Premium Field"; Code[20]) { }
#endif
}
}
Example 3: Multiple conditions with logical operators
#define DEBUG
#define TESTING
codeunit 50101 ConditionalCode
{
trigger OnRun()
begin
#if DEBUG and TESTING
Message('Both DEBUG and TESTING are defined');
#elif DEBUG or TESTING
Message('At least one is defined');
#else
Message('Neither DEBUG nor TESTING is defined');
#endif
end;
}
Example 4: Environment-specific code
page 50100 MyPage
{
trigger OnOpenPage()
begin
#if CLOUD
// Cloud-specific logic
SetupCloudConnection();
#elif ONPREM
// On-premises specific logic
SetupOnPremConnection();
#else
// Default behavior
SetupStandardConnection();
#endif
end;
}
Example 5: Using not operator
#define PRODUCTION
codeunit 50102 FeatureToggle
{
trigger OnRun()
begin
#if not PRODUCTION
// This code only runs when PRODUCTION is NOT defined
EnableExperimentalFeatures();
#endif
#if PRODUCTION
// This code only runs when PRODUCTION IS defined
EnableStableFeatures();
#endif
end;
}
Related information
Development in AL
AL development environment
Conditional directives
Region directive in AL
Pragma directive in AL
Deprecating explicit and implicit with statements
Best practices for deprecation of code in the Base App
ObsoleteState property
ObsoleteReason property
ObsoleteTag property
Obsolete attribute