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

  Part of the A-A-P recipe executive: Tutorial - more recipes

  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>
When you are working on a project that is split up in several directories it
is convenient to use one recipe for each directory.  There are several ways to
split up the work and use a recipe from another recipe.
</para>


<bridgehead>Children</bridgehead>

<para>
A large program can be split in several parts.  This makes it easy for several
persons to work in parallel.  You then need to allow the files in each part to
be compiled separately and also want to build the complete program.  A
convenient way to do this is putting files in separate directories and
creating a recipe in each directory.  The recipe at the top level is called
the parent.  Here is an example that includes two recipes in subdirectories,
called the children:
</para>

<programlisting>
1    :child core/main.aap       # sets Core_obj
2    :child util/main.aap       # sets Util_obj
3
4    :program theprog : core/$*Core_obj util/$*Util_obj
</programlisting>

<para>
In the first two lines the child recipes are included.  These specify how the
source files in each directory are to be compiled and assign the list of
object files to <literal>Core_obj</literal> and <literal>Util_obj</literal>.  This parent
recipe then defines how the object files are linked together to build the
program "theprog".
</para>

<para>
In line 4 a special mechanism is used.  Assume that <literal>Core_obj</literal> has
the value "main.c version.c".  Then "core/$*Core_obj" will expand into
"core/main.c core/version.c".  Thus "core/" is prepended to each item in
<literal>Core_obj</literal>.  This is called rc-style expansion.  You can
remember it by thinking of the "*" to multiply the items.
</para>

<para>
An important thing to notice is that the parent recipe does not need to know
what files are present in the subdirectories.  Only the child recipes contain
the list of files.  Thus when a file is added, only one recipe needs to be
changed.  The "core/main.aap" recipe contains the list of files in the "core"
directory:
</para>

<programlisting>
1    Source =  main.c
2              version.c
3
4    CPPFLAGS += -I../util
5
6    _top.Core_obj = `src2obj(Source)`
7
8    all: $_top.Core_obj
</programlisting>

<para>
Variables in a child recipe are local to that recipe.  The
<literal>CPPFLAGS</literal> variable that is changed in line 4 will remain unchanged
in the parent recipe and other children.  That is desired here, since finding
header files in "../util" is only needed for source files used in this recipe.
</para>

<para>
The <literal>Core_obj</literal> variable we do want to be available in the parent
recipe.  That is done by prepending the "_top" scope name.  The generic way to
use a scope is:
</para>
<literallayout>         {scopename} . {variablename} </literallayout>
<para>
Several scope names are defined, such as "_recipe" for the current recipe and
"_top" for the toplevel recipe.
The full list of scope names can be found in the reference manual, chapter
<xref linkend="ref-varscope"/>"Recipe Syntax and Semantics".
When a variable is used without a scope name, it is looked up in the
local scope and surrounding scopes.  Thus the variables from the parent recipe
are also available in the child.  But when assigning to a variable without a
scope, it is always set in the local scope only.  To make the variable appear
in another scope you must give the scope name.
</para>

<para>
The value of <literal>Core_obj</literal> is set with a Python expression.  The
<link linkend="python-src2obj">src2obj()</link> function takes a list of
source file names and transforms them into object file names.  This takes care
of changing the files
in <literal>Source</literal> to prepend $BDIR and change the file suffix to $OBJSUF.
It also takes care of using the "var_BDIR" attribute if it is present.
</para>

<para>
In the last line is specified what happens when running <userinput>aap</userinput>
without arguments in the "core" directory: The object files are built.  There
is no specification for how this is done, thus the default rules will be used.
</para>

<para>
All the files in the child recipe are defined without mentioning the "core"
directory.  That is because all parent and child recipes are executed with the
current directory set to where the recipe is.  Note the files in
<literal>Core_obj</literal> are passed to the parent recipe, which is in a different
directory.  That is why the parent recipe had to prepend "core/" when using
<literal>Core_obj</literal>.  This is so that the child recipe doesn't need to know
what its directory name is, only the parent recipe contains this directory
name.
</para>


<bridgehead>Sharing Settings</bridgehead>

<para>
Another mechanism to use a recipe is by including it.  This is useful to put
common variables and rules in a recipe that is included by several other
recipes.  Example:
</para>

<programlisting>
    CPPFLAGS += -DFOOBAR
    :rule %$OBJSUF : %.foo
        :sys foocomp $source -o $target
</programlisting>

<para>
This recipe adds something to <literal>CPPFLAGS</literal> and defines a rule to turn
a ".foo" file into an object file.  Suppose you want to include this recipe in
all the recipes in your project.  Write the above recipe as "common.aap" in
the top directory of the project.  Then in "core/main.aap" and "util/main.aap"
put this command at the top:
</para>

<programlisting>
    :include ../common.aap
</programlisting>

<para>
The <computeroutput>:include</computeroutput> command works like the commands
in the
included recipe were typed instead of the
<computeroutput>:include</computeroutput> command.
There is no change of directory, like with the
<computeroutput>:child</computeroutput>
command and the included recipe uses the same scope.</para>

<para>
In the toplevel recipe you need include "common.aap" as well.  Suppose you
include it in the first line of the recipe, before the
<computeroutput>:child</computeroutput> commands.  The children also include
"common.aap".  The <literal>CPPFLAGS</literal> variable would first be appended to 
in the toplevel recipe, then passed to the child and appended to again.
That is not what is supposed to happen.
</para>
<para>
To avoid this, add the <computeroutput>{once}</computeroutput> option to the
<link linkend="cmd-include">:include</link> command.
This means that the recipe is only included once and not a second time.
The child recipes use:
</para>

<programlisting>
    :include {once} ../common.aap
</programlisting>

<para>
  And the parent uses:
</para>

<programlisting>
1    :include {once} common.aap
2    :child core/main.aap       # sets Core_obj
3    :child util/main.aap       # sets Util_obj
4
5    all: theprog$EXESUF
6
7    theprog$EXESUF : core/$*Core_obj util/$*Util_obj
8        :do build $source
</programlisting>

<para>
You might argue that another way would be to put the
<computeroutput>:include</computeroutput> command at the top of the parent recipe, so that
the children don't have to include "common.aap".  You could do this, but then
it is no longer possible to execute a child recipe by itself.
</para>

<para>
Note that using <link linkend="cmd-include">:include</link> like this will
always use the <computeroutput>_top</computeroutput> scope for the variables
set in the included recipe.  Be careful that the
<computeroutput>_recipe</computeroutput>
scope isn't
used in one of the child recipes.
</para>

<bridgehead>Sharing Modules</bridgehead>

<para>
Sometimes a group of settings is so generally useful
that you want to use it in many different projects.
A typical example of such a group of settings
is language support for a specific programming language.
In order to add support for a new language
(say, <computeroutput>D</computeroutput>), you need
to define actions, set variables, etc.
It is tedious to use <computeroutput>:include</computeroutput>,
so &Aap; allows you to store such settings in a <emphasis>module</emphasis>.
</para>

<para>
A module is a recipe like any other, except it is stored in the
main &Aap; directory (along with the system
<filename>default.aap</filename>).
You can read a module with the
<computeroutput>:import</computeroutput> command.
This works very much like the
<computeroutput>:include</computeroutput> command, except:
<orderedlist>
<listitem>
    <para>The recipe is read from the main &Aap; directory.</para>
</listitem>
<listitem>
    <para>Each module is imported only once.</para>
</listitem>
</orderedlist>
</para>

<para>
&Aap; includes modules for standard languages
and build systems. It does not read these recipes
by default because they add additional overhead,
even when you do not use the languages they specify.
Therefore, support for the D language, using libtool
to build libraries, and KDE support (among others)
is included in
modules that you can use when needed.
A full list of modules
can be found in <xref linkend="user-language"/>.
</para>



<bridgehead>Executing a Recipe</bridgehead>

<para>
Besides <computeroutput>:child</computeroutput> and <computeroutput>:include</computeroutput> there is a
third way to use another recipe: <computeroutput>:execute</computeroutput>.  This command
executes a recipe.  This works as if &Aap; was run as a separate program with
this recipe, except that it is possible to access variables in the recipe that
has the
<link linkend="cmd-execute">:execute</link> command.  Here is an example:
</para>

<programlisting>
    :program prog : main.c common.c

    test:
        :execute test.aap test
        :print $TestResult
</programlisting>

<para>
This recipe uses the <literal>:program</literal> command as we have seen
before.  This takes care of building the "prog" program.  For testing a
separate recipe is used, called "test.aap".  The first argument of the
<computeroutput>:execute</computeroutput> command is the recipe name.  Further arguments are
handled like the arguments of the <userinput>aap</userinput> command.  In this case the
target "test" is used.
</para>

<para>
The "test.aap" recipe sets the <literal>TestResult</literal> variable to a message
that summarizes the test results.  To get this variable back to the recipe
that executed "test.aap" the "_parent" scope is used:
</para>

<programlisting>
    @if all_done:
        _parent.TestResult = All tests completed successfully.
    @else:
        _parent.TestResult = Some tests failed!
</programlisting>

<para>
It would also be possible to use the <computeroutput>:child</computeroutput> command to
reach the "test" target in it.  The main difference is that other targets in
"test.aap" could interfere with targets in this recipe.  For example,
"test.aap" could define a different "prog" target, to compile the program with
specific test options.  By using <computeroutput>:execute</computeroutput> we don't need to
worry about this.  In general, the <computeroutput>:child</computeroutput> command is useful
when splitting up a tree of dependencies in parts, while
<computeroutput>:execute</computeroutput> is useful for two tasks that have no common
dependencies.
</para>


<bridgehead>Fetching a Recipe</bridgehead>

<para>
So far we assumed the included recipes were stored on the local system.  It is
also possible to obtain them from elsewhere.  The example with children above
can be extended like this:
</para>

<programlisting>
1    Origin = ftp://ftp.foo.org/recipes
2    :include {once} common.aap {fetch = $Origin/common.aap}
3    :child core/main.aap {fetch = $Origin/core.aap}
4    :child util/main.aap {fetch = $Origin/util.aap}
5
6    all: theprog$EXESUF
7
8    theprog$EXESUF : core/$*Core_obj util/$*Util_obj
9        :do build $source
</programlisting>

<para>
The <literal>fetch</literal> attribute is used to specify the URL where the recipe
can be obtained from.  This works just like fetching source files.  Notice in
the example that the file name in the URL can be different from the local file
name.  When &Aap; reads this recipe and discovers that a child or included
recipe does not exist, it will use the <literal>fetch</literal> attribute to download
it.  The <literal>fetch</literal> attribute can also be used with the
<computeroutput>:execute</computeroutput> command.
</para>

<para>
Once a recipe exists locally it will be used, even when the remote version has
been updated.  If you explicitly want to get the latest version of the recipes
used, run <userinput>aap -R</userinput> or <userinput>aap fetch</userinput>.
</para>
