This is an attempt to rewrite the "Building a Shared Library" section of the manual, in order to answer some recent questions about Libtool libraries (notably "gathering convenience libraries", "conditional compilation using .lo files", and "foo.lo build both with libtool and without").
All these examples ought be backed up with test cases, but I haven't yet got around to do it. By the meantime, comments and corrections (related to English or to Automake...) are greatly welcome. ------------------------------ Building a Shared Library ========================= Building shared libraries is a relatively complex matter. For this reason, GNU Libtool (*note Introduction: (libtool)Top.) was created to help build shared libraries in a platform-independent way. Presentation of Libtool ----------------------- Actually, Libtool abstracts shared and static libraries into an unified concept henceforth called "Libtool libraries". Libtool libraries are files using the `.la' suffix, and can designate a static library, a shared library, or maybe both. What exactly it is, you cannot know before `./configure'-time: not all platforms support all kinds of libraries, and users can explicitly select which libraries should be built. (However the package's maintainers can tune the default, *Note The `AC_PROG_LIBTOOL' macro: (Libtool)AC_PROG_LIBTOOL.) Because object files for shared and static libraries must be compiled differently, Libtool also uses its own abstraction: "Libtool objects". These are files ending with the `.lo' suffix. Libtool libraries are built with Libtool objects. People considering writing a plug-in system, with dynamically loaded modules, should look into `libltdl': Libtool's dlopening library (*note Using libltdl: (libtool)Using libltdl.). This offers a portable dlopening facility to load Libtool libraries dynamically, and can also achieve static linking where unavoidable. Before we discuss how to use Libtool with Automake in details, it should be noted that the Libtool manual also has a section about how to use Automake with Libtool (*note Using Automake with Libtool: (libtool)Using Automake.). Building Libtool libraries -------------------------- Automake uses Libtool to build libraries declared with the `LTLIBRARIES' primary. Each `_LTLIBRARIES' variable is a list of Libtool library to build. For instance, to create a Libtool library named `libgettext.la', and install it in `libdir', write: lib_LTLIBRARIES = libgettext.la libgettext_la_SOURCES = gettext.c gettext.h ... Automake predefines the variable `pkglibdir', so you can use `pkglib_LTLIBRARIES' to install libraries in `$(libdir)/@PACKAGE@/'. Building conditional Libtool libraries -------------------------------------- As for conditional programs (*note Conditional Programs::), there are two main ways to build conditonal libraries: using Automake conditionals or using Autoconf `AC_SUBST'itutions. The important implementation detail you have to know is that the place where a library will be installed matters to Libtool: it needs to be indicated _at link-time_ using the `-rpath' option. For libraries whose destinations directory is known by the time Automake runs, Automake will automatically supply the appropriate `-rpath' option to Libtool. This is the case for libraries listed explicitly in some `DIR_LTLIBRARIES' variable. However, for libraries determined at configure time (and thus mentioned in `EXTRA_LTLIBRARIES'), Automake does not know the eventual installation directory. For such libraries you must add the `-rpath' option to the appropriate `_LDFLAGS' variable by hand. You can see this difference by comparing these two ways to build Libtool libraries conditionally. Here is an example where `$(WANTEDLIBS)' is an `AC_SUBST'ed variable set at `./configure'-time to either `libfoo.la', `libbar.la', both, or none. Although `$(WANTEDLIBS)' appears in the `lib_LTLIBRARIES', Automake cannot guess it relates to `libfoo.la' or `libbar.la' by the time it creates the link rule for these two libraries. Therefore the `-rpath' argument must be explicitly supplied. EXTRA_LTLIBRARIES = libfoo.la libbar.la lib_LTLIBRARIES = $(WANTEDLIBS) libfoo_la_SOURCES = foo.c ... libfoo_LDFLAGS = -rpath '$(libdir)' libbar_la_SOURCES = bar.c ... libbar_LDFLAGS = -rpath '$(libdir)' Here is how the same `Makefile.am' would look using Automake conditionals named `WANT_LIBFOO' and `WANT_LIBBAR'. Now Automake is able to compute the `-rpath' setting itself, because it's clear that both libraries will end up in `$(libdir)' if they are installed. lib_LTLIBRARIES = if WANT_LIBFOO lib_LTLIBRARIES += libfoo.la endif if WANT_LIBBAR lib_LTLIBRARIES += libbar.la endif libfoo_la_SOURCES = foo.c ... libbar_la_SOURCES = bar.c ... Libtool libraries with conditional sources ------------------------------------------ Conditional compilation of sources in a library can be achieved in the same way as conditional compilation of sources in a program (*note Conditional Sources::). The only difference is that `_LIBADD' should be used instead of `_LDADD' and that it should mention Libtool objects (`.lo' files). So, to mimic the `hello' example from *Note Conditional Sources::, we could build a `libhello.la' library using either `hello-linux.c' or `hello-generic.c' with the following `Makefile.am'. lib_LTLIBRARIES = libhello.la libhello_la_SOURCES = hello-common.c EXTRA_libhello_la_SOURCES = hello-linux.c hello-generic.c libhello_la_LIBADD = $(HELLO_SYSTEM) libhello_la_DEPENDENCIES = $(HELLO_SYSTEM) And make sure `$(HELLO_SYSTEM)' is set to either `hello-linux.lo' or `hello-generic.lo' in `./configure'. Or we could simply use an Automake conditional as follows. lib_LTLIBRARIES = libhello.la if LINUX libhello_la_SOURCES = hello-linux.c hello-common.c else libhello_la_SOURCES = hello-generic.c hello-common.c endif Libtool convenience libraries ----------------------------- Sometime you want to build Libtool libraries which are not to be installed. These are called "Libtool convenience libraries" and are usually used to encapsulate many sublibraries, latter gathered into one big installed library. Libtool convenience libraries are declared by `noinst_LTLIBRARIES', `check_LTLIBRARIES', or even `EXTRA_LTLIBRARIES'. Unlike installed Libtool libraries they do not need an `-rpath' flag at link time (actually this is the only difference). Convenience libraries listed in `noinst_LTLIBRARIES' are always built. Those listed in `check_LTLIBRARIES' are built only upon `make check'. Finally, libraries listed in `EXTRA_LTLIBRARIES' are never built explicitely: Automake outputs rules to build them, but if the library does not appears as a Makefile dependency anywhere it won't be built (this is why `EXTRA_LTLIBRARIES' is used for conditional compilation). Here is an sample setup merging Libtool convenience libraries from subdirectories into one main `libtop.la' library. # -- Top-level Makefile.am -- SUBDIRS = sub1 sub2 ... lib_LTLIBRARIES = libtop.la libtop_la_SOURCES = libtop_la_LIBADD = \ sub1/libsub1.la \ sub2/libsub2.la \ ... # -- sub1/Makefile.am -- noinst_LTLIBRARIES = libsub1.la libsub1_la_SOURCES = ... # -- sub2/Makefile.am -- # showing nested convenience libraries SUBDIRS = sub2.1 sub2.2 ... noinst_LTLIBRARIES = libsub2.la libsub2_la_SOURCES = libsub2_la_LIBADD = \ sub2.1/libsub1.2.la \ sub2.2/libsub2.2.la \ ... Libtool modules --------------- These are Libtool libraries meant to be dlopened. They are indicated to Libtool by passing `-module' at link-time. pkglib_LTLIBRARIES = mymodule.la mymodule_la_SOURCES = doit.c mymodule_LDFLAGS = -module Ordinarily, Automake requires that a Library's name starts with `lib'. However, when building a dynamically loadable module you might wish to use a "nonstandard" name. _LIBADD and _LDFLAGS -------------------- As shown in previous sections, the `LIBRARY_LIBADD' variable should be used to list extra Libtool objects (`.lo' files) or Libtool libraries (`.la') to add to LIBRARY. The `LIBRARY_LDFLAGS' variable is the place to list additional libtool flags, such as `-version-info', `-static', and a lot more. See *Note Using libltdl: (libtool)Link mode. `LTLIBOBJS' ----------- Where an ordinary library might include `$(LIBOBJS)', a libtool library must use `$(LTLIBOBJS)'. This is required because the object files that libtool operates on do not necessarily end in `.o'. Nowadays, the computation of `LTLIBOBJS' for `LIBOBJS' is performed automatically by Autoconf (*note `AC_LIBOBJ' vs. `LIBOBJS': (autoconf)AC_LIBOBJ vs LIBOBJS.). The `created with both libtool and without' issue ------------------------------------------------- Sometimes, the same source file is used both to build a Libtool library and to build a program or another (non Libtool) library. Let's consider the following `Makefile.am'. bin_PROGRAMS = prog prog_SOURCES = prog.c foo.c ... lib_LTLIBRARIES = libfoo.la libfoo_la_SOURCES = foo.c ... (In this trivial case the issue could be avoided by linking `libfoo.la' with `prog' instead of listing `foo.c' in `prog_SOURCES'. But let's assume we really want to keep these program and library separate.) Technically, it means that we should build `foo.$(OBJEXT)' for `prog', and `foo.lo' for `libfoo.la'. The problem is that when Libtool creates `foo.lo' it can erase `foo.$(OBJEXT)', and we really cannot help it. Therefore, when Automake detects this situation it will complain with a message such as object `foo.lo' created both with libtool and without A work around to this issue is to ensure that these two objects get different basenames. As explained in *note renamed objects::, this happens automatically when per-targets flags are used. bin_PROGRAMS = prog prog_SOURCES = prog.c foo.c ... prog_CFLAGS = $(AM_CFLAGS) lib_LTLIBRARIES = libfoo.la libfoo_la_SOURCES = foo.c ... Adding `prog_CFLAGS = $(AM_CFLAGS)' is almost a no-op, because when the `prog_CFLAGS' is defined, it is used instead of `AM_CFLAGS'. However as a side effect it will cause `prog.c' and `foo.c' to be compiled as `prog-prog.$(OBJEXT)' and `prog-foo.$(OBJEXT)' which solves the issue. -- Alexandre Duret-Lutz