A-A-P home page | A-A-P Recipe Executive | |
Prev | Tutorial | Next |
A-A-P can recognize what the type of a file is, either by looking at the file name or by inspecting the contents of the file. The filetype can then be used to decide how to perform an action with the file.
Suppose you are using the "foo" programming language and want to use A-A-P to compile your programs. Once this is has been setup you can compile "hello.foo" into the "hello" program with a simple recipe:
:program hello : hello.foo
You need to explain Aap how to deal with "foo" files. This is done with a recipe:
:filetype suffix foo foo :action compile foo :sys foocomp $?FOOFLAGS $source -o $target :route foo object compile
For Unix, write this recipe as "/usr/local/share/aap/startup/foo.aap" or "~/.aap/startup/foo.aap". The recipes in these "startup" directories are always read when Aap starts up.
Now try it out, using the simple recipe at the top as "main.aap":
% aap
Aap: foocomp hello.foo -o build-FreeBSD4_5_RELEASE/hello.o
Aap: cc -L/usr/local/lib -g -O2 -o hello build-FreeBSD4_5_RELEASE/hello.o
%
The "foo.aap" recipe does three things:
The :filetype
command is used to tell A-A-P to recognize
your "hello.foo" file as being a "foo" file.
The :action
command is used to specify how the "foocomp"
compiler is used to compile a "foo" program into an object file.
The user can set the FOOFLAGS variable to options he wants to use.
The convention is that the option variable is in uppercase, starts with the
filetype and ends in "FLAGS".
The :route
command is used to specify which actions are to
be used to turn a "foo" file into an "object" file.
The :filetype
command is followed by the line "suffix foo
foo". The first word "suffix" means that recognizing is done by the suffix of
the file name (the suffix is what comes after the last dot in the name).
The second word is the suffix and the third word is the type. Quite often the
type is equal to the suffix, but not always. Here are a few more examples of
lines used with :filetype
:
:filetype suffix fooh foo suffix bash sh
It is also possible to recognize a file by matching the name with a pattern, checking the contents of the file or using a Python script. See the user manual.
The lower half of "foo.aap" specifies the compile action for the "foo" filetype:
:action compile foo :sys foocomp $source -o $target
The :action
command has two arguments. The first one
specifies the kind of action that is being defined. In this case "compile".
This action is used to make an object file from a source file. The second
argument specifies the type of source file this action is used for, in this
case "foo".
Below the :action
line the build commands are specified. In
this case just one, there could be more.
The :sys
command invokes an exteral program, "foocomp", and
passes the arguments. In an action $source
is expanded to
the source of the action and $target
to the target. These
are obtained from the :do
command that invokes the action.
Example:
:do compile {target = `src2obj("main.foo")`} main.foo
This :do
command invokes the compile action, specified with
its first argument. The target is specified as an attribute to the action,
the source is the following argument "main.foo".
When executing the :do
command the filetype of "main.foo"
is detected to be "foo", resulting in the compile action for "foo" to be
invoked. In the build command of the action
$source
and $target
are replaced,
resulting in:
:sys foocomp main.foo -o `src2obj("main.foo")`
Note that in many cases $target
is passed implicitly from a
dependency and does not appear in the :do
command argument.
When building a program you often want to include the date and time when it was built. A simple way of doing this is creating a source file "version.c" that contains the timestamp. This file needs to be compiled every time your program is built. Here is an example how this can be done:
1 :program prog : main.c work.c 2 3 :attr prog {filetype = myprog} 4 5 :action build myprog object 6 version_obj = `src2obj("version.c")` 7 :do compile {target = $version_obj} version.c 8 :do build {filetype = program} $source $version_obj
The target "prog" is explicitly given a different filetype in line 3. The default filetype for a program is "program", here it is set to "myprog". This allows us to specify a different build action for "prog".
Write the recipe as "main.aap" (without the line numbers) and execute it with
aap
. The first time all the files will be compiled and linked
together. Executing aap
again will do nothing. Thus the
timestamp used in "version.c" will not be updated if the files were not
changed. If you now make a change in "main.c" and run aap
you
will see that both "main.c" and "version.c" are compiled.
The :action
command in line 5 has three arguments. The
first one "build" is the kind of action, like before. The second argument
"myprog" specifies the target filetype, the third one "object" the source
filetype. Thus the template is:
:action
kind-of-action target-filetype source-filetype
This order may seem a bit strange. Remember that putting the target left of the source also happens in a dependency and an assignment.
There are three commands for the build action, lines 6 to 8. The first one
assigns the name of the object file for "version.c" to
version_obj
. "version.c" was not included in the
:program
command at
the top, it is compiled here explicitly in line 7. This is what makes sure
"version.c" is compiled each time "prog" is built. The other source files
will be compiled with the default rules for :command
.
Finally the :do build
command in line 8 invokes the build
action to link all the object files together. Note that the filetype for the
build action is explicitly defined to "program". This is required for this
:do
command to use the default action for a program target.
Otherwise the action would invoke itself, since the filetype for $target is
"myprog".
For more information about customizing filetype detection and actions see Chapter 28, Customizing Filetype Detection and Actions.