A-A-P home page | A-A-P Recipe Executive |
Prev | User Manual | Next

## Chapter 14. Variants

You might first want to read the tutorial for a few examples of using variants.

Here is an example how build variants can be specified. This will be used to explain how it works.

         :variant Opt
             some
                 OPTIMIZE = 2
             much
                 OPTIMIZE = 6
             *
                 OPTIMIZE = 1

"Opt" is the name of a variable. It is used to select one of the variants. Each possible value is listed in the following line and further lines with the same indent. In the example these are "some" and "much". "*" is used to accept any value, it must be the last one. The first value mentioned is the default when the variable isn't set.

You can now start Aap with various arguments to specify the kind of optimizing you want to use:

`aap Opt=some` will set `OPTIMIZE` to 2
`aap Opt=much` will set `OPTIMIZE` to 6
`aap Opt=other` will set `OPTIMIZE` to 1
`aap` will set `OPTIMIZE` to 2

Note that when "Opt" is not given a value the first entry is used, resulting in `OPTIMIZE` being set to 2. But when it is set to a value that isn't mentioned the last entry "*" is used.

## The `BDIR` Variable

The `$BDIR` variable will be adjusted for the variant used. CAREFUL: this means that using `$BDIR` before :variant commands will use a different value, that might not always be what you want.

Inside the :variant command the value of `$BDIR` has already been adjusted.

When a target that is being build starts with `$BDIR` and `$BDIR` doesn't exist, it is created. (Actually, this happens when an item in the path is "build" or starts with "build-".

`$BDIR` is relative to the recipe. When using ":child dir/main.aap" the child recipe will use a different build directory `dir/$BDIR`. Note that when building the same source file twice from recipes that are in different directories, you will get two results. Best is to always build a target from the same recipe (that makes it easier to understand the recipe anyway).

## Compile only when needed

This continues the last example of the tutorial.

We happen to know that the main.c file does not depend on the GUI used. With the recipe above it will nevertheless be compiled again for every GUI version. Although this is a small thing in this example, in a bigger project it becomes more important to skip compilation when it is not needed. Here is the modified recipe:

    1    Source = main.c version.c gui.c
    2
    3    :variant Build
    4        release
    5            OPTIMIZE = 4
    6            Target = myprog
    7        debug
    8            DEBUG = yes
    9            Target = myprogd
    10
    11   :attr {var_DEFINE = $DEFINE} {var_BDIR = $BDIR} main.c
    12
    13   Gui ?= motif
    14   :variant Gui
    15       console
    16       motif
    17            Source += motif.c
    18       gtk
    19            Source += gtk.c
    20
    21   DEFINE += -DGUI=$Gui
    22
    23   :program $Target : $Source

The only new line is line 11. The "main.c" file is given two extra attributes: `var_DEFINE` and `var_BDIR`. What happens is that when "main.c" is being build, Aap will check for attributes of this source file that start with "var_". The values will be used to set variables with the following name to the value of the attribute. Thus `DEFINE` gets the value of `var_DEFINE`. This means that the variable is overruled by the attribute while building "main.c".

The `var_BDIR` attribute is set to "$BDIR" before the second `:variant` command. It does not yet have the selected GUI appended there. The list of directories used is now:

directory | contains files
--- | ---
build-SYS-release | main
build-SYS-debug | main
build-SYS-release-console | version, gui
build-SYS-debug-console | version, gui
build-SYS-release-motif | version, gui, motif
build-SYS-debug-motif | version, gui, motif
build-SYS-release-gtk | version, gui, gtk
build-SYS-debug-gtk | version, gui, gtk

## Building multiple variants at once

If you want to build all the variants that are possible, use a few lines of Python code. Here is an example:

     1   :variant license
     2       trial
     3           DEFINE += -DTRIAL
     4       demo
     5           DEFINE += -DDEMO
     6       full
     7           DEFINE += -DFULL
     8
     9   :variant language
    10       chinese
    11           DEFINE += -DCHINESE
    12       bulgarian
    13           DEFINE += -DBULGARIAN
    14       *
    15           DEFINE += -DENGLISH
    16
    17   build:
    18       :print Building with $license license for language $language.
    19       :print DEFINE=$DEFINE
    10
    21   all:
    22       @for a in ['trial', 'demo', 'full']:                    #license
    23       @   for c in ['chinese', 'bulgarian', 'english']:       #language
    24               :execute main.aap build license=$a language=$c

Invoking Aap without arguments builds the "all" target, which loops over all possible variants and invokes the :execute command with the "build" target. The reason to use the "build" target is that without it the "all" target would be built again and result in an endless loop.

This is the resulting output:

Building with trial license for language chinese.
DEFINE=-DTRIAL -DCHINESE
Building with trial license for language bulgarian.
DEFINE=-DTRIAL -DBULGARIAN
Building with trial license for language english.
DEFINE=-DTRIAL -DENGLISH
Building with demo license for language chinese.
DEFINE=-DDEMO -DCHINESE
Building with demo license for language bulgarian.
DEFINE=-DDEMO -DBULGARIAN
Building with demo license for language english.
DEFINE=-DDEMO -DENGLISH
Building with full license for language chinese.
DEFINE=-DFULL -DCHINESE
Building with full license for language bulgarian.
DEFINE=-DFULL -DBULGARIAN
Building with full license for language english.
DEFINE=-DFULL -DENGLISH

Prev | Up | Next
Chapter 13. Dependencies, Rules and Actions | Contents | Chapter 15. Publishing