the

     A-A-P logo     

project


 

Recipe Examples

These are examples for what can be done with A-A-P recipes. This is not intended to teach you writing recipes, only a few things are explained. See the Aap manual for a verbose explanation. The tutorial is a good place to start learning Aap, it contains plenty of examples that are explained.

Short examples:
1. Compiling a program
2. Compiling two programs
3. Two variants of a program
4. Publishing a web site
5. A Ported application
6. Building on multiple platforms
7. Generating files
8. Version controlled sources
  Larger examples:
Building and instaling Exuberant Ctags
Maintaining a web site


1. Compiling a program

This recipe compiles the "myprog" program from C source files:
      :program myprog : main.c
			version.c
			work.c
			util.c
The ":program" command specifies that a program is to be build. The first argument "myprog" is the name of the program. The file names after the colon are the source files. This is all that Aap needs to know to build a simple program.

The C compiler will be invoked with the default arguments. The choice of compiler and the arguments can be changed in the system or user configuration file. But mostly you do not need to change anything, the default setup is sufficient for simple programs.

Note that the list of files uses multiple lines. No special characters are needed for line continuation or termination of the list. The only requirement is that the lines have more indent than ":program".

There is no need to mention included header files, Aap finds them by inspecting the source files. The dependencies will be detected automatically. Thus if you change a header file, the source files that include this header file will be compiled.

On MS-Windows ".exe" will automatically be added to "myprog".

To install your program use this command:

    aap install PREFIX=/usr/
When there is no "install" target in the recipe, Aap will automatically generate one for you, using the file that the ":program" command generates. The PREFIX variable specifies the top directory to install to. The default is "/usr/local". For a program the "bin" subdirectory is used. The example will install "/usr/bin/myprog".

If you want to install on a remote machine set the DESTDIR variable to the URL of the root of the machine. Example:

    aap install DESTDIR=scp://piet@puk.org/
This tells Vim to install "myprog" to "scp://piet@puk.org/$PREFIX/bin/myprog". Obviously you need to have write permission in this directory!

The "uninstall", "clean" and "cleanALL" targets are also added automatically if you didn't specify one:

    aap uninstall      undo the install
    aap clean          clean up the generated files
    aap cleanALL       clean up all the generated files, signatures and log files
The "clean" target deletes the compiled program and intermediate files (the object files). "cleanALL" is rather drastic: it deletes all "AAPDIR" and "build-*" directories, also when they have not been generated by the recipe. Be careful with this!

top

2. Compiling two programs

This recipe compiles the "foo" and "bar" programs. Most sources files are in common while "foo.c" and "bar.c" are specific for each program.
      all: foo bar

      COMMON = main.c
               version.c
               work.c
               util.c

      :program foo : $COMMON foo.c
      :program bar : $COMMON bar.c
The COMMON variable is used to avoid typing the list of files twice.

On MS-Windows the "foo.exe" and "bar.exe" programs will be build. Still, you can use the names without ".exe" in the first dependency. Aap remembers the unchanged name as an alias, so that the recipe is portable. In case you need it, the $EXESUF variable contains ".exe" on MS-Windows, on Unix it is empty.

top

3. Two variants of a program

      :variant BUILD
          release
             OPTIMIZE = 4
             target = myprog
          debug
	     OPTIMIZE = 0
             DEBUG = yes
             target = myprogd
    
      :program $target : main.c ui.c version.c
The BUILD variable is used to select between a "release" and a "debug" variant. The first one is the default. To build a debug variant use the command "aap BUILD=debug".

The "release" variant sets $OPTIMIZE to level 4. This means more than usual optimizing is done (the default is 2). This mostly results in the compiler being invoked with "-O4". For "debug" $DEBUG is set to "yes". This mostly results in the compiler being invoked with "-g". It also sets $OPTIMIZE to zero, which means no optimizing is done.

The object files for "release" and "debug" are stored separatly. If you do:

   aap BUILD=release
   aap BUILD=debug
   aap BUILD=release
You will see that the last command will not build anything. The results from the first command are still available.

To make it more interesting let's add another choice:
      :variant BUILD
          release
             OPTIMIZE = 4
             target = myprog
          debug
             DEBUG = yes
             target = myprogd
    
      FILES = $BDIR/main$OBJSUF $BDIR/version$OBJSUF
   
      GUI ?= gtk
      :variant GUI
         console
         motif
             FILES += motif.c
         gtk
             FILES += gtk.c

      :program $target : $FILES ui.c
The GUI variant selects between "console", "motif" and "gtk". The default is explictly set to "gtk". To use Motif use "aap GUI=motif".

Combining the two variant choices you can build six versions of the program. For each version a different build directory is used, there is no need to delete all intermediate files when selecting another variant.

The value of $BDIR is the build directory. Aap sets it such that for each variant a different build directory is used. In the example the value of $BDIR is used in between the two variants. This means it does depend on the first variant, but not the second one. By specifying that the "main" and "version" object files are in this directory, they will be common for all GUI variants. This reduces the number of situations these two files need to be compiled.

The value of $OBJSUF is ".obj" on MS-Windows and ".o" on Unix. This makes the recipe portable.

Notice that the ":program" command will get a mix of C files and object files. Aap will figure out how these are to be build to result in the target program.

top

4. Publishing a web site

      FILES =  *.html
               images/*.png

      :attr {publish = scp://user@ftp.foo.org/public_html/%file%} $FILES

      all: publish
The FILES variable is set to contain a list of all files that must be uploaded to the web site. Wildcards are used to find all HTML and PNG files. This uses the standard method for expanding wildcards in file names.

The "publish" attribute is added to the file names in FILES. This specifies using the "scp" program with a semi-URL.

The "all" target is specified so that invoking "aap" without arguments updates the "publish" target. This is a predefined target that takes care of uploading all files with a "publish" attribute that changed since the last time they were uploaded.

top

5. A Ported application

A recipe that uses the "PORTNAME" variable is recognized as a special kind of recipe used for porting an application. The port recipe specifies a number of things by setting specific variables, such as the files to download and where to download them from. This is sufficient for Aap to know what needs to be done to build the application and install it.
      # A-A-P port recipe for Vim
      AAPVERSION =      1.0

      PORTNAME =        vim
      PORTVERSION =     6.1.004
      MAINTAINER =      Bram@vim.org

      CATEGORIES =      editors
      PORTCOMMENT =     Vim - Vi IMproved, the text editor
      PORTDESCR << EOF
      This is the description for the Vim package.
      A very nice editor indeed.
      You can find all info on http://www.vim.org.
              EOF

      # Where to obtain an update of this recipe from.
      AAPROOT = http://www.a-a-p.org/ports/vim
      :recipe {fetch = $AAPROOT/main.aap}

      WRKSRC =          vim61                          # Vim doesn't use vim-6.1
      DEPENDS =         gtk>=1.2<2.0 | motif>=1.2      # GTK 2.0 doesn't work yet
      BUILDCMD =        make
      TESTCMD =         make
      INSTALLCMD =      make install DESTDIR=$PKGDIR
      PREFIX =          /usr/local

      MASTER_SITES =    ftp://ftp.vim.org/pub/vim
                        ftp://ftp.us.vim.org/pub/vim
      PATCH_SITES =     $*MASTER_SITES/patches
      DISTFILES =       unix/vim-6.1.tar.bz2
                        extra/vim-6.1-lang.tar.gz
      PATCHFILES =      6.1.001 6.1.003 6.1.004

      #>>> automatically inserted by "aap makesum" <<<
      do-checksum:
              :checksum $DISTDIR/vim-6.1.tar.bz2 {md5 = 7fd0f915adc7c0dab89772884268b030}
              :checksum $DISTDIR/vim-6.1-lang.tar.gz {md5 = ed6742805866d11d6a28267330980ab1}
              :checksum $PATCHDISTDIR/6.1.001 {md5 = 97bdbe371953b9d25f006f8b58b53532}
              :checksum $PATCHDISTDIR/6.1.003 {md5 = 0e000edba66562473a5f1e9b5b269bb8}
              :checksum $PATCHDISTDIR/6.1.004 {md5 = 90e6ac3d029d3b97303049d5b8597fb0}
      #>>> end <<<
The PORTDESCR variable is set to multiple lines with a "<<" assignment.
The MD5 checksums are automatically added by the port maintainer with the command "aap makesum".

top

6. Building on multiple platforms

Most of the items in a recipe are portable, nothing special needs to be done to build a program on many different platforms. To make portability easier the $INCLUDE and $DEFINE variables are used. Example:
      :program myprog : main.c version.c
      INCLUDE = -Iheader
      DEFINE = -DNODEBUG 
The compiler action will understand the meaning of $INCLUDE and $DEFINE and translate them into what the compiler accepts. For some compilers the "-I" may be changed to "/I:" and "-D" to "/D".

In those situations where the builtin mechanisms are not sufficient, Python conditionals can be used to select alternatives.
      :program myprog : main.c version.c
      @if OSTYPE == "mswin":
           CFLAGS += /OPT:yes
   
Sometimes it is easier to make a separate recipe for each platform and make one toplevel recipe that selects between them. Specifying where they can be downloaded makes it easy for a user, he only needs to download the toplevel recipe:
      FTPBASE = ftp://ftp.vim.org/pub/vim  ftp://ftp.us.vim.org/pub/vim
      :recipe {fetch = $*FTPBASE/aap/main.aap}
      
      @if OSTYPE == "posix":
          :child unix.aap {fetch = $*FTPBASE/unix/vim.aap.gz}
      @elif OSTYPE == "mswin":
          :child pc.aap {fetch = $*FTPBASE/pc/vim.zip//vim.aap}
      @else:
          :error OS not supported: $OSTYPE
Note: automatic decompressing and unpacking a file from an archive has not been implemented yet.

top

7. Generating files

This example reads a template file and replaces "@date@" with the current date and writes the result as a new file.
       version.h : version.h.in
           :cat $source | :eval re.sub('@date@', DATESTR, stdin) >! $target
	   :print Changed date in $target to "$DATESTR".
The second line contains two commands ":cat" and ":eval" in a pipe. This works like in a shell: the output of the first command is used as the input for the second command.
The ":eval" command evaluates a Python function. When used in a pipe the "stdin" variable holds the input.

The variable "DATESTR" is a standard variable, it contains the date in a standard format, for example "2002 Oct 14".
A-A-P will automatically recognize when $DATESTR has changed since the last time version.h was generated. A signature is made of the build commands and remembered.

top

8. Version controlled sources

This example shows source files that are under the control of CVS.
	VERSION = 1.013
	CVSROOT = :ext:$CVSUSER_FOO@cvs.foo.sf.net:/cvsroot/foo

        FILES =   COPYING
                  README.txt
                  main.aap
                  *.py

        :attr {commit = cvs://$CVSROOT} $FILES
        :attr {logentry = updated for version $VERSION} $FILES
Updating to the latest version is done with "aap fetch" or "aap checkout". Committing local changes is done with "aap revise". A-A-P will automatically add new files and remove deleted files. Thus the list of files must contain exactly those files that are in the CVS repository. In the example "*.py" is used, thus you must make sure there are no Python files that are not to be checked in.

The user must set "CVSUSER_FOO" to his user name on the CVS repository. This can be done in his personal default recipe "~/.aap/startup/default.aap".

top
 
 
  The A-A-P pages:
home
news
documentation
     Recipe examples
     Aap manual
     Agide tutorial
     features
     presentations
download
     Aap version log
     Agide version log
     ported applications
maillists and chat
plan and tasks
     SourceForge project
     Aap todo list
     Agide todo list
architecture
     use cases
     modules
     interfaces
     design decisions
tools overview
     script languages
     build tools
     Install tools
     issue tracking
     version control
     browse tools
     IDEs
     various tools


visit the A-A-P presentation at:

O'Reilly Open Source Convention.


OSDir.com interview about A-A-P

 
funded by: NLnet
	 logo

Send comments on this page to Webmaster AT a-a-p.org.            Hosted by SourceForge Logo            Also known as www.Agide.org.