Although Libtool is usable by itself, either from the command line or from a non-make driven build system, it is also tightly integrated into Autoconf and Automake.  This chapter discusses how to use Libtool with Autoconf and Automake and explains how to set up the files you write (Makefile.am and configure.in) to take advantage of libtool.  For a more in depth discussion of the workings of Libtool, particularly its command line interface, see Introducing GNU Libtool.  Using libtool for dynamic runtime loading is described in see Using GNU libltdl.

Using libtool to build the libraries in a project, requires declaring your use of libtool inside the project's configure.in and adding the Libtool support scripts to the distribution.  You will also need to amend the build rules in either Makefile.am or Makefile.in, depending on whether you are using Automake.

Integration with configure.in
=============================

Declaring your use of libtool in the project's configure.in is a simple matter of adding the AC_PROG_LIBTOOL (AM_PROG_LIBTOOL if you have an older automake or libtool installation.) somewhere near the top of the file.  I always put it immediately after the other AC_PROG_... macros.  If you are converting an old project to use libtool, then you will also need to remove any calls to AC_PROG_RANLIB.  Since Libtool will be handling all of the libraries, it will decide whether or not to call ranlib as appropriate for the build environment.

     The code generated by AC_PROG_LIBTOOL relies on the shell variable $top_builddir to hold the relative path to the directory which contains the configure script.  If you are using Automake, $top_builddir is set in the environment by the generated Makefile.  If you use Autoconf without  Automake then you must ensure that $top_builddir is set before the call to AC_PROG_LIBTOOL in configure.in.

     Adding the following code to configure.in is often sufficient:

          for top_builddir in . .. ../.. $ac_auxdir $ac_auxdir/..; do
            test -f $top_builddir/configure && break
          done

Having made these changes to add libtool support to your project, you will need to regenerate the aclocal.m4 file to pick up the macro definitions required for AC_PROG_LIBTOOL, and then rebuild your configure script with these new definitions in place.  After you have done that, there will be some new options available from configure:

     $ aclocal
     $ autoconf

     $ ./configure --help
     ...
     --enable and --with options recognized:
       --enable-shared[=PKGS]  build shared libraries [yes]
       --enable-static[=PKGS]  build static libraries [yes]
       --enable-fast-install[=PKGS]  optimize for fast installation [yes]
       --with-gnu-ld           assume the C compiler uses GNU ld [no]
       --disable-libtool-lock  avoid locking (might break parallel builds)
       --with-pic              try to use only PIC/non-PIC objects [both]

These new options allow the end user of your project some control over how they want to build the project's libraries.  The opposites of each of these switches are also accepted, even though they are not listed by configure --help.  You can equally pass, --disable-fast-install or --without-gnu-ld for example.

Extra Configure Options
-----------------------

What follows is a list that describes the more commonly used options that are automatically added to configure, by virtue of using AC_PROG_LIBTOOL in your configure.in.  The Libtool Manual distributed with Libtool releases always contains the most up to date information about libtool options:

--enable-shared
--enable-static
     More often invoked as --disable-shared or equivalently --enable-shared=no these switches determine whether libtool should build shared and/or static libraries in this package.  If the installer is short of disk space, they might like to build entirely without static archives.  To do this they would use:

          $ ./configure --disable-static

     Sometimes it is desirable to configure several related packages with the same command line.  From a scheduled build script or where subpackages with their own configure scripts are present, for example. The --enable-shared and --enable-static switches also accept a list of package names, causing the option to be applied to packages whose name is listed, and the opposite to be applied to those not listed.

     By specifying:

          $ ./configure --enable-static=libsnprintfv,autoopts

     libtool would pass --enable-static to only the packages named libsnprintfv and autoopts in the current tree.  Any other packages configured would effectively be passed --disable-static.  Note that this doesn't necessarily mean that the packages must honour these options.  Enabling static libraries for a package which consists of only dynamic modules makes no sense, and the package author would probably have decided to ignore such requests, see Extra Macros for Libtool.

--enable-fast-install
     On some machines, libtool has to relink executables when they are installed, see Installing an Executable.  Normally, when an end user builds your package, they will probably type:

          $ ./configure
          $ make
          $ make install

     libtool will build executables suitable for copying into their respective installation destinations, obviating the need for relinking them on those hosts which would have required it.  Whenever libtool links an executable which uses shared libraries, it also creates a wrapper script which ensures that the environment is correct for loading the correct libraries, see Executing Uninstalled Binaries.  On those hosts which require it, the wrapper script will also relink the executable in the build tree if you attempt to run it from there before installation.

     Sometimes this behaviour is not what you want, particularly if you are developing the package and not installing between test compilations.  By passing --disable-fast-install, the default behaviour is reversed;  executables will be built so that they can be run from the build tree without relinking, but during installation they may be relinked.

     You can pass a list of executables as the argument to --enable-fast-install to determine which set of executables will not be relinked at installation time (on the hosts that require it).  By specifying:

          $ ./configure --enable-fast-install=autogen

     The autogen executable will be linked for fast installation (without being relinked), and any other executables in the build tree will be linked for fast execution from their build location.  This is useful if the remaining executables are for testing only, and will never be installed.

     Most machines do not require that executables be relinked in this way, and in these cases libtool will link each executable once only, no matter whether --disable-fast-install is used.

--with-gnu-ld

     This option is used to inform libtool that the C compiler is using GNU ld as its linker.  It is more often used in the opposite sense when both gcc and GNU ld are installed, but gcc was built to use the native linker.  libtool will probe the system for GNU ld, and assume that it is used by gcc if found, unless --without-gnu-ld is passed to configure.

--disable-libtool-lock

     In normal operation, libtool will build two objects for every source file in a package, one PIC (Position Independent Code -- suitable for shared libraries which might be loaded to different addresses when linked by the runtime loader.) and one non-PIC.  With gcc and some other compilers, libtool can specify a different output location for the PIC object:

          $ libtool gcc -c shell.c
          gcc -c -pic -DPIC shell.c -o .libs/shell.lo
          gcc -c foo.c -o shell.o >/dev/null 2>&1

     When using a compiler that doesn't accept both -o and -c in the same command, libtool must compile first the PIC and then the non-PIC object to the same destination file and then move the PIC object before compiling the non-PIC object.  This would be a problem for parallel builds, since one file might overwrite the other.  libtool uses a simple shell locking mechanism to avoid this eventuality.

     If you find yourself building in an environment that has such a compiler, and not using parallel make, then the locking mechanism can be safely turned off by using --disable-libtool-lock to gain a little extra speed in the overall compilation.

--with-pic
     In normal operation, Libtool will build shared libraries from PIC objects and static archives from non-PIC objects, except where one or the other is not provided by the target host.  By specifying --with-pic you are asking libtool to build static archives from PIC objects, and similarly by specifying --without-pic you are asking libtool to build shared libraries from non-PIC objects.

     libtool will only honour this flag where it will produce a working library, otherwise it reverts to the default.

Extra Macros for Libtool
------------------------

There are several macros which can be added to configure.in which will change the default behaviour of libtool.  If they are used they must appear before the call to the AC_PROG_LIBTOOL macro.  Note that these macros only change the default behaviour, and options passed in to configure on the command line will always override the defaults.  The most up to date information about these macros is available from the Libtool Manual.

AC_DISABLE_FAST_INSTALL
     This macro tells libtool that on platforms which require relinking at install time, it should build executables so that they can be run from the build tree at the expense of relinking during installation, as if --disable-fast-install had been passed on the command line.

AC_DISABLE_SHARED
AC_DISABLE_STATIC
     These macros tell libtool to not try and build either shared or static libraries respectively.  libtool will always try to build something however, so even if you turn off static library building in configure.in, building your package for a target host without shared library support will fallback to building static archives.

The time spent waiting for builds during development can be reduced a little by including these macros temporarily.  Don't forget to remove them before you release the project though!

In addition to the macros provided with AC_PROG_LIBTOOL, there are a few shell variables that you may need to set yourself, depending on the structure of your project:

LTLIBOBJS
     If your project uses the AC_REPLACE_FUNCS macro, or any of the other macros which add object names to the LIBOBJS variable, you will also need to provide an equivalent LTLIBOBJS definition.  At the moment, you must do it manually, but needing to do that is considered to be a bug and will fixed in a future release of Autoconf. The manual generation of LTLIBOBJS is a simple matter of replacing the names of the objects mentioned in LIBOBJS with equivalent .lo suffixed Libtool object names.  The easiest way to do this is to add the following snippet to your configure.in near the end, just before the call to AC_OUTPUT.

          m4_changequote(,)m4_dnl

          Xsed="sed -e s/^X//"
          LTLIBOBJS=`echo X"$LIBOBJS"|\
                     [$Xsed -e "s,\.[^.]* ,.lo ,g;s,\.[^.]*$,.lo,"]`
          AC_SUBST(LTLIBOBJS)

          m4_changequote(`,')m4_dnl

     The Xsed is not usually necessary, though it can prevent problems with the echo command in the event that one of the LIBOBJS files begins with a - character.  It is also a good habit to write shell code like this, as it will avoid problems in your programs.

LTALLOCA
     If your project uses the AC_FUNC_ALLOCA macro, you will need to provide a definition of LTALLOCA equivalent to the ALLOCA value provided by the macro.

          m4_changequote(,)m4_dnl

          Xsed="sed -e s/^X//"
          LTALLOCA=`echo X"$ALLOCA"|[$Xsed -e "s,\.$[^.]*,.lo,g"]`
          AC_SUBST(LTALLOCA)

          m4_changequote(`,')m4_dnl

     Obviously you don't need to redefine Xsed if you already use it for LTLIBOBJS above.

LIBTOOL_DEPS
     To help you write make rules for automatic updating of the Libtool configuration files, you can use the value of LIBTOOL_DEPS after the call to AC_PROG_LIBTOOL:

          AC_PROG_LIBTOOL
          AC_SUBST(LIBTOOL_DEPS)

     Then add the following to the top level Makefile.in:

          libtool: @LIBTOOL_DEPS@
                  cd $(srcdir) && \
                    $(SHELL) ./config.status --recheck

     If you are using automake in your project, it will generate equivalent rules automatically.  You don't need to use this except in circumstances where you want to use libtool and autoconf, but not automake.

Integration with Makefile.am
============================

Automake supports Libtool libraries in two ways.  It can help you to build the Libtool libraries themselves, and also to build executables which link against Libtool libraries.

Creating Libtool Libraries with Automake
----------------------------------------

Continuing in the spirit of making Libtool library management look like native static archive management, converting a Makefile.am from static archive use to Libtool library use is a matter of changing the name of the library, and adding a Libtool prefix somewhere.  For example, a Makefile.am for building a static archive might be:

     lib_LIBRARIES      = libshell.a
     libshell_a_SOURCES = object.c subr.c symbol.c

This would build a static archive called libshell.a consisting of the objects object.o, subr.o and bar.o.  To build an equivalent Libtool library from the same objects, you change this to:

     lib_LTLIBRARIES     = libshell.la
     libshell_la_SOURCES = object.c subr.c symbol.c

The only changes are that the library is now named with a .la suffix,  and the Automake primary is now LTLIBRARIES. Note that since the name of the library has changed, you also need to use libshell_la_SOURCES, and similarly for any other Automake macros which used to refer to the old archive.  As for native libraries, Libtool library names should begin with the letters lib, so that the linker will be able to find them when passed -l options.

Often you will need to add extra objects to the library as determined by configure, but this is also a mechanical process.  When building native libraries, the Makefile.am would have contained:

     libshell_a_LDADD = xmalloc.o @LIBOBJS@

To add the same objects to an equivalent Libtool library would require:

     libshell_la_LDADD = xmalloc.lo @LTLIBOBJS@

That is, objects added to a Libtool library must be Libtool objects (with a .lo) suffix.  You should add code to configure.in to ensure that LTALLOCA and LTLIBOBJS are set appropriately, see Extra Macros for Libtool.  Automake will take care of generating appropriate rules for building the Libtool objects mentioned in an LDADD macro.

If you want to pass any additional flags to libtool when it is building, you use the LDFLAGS macro for that library, like this:

     libshell_la_LDFLAGS = -version-info 1:0:1

For a detailed list of all the available options, see Link mode (The Libtool Manual).

     Libtool's use of -rpath has been a point of contention for some users, since it prevents you from moving shared libraries to another location in the library search path.  Or, at least, if you do, all of the executables that were linked with -rpath set to the old location will need to be relinked.

     We (the Libtool maintainers) assert that always using -rpath is a good thing:  Mainly because you can guarantee that any executable linked with -rpath will find the correct version of the library, in the rpath directory, that was intended when the executable was linked.  Library versions can still be managed correctly, and will be found by the run time loader, by installing newer versions to the same directory.  Additionally, it is much harder for a malicious user to leave a modified copy of system library in a directory that someone might wish to list in their LD_LIBRARY_PATH in the hope that some code they have written will be executed unexpectedly.

     The argument against -rpath was instigated when one of the GNU/Linux distributions moved some important system libraries to another directory to make room for a different version, and discovered that all of the executables that relied on these libraries and were linked with Libtool no longer worked.  Doing this was, arguably, bad system management -- the new libraries should have been placed in a new directory, and the old libraries left alone.  Refusing to use -rpath in case you want to restructure the system library directories is a very weak argument.

The -rpath option (which is required for Libtool libraries) is automatically supplied by automake based on the installation directory specified with the library primary.

     lib_LTLIBRARIES = libshell.la

The example would use the value of the make macro $(libdir) as the argument to -rpath, since that is where the library will be installed.

A few of the other options you can use in the library LDFLAGS are:

-no-undefined
     Modern architectures allow us to create shared libraries with undefined symbols, provided those symbols are resolved (usually by the executable which loads the library) at runtime.  Unfortunately, there are some architectures (notably AIX and Windows) which require that all symbols are resolved when the library is linked.  If you know that your library has no unresolved symbols at link time, then adding this option tells libtool that it will be able to build a shared library, even on architectures which have this requirement.

-static
     Using this option will force libtool to build only a static archive for this library.

-release
     On occasion, it is desirable to encode the release number of a library into its name.  By specifying the release number with this option, libtool will build a library that does this, but will break binary compatibility for each change of the release number.  By breaking binary compatibility this way, you negate the possibility of fixing bugs in installed programs by installing an updated shared library.  You should probably be using -version-info instead.

          libshell_la_LDFLAGS = -release 27

     The above fragment might create a library called libshell-27.so.0.0.0 for example.

-version-info
     Set the version number of the library according to the native versioning rules based on the numbers supplied, see Library Versioning.  You need to be aware that the library version number is for the use of the runtime loader, and is completely unrelated to the release number of your project.  If you really want to encode the project release into the library, you can use -release to do it.

     If this option is not supplied explicitly, it defaults to -version-info 0:0:0.

     Historically, the default behaviour of Libtool was as if -no-undefined was always passed on the command line, but it proved to be annoying to developers who had to constantly turn it off so that  their ELF libraries could be featureful.  Now it has to be defined explicitly if you need it.

     There are is a tradeoff:

       * If you don't specify -no-undefined, then Libtool will not build shared libraries on platforms which don't allow undefined symbols at link time for such a library.

       * It is only safe to specify this flag when you know for certain that all of the libraries symbols are defined at link time, otherwise the -no-undefined link will appear to work until it is tried on a platform which requires all symbols to be defined.  Libtool will try to link the shared library in this case (because you told it that you have not left any undefined symbols), but the link will fail, because there are undefined symbols in spite of what you told Libtool.

     For more information about this topic, see Portable Library Design.

Linking against Libtool Libraries with Automake
-----------------------------------------------

Once you have set up your Makefile.am to create some Libtool libraries. you will want to link an executable against them.  You can do this easily with automake by using the program's qualified LDADD macro:

     bin_PROGRAMS  = shell
     shell_SOURCES = shell.c token.l
     shell_LDADD   = libshell.la

This will choose either the static or shared archive from the libshell.la Libtool library depending on the target host and any Libtool mode switches mentioned in the Makefile.am, or passed to configure.  The chosen archive will be linked with any objects generated from the listed sources to make an executable.  Note that the executable itself is a hidden file, and that in its place libtool creates a wrapper script, see Executing Uninstalled Binaries.

As with the Libtool libraries, you can pass additional switches for the libtool invocation in the qualified LDFLAGS macros to control how the shell executable is linked:

-all-static
     Always choose static libraries where possible, and try to create a completely statically linked executable.

-no-fast-install
     If you really want to use this flag on some targets, you can pass it in an LDFLAGS macro.  This is not overridden by the configure --enable-fast-install switch.  Executables built with this flag will not need relinking to be executed from the build tree on platforms which might have otherwise required it.

-no-install
     You should use this option for any executables which are used only for testing, or for generating other files and are consequently never installed.  By specifying this option, you are telling Libtool that the executable it links will only ever be executed from where it is built in the build tree.  Libtool is usually able to considerably speed up the link process for such executables.

-static
     This switch is similar to -all-static, except that it applies to only the uninstalled Libtool libraries in the build tree.  Where possible the static archive from these libraries is used, but the default linking mode is used for libraries which are already installed.

When debugging an executable, for example, it can be useful to temporarily use:

     shell_LDFLAGS = -all-static

     You can pass Libtool link options to all of the targets in a given directory by using the unadorned LDFLAGS macro:

          LDFLAGS = -static

     This is best reserved for directories which have targets of the same type, all Libtool libraries or all executables for instance.  The technique still works in a mixed target type directory, and libtool will ignore switches which don't make sense for particular targets.  It is less maintainable, and makes it harder to understand what is going on if you do that though.

Using libtoolize
================

Having made the necessary editions in configure.in and Makefile.am, all that remains is to add the Libtool infrastructure to your project.

First of all you must ensure that the correct definitions for the new macros you use in configure.in are added to aclocal.m4, see Generated File Dependencies.  At the moment, the safest way to do this is to copy libtool.m4 from the installed libtool to acinclude.m4 in the toplevel source directory of your package. This is to ensure that when your package ships, there will be no mismatch errors between the M4 macros you provided in the version of libtool you built the distribution with, versus the version of the Libtool installation in another developer's environment.  In a future release, libtool will check that the macros in aclocal.m4 are from the same Libtool distribution as the generated libtool script.

     $ cp /usr/share/libtool/libtool.m4 ./acinclude.m4
     $ aclocal

By naming the file acinclude.m4 you ensure that aclocal can see it and will use macros from it, and that automake will add it to the distribution when you create the tarball.

Next, you should run libtoolize, which adds some files to your distribution that are required by the macros from libtool.m4. In particular, you will get ltconfig (The functionality of ltconfig is slated for migration into libtool.m4 for a future release of libtool, whereupon this file will no longer be necessary.) and ltmain.sh which are used to create a custom libtool script on the installer's machine.

If you do not yet have them, libtoolize will also add config.guess and config.sub to your distribution. Sometimes you don't need to run libtoolize manually, since automake will run it for you when it sees the changes you have made to configure.in, as follows:

     $ automake --add-missing
     automake: configure.in: installing `./install-sh'
     automake: configure.in: installing `./mkinstalldirs'
     automake: configure.in: installing `./missing'
     configure.in: 8: required file `./ltconfig' not found

The error message in the last line is an aberration.  If it were consistent with the other lines, it would say:

     automake: configure.in: installing `./ltconfig'
     automake: configure.in: installing `./ltmain.sh'
     automake: configure.in: installing `./config.guess'
     automake: configure.in: installing `./config.sub'

But the effect is the same, and the files are correctly added to the distribution despite the misleading message.

     Before you release a distribution of your project, it is wise to get the latest versions of config.guess and config.sub from the GNU site (ftp://ftp.gnu.org/gnu/config/), since they may be newer than the versions automatically added by libtoolize and automake.  Note that automake --add-missing will give you its own version of these two files if AC_PROG_LIBTOOL is not used in the project configure.in, but will give you the versions shipped with libtool if that macro is present!

Library Versioning
==================

It is important to note from the outset that the version number of your project is a very different thing to the version number of any libraries shipped with your project.  It is a common error for maintainers to try to force their libraries to have the same version number as the current release version of the package as a whole.  At best, they will break binary compatibility unnecessarily, so that their users won't gain the benefits of the changes in their latest revision without relinking all applications that use it.  At worst, they will allow the runtime linker to load binary incompatible libraries, causing applications to crash.

Far better, the Libtool versioning system will build native shared libraries with the correct native library version numbers. Although different architectures use various numbering schemes, Libtool abstracts these away behind the system described here. The various native library version numbering schemes are designed so that when an executable is started, the runtime loader can, where appropriate, choose a more recent installed library version than the one with which the executable was actually built.  This allows you to fix bugs in your library, and having  built it with the correct Libtool version number, have those fixes propagate into any executables that were built with the old buggy version.  This can only work if the runtime loader can tell whether it can load the new library into the old executable and expect them to work together.  The library version numbers give this information to the runtime loader, so it is very important to set them correctly.

The version scheme used by Libtool tracks interfaces, where an interface is the set of exported entry points into the library. All Libtool libraries start with -version-info set to 0:0:0 -- this will be the default version number if you don't explicitly set it on the Libtool link command line.  The meaning of these numbers (from left to right) is as follows:

current
     The number of the current interface exported by the library.  A CURRENT value of 0, means that you are calling the interface exported by this library interface 0.

revision
     The implementation number of the most recent interface exported by this library.  In this case, a REVISION value of 0 means that this is the first implementation of the interface.

     If the next release of this library exports the same interface, but has a different implementation (perhaps some bugs have been fixed), the REVISION number will be higher, but CURRENT number will be the same.  In that case, when given a choice, the library with the highest REVISION will always be used by the runtime loader.

age
     The number of previous additional interfaces supported by this library. If AGE were 2, then this library can be linked into executables which were built with a release of this library that exported the current interface number, CURRENT, or any of the previous two interfaces.

     By definition AGE must be less than or equal to CURRENT. At the outset, only the first ever interface is implemented, so AGE can only be 0.

For later releases of a library, the -version-info argument needs to be set correctly depending on any interface changes you have made. This is quite straightforward when you understand what the three numbers mean:

 1. If you have changed any of the sources for this library, the REVISION number must be incremented.  This is a new revision of the current interface.

 2. If the interface has changed, then CURRENT must be incremented, and REVISION reset to 0.  This is the first revision of a new interface.

 3. If the new interface is a superset of the previous interface (that is, if the previous interface has not been broken by the changes in this new release), then AGE must be incremented.  This release is backwards compatible with the previous release.

 4. If the new interface has removed elements with respect to the previous interface, then you have broken backward compatibility and AGE must be reset to 0.  This release has a new, but backwards incompatible interface.

     For example, if the next release of the library included some new commands for an existing socket protocol, you would use -version-info 1:0:1.  This is the first revision of a new interface.  This release is backwards compatible with the previous release.

     Later, you implement a faster way of handling part of the algorithm at the core of the library, and release it with -version-info 1:1:1. This is a new revision of the current interface.

     Unfortunately the speed of your new implementation can only be fully exploited by changing the API to access the structures at a lower level, which breaks compatibility with the previous interface, so you release it as -version-info 2:0:0.  This release has a new, but backwards incompatible interface.

When deciding which numbers to change in the -version-info argument for a new release, you must remember that an interface change is not limited to the API of the library.  The notion of an interface must include any method by which a user (code or human) can interact with the library: adding new builtin commands to a shell library; the format used in an output file; the handshake protocol required for a client connecting over a socket, and so on.

Additionally, If you use a development model which has both a stable and an unstable tree being developed in parallel, for example, and you don't mind forcing your users to relink all of the applications which use one of your Libtool libraries every time you make a release, then libtool provides the -release flag to encode the project version number in the name of the library, see Creating Libtool Libraries with Automake. This can save you library compatibility problems later if you need to, say, make a patch release of an older revision of your library, but the library version number that you should use has already been taken by another earlier release. In this case, you could be fairly certain that library releases from the unstable branch will not be binary compatible with the stable releases, so you could make all the stable releases with -release 1.0 and begin the first unstable release with -release 1.1.

Convenience Libraries
=====================

Sometimes it is useful to group objects together in an intermediate stage of a project's compilation to provide a useful handle for that group without having to specify all of the individual objects every time.  Convenience libraries are a portable way of creating such a partially linked object:  Libtool will handle all of the low level details in a way appropriate to the target host.  This section describes the use of convenience libraries in conjunction with Automake.  The principles of convenience libraries are discussed in Creating Convenience Libraries.

The key to creating Libtool convenience libraries with Automake is to use the
 noinst_LTLIBRARIES macro.  For the Libtool libraries named in this macro, Automake will create Libtool convenience libraries which can subsequently be linked into other Libtool libraries.

In this section I will create two convenience libraries, each in their own subdirectory, and link them into a third Libtool library, which is ultimately linked into an application.

If you want to follow this example, you should create a directory structure to hold the sources by running the following shell commands:

     $ mkdir convenience
     $ cd convenience
     $ mkdir lib
     $ mkdir replace

The first convenience library is built from two source files in the lib subdirectory.

 1. source.c:

          m4_include(examples/convenience/lib/source.texi)

     This file defines a single function to display the cosine of its argument on standard output, and consequently relies on an implementation of the cos function from the system libraries. Note the conditional inclusion of config.h, which will contain a definition of HAVE_MATH_H if configure discovers a math.h system header (the usual location for the declaration of cos).  The HAVE_CONFIG_H guard is by convention, so that the source can be linked by passing the preprocessor macro definitions to the compiler on the command line -- if configure.in does not use AM_CONFIG_HEADER for instance.

 2. source.h:

          m4_include(examples/convenience/lib/source_h.texi)

     For brevity, there is no #ifndef SOURCE_H guard.  The header is not installed, so you have full control over where it is #includeed, and in any case, function declarations can be safely repeated if the header is accidentally processed more than once.  In a real program, it would be better to list the function parameters in the declaration so that the compiler can do type checking.  This would limit the code to working only with ANSI compilers, unless you also use a PARAMS macro to conditionally preprocess away the parameters when a K&R compiler is used.  These details are beyond the scope of this convenience library example, but are described in full in K&R Compilers.

You also need a Makefile.am to hold the details of how this convenience library is linked:

     m4_include(examples/convenience/lib/Makefile.texi)

The noinst_LTLIBRARIES macro names the Libtool convenience libraries to be built in this directory, library.la.   Although not required for compilation, source.h is listed in the SOURCES macro of library.la so that correct source dependencies are generated, and so that it is added to the distribution tarball by automake's dist rule.

Finally, since the foo function relies on the cos function from the system math library, -lm is named as a required library in the LIBADD macro.  As with all Libtool libraries, interlibrary dependencies are maintained for convenience libraries so that you need only list the libraries you are using directly when you link your application later.  The libraries used by those libraries are added by Libtool.

The parent directory holds the sources for the main executable, main.c, and for a (non-convenience) Libtool library, error.c & error.h.

Like source.h, the functions exported from the Libtool library liberror.la are listed in error.h:

     m4_include(examples/convenience/error_h.texi)

The corresponding function definitions are in error.c:

     m4_include(examples/convenience/error.texi)

The gratuitous() function calls the foo() function defined in the library.la convenience library in the lib directory, hence source.h is included.

The definition of error() displays an error message to standard error, along with the name of the program, program_name, which is set by calling set_program_name().  This function, in turn, extracts the basename of the program from the full path using the system function, basename(), and stores it in the library private variable, program_name.

Usually, basename() is part of the system C library, though older systems did not include it.  Because of this, there is no portable header file that can be included to get a declaration, and you might see a harmless compiler warning due to the use of the function without a declaration.  The alternative would be to add your own declaration in error.c.  The problem with this approach is that different vendors will provide slightly different declarations (with or without const for instance), so compilation will fail on those architectures which do provide a declaration in the system headers that is different from the declaration you have guessed.

For the benefit of architectures which do not have an implementation of the basename() function, a fallback implementation is provided in the replace subdirectory.  The file basename.c follows:

     m4_include(examples/convenience/replace/basename.texi)

For brevity, the implementation does not use any const declarations which would be good style for a real project, but would need to be checked at configure time in case the end user needs to compile the package with a K&R compiler.

The use of strrchr() is noteworthy.  Sometimes it is declared in string.h, otherwise it might be declared in strings.h. BSD based Unices, on the other hand, do not have this function at all, but provide an equivalent function, rindex().  The preprocessor code at the start of the file is designed to cope with all of these eventualities.  The last block of preprocessor code assumes that if strrchr is already defined that it holds a working macro, and does not redefine it.

Makefile.am contains:

     m4_include(examples/convenience/replace/Makefile.texi)

Once again, the noinst_LTLIBRARIES macro names the convenience library,
 libreplace.la.  By default there are no sources, since we expect to have a system definition of basename().  Additional Libtool objects which should be added to the library based on tests at configure time are handled by the LIBADD macro.  LTLIBOBJS will contain basename.lo if the system does not provide basename, and will be empty otherwise.  Illustrating another feature of convenience libraries: on many architectures, libreplace.la will contain no objects.

Back in the toplevel project directory, all of the preceding objects are combined by another Makefile.am:

     m4_include(examples/convenience/Makefile.texi)

The initial SUBDIRS macro is necessary to ensure that the libraries in the subdirectories are built before the final library and executable in this directory.

Notice that I have not listed error.h in liberror_la_SOURCES this time, since liberror.la is an installed library, and error.h defines the public interface to that library.  Since the liberror.la Libtool library is installed, I have used the -version-info option, and I have also used -no-undefined so that the project will compile on architectures which require all library symbols to be defined at link time -- the reason program_name is maintained in liberror rather than main.c is so that the library does not have a runtime dependency on the executable which links it.

The key to this example is that by linking the libreplace.la and library.la convenience libraries into liberror.la, all of the objects in both convenience libraries are compiled into the single installed library, liberror.la.  Additionally, all of the inter-library dependencies of the convenience libraries (-lm, from library.la) are propagated to liberror.la.

     A common difficulty people experience with Automake is knowing when to use a LIBADD primary versus a LDADD primary.  A useful mnemonic is: LIBADD is for ADDitional LIBrary objects. LDADD is for ADDitional linker (LD) objects.

The executable, convenience, is built from main.c, and requires only liberror.la.  All of the other implicit dependencies are encoded within liberror.la.  Here is main.c:

     m4_include(examples/convenience/main.texi)

The only file that remains before you can compile the example is configure.in:

     m4_include(examples/convenience/configure.texi)

There are checks for all of the features used by the sources in the project: math.h and either string.h or strings.h; the existence of strrchr (after the tests for string headers); adding basename.o to LIBOBJS if there is no system implementation; and the shell code to set LTLIBOBJS.

With all the files in place, you can now bootstrap the project:

     $ ls -R
     .:
     Makefile.am  configure.in  error.c  error.h  lib  main.c  replace

     lib:
     Makefile.am  source.c  source.h

     replace:
     Makefile.am  basename.c

     $ aclocal
     $ autoheader

     $ automake --add-missing --copy
     automake: configure.in: installing `./install-sh'
     automake: configure.in: installing `./mkinstalldirs'
     automake: configure.in: installing `./missing'
     configure.in: 7: required file `./ltconfig' not found

     $ autoconf

     $ ls -R
     .:
     Makefile.am   config.h.in   error.c     ltconfig   mkinstalldirs
     Makefile.in   config.sub    error.h     ltmain.sh  replace
     aclocal.m4    configure     install-sh  main.c
     config.guess  configure.in  lib         missing

     lib:
     Makefile.am  Makefile.in  source.c  source.h

     replace:
     Makefile.am  Makefile.in  basename.c

With these files in place, the package can now be configured:

     $ ./configure
     ...
     checking how to run the C preprocessor... gcc -E
     checking for math.h... yes

     checking for string.h... yes
     checking for strrchr... yes
     checking for basename... yes
     updating cache ./config.cache
     creating ./config.status
     creating replace/Makefile

     creating lib/Makefile
     creating Makefile
     creating config.h

Notice that my host has an implementation of basename().

Here are the highlights of the compilation itself:

     $ make
     Making all in replace
     make[1]: Entering directory `/tmp/replace'
     /bin/sh ../libtool --mode=link gcc  -g -O2  -o libreplace.la
     rm -fr .libs/libreplace.la .libs/libreplace.* .libs/libreplace.*
     ar cru .libs/libreplace.al
     ranlib .libs/libreplace.al
     creating libreplace.la
     (cd .libs && rm -f libreplace.la && ln -s ../libreplace.la \
     libreplace.la)
     make[1]: Leaving directory `/tmp/replace'

Here the build descends into the replace subdirectory and creates libreplace.la, which is empty on my host since I don't need an implementation of basename():

     Making all in lib
     make[1]: Entering directory `/tmp/lib'
     /bin/sh ../libtool --mode=compile gcc -DHAVE_CONFIG_H  -I. -I. \
     -g -O2 -c source.c
     rm -f .libs/source.lo
     gcc -DHAVE_CONFIG_H -I. -I. -g -O2 -c -fPIC -DPIC source.c \
     -o .libs/source.lo
     gcc -DHAVE_CONFIG_H -I. -I. -g -O2 -c source.c \
     -o source.o >/dev/null 2>&1
     mv -f .libs/source.lo source.lo
     /bin/sh ../libtool --mode=link gcc  -g -O2  -o library.la source.lo -lm
     rm -fr .libs/library.la .libs/library.* .libs/library.*
     ar cru .libs/library.al source.lo
     ranlib .libs/library.al
     creating library.la
     (cd .libs && rm -f library.la && ln -s ../library.la library.la)
     make[1]: Leaving directory `/tmp/lib'

Next, the build enters the lib subdirectory to build library.la.  The configure preprocessor macros are passed on the command line, since no config.h was created by AC_CONFIG_HEADER:

     Making all in .
     make[1]: Entering directory `/tmp'
     /bin/sh ./libtool --mode=compile gcc -DHAVE_CONFIG_H -I. -I. -I./lib \
     -g -O2 -c error.c
     mkdir .libs
     gcc -DHAVE_CONFIG_H -I. -I. -I./lib -g -O2 -Wp,-MD,.deps/error.pp -c \
     -fPIC -DPIC error.c -o .libs/error.lo
     error.c: In function `set_program_name':
     error.c:20: warning: assignment makes pointer from integer without cast

     gcc -DHAVE_CONFIG_H -I. -I. -I./lib -g -O2 -Wp,-MD,.deps/error.pp -c \
     error.c -o error.o >/dev/null 2>&1
     mv -f .libs/error.lo error.lo

     /bin/sh ./libtool --mode=link gcc  -g -O2  -o liberror.la -rpath \
     /usr/local/lib -no-undefined -version-info 0:0:0 error.lo \
     replace/libreplace.la lib/library.la
     rm -fr .libs/liberror.la .libs/liberror.* .libs/liberror.*
     gcc -shared  error.lo -Wl,--whole-archive replace/.libs/libreplace.al \
     lib/.libs/library.al -Wl,--no-whole-archive  \
     replace/.libs/libreplace.al lib/.libs/library.al -lc  -Wl,-soname \
     -Wl,liberror.so.0 -o .libs/liberror.so.0.0.0

     (cd .libs && rm -f liberror.so.0 && ln -s liberror.so.0.0.0 \
     liberror.so.0)
     (cd .libs && rm -f liberror.so && ln -s liberror.so.0.0.0 liberror.so)
     rm -fr .libs/liberror.lax
     mkdir .libs/liberror.lax
     rm -fr .libs/liberror.lax/libreplace.al
     mkdir .libs/liberror.lax/libreplace.al
     (cd .libs/liberror.lax/libreplace.al && ar x \
     /tmp/replace/.libs/libreplace.al)
     rm -fr .libs/liberror.lax/library.al
     mkdir .libs/liberror.lax/library.al
     (cd .libs/liberror.lax/library.al && ar x \
     /tmp/lib/.libs/library.al)

     ar cru .libs/liberror.a error.o .libs/liberror.lax/library.al/source.lo
     ranlib .libs/liberror.a
     rm -fr .libs/liberror.lax
     creating liberror.la
     (cd .libs && rm -f liberror.la && ln -s ../liberror.la liberror.la)

The resulting convenience library is an archive of the resulting PIC objects.  The inter-library dependency, -lm, is passed to libtool and, although not needed to create the convenience library, is stored in the pseudo-archive, library.la, to be used when another object links against it.

Also you can see the harmless compiler warning I mentioned earlier, due to the missing declaration for basename().  Notice how libtool uses the --whole-archive option of GNU ld to link the convenience library contents directly into liberror.so, but extracts the PIC objects from each of the convenience libraries so that a new liberror.a can be made from them.  Unfortunately, this means that the resulting static archive component of liberror.la has a mixture of PIC and non-PIC objects.  In a future release of libtool, this will be addressed by tracking both types of objects in the convenience archive if necessary, and using the correct type of object depending on context.

Here, main.c is compiled (not to a Libtool object, since it is not compiled using libtool), and linked with the liberror.la Libtool library:

     gcc -DHAVE_CONFIG_H -I. -I.  -I./lib  -g -O2 -c main.c
     /bin/sh ./libtool --mode=link gcc  -g -O2  -o convenience  main.o \
     liberror.la
     gcc -g -O2 -o .libs/convenience main.o ./.libs/liberror.so -lm \
     -Wl,--rpath -Wl,/usr/local/lib
     creating convenience
     make[1]: Leaving directory `/tmp/convenience'

libtool calls gcc to link the convenience executable from main.o and the shared library component of liberror.la.  libtool also links with -lm, the propagated inter-library dependency of the library.la convenience library.  Since libreplace.la and library.la were convenience libraries, their objects are already present in liberror.la, so they are not listed again in the final link line -- the whole point of convenience archives.

This just shows that it all works:

     $ ls
     Makefile      config.h       configure.in  install-sh   main.c
     Makefile.am   config.h.in    convenience   lib          main.o
     Makefile.in   config.log     error.c       liberror.la  missing
     aclocal.m4    config.status  error.h       libtool      mkinstalldirs
     config.cache  config.sub     error.lo      ltconfig     replace
     config.guess  configure      error.o       ltmain.sh

     $ libtool --mode=execute ldd convenience
             liberror.so.0 => /tmp/.libs/liberror.so.0 (0x40014000)
             libm.so.6 => /lib/libm.so.6 (0x4001c000)
             libc.so.6 => /lib/libc.so.6 (0x40039000)
             /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)
     $ ./convenience
     cos (0) => 1
     lt-convenience: ERROR: This program does nothing!

Notice that you are running the uninstalled executable, which is in actual fact a wrapper script, see Executing Uninstalled Binaries. That is why you need to use libtool to run ldd on the real executable.  The uninstalled executable called by the wrapper script is called lt-convenience, hence the output from basename().

Finally, you can see from the output of ldd, that convenience really isn't linked against either library.la and libreplace.la.