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

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

  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

-->

<anchor id="sec-hello"/>
<bridgehead>A "Hello world" (of sorts)</bridgehead>

<para>
Most programming languages start with a short example that prints a "hello
world" message.  With &Aap;, this is also possible.
In a file called <filename>main.aap</filename>,
enter the following:
</para>
<programlisting>
    :print Hello, World!
</programlisting>
<para>
Now run &Aap; by entering <userinput>aap</userinput> at the
command line. &Aap; will respond something like this:
<literallayout>    % <userinput>aap</userinput>
    <computeroutput>Hello, World!</computeroutput>
    <computeroutput>Aap: No target on the command line and no $TARGET, build rules or "all" target in a recipe</computeroutput>
</literallayout>
As you can see, &Aap; outputs the desired text, but also prints an error message.
This is because &Aap; is not a programming language, but a language
for describing how to
<emphasis>compile and build</emphasis> programs (written in other languages).
In other words, if you have written a "hello world" program in some language,
then you can use &Aap; to compile that program.
</para>


<bridgehead>Using &Aap; to compile "hello.c"</bridgehead>
<para>
Suppose you have written a "hello world" program in C, and the
sources are stored in a file called <filename>hello.c</filename>.
&Aap; already knows about the C language (and several others),
so the instructions to &Aap; about how to compile this program are very
short.
Instructions for &Aap; are stored in a file with the extension
<filename>.aap</filename>.  Such a file is called a recipe.
</para>


<para>
<indexterm><primary>:program</primary></indexterm>
This is the recipe for compiling such a program with &Aap;:
</para>
<programlisting>
    :program hello : hello.c
</programlisting>
<para>
Write this text in a file <filename>main.aap</filename>, in the same directory as
<filename>hello.c</filename>.
Now invoke &Aap; to compile <filename>hello.c</filename> into the program
<filename class="directory">hello</filename>:
<indexterm><primary>Running &Aap;</primary><secondary>Compilation</secondary></indexterm>
<literallayout>    % <userinput>ls</userinput>
    hello.c             main.aap
    % <userinput>aap</userinput>
1   Aap: Creating directory "/home/mool/tmp/build-FreeBSD4_5_RELEASE"
2   Aap: cc -I/usr/local/include -g -O2 -E -MM hello.c > build-FreeBSD4_5_RELEASE/hello.c.aap
3   Aap: cc -I/usr/local/include -g -O2 -c -o build-FreeBSD4_5_RELEASE/hello.o hello.c
4   Aap: cc -L/usr/local/lib -g -O2 -o hello build-FreeBSD4_5_RELEASE/hello.o
</literallayout>
You see the commands &Aap; uses to compile the program:
<orderedlist>
  <listitem>
    <para>
    A directory is created to write the intermediate results in.  This
    directory is different for each platform, thus you can compile the same
    program for different systems without cleaning up.
    </para>
  </listitem>
  <listitem>
    <para>
    Dependencies are figured out for the source file.
    &Aap; will automatically detect
    dependencies on included files and knows that if one of the included files
    changed compilation needs to be done, even when the file itself didn't
    change.
    In this example, &Aap; uses the C compiler with the <literal>-MM</literal>
    option to determine the included files.
    </para>
  </listitem>
  <listitem>
    <para>
    The "hello.c" program file is compiled into the "hello.o" object file
    (on MS-Windows that would be "hello.obj").
    </para>
  </listitem>
  <listitem>
    <para>
    The "hello.o" object file is linked to produce the "hello" program
    (on MS-Windows this would be "hello.exe", the ".exe" is added
    automatically).
    </para>
  </listitem>
</orderedlist>
</para>


<bridgehead>Other things to do with "hello world"</bridgehead>
<para>
The same simple recipe not only specifies how to build the "hello" program, it
can also be used to install the program:
<indexterm><primary>Running &Aap;</primary><secondary>Installation</secondary></indexterm>
<literallayout>    % <userinput>aap install PREFIX=try</userinput>
    Aap: Creating directory "try/bin/"
    Aap: Copied "test/hello" to "try/bin/hello"
    Aap: /usr/bin/strip 'try/bin/hello'
</literallayout>
The <literal>PREFIX</literal> variable specifies where to install the program.
The default is <filename>/usr/local</filename>.
For the example we use the <filename>try</filename> directory,
which doesn't exist.  &Aap; creates  it for you.
</para>

<para>
Other ways that this recipe can be used:
<literallayout>    <userinput>aap uninstall</userinput>    undo installing the program
    <userinput>aap clean</userinput>          cleanup the generated files
    <userinput>aap cleanALL</userinput>     cleanup all files (careful!)
</literallayout>
</para>

<para>
  See the reference manual for details about
  <link linkend="cmd-program">:program</link>.
</para>


<bridgehead>Several Source Files</bridgehead>

<para>
When you have several files with source code you can specify them as a list:
</para>

<programlisting>
    :program myprogram : main.c
                         version.c
                         help.c
</programlisting>

<para>
There are three source files: <filename>main.c</filename>,
<filename>version.c</filename> and <filename>help.c</filename>.
Notice that it is not necessary to use a line continuation character, as you
would have to do in a Makefile.  The list ends at a line where the indent is
equal to or less than what the assignment started with.
The amount of indent for the continuation lines is irrelevant, so long as it's
more than the indent of the first line.
</para>

<para>
  The Makefile-style line continuation with a backslash just before the line
  break can also be used, by the way.
</para>

<para>
<indexterm><primary>Indentation</primary></indexterm>
Indents are very important, just like in a Python script.  Make sure your
tabstop is always set to the standard value of eight, otherwise you might run
into trouble when mixing tabs and spaces!
</para>

<para>
When you give a list of files to <link linkend="cmd-program">:program</link>,
&Aap; will determine dependencies and compile each of the source
files in turn, and then link them all together into an executable.
</para>


<bridgehead>Variables and Assignments</bridgehead>

<para>
Sometimes it is convenient to have an abbreviation for a long list
of files.
&Aap; supports this through variables (just like
the <application>make</application> command and the shell).
</para>

<para>
An assignment has the form:
<literallayout>    variablename = expression
</literallayout>
The variable name is the usual combination of letters, digits and underscore.
It must start with a letter.  Upper and lower case letters can be used and case
matters.  To see this in action, write this recipe in a file with the name
<filename>try.aap</filename>:
</para>
<programlisting>
    foo = one
    Foo = two
    FOO = three
    :print $foo $Foo $FOO
</programlisting>
<para>
&Aap; normally reads the recipe from <filename>main.aap</filename>,
but you can tell it to read a different file if you want to.
Use the <userinput>-f</userinput> flag for this.
Now execute the recipe:
<indexterm><primary>Reading a different <filename>.aap</filename> file</primary></indexterm>
<literallayout>    % <userinput>aap -f try.aap</userinput>
    one two three
    Aap: No target on the command line and no build rules or "all" target in a recipe
</literallayout>
<indexterm><primary>Printing variables</primary></indexterm>
<indexterm><primary>Variables</primary><secondary>Printing</secondary></indexterm>
The
<link linkend="cmd-print">:print</link>
command prints its argument.  You can see that a variable name
preceded with a dollar is replaced by the value of the variable.
The three variables that only differ by case each have a different value.
&Aap; also complains that there is nothing to build, just like
in the <link linkend="sec-hello">hello world example</link>.
</para>

<para>
If you want text directly after the variable's value, for example,
to append an extension to the value of a variable,
the text may be impossible to distinguish from a variable name.
In these cases you must put
parenthesis around the variable name, so that &Aap; knows where it ends:
</para>

<programlisting>
    all:
      MakeName = Make
      :print $(MakeName)file    # 'f' can be in a variable name
      :print $(MakeName).txt    # '.' can be in a variable name
      :print $MakeName-more     # '-' is not in a variable name
</programlisting>

<literallayout>    % <userinput>aap -f try.aap</userinput>
    Makefile
    Make.txt
    Make-more
    %
</literallayout>


<para>
All &Aap; commands, except the assignment, start with a colon.  That makes
them easy to recognize.
</para>

<para>
  Some characters in the expression have a special meaning.  The
  <link linkend="cmd-print">:print</link>
command also handles a few arguments in a special way.  To avoid the special
meaning use the $(x) form, where "x" is the special character.  For example,
to print a literal dollar use $($).  See
<link linkend="special-characters">the user manual</link> for 
a complete list.
</para>



<bridgehead>Comments</bridgehead>

<para>
Someone who sees this recipe would like to know what it's for.  This requires
adding comments.  These start with a "#" character and extend until the end of
the line (like in a Makefile and Python script).
</para>

<para>
It is also possible to associate a comment with a specific item:
</para>

<programlisting>
    # A-A-P recipe for compiling "myprogram"
    :program myprogram { comment = MyProgram is really great } :
            main.c            # startup stuff
            version.c         # just the date stamp
            help.c            # display a help message
</programlisting>

<para>
Now run &Aap; with a "comment" argument:
</para>

<literallayout>    % <userinput>aap comment</userinput>
    <computeroutput>target "myprogram": MyProgram is really great</computeroutput>
    <computeroutput>target "clean": delete generated files that are not distributed</computeroutput>
    <computeroutput>target "cleanmore": delete all generated files</computeroutput>
    <computeroutput>target "cleanALL": delete all generated files, AAPDIR and build-* directories</computeroutput>
    <computeroutput>target "install": install files</computeroutput>
    <computeroutput>target "uninstall": delete installed files</computeroutput>
    %
</literallayout>

<para>
<indexterm><primary>Attributes</primary></indexterm>
The text inside curly braces is called an attribute.
In this case the attribute name is "comment" and the attribute value is 
"MyProgram is really great".
An attribute can be used to attach extra information to a file name.  We will
encounter more attributes later on.
</para>


<bridgehead>Dependencies</bridgehead>

<para>
Let's go back to the "Hello world" example and find out what happens when
you change a source file.  Use this <filename>hello.c</filename> file:
</para>

<programlisting>
    #include &lt;stdio.h&gt;
    #include "hello.h"
    main()
    {
        printf("Hello %s\n", world);
    }
</programlisting>

<para>
The included "hello.h" file defines "world":
</para>

<programlisting>
    #define world "World!"
</programlisting>

<para>
If you run &Aap;, the "hello" program will be built as before.  If you run
&Aap; again you will notice that nothing happens.  &Aap; remembers that
"hello.c" was already compiled.  Now try this:
</para>

<literallayout>    % <userinput>touch hello.c</userinput>
    % <userinput>aap</userinput>
    %
</literallayout>

<para>
If you have been using the "make" program you would expect something to happen.
But &Aap; checks the <emphasis>contents</emphasis> 
of the file, not the timestamp.  A signature of
"hello.c" is computed and if it is still the same as before &Aap; knows that
it does not need to be compiled, even though "hello.c" is newer than the
"hello" program.
</para>

<para>
  &Aap; uses the mechanism of dependencies.  When you use the
  <link linkend="cmd-program">:program</link>
  command
&Aap; knows that the target depends on the sources.  When one of the
sources changes, the commands to build the target from the sources must be
executed.  This can also be specified explicitly:
</para>

<programlisting>
      hello$EXESUF : $BDIR/hello$OBJSUF
          :do build $source

      $BDIR/hello$OBJSUF : hello.c
          :do compile $source
</programlisting>

<para>
The generic form of a dependency is:
</para>

<literallayout>      target : list-of-sources
           build-commands
</literallayout>

<para>
The colon after the target is important, it separates the target from the
sources.  It is not required to put a space before it, but there must be a
space after it.  We mostly put white space before the colon, so that it is
easy to spot.  There could be several targets, but that is unusual.
</para>

<para>
There are two dependencies in the example.
In the first one the target is "hello$EXESUF", the source file is
"$BDIR/hello$OBJSUF" and the build command is ":do build $source".  This
specifies how to build the "hello$EXESUF" program from the
"$BDIR/hello$OBJSUF" object file.
The second dependency specifies how to compile "hello.c" into
"$BDIR/hello$OBJSUF"
with the command ":do compile $source".
The "BDIR" variable holds the name of the platform-dependent directory for
intermediate results, as mentioned in the first example of this chapter.

In case you need it, the $EXESUF variable &Aap; is empty
on Unix and ".exe" on MS-Windows.
</para>

<para>
The relation between the two dependencies in the example is that the
source of the first one is the target in the second one.  The logic is that
&Aap; follows the dependencies and executes the associated build commands. In
this case "hello$EXESUF" depends on "$BDIR/hello$OBJSUF", which then depends on
"hello.c".  The last dependency is handled first, thus first hello.c is
compiled by the build command of the second dependency, and then linked into
"hello$EXESUF" by the build command of the first dependency.
</para>

<para>
Now change the "hello.h" file by replacing "World" with 'Universe":
</para>

<programlisting>
    #define world "Universe!"
</programlisting>

<para>
If you now run &Aap; with "aap hello" or "aap hello.exe" the "hello" program
will be built.  But you never mentioned the "hello.h" file in the recipe.  How
did &Aap; find out the change in this file matters?
When &Aap; is run to update the "hello" program, this is what will happen:
<orderedlist>
  <listitem>
    <para>
    The first dependency with "hello$EXESUF" as the target is found,
    it depends on "$BDIR/hello$OBJSUF".
    </para>
  </listitem>
  <listitem>
    <para>
    The second dependency with "$BDIR/hello$OBJSUF" as the target is found.  The
    source file "hello.c" is recognized as a C program file.  It is inspected
    for included files.  This finds the "hello.h" file.  "stdio.h" is ignored,
    since it is a system file.  "hello.h" is added to the list of files that
    the target depends on.
    </para>
  </listitem>
  <listitem>
    <para>
    Each file that the target depends on is updated.  In this case "hello.c"
    and "hello.h".  No dependency has been specified for them and the files
    exist, thus nothing happens.
    </para>
  </listitem>
  <listitem>
    <para>
    &Aap; computes signatures for "hello.c" and "hello.h".  It also computes a
    signature for the build commands.  If one of them changed since the last
    time the target was built, or the target was never built before, the
    target is considered "outdated" and the build commands are executed.
    </para>
  </listitem>
  <listitem>
    <para>
    The second dependency is now finished, "$BDIR/hello$OBJSUF" is up-to-date.
    &Aap; goes back to the first dependency.
    </para>
  </listitem>
  <listitem>
    <para>
    &Aap; computes a signature for "$BDIR/hello$OBJSUF".  Note that this happens
    after the second dependency was handled, it may have changed the file.
    It also computes a signature for the build command.
    If one of them changed since the last time the target was built, or the
    target was never built before, the target is considered "outdated" and the
    build commands are executed.
    </para>
  </listitem>
</orderedlist>
</para>

<para>
Now try this: Append a comment to one of the lines in the "hello.c" file.
This means the file is changed, thus when invoking &Aap; it will compile
"hello.c".  But the program is not built, because the produced intermediate
file "$BDIR/hello$OBJSUF" is still equal to what it was the last time.  When
compiling a large program with many dependencies this mechanism avoids that
adding a comment may cause a snowball effect. (Note: some compilers include
line numbers or a timestamp in the object file, in that case building the
program will happen anyway).
</para>


<bridgehead>Compiling Multiple Programs</bridgehead>

<para>
Suppose you have a number of sources files that are used to build two
programs.  You need to specify which files are used for which program.  Here
is an example:
</para>

<programlisting>
1.    Common = help.c util.c
2.
3.    all : foo bar
4.
5.    :program foo : $Common foo.c
6.
7.    :program bar : $Common bar.c
</programlisting>

<para>
This recipe defines three targets: "all", "foo" and "bar".
"foo" and "bar are programs that &Aap; can build from source files.
But the "all" target is not a file.  This is called a virtual target: A name
used for a target that does not exist as a file.  Let's list the terminology
of the items in a dependency:
</para>

<table frame="none">
  <title>items in a dependency</title>
  <tgroup cols="2">
    <colspec colwidth="150"/>
    <tbody>
      <row>
        <entry>source</entry>
        <entry>item on the right hand side of a dependency</entry>
      </row>
      <row>
        <entry>source file</entry>
        <entry>source that is a file</entry>
      </row>
      <row>
        <entry>virtual source</entry>
        <entry>source that is NOT a file</entry>
      </row>
      <row>
        <entry>target</entry>
        <entry>on the left hand side of a dependency</entry>
      </row>
      <row>
        <entry>target file</entry>
        <entry>target that is a file</entry>
      </row>
      <row>
        <entry>virtual target</entry>
        <entry>target that is NOT a file</entry>
      </row>
      <row>
        <entry>node</entry>
        <entry>source or target</entry>
      </row>
      <row>
        <entry>file node</entry>
        <entry>source or target that is a file</entry>
      </row>
      <row>
        <entry>virtual node</entry>
        <entry>source or target that is NOT a file</entry>
      </row>
    </tbody>
  </tgroup>
</table>
<para>
&Aap; knows the target with the name "all" is always used as a virtual
target.  There are a few other names which &Aap; knows are virtual, see
<xref linkend="virtual-targets"/>.  For other
targets you need to specify it with the "{virtual}" attribute.
</para>

<para>
The first dependency has no build commands.  This only specifies that "all"
depends on "foo" and "bar".  Thus when &Aap; updates the "all" target, this
dependency specifies that "foo" and "bar" need to be updated.  Since the "all"
target is the default target, this dependency causes both "foo" and "bar" to
be updated when &Aap; is started without an argument.  You can use "aap foo"
to build "foo" only.  The dependencies for "all" and "bar" will not be used
then.
</para>

<para>
The two files <filename>help.c</filename> and <filename>util.c</filename> are used by both the "foo" and the "bar"
program.  To avoid having to type the file names twice, the "Common" variable
is used.  
</para>


<bridgehead>Kinds of things you can build</bridgehead>

<para>
Not everything you want to build is a program.
Your recipe might need too build a library
or a libtool archive.
In these cases,
<link linkend="cmd-lib">:lib</link>,
<link linkend="cmd-dll">:dll</link> or
<link linkend="cmd-ltlib">:ltlib</link>
provide the same level of automation
as <link linkend="cmd-program">:program</link>
does for programs.  The <link linkend="cmd-produce">:produce</link> command is
more generic, you can use this to build various kinds of things.
</para>

<para>
If all else fails, you can use &Aap; like the <application>make</application>
program
and explicitly list the commands you need to build your project.
</para>



<!--
Note that the assignment in the first line uses "Common" without a
dollar, while in line 5 and 8 "$Common" is used.  This makes it possible to
mix the use of a variable with plain text and file names.  This recipe would
do the same thing:
</para>

<programlisting>
1.    all : foo bar
2.
3.    :program foo : help.c util.c foo.c
4.
5.    :program bar : help.c util.c bar.c
</programlisting>

<para>
You can see that "$Common" has been replaced by the value of the "Common"
variable.
</para>

-->


