Sophie

Sophie

distrib > Mandriva > 2010.0 > i586 > media > contrib-release > by-pkgid > a6d417e36f6bb1154f4c003e6717e298 > files > 139

a-a-p-1.090-2mdv2009.0.noarch.rpm

<html><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><title>Chapter 9. More Than One Recipe</title><meta name="generator" content="DocBook XSL Stylesheets V1.71.1"><link rel="start" href="index.html" title="A-A-P Recipe Executive"><link rel="up" href="tutorial.html" title="Part I. Tutorial"><link rel="prev" href="tutor-actions.html" title="Chapter 8. Filetypes and Actions"><link rel="next" href="tutor-pipe.html" title="Chapter 10. Commands in a Pipe"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><table width="100%" id="navtable"><tbody><tr><td align="left" class="left" width="33%"><b><a href="http://www.a-a-p.org">A-A-P home page</a></b></td><td align="center" class="center" width="34%"><b><a href="index.html">A-A-P Recipe Executive</a></b></td><td align="right" class="right" width="33%"></td></tr><tr><td align="left" class="left"><a accesskey="p" href="tutor-actions.html">Prev</a></td><td align="center" class="center">Tutorial</td><td align="right" class="right"><a accesskey="n" href="tutor-pipe.html">Next</a></td></tr></tbody></table><hr><div class="chapter" lang="en"><div class="titlepage"><div><div><h2 class="title"><a name="tutor-include"></a>Chapter 9. More Than One Recipe</h2></div></div></div><p>
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.
</p><h2><a name="id2630484"></a>Children</h2><p>
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:
</p><pre class="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
</pre><p>
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 <code class="literal">Core_obj</code> and <code class="literal">Util_obj</code>.  This parent
recipe then defines how the object files are linked together to build the
program "theprog".
</p><p>
In line 4 a special mechanism is used.  Assume that <code class="literal">Core_obj</code> 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
<code class="literal">Core_obj</code>.  This is called rc-style expansion.  You can
remember it by thinking of the "*" to multiply the items.
</p><p>
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:
</p><pre class="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
</pre><p>
Variables in a child recipe are local to that recipe.  The
<code class="literal">CPPFLAGS</code> 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.
</p><p>
The <code class="literal">Core_obj</code> 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:
</p><div class="literallayout"><p>         {scopename} . {variablename} </p></div><p>
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
<a href="ref-varscope.html" title="Chapter 34. Variables and Scopes">Chapter 34, <i>Variables and Scopes</i></a>"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.
</p><p>
The value of <code class="literal">Core_obj</code> is set with a Python expression.  The
<a href="ref-python.html#python-src2obj">src2obj()</a> function takes a list of
source file names and transforms them into object file names.  This takes care
of changing the files
in <code class="literal">Source</code> to prepend $BDIR and change the file suffix to $OBJSUF.
It also takes care of using the "var_BDIR" attribute if it is present.
</p><p>
In the last line is specified what happens when running <strong class="userinput"><code>aap</code></strong>
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.
</p><p>
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
<code class="literal">Core_obj</code> are passed to the parent recipe, which is in a different
directory.  That is why the parent recipe had to prepend "core/" when using
<code class="literal">Core_obj</code>.  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.
</p><h2><a name="id2631909"></a>Sharing Settings</h2><p>
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:
</p><pre class="programlisting">
    CPPFLAGS += -DFOOBAR
    :rule %$OBJSUF : %.foo
        :sys foocomp $source -o $target
</pre><p>
This recipe adds something to <code class="literal">CPPFLAGS</code> 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:
</p><pre class="programlisting">
    :include ../common.aap
</pre><p>
The <code class="computeroutput">:include</code> command works like the commands
in the
included recipe were typed instead of the
<code class="computeroutput">:include</code> command.
There is no change of directory, like with the
<code class="computeroutput">:child</code>
command and the included recipe uses the same scope.</p><p>
In the toplevel recipe you need include "common.aap" as well.  Suppose you
include it in the first line of the recipe, before the
<code class="computeroutput">:child</code> commands.  The children also include
"common.aap".  The <code class="literal">CPPFLAGS</code> 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.
</p><p>
To avoid this, add the <code class="computeroutput">{once}</code> option to the
<a href="ref-commands.html#cmd-include">:include</a> command.
This means that the recipe is only included once and not a second time.
The child recipes use:
</p><pre class="programlisting">
    :include {once} ../common.aap
</pre><p>
  And the parent uses:
</p><pre class="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
</pre><p>
You might argue that another way would be to put the
<code class="computeroutput">:include</code> 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.
</p><p>
Note that using <a href="ref-commands.html#cmd-include">:include</a> like this will
always use the <code class="computeroutput">_top</code> scope for the variables
set in the included recipe.  Be careful that the
<code class="computeroutput">_recipe</code>
scope isn't
used in one of the child recipes.
</p><h2><a name="id2632029"></a>Sharing Modules</h2><p>
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, <code class="computeroutput">D</code>), you need
to define actions, set variables, etc.
It is tedious to use <code class="computeroutput">:include</code>,
so <span class="application">Aap</span> allows you to store such settings in a <span class="emphasis"><em>module</em></span>.
</p><p>
A module is a recipe like any other, except it is stored in the
main <span class="application">Aap</span> directory (along with the system
<code class="filename">default.aap</code>).
You can read a module with the
<code class="computeroutput">:import</code> command.
This works very much like the
<code class="computeroutput">:include</code> command, except:
</p><div class="orderedlist"><ol type="1"><li><p>The recipe is read from the main <span class="application">Aap</span> directory.</p></li><li><p>Each module is imported only once.</p></li></ol></div><p>
</p><p>
<span class="application">Aap</span> 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 <a href="user-language.html" title="Chapter 31. Adding A Language Module">Chapter 31, <i>Adding A Language Module</i></a>.
</p><h2><a name="id2632124"></a>Executing a Recipe</h2><p>
Besides <code class="computeroutput">:child</code> and <code class="computeroutput">:include</code> there is a
third way to use another recipe: <code class="computeroutput">:execute</code>.  This command
executes a recipe.  This works as if <span class="application">Aap</span> was run as a separate program with
this recipe, except that it is possible to access variables in the recipe that
has the
<a href="ref-commands.html#cmd-execute">:execute</a> command.  Here is an example:
</p><pre class="programlisting">
    :program prog : main.c common.c

    test:
        :execute test.aap test
        :print $TestResult
</pre><p>
This recipe uses the <code class="literal">:program</code> 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
<code class="computeroutput">:execute</code> command is the recipe name.  Further arguments are
handled like the arguments of the <strong class="userinput"><code>aap</code></strong> command.  In this case the
target "test" is used.
</p><p>
The "test.aap" recipe sets the <code class="literal">TestResult</code> 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:
</p><pre class="programlisting">
    @if all_done:
        _parent.TestResult = All tests completed successfully.
    @else:
        _parent.TestResult = Some tests failed!
</pre><p>
It would also be possible to use the <code class="computeroutput">:child</code> 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 <code class="computeroutput">:execute</code> we don't need to
worry about this.  In general, the <code class="computeroutput">:child</code> command is useful
when splitting up a tree of dependencies in parts, while
<code class="computeroutput">:execute</code> is useful for two tasks that have no common
dependencies.
</p><h2><a name="id2632296"></a>Fetching a Recipe</h2><p>
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:
</p><pre class="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
</pre><p>
The <code class="literal">fetch</code> 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 <span class="application">Aap</span> reads this recipe and discovers that a child or included
recipe does not exist, it will use the <code class="literal">fetch</code> attribute to download
it.  The <code class="literal">fetch</code> attribute can also be used with the
<code class="computeroutput">:execute</code> command.
</p><p>
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 <strong class="userinput"><code>aap -R</code></strong> or <strong class="userinput"><code>aap fetch</code></strong>.
</p></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="tutor-actions.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="tutorial.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="tutor-pipe.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Chapter 8. Filetypes and Actions </td><td width="20%" align="center"><a accesskey="h" href="index.html">
		    Contents</a></td><td width="40%" align="right" valign="top"> Chapter 10. Commands in a Pipe</td></tr></table></div></body></html>