<!--  vim: set sw=2 sts=2 et ft=docbk:

  Part of the A-A-P recipe executive: Tutorial - Variants

  Copyright (C) 2002-2003 Stichting NLnet Labs
  Permission to copy and use this file is specified in the file COPYING.
  If this file is missing you can find it here: http://www.a-a-p.org/COPYING

-->

<para>
A-A-P provides a way to build two variants of the same application.  You
just need to specify what is different about them.  A-A-P will then take care
of putting the resulting files in a different directory, so that you don't
have to recompile everything when you toggle between two variants.
</para>
<para>
  For the details see
  <link linkend="cmd-variant">:variant</link> in the reference manual.
</para>

<bridgehead id="build-variant">One Choice</bridgehead>

<para>
Quite often you want to compile an application for release with maximal
optimizing.  But the optimizer confuses the debugger, thus when stepping
through the program to locate a problem, you want to recompile without
optimizing.  Here is an example:
</para>

<programlisting>
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   :program $Target : $Source
</programlisting>

<para>
Write this recipe as "main.aap" and run &Aap; without arguments.  This will
build "myprog" and use a directory for the object files that ends in
"-release".  The release variant is the first one mentioned, that makes it the
default choice.
</para>

<para>
The first argument for the <computeroutput>:variant</computeroutput> command is
<literal>Build</literal>.  This is
the name of the variable that specifies what variant will be selected.  The
names of the alternatives
are specified with a bit more indent in lines 4 and 7.  For each alternative
two commands are given, again with more indent.  Note that the indent not only
makes it easy for you to see the parts of the <computeroutput>:variant</computeroutput> command, they are
essential for &Aap; to recognize them.
</para>

<para>
To select the "debug" variant the <literal>Build</literal> variable must be set to "debug".  A
convenient way to do this is by specifying this on the command line:
</para>
<literallayout>    % <userinput>aap Build=debug</userinput>
</literallayout>

<para>
This will build the "myprogd" program for debugging instead of for release.
The <literal>DEBUG</literal> variable is recognized by &Aap;.
The object files are stored in a directory ending in
"-debug".  Once you finished debugging and fixed the problem in, for example,
"gui.c", running &Aap; to build the release variant will only compile the
modified file.  There is no need to compile all the C files, because the object
files for the "release" variant are still in the "-release" directory.
</para>


<bridgehead>Two Choices</bridgehead>

<para>
You can extend the <literal>Build</literal> variant with more items, for example
"profile".  This is useful for alternatives that exclude each other.  Another
possibility is to add a second <computeroutput>:variant</computeroutput> command.  Let us
extend the example with a selection of the user interface type.
</para>

<programlisting>
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   Gui ?= motif
12   :variant Gui
13       console
14       motif
15            Source += motif.c
16       gtk
17            Source += gtk.c
18
19   DEFINE += -DGUI=$Gui
20
21   :program $Target : $Source
</programlisting>

<para>
The <computeroutput>:variant</computeroutput> command in line 12 uses the <literal>Gui</literal>
variable to select one of "console", "motif" or "gtk".  Together with the
earlier <computeroutput>:variant</computeroutput> command this offers six alternatives:
"release" with "console", "debug" with "console", "release" with "motif", etc.
To build "debug" with "gtk" use this command:
</para>
<literallayout>    % <userinput>aap Build=debug Gui=gtk</userinput>
</literallayout>

<para>
In line 11 an optional assignment "?=" is used.  This assignment is skipped if
the <literal>Gui</literal> variable already has a value.  Thus if <literal>Gui</literal> was
given a value on the command line, as in the example above, it will keep this
value.  Otherwise it will get the value "motif".
</para>

<note>
  <title>Environment variables</title>
<para>
Environment variables are not used for variables in the recipe, like
<literal>make</literal> does.  When you happen to have a <literal>Gui</literal> environment
variable, this will not influence the variant in the recipe.  This is
especially useful if you are not aware of what environment variables are set
and/or which variables are used in the recipe.  If you intentionally want to
use an environment variable this can be specified with a Python expression (see the next chapter).
</para>
</note>

<para>
In line 15, 17 and 19 the append assignment "+=" is used.  This appends the argument
to an existing variable.  A space is inserted if the value was not empty.  For
the variant "motif" the result of line 15 is that
<literal>Source</literal> becomes "main.c version.c gui.c motif.c".
</para>

<para>
The "motif" and "gtk" variants each add a source file in line 15 and 17.  For
the console version no extra file is needed.  The object files for each
combination of variants end up in a different directory.  Ultimately you get
object files in each of the six directories ("SYS" stands for the platform
being used):

<informaltable frame="none">
  <tgroup cols="2">
    <colspec colwidth="250"/>
    <thead>
      <row><entry>directory</entry> <entry>contains files</entry></row>
    </thead>
    <tbody>
      <row><entry>build-SYS-release-console</entry> <entry>main, version, gui</entry></row>
      <row><entry>build-SYS-debug-console</entry>   <entry>main, version, gui</entry></row>
      <row><entry>build-SYS-release-motif</entry>   <entry>main, version, gui, motif</entry></row>
      <row><entry>build-SYS-debug-motif</entry>	    <entry>main, version, gui, motif</entry></row>
      <row><entry>build-SYS-release-gtk</entry>	    <entry>main, version, gui, gtk</entry></row>
      <row><entry>build-SYS-debug-gtk</entry>	    <entry>main, version, gui, gtk</entry></row>
    </tbody>
  </tgroup>
</informaltable>
</para>

<para>
See the <link linkend='user-variant'>user manual</link>
for more examples of using variants.
</para>

