Autoconf, Automake, and Libtool: Using Libtool Libraries

| ## 12.1 Using Libtool Libraries As you have seen, It is very easy to convert `automake` built static libraries to `automake` built Libtool libraries. In order to build ``libsic'` as a Libtool library, I have changed the name of the library from ``libsic.a'` (the old archive name in Libtool terminology) to ``libsic.la'` (the pseudo-library), and must use the `LTLIBRARIES` Automake primary:
    lib_LTLIBRARIES         = libsic.la
    libsic_la_LIBADD        = $(top_builddir)/replace/libreplace.la
    libsic_la_SOURCES       = builtin.c error.c eval.c list.c sic.c \
                            syntax.c xmalloc.c xstrdup.c xstrerror.c
Notice the ``la'` in `libsic_la_SOURCES` is new too. It is similarly easy to take advantage of Libtool convenience libraries. For the purposes of Sic, ``libreplace'` is an ideal candidate for this treatment -- I can create the library as a separate entity from selected sources in their own directory, and add those objects to ``libsic'`. This technique ensures that the installed library has all of the support functions it needs without having to link ``libreplace'` as a separate object. In ``replace/Makefile.am'`, I have again changed the name of the library from ``libreplace.a'` to ``libreplace.la'`, and changed the automake primary from ``LIBRARIES'` to ``LTLIBRARIES'`. Unfortunately, those changes alone are insufficient. Libtool libraries are compiled from Libtool objects (which have the ``.lo'` suffix), so I cannot use ``LIBOBJS'` which is a list of ``.o'` suffixed objects(22). See section 11.1.2 Extra Macros for Libtool, for more details. Here is ``replace/Makefile.am'`:
    MAINTAINERCLEANFILES    = Makefile.in

    noinst_LTLIBRARIES      = libreplace.la
    libreplace_la_SOURCES   =
    libreplace_la_LIBADD    = @LTLIBOBJS@
And not forgetting to set and use the ``LTLIBOBJS'` configure substitution (see section 11.1.2 Extra Macros for Libtool):
    Xsed="sed -e s/^X//"
    LTLIBOBJS=echo X"$LIBOBJS" | \
        [$Xsed -e s,\.[^.]* ,.lo ,g;s,\.[^.]*$,.lo,']
    AC_SUBST(LTLIBOBJS)
As a consequence of using `libtool` to build the project libraries, the increasing number of configuration files being added to the ``config'` directory will grow to include ``ltconfig'` and ``ltmain.sh'`. These files will be used on the installer's machine when Sic is configured, so it is important to distribute them. The naive way to do it is to give the ``config'` directory a ``Makefile.am'` of its own; however, it is not too difficult to distribute these files from the top ``Makefile.am'`, and it saves clutter, as you can see here:
    AUX_DIST                = $(ac_aux_dir)/config.guess \
                            $(ac_aux_dir)/config.sub \
                            $(ac_aux_dir)/install-sh \
                            $(ac_aux_dir)/ltconfig \
                            $(ac_aux_dir)/ltmain.sh \
                            $(ac_aux_dir)/mdate-sh \
                            $(ac_aux_dir)/missing \
                            $(ac_aux_dir)/mkinstalldirs
    AUX_DIST_EXTRA          = $(ac_aux_dir)/readline.m4 \
                            $(ac_aux_dir)/sys_errlist.m4 \
                            $(ac_aux_dir)/sys_siglist.m4
    EXTRA_DIST                = bootstrap

    MAINTAINERCLEANFILES         = Makefile.in aclocal.m4 configure config-h.in \
                            stamp-h.in $(AUX_DIST)

    dist-hook:
            (cd $(distdir) && mkdir $(ac_aux_dir))
            for file in $(AUX_DIST) $(AUX_DIST_EXTRA); do \
              cp $$file $(distdir)/$$file; \
            done
The ``dist-hook'` rule is used to make sure the ``config'` directory and the files it contains are correctly added to the distribution by the ``make dist'` rules, see section 13.1 Introduction to Distributions. I have been careful to use the `configure` script's location for `ac_aux_dir`, so that it is defined (and can be changed) in only one place. This is achieved by adding the following macro to ``configure.in'`:
    AC_SUBST(ac_aux_dir)
There is no need to explicitly set a macro in the ``Makefile.am'`, because Automake automatically creates macros for every value that you ``AC_SUBST'` from ``configure.in'`. I have also added the `AC_PROG_LIBTOOL` macro to ``configure.in'` in place of `AC_PROG_RANLIB` as described in 11. Using GNU Libtool with ``configure.in'` and ``Makefile.am'`. Now I can upgrade the configury to use `libtool` -- the greater part of this is running the `libtoolize` script that comes with the Libtool distribution. The `bootstrap` script then needs to be updated to run `libtoolize` at the correct juncture:
    #! /bin/sh

    set -x
    aclocal -I config
    libtoolize --force --copy
    autoheader
    automake --add-missing --copy
    autoconf
Now I can re-bootstrap the entire project so that it can make use of `libtool`:
    $ ./bootstrap
    + aclocal -I config
    + libtoolize --force --copy
    Putting files in AC_CONFIG_AUX_DIR, config.
    + autoheader
    + automake --add-missing --copy
    automake: configure.in: installing config/install-sh
    automake: configure.in: installing config/mkinstalldirs
    automake: configure.in: installing config/missing
    + autoconf
The new macros are evident by the new output seen when the newly regenerated `configure` script is executed:
    $ ./configure --with-readline
    ...
    checking host system type... i586-pc-linux-gnu
    checking build system type... i586-pc-linux-gnu
    checking for ld used by GCC... /usr/bin/ld
    checking if the linker (/usr/bin/ld) is GNU ld... yes
    checking for /usr/bin/ld option to reload object files... -r
    checking for BSD-compatible nm... /usr/bin/nm -B
    checking whether ln -s works... yes
    checking how to recognise dependent libraries... pass_all
    checking for object suffix... o
    checking for executable suffix... no
    checking for ranlib... ranlib
    checking for strip... strip
    ...
    checking if libtool supports shared libraries... yes
    checking whether to build shared libraries... yes
    checking whether to build static libraries... yes
    creating libtool
    ...
    $ make
    ...
    gcc -g -O2 -o .libs/sic sic.o sic_builtin.o sic_repl.o sic_syntax.o \
    ../sic/.libs/libsic.so -lreadline -Wl,--rpath -Wl,/usr/local/lib
    creating sic
    ...
    $ src/sic
    ] libtool --mode=execute ldd src/sic
        libsic.so.0 => /tmp/sic/sic/.libs/libsic.so.0 (0x40014000)
        libreadline.so.4 => /lib/libreadline.so.4 (0x4001e000)
        libc.so.6 => /lib/libc.so.6 (0x40043000)
        libncurses.so.5 => /lib/libncurses.so.5 (0x40121000)
        /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)
    ] exit
    $
As you can see, `sic` is now linked against a shared library build of ``libsic'`, but not directly against the convenience library, ``libreplace'`.

This document was generated by Gary V. Vaughan on February, 8 2006 using texi2html