Integrated Preprocessing (GNAT User’s Guide for Native Platforms)

#### 3.10.3 Integrated Preprocessing ¶

As noted above, a file to be preprocessed consists of Ada source code in which preprocessing lines have been inserted. However, instead of using `gnatprep` to explicitly preprocess a file as a separate step before compilation, you can carry out the preprocessing implicitly as part of compilation. Such ‘integrated preprocessing’, which is the common style with C, is performed when you pass either or both of the following switches to the compiler:

> - `-gnatep`, which specifies the ‘preprocessor data file’. This file dictates how the source files will be preprocessed (e.g., which symbol definition files apply to which sources).
> - `-gnateD`, which defines values for preprocessing symbols.

Integrated preprocessing applies only to Ada source files; it’s not available for configuration pragma files.

With integrated preprocessing, GNAT doesn’t write the output from the preprocessor, by default, to any external file. Instead it’s passed internally to the compiler. To preserve the result of preprocessing in a file, either run `gnatprep` in standalone mode or supply the `-gnateG` switch to the compiler.

When using project files:

> - you should use the builder switch `-x` if any Ada source is compiled with `gnatep=` so that the compiler finds the ‘preprocessor data file’.
> - you should place the preprocessing data file and the symbol definition files in the source directories of the project.

Note that the `gnatmake` switch `-m` will almost always trigger recompilation for sources that are preprocessed, because `gnatmake` cannot compute the checksum of the source after preprocessing.

The actual preprocessing function is described in detail in Preprocessing with gnatprep. This section explains the switches that relate to integrated preprocessing.

`-gnatep=`preprocessor_data_file'`

  This switch specifies the file name (without directory information) of the preprocessor data file. Either place this file in one of the source directories, or, when using project files, reference the project file’s directory via the `project_name'Project_Dir` project attribute; e.g:

  >     project Prj is
  >        package Compiler is
  >           for Switches ("Ada") use
  >             ("-gnatep=" & Prj'Project_Dir & "prep.def");
  >        end Compiler;
  >     end Prj;

  A preprocessor data file is a text file that contains ‘preprocessor control lines’. A preprocessor control line directs the preprocessing of either a particular source file, or, analogous to `others` in Ada, all sources not specified elsewhere in the preprocessor data file. A preprocessor control line can optionally identify a ‘definition file’ that assigns values to preprocessor symbols, as well as a list of switches that relate to preprocessing. You can also include empty lines and comments (using Ada syntax), with no semantic effect.

  Here’s an example of a preprocessor data file:

  >     "toto.adb"  "prep.def" -u
  >     --  Preprocess toto.adb, using definition file prep.def
  >     --  Undefined symbols are treated as False

  >     * -c -DVERSION=V101
  >     --  Preprocess all other sources without using a definition file
  >     --  Suppressed lined are commented
  >     --  Symbol VERSION has the value V101

  >     "tata.adb" "prep2.def" -s
  >     --  Preprocess tata.adb, using definition file prep2.def
  >     --  List all symbols with their values

  A preprocessor control line has the following syntax:

  >     <preprocessor_control_line> ::=
  >        <preprocessor_input> [ <definition_file_name> ] { <switch> }

  >     <preprocessor_input> ::= <source_file_name> | '*'

  >     <definition_file_name> ::= <string_literal>

  >     <source_file_name> := <string_literal>

  >     <switch> := (See below for list)

  Thus, you start each preprocessor control line either a literal string or the character ‘*’:

  - A literal string is the file name (without directory information) of the source file that will be input to the preprocessor.
  - The character ‘*’ is a wild-card indicator; the additional parameters on the line indicate the preprocessing for all the sources that are not specified explicitly on other lines (the order of the lines is not significant).

  You cannot have two lines with the same file name or two lines starting with the ‘*’ character.

  After the file name or ‘*’, you can place an optional literal string to specify the name of the definition file to be used for preprocessing (Form of Definitions File). The definition files are found by the compiler in one of the source directories. In some cases, when compiling a source in a directory other than the current directory, if the definition file is in the current directory, you may need to add the current directory as a source directory through the `-I` switch; otherwise the compiler would not find the definition file.

  Finally, switches similar to those of `gnatprep` may optionally appear:

  `-b`

    Causes both preprocessor lines and the lines deleted by preprocessing to be replaced by blank lines, preserving the line number. This switch is always implied; however, if specified after `-c` or `-e` it cancels the effect of those switches.

  `-c`

    Causes both preprocessor lines and the lines deleted by preprocessing to be retained as comments marked with the special string ‘–!’.

  `-D`symbol'=`new_value'`

    Define or redefine `symbol` to have `new_value` as its value. You can write `symbol` as either an Ada identifier or any Ada reserved word aside from `if`, `else`, `elsif`, `end`, `and`, `or` and `then`. You can write `new_value` as a literal string, an Ada identifier or any Ada reserved word. A symbol declared with this switch replaces a symbol with the same name defined in a definition file.

  `-e`

    Causes both preprocessor lines and the lines deleted by preprocessing to be replaced by empty comment lines marked with ‘–!’ (and no other text) in the output source file,

  `-s`

    Causes a sorted list of symbol names and values to be listed on the standard output file.

  `-u`

    Causes undefined symbols to be treated as having the value `FALSE` in the context of a preprocessor test. If you don’t specify this switch, an undefined symbol in a `#if` or `#elsif` test is treated as an error.

`-gnateD`symbol'[=`new_value']`

  Define or redefine `symbol` to have `new_value` as its value. If you don’t specify a value, the value of `symbol` is `True`. You write `symbol` as an identifier, following normal Ada (case-insensitive) rules for its syntax, and `new_value` as either an arbitrary string between double quotes or any sequence (including an empty sequence) of characters from the set (letters, digits, period, underline). Ada reserved words may be used as symbols, with the exceptions of `if`, `else`, `elsif`, `end`, `and`, `or` and `then`.

  Examples:

  >     -gnateDToto=Tata
  >     -gnateDFoo
  >     -gnateDFoo=\"Foo-Bar\"

  A symbol declared with this switch on the command line replaces a symbol with the same name either in a definition file or specified with a switch `-D` in the preprocessor data file.

  This switch is similar to switch `-D` of `gnatprep`.

`-gnateG[bce]`

  When integrated preprocessing is performed on source file `filename.extension`, create or overwrite `filename.extension.prep` to contain the result of the preprocessing. For example if the source file is `foo.adb` then the output file is `foo.adb.prep`. An optional character (b, c, or e) can be appended to indicate that filtered lines are to be replaced by blank lines, comments, or empty comments (see documentation above about `-b`, `-c`, and `-e`). If one of those switches is given in a preprocessor data file, then it will override any option included with `-gnateG`.