Chapter 17. Installing

This section contains details about the installation of the produced programs and other items. Those other items can be libraries (produced by the :lib, :dll, or :ltlib commands), header files for the API of a library, documentation (like manpages or info files), and as a catch-all, "data."

Usually installing is done with aap install. If you do not define an "install" target in the recipe, Aap will add one for you. The default install target invokes up to 15 other install targets, one for each kind of item you can install. This makes it easy to customize the installation of some particular kind of item (e.g. libtool archives).

The default install target invokes two or three other targets: install-platform, install-shared, and (optionally, only if you define it in the recipe) install-local. Each of these invokes other install targets for specific kinds of files, as follows:

Table 17.1. Install targets

High-level TargetLower-level TargetsInstall these Files
install-platform This is for installing platform-dependent files.
 install-exec

Install programs (generally produced through :program command).

 install-sbinInstall programs for system administration. These may have additional security considerations, hence a separate target.
 install-libInstall static libraries (from the :lib command).
 install-dllInstall shared libraries (from the :dll command).
 install-ltlib Install shared libtool libraries (from the :ltlib command). These require special treatment by the libtool program, hence a separate target.
 install-confInstall platform-specific configuration files (such as pkg-config files).
 install-platform-localA catch-all for things that don't fit anywhere else.
install-shared This is for installing files shared between platforms.
 install-dataInstall data for the package. This would typically include translation files, examples (if they're not in the manpage), and images used by the package.
 install-manInstall manpages.
 install-infoInstall GNU-style info pages.
 install-includeInstalls header files (also known as includes).
 install-shared-localA catch-all for things that don't fit anywhere else.
install-local 

this is an optional target that you can define for extra installing, without changing the other install targets.


Each of these dependencies is only added automatically if you do not define it yourself. In other words, if you do not define a dependency with install-data as a target, Aap will add such a dependency internally. Unless you need special processing for specific kinds of items, you should rarely need to define any of the install targets yourself. The exceptions are install-platform-local, install-shared-local and install-local, which you can define without disturbing Aap's normal mechanisms for installing the programs and libraries you create.

All these dependencies that Aap adds are at the toplevel. Thus there is only one of each for all the recipes in your project. See below for an example of including the path of an item. Note that this works different from the "clean" and "cleanmore" targets. These can exist multiple times, each parent and child recipe can have one.

All of Aap's default install targets operate in roughly the same fashion: specific actions are invoked for each install target. The default actions all use top-level variables named INSTALL_target which collect filenames to install. Other toplevel variables control where those files are installed (targetDIR) and what file mode is used (targetMODE). This table shows the specific settings for each of the default install targets:

Table 17.2. Settings for the install target

targetvariableactiondirectorydefault directorymodedefault mode
install-exec$INSTALL_EXECinstallexec$EXECDIRbin/$EXECMODE0755
install-sbin$INSTALL_SBINinstallsbin$SBINDIRsbin/$EXECMODE0755
install-lib$INSTALL_LIBinstalllib$LIBDIRlib/$LIBMODE0644
install-dll$INSTALL_DLLinstalldll$DLLDIRlib/$DLLMODE0755
install-ltlib$INSTALL_LTLIB No default settings for libtool libraries have been added to Aap yet. It seems likely that DLLDIR and DLLMODE will be used.
install-conf$INSTALL_CONFinstallconf$CONFDIRetc/$CONFMODE0644
install-data$INSTALL_DATAinstalldata$DATADIRshare/ [a]$DATAMODE0644
install-man$INSTALL_MANinstallman$MANDIRman/ [b]$MANMODE0644
install-info$INSTALL_INFOinstallinfo$INFODIRinfo/$INFOMODE0644
install-include$INSTALL_INCLUDEinstallinclude$INCLUDEDIRinclude/$INCLUDEMODE0644

[a] A subdirectory will be added with the name $PKGNAME. You must set this variable to the name of your application! In the rare situation that you need to install into multiple directories you may set $PKGNAME to an empty string and prepend the directory name to your data files.

[b] A subdirectory will be added that uses the extension of the file. For "foo.1" the directory is "man1", for "foo.2" it is "man2", and so on.


The :program command adds its target to the $INSTALL_EXEC variable. The :lib command adds its target to the $INSTALL_LIB variable. The :dll command adds its target to the $INSTALL_DLL variable. The :ltlib command adds its target to the $INSTALL_LTLIB variable.

The "installexec" action will strip the program by default, if the "strip" program can be found. If you don't want this add the {nostrip} attribute to the program or set $STRIP to an empty value.

You can also overrule the default actions by one of your own. The install_files() function can be useful then. See the default.aap recipe for examples.

Destination Directories

All the install targets prepend a path to the directory they install into. The directory mentioned above is appended.

$DESTDIRNormally empty, which means that the root directory is used. Set this when you don't want to install to the local machine, but still pretend to install in the root. Examples: "~/dummyroot", "scp://foo.org/". Yes, you can do remote installing this way! Although not everything that works locally will work remotely.
$PREFIXDefault is "/usr/local/" on Unix. This specifies where to install to. The installed program is aware of being installed here, $PREFIX may be put in configuration files.

The variables are concatenated. For example, programs are installed in $DESTDIR$PREFIX$EXECDIR. Slashes are added in between where needed.

The directories that are used are automatically created when needed. Note that "uninstall" does not delete the directories!

When installing the path to a file is normally removed. Thus when you produced a program "results/myprog" it will be installed as "myprog". If you need to keep the path use the "keepdir" attribute on the file name.

          INSTALL_INCLUDE += sys/myheader.h {keepdir}

As an alternative to {keepdir}, there is the {installdir} attribute, which explicitly sets the relative path of the file to be installed. Files with an {installdir} attribute are installed in $DESTDIR$PREFIX$targetDIR$installdir. The above setting could also be done as:

          INSTALL_INCLUDE += sys/myheader.h {installdir=sys}

The advantage of {installdir} over {keepdir} is that the relative paths (from toplevel recipe to file and from install directory to the desired install location) need not be the same. For instance:

          INSTALL_INCLUDE += api/2.2/c/myheader.h {installdir=sys}

For additional flexibility, the source and target filenames need not be the same, either. For this you can use the attribute {installname} which is similar to {installdir}. If {installname} is set, this is used as the filename instead of the name of the source file, thus:

          INSTALL_INCLUDE += api/2.2/c/myheader.h {installname=header.h}

This will install the source file "myheader.h" as "header.h". You can combine {installname} with {keepdir} or {installdir} to install a source file to an arbitrarily-named destination. In summary:

(none) Source file name is preserved. Path to source file is not preserved, install to target directory determined by Aap. The source file "api/2.2/c/myheader.h" is installed as "myheader.h" in the $INCLUDEDIR directory.
{installname} Source file name is not preserved; source file is installed under name given by {installname} attribute. Path to source file is not preserved, install to target directory determined by Aap. The source file "api/2.2/c/myheader.h" with attribute {installname=header.h} is installed as "header.h" in the $INCLUDEDIR directory.
{keepdir} Source file name is preserved. Path to source file is preserved, install to subdirectory under target directory determined by Aap. Subdirectory is the relative path to the source file. The source file "api/2.2/c/myheader.h" with attribute {keepdir} is installed as "myheader.h" in $INCLUDEDIR/api/2.2/c/ .
{installdir} Source file name is preserved. Path to source file is replaced by the value of {installdir} and the file installs to a subdirectory under the target directory determined by Aap. Subdirectory is the value of {installdir} The source file "api/2.2/c/myheader.h" with attribute {installdir=myinclude} is installed as "myheader.h" in $INCLUDEDIR/myinclude/ .
{installdir} {installname} or {keepdir} {installname} The path to the source file is either kept or replaced by the value of {installdir}, and the name of the file is replaced by the value of {installname}. The source file "api/2.2/c/myheader.h" with attributes {keepdir} {installname=header.h} is installed as "header.h" in $INCLUDEDIR/api/2.2/c/ . The source file "api/2.2/c/myheader.h" with attributes {installdir=myinclude} {installname=header.h} is installed as "header.h" in $INCLUDEDIR/include/ .

The mode variable mentioned above is used to set the mode bits of the file after installing. If this is not wanted, use the {keepmode} attribute. Example:

          INSTALL_DATA += myscript.sh {keepmode}

To use another mode for a specific file add the {mode = 0555} attribute:

          INSTALL_DATA += myscript.sh {mode = 0750}

Installing to a remote machine should work, although setting the file mode may not always work properly, depending on the transfer method used.

Keep in mind that installation is done from the top directory. In a child recipe that is located in another directory you need to specify the path to the file to install relative to the top directory. Using the $TOPDIR variable and rc-style expansion should work. Example:

    # Filenames relative to the child directory
    child_INSTALL_DATA = myscript.sh myicon.png

    # Now add those filenames, relative to the top
    INSTALL_DATA += $TOPDIR/$*child_INSTALL_DATA

If you hard code the paths from the parent to the files to install, say by writing INSTALL_DATA += child/myscript.sh, then you cannot execute the child recipe by itself (as if it were a toplevel recipe), since the paths will be wrong. Using $TOPDIR, or equivalently the topdir function, is the safe way to do so.

Uninstall

"aap uninstall" deletes the file that "aap install" has installed. All the targets and actions have the same name with "install" replaced with "uninstall". The same variables are used.

Files that do not exist are silently skipped. Files that do exist but cannot be deleted will cause a warning message.

Sometimes your recipe offers installing optional files. You probably want to uninstall those optional files as well, without requiring the user the specify the same options again. For this you can set the $UNINSTALL_* variables. For example, if you install either the "foo" or "bar" program:

        :variant What
             foo
                  Target = foo
                  UNINSTALL_EXEC = bar$EXESUF
             bar
                  Target = bar
                  UNINSTALL_EXEC = foo$EXESUF

        :program $Target : $Sources

Installing in non-standard places

When you need to install in other directories than the ones Aap provides there are several alternatives. First of all, you could use $INSTALL_DATA and set $DATADIR to the installation directory. This works if you are otherwise not using $INSTALL_DATA.

If you have several different directories you could use this scheme:

  INSTALL_ITEM1 = file1.txt file2.txt
  INSTALL_DIR1 = somewhere
  INSTALL_ITEM2 = file3.txt file4.txt
  INSTALL_DIR2 = elsewhere

  install-local:
      @install_files(_no.INSTALL_DIR1, _no.INSTALL_ITEM1, '0644')
      @install_files(_no.INSTALL_DIR2, _no.INSTALL_ITEM2, '0644')

  uninstall-local:
      @uninstall_files(_no.INSTALL_DIR1, _no.INSTALL_ITEM1)
      @uninstall_files(_no.INSTALL_DIR2, _no.INSTALL_ITEM2)

In the Python reference chapter you can find explanations for install_files() and uninstall_files()

You could also add a command to set the protection flags of the installed files: :chmod $INSTALL_DIR1/$*INSTALL_ITEM1.