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

  Part of the A-A-P recipe executive: Install

  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

-->

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



<para>
Usually installing is done with
<userinput>aap install</userinput>.
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.&nbsp;libtool archives).
</para>


<para>
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:
</para>

<table frame="none" id="tbl-install">
  <title>Install targets</title>
  <tgroup cols="3">
    <colspec colwidth="200,200,400"/>
    <thead>
    <row>
    <entry>High-level Target</entry>
    <entry>Lower-level Targets</entry>
    <entry>Install these Files</entry>
    </row>
    </thead>

    <tbody>
      <row>
      <entry>install-platform</entry>
      <entry>&nbsp;</entry>
      <entry>This is for installing platform-dependent files.</entry>
      </row>

      <row>
      <entry>&nbsp;</entry><!-- under install-platform -->
      <entry>install-exec</entry>
      <entry><para>Install programs (generally produced through
      <link linkend="cmd-program"><literal>:program</literal></link>
      command).
      </para></entry>
      </row>

      <row>
      <entry>&nbsp;</entry><!-- under install-platform -->
      <entry>install-sbin</entry>
      <entry>Install programs for system administration.
      These
      may have additional security considerations, hence a separate target.
      </entry>
      </row>

      <row>
      <entry>&nbsp;</entry><!-- under install-platform -->
      <entry>install-lib</entry>
      <entry>Install static libraries (from the
      <link linkend="cmd-lib"><literal>:lib</literal></link> command).
      </entry>
      </row>

      <row>
      <entry>&nbsp;</entry><!-- under install-platform -->
      <entry>install-dll</entry>
      <entry>Install shared libraries (from the
      <link linkend="cmd-dll"><literal>:dll</literal></link> command).
      </entry>
      </row>

      <row>
      <entry>&nbsp;</entry><!-- under install-platform -->
      <entry>install-ltlib</entry>
      <entry>
      Install shared libtool libraries (from the
      <link linkend="cmd-ltlib"><literal>:ltlib</literal></link> command).
      These require special treatment by the libtool program,
      hence a separate target.
      </entry>
      </row>

      <row>
      <entry>&nbsp;</entry><!-- under install-platform -->
      <entry>install-conf</entry>
      <entry>Install platform-specific configuration files
      (such as pkg-config files).
      </entry>
      </row>

      <row>
      <entry>&nbsp;</entry><!-- under install-platform -->
      <entry>install-platform-local</entry>
      <entry>A catch-all for things that don't
      fit anywhere else.
      </entry>
      </row>

      <row>
      <entry>install-shared</entry>
      <entry>&nbsp;</entry>
      <entry>This is for installing files shared between platforms.</entry>
      </row>

      <row>
      <entry>&nbsp;</entry><!-- under install-shared -->
      <entry>install-data</entry>
      <entry>Install data for the package.
      This would typically include translation files,
      examples (if they're not in the manpage),
      and images used by the package.
      </entry>
      </row>

      <row>
      <entry>&nbsp;</entry><!-- under install-shared -->
      <entry>install-man</entry>
      <entry>Install manpages.</entry>
      </row>

      <row>
      <entry>&nbsp;</entry><!-- under install-shared -->
      <entry>install-info</entry>
      <entry>Install GNU-style info pages.</entry>
      </row>

      <row>
      <entry>&nbsp;</entry><!-- under install-shared -->
      <entry>install-include</entry>
      <entry>Installs header files (also known as includes).
      </entry>
      </row>

      <row>
      <entry>&nbsp;</entry><!-- under install-shared -->
      <entry>install-shared-local</entry>
      <entry>A catch-all for things that don't fit anywhere else.</entry>
      </row>


      <row>
      <entry>install-local</entry>
      <entry>&nbsp;</entry>
      <entry><para>this is an optional target that you can define for extra
      installing, without changing the other install targets.</para></entry>
      </row>
    </tbody>
  </tgroup>
</table>


<para>
  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
  <computeroutput>install-data</computeroutput> 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
  <computeroutput>install-platform-local</computeroutput>,
  <computeroutput>install-shared-local</computeroutput> and
  <computeroutput>install-local</computeroutput>,
  which you can define without disturbing &Aap;'s normal
  mechanisms for installing the programs and libraries you create.
</para>

<para>
  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
  <link linkend="install-path">below</link> 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.
</para>


<para>
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 <literal>INSTALL_<replaceable>target</replaceable></literal>
which collect filenames to install.
Other toplevel variables control where those
files are installed (<literal><replaceable>target</replaceable>DIR</literal>)
and what file mode is used (<literal><replaceable>target</replaceable>MODE</literal>).
This table shows the specific settings for each of
the default install targets:
</para>

<table frame="none" id="installvar">
  <title>Settings for the install target</title>
  <tgroup cols="7">
    <colspec colname="c1"/>
    <colspec colname="c2"/>
    <colspec colname="c3"/>
    <colspec colname="c4"/>
    <colspec colname="c5"/>
    <colspec colname="c6"/>
    <colspec colname="c7"/>
    <thead>
      <row>
        <entry>target</entry>
        <entry>variable</entry>
        <entry>action</entry>
        <entry>directory</entry>
        <entry>default directory</entry>
        <entry>mode</entry>
        <entry>default mode</entry>
      </row>
    </thead>
    <tbody>
    <row>
    <entry>install-exec</entry>
    <entry>$INSTALL_EXEC</entry>
    <entry>installexec</entry>
    <entry>$EXECDIR</entry>
    <entry>bin/</entry>
    <entry>$EXECMODE</entry>
    <entry>0755</entry>
    </row>
    <row>
    <entry>install-sbin</entry>
    <entry>$INSTALL_SBIN</entry>
    <entry>installsbin</entry>
    <entry>$SBINDIR</entry>
    <entry>sbin/</entry>
    <entry>$EXECMODE</entry>
    <entry>0755</entry>
    </row>
    <row>
    <entry>install-lib</entry>
    <entry>$INSTALL_LIB</entry>
    <entry>installlib</entry>
    <entry>$LIBDIR</entry>
    <entry>lib/</entry>
    <entry>$LIBMODE</entry>
    <entry>0644</entry>
    </row>
    <row>
    <entry>install-dll</entry>
    <entry>$INSTALL_DLL</entry>
    <entry>installdll</entry>
    <entry>$DLLDIR</entry>
    <entry>lib/</entry>
    <entry>$DLLMODE</entry>
    <entry>0755</entry>
    </row>

    <row>
    <entry>install-ltlib</entry>
    <entry>$INSTALL_LTLIB</entry>
    <entry namest="c3" nameend="c7">
    No default settings for libtool libraries have been
    added to &Aap; yet. It seems likely that DLLDIR and DLLMODE will be used.
    </entry>
    </row>

    <row>
    <entry>install-conf</entry>
    <entry>$INSTALL_CONF</entry>
    <entry>installconf</entry>
    <entry>$CONFDIR</entry>
    <entry>etc/</entry>
    <entry>$CONFMODE</entry>
    <entry>0644</entry>
    </row>
    <row>
    <entry>install-data</entry>
    <entry>$INSTALL_DATA</entry>
    <entry>installdata</entry>
    <entry>$DATADIR</entry>
    <entry>share/
    <footnote>
    <para>
    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.
    </para>
    </footnote></entry>
    <entry>$DATAMODE</entry>
    <entry>0644</entry>
    </row>
    <row>
    <entry>install-man</entry>
    <entry>$INSTALL_MAN</entry>
    <entry>installman</entry>
    <entry>$MANDIR</entry>
    <entry>man/
    <footnote>
    <para>
    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.
    </para>
    </footnote></entry>
    <entry>$MANMODE</entry>
    <entry>0644</entry>
    </row>
    <row>
    <entry>install-info</entry>
    <entry>$INSTALL_INFO</entry>
    <entry>installinfo</entry>
    <entry>$INFODIR</entry>
    <entry>info/</entry>
    <entry>$INFOMODE</entry>
    <entry>0644</entry>
    </row>
    <row>
    <entry>install-include</entry>
    <entry>$INSTALL_INCLUDE</entry>
    <entry>installinclude</entry>
    <entry>$INCLUDEDIR</entry>
    <entry>include/</entry>
    <entry>$INCLUDEMODE</entry>
    <entry>0644</entry>
    </row>

    </tbody>
  </tgroup>
</table>


<para>
  The
  <link linkend="cmd-program">:program</link> command adds its target to the $INSTALL_EXEC variable.
  The
  <link linkend="cmd-lib">:lib</link> command adds its target to the $INSTALL_LIB variable.
  The
  <link linkend="cmd-dll">:dll</link> command adds its target to the $INSTALL_DLL variable.
  The
  <link linkend="cmd-ltlib">:ltlib</link> command adds its target to the $INSTALL_LTLIB variable.
</para>
<para>
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.
</para>
<para>
You can also overrule the default actions by one of your own.  The
<link linkend="python-install-files">install_files()</link> function can be
useful then.  See the default.aap recipe for examples.
</para>


<bridgehead id="install-dirs">Destination Directories</bridgehead>

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

<informaltable frame="none">
  <tgroup cols="2">
    <colspec colwidth="100"/>
    <tbody>
      <row>
      <entry>$DESTDIR</entry>
      <entry>Normally 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.
                      </entry>

      </row>
      <row>
      <entry>$PREFIX</entry>
      <entry>Default 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.</entry>
      </row>
    </tbody>
  </tgroup>
</informaltable>
</para>
<para>
The variables are concatenated.  For example, programs are installed in
$DESTDIR$PREFIX$EXECDIR.  Slashes are added in between where needed.
</para>
<para>
The directories that are used are automatically created when needed.  Note
that "uninstall" does not delete the directories!
</para>
<para>
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.
</para>
<programlisting>
          INSTALL_INCLUDE += sys/myheader.h {keepdir}
</programlisting>

<para>
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
<literal>$DESTDIR$PREFIX$<replaceable>target</replaceable>DIR$installdir</literal>.
The above setting could also be done as:
<programlisting>
          INSTALL_INCLUDE += sys/myheader.h {installdir=sys}
</programlisting>
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:
<programlisting>
          INSTALL_INCLUDE += api/2.2/c/myheader.h {installdir=sys}
</programlisting>
</para>

<para>
For additional flexibility, the source and target <emphasis>filenames</emphasis>
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:
<programlisting>
          INSTALL_INCLUDE += api/2.2/c/myheader.h {installname=header.h}
</programlisting>
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:
</para>

<informaltable frame="none">
  <tgroup cols="2">
    <colspec colwidth="100"/>
    <tbody>
      <row>
      <entry>(none)</entry>
      <entry>
        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.
      </entry>
      </row>
      <row>
      <entry>{installname}</entry>
      <entry>
        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.
      </entry>
      </row>
      <row>
      <entry>{keepdir}</entry>
      <entry>
        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/ .
      </entry>
      </row>
      <row>
      <entry>{installdir}</entry>
      <entry>
        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/ .
      </entry>
      </row>
      <row>
      <entry>{installdir} {installname} or {keepdir} {installname}</entry>
      <entry>
        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/ .
      </entry>
      </row>
    </tbody>
  </tgroup>
</informaltable>


<para>
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:
</para>
<programlisting>
          INSTALL_DATA += myscript.sh {keepmode}
</programlisting>
<para>
To use another mode for a specific file add the {mode = 0555} attribute:
</para>
<programlisting>
          INSTALL_DATA += myscript.sh {mode = 0750}
</programlisting>
<para>
Installing to a remote machine should work, although setting the file mode may
not always work properly, depending on the transfer method used.
</para>
<para id="install-path">
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:
</para>

<programlisting>
    # 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
</programlisting>

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

<bridgehead>Uninstall</bridgehead>

<para>
"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.
</para>
<para>
Files that do not exist are silently skipped.  Files that do exist but cannot
be deleted will cause a warning message.
</para>
<para>
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:
</para>
<programlisting>
        :variant What
             foo
                  Target = foo
                  UNINSTALL_EXEC = bar$EXESUF
             bar
                  Target = bar
                  UNINSTALL_EXEC = foo$EXESUF

        :program $Target : $Sources
</programlisting>

<bridgehead>Installing in non-standard places</bridgehead>

<para>
  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.
</para>

<para>
  If you have several different directories you could use this scheme:
</para>
<programlisting>
  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)
</programlisting>
<para>
  In the Python reference chapter you can find explanations for
  <link linkend="python-install-files">install_files()</link> and
  <link linkend="python-uninstall-files">uninstall_files()</link>
</para>
<para>
  You could also add a command to set the protection flags of the installed
  files: <literal>:chmod $INSTALL_DIR1/$*INSTALL_ITEM1</literal>.
</para>
