11.6 How to distribute libltdl with your package

Even though libltdl is installed together with libtool, you may wish to include libltdl in the distribution of your package, for the convenience of users of your package that don’t have libtool or libltdl installed, or if you are using features of a very new version of libltdl that you don’t expect your users to have yet. In such cases, you must decide what flavor of libltdl you want to use: a convenience library or an installable libtool library.

The most simplistic way to add libltdl to your package is to copy all the libltdl source files to a subdirectory within your package and to build and link them along with the rest of your sources. To help you do this, the m4 macros for Autoconf are available in ltdl.m4. You must ensure that they are available in aclocal.m4 before you run Autoconf13. Having made the macros available, you must add a call to the ‘LTDL_INIT’ macro (after the call to ‘LT_INIT’) to your package’s configure.ac to perform the configure time checks required to build the library correctly. Unfortunately, this method has problems if you then try to link the package binaries with an installed libltdl, or a library that depends on libltdl, because of the duplicate symbol definitions. For example, ultimately linking against two different versions of libltdl, or against both a local convenience library and an installed libltdl is bad. Ensuring that only one copy of the libltdl sources are linked into any program is left as an exercise for the reader.

Macro: LT_CONFIG_LTDL_DIR (directory)

Declare directory to be the location of the libltdl source files, for libtoolize --ltdl to place them. See Invoking libtoolize, for more details. Provided that you add an appropriate LT_CONFIG_LTDL_DIR call in your configure.ac before calling libtoolize, the appropriate libltdl files will be installed automatically.

Macro: LTDL_INIT (options)
Macro: LT_WITH_LTDL
Macro: AC_WITH_LTDL

AC_WITH_LTDL and LT_WITH_LTDL are deprecated names for older versions of this macro; autoupdate will update your configure.ac file.

This macro adds the following options to the configure script:

--with-ltdl-include installed-ltdl-header-dir

The LTDL_INIT macro will look in the standard header file locations to find the installed libltdl headers. If LTDL_INIT can’t find them by itself, the person who builds your package can use this option to tell configure where the installed libltdl headers are.

--with-ltdl-lib installed-ltdl-library-dir

Similarly, the person building your package can use this option to help configure find the installed libltdl.la.

--with-included-ltdl

If there is no installed libltdl, or in any case if the person building your package would rather use the libltdl sources shipped with the package in the subdirectory named by LT_CONFIG_LTDL_DIR, they should pass this option to configure.

If the --with-included-ltdl is not passed at configure time, and an installed libltdl is not found14, then configure will exit immediately with an error that asks the user to either specify the location of an installed libltdl using the --with-ltdl-include and --with-ltdl-lib options, or to build with the libltdl sources shipped with the package by passing --with-included-ltdl.

If an installed libltdl is found, then LIBLTDL is set to the link flags needed to use it, and LTDLINCL to the preprocessor flags needed to find the installed headers, and LTDLDEPS will be empty. Note, however, that no version checking is performed. You should manually check for the libltdl features you need in configure.ac:

LT_INIT([dlopen])
LTDL_INIT

# The lt_dladvise_init symbol was added with libtool-2.2
if test yes != "$with_included_ltdl"; then
  save_CFLAGS=$CFLAGS
  save_LDFLAGS=$LDFLAGS
  CFLAGS="$CFLAGS $LTDLINCL"
  LDFLAGS="$LDFLAGS $LIBLTDL"
  AC_CHECK_LIB([ltdl], [lt_dladvise_init],
                [],
        [AC_MSG_ERROR([installed libltdl is too old])])
  LDFLAGS=$save_LDFLAGS
  CFLAGS=$save_CFLAGS
fi

options may include no more than one of the following build modes depending on how you want your project to build libltdl: ‘nonrecursive’, ‘recursive’, or ‘subproject’. In order for libtoolize to detect this option correctly, if you supply one of these arguments, they must be given literally (i.e., macros or shell variables that expand to the correct ltdl mode will not work).

nonrecursive

This is how the Libtool project distribution builds the libltdl we ship and install. If you wish to use Automake to build libltdl without invoking a recursive make to descend into the libltdl subdirectory, then use this option. You will need to set your configuration up carefully to make this work properly, and you will need releases of Autoconf and Automake that support subdir-objects and LIBOBJDIR properly. In your configure.ac, add:

AM_INIT_AUTOMAKE([subdir-objects])
AC_CONFIG_HEADERS([config.h])
LT_CONFIG_LTDL_DIR([libltdl])
LT_INIT([dlopen])
LTDL_INIT([nonrecursive])

You have to use a config header, but it may have a name different than config.h.

Also, add the following near the top of your Makefile.am:

AM_CPPFLAGS =
AM_LDFLAGS =

BUILT_SOURCES =
EXTRA_DIST =
CLEANFILES =
MOSTLYCLEANFILES =

include_HEADERS =
noinst_LTLIBRARIES =
lib_LTLIBRARIES =
EXTRA_LTLIBRARIES =

include libltdl/ltdl.mk

Unless you build no other libraries from this Makefile.am, you will also need to change lib_LTLIBRARIES to assign with ‘+=’ so that the libltdl targets declared in ltdl.mk are not overwritten.

recursive

This build mode still requires that you use Automake, but (in contrast with ‘nonrecursive’) uses the more usual device of starting another make process in the libltdl subdirectory. To use this mode, you should add to your configure.ac:

AM_INIT_AUTOMAKE
AC_CONFIG_HEADERS([config.h])
LT_CONFIG_LTDL_DIR([libltdl])
LT_INIT([dlopen])
LTDL_INIT([recursive])
AC_CONFIG_FILES([libltdl/Makefile])

Again, you have to use a config header, but it may have a name different than config.h if you like.

Also, add this to your Makefile.am:

SUBDIRS = libltdl
subproject

This mode is the default unless you explicitly add recursive or nonrecursive to your LTDL_INIT options; subproject is the only mode supported by previous releases of libltdl. Even if you do not use Autoconf in the parent project, then, in ‘subproject’ mode, still libltdl contains all the necessary files to configure and build itself – you just need to arrange for your build system to call libltdl/configure with appropriate options, and then run make in the libltdl subdirectory.

If you are using Autoconf and Automake, then you will need to add the following to your configure.ac:

LT_CONFIG_LTDL_DIR([libltdl])
LTDL_INIT

and to Makefile.am:

SUBDIRS = libltdl

Aside from setting the libltdl build mode, there are other keywords that you can pass to LTDL_INIT to modify its behavior when --with-included-ltdl has been given:

convenience

This is the default unless you explicitly add installable to your LTDL_INIT options.

This keyword will cause options to be passed to the configure script in the subdirectory named by LT_CONFIG_LTDL_DIR to cause it to be built as a convenience library. If you’re not using automake, you will need to define top_build_prefix, top_builddir, and top_srcdir in your makefile so that LIBLTDL, LTDLDEPS, and LTDLINCL expand correctly.

One advantage of the convenience library is that it is not installed, so the fact that you use libltdl will not be apparent to the user, and it won’t overwrite a pre-installed version of libltdl the system might already have in the installation directory. On the other hand, if you want to upgrade libltdl for any reason (e.g. a bugfix) you’ll have to recompile your package instead of just replacing the shared installed version of libltdl. However, if your programs or libraries are linked with other libraries that use such a pre-installed version of libltdl, you may get linker errors or run-time crashes. Another problem is that you cannot link the convenience library into more than one libtool library, then link a single program with those libraries, because you may get duplicate symbols. In general you can safely use the convenience library in programs that don’t depend on other libraries that might use libltdl too.

installable

This keyword will pass options to the configure script in the subdirectory named by LT_CONFIG_LTDL_DIR to cause it to be built as an installable library. If you’re not using automake, you will need to define top_build_prefix, top_builddir and top_srcdir in your makefile so that LIBLTDL, LTDLDEPS, and LTDLINCL are expanded properly.

Be aware that you could overwrite another libltdl already installed to the same directory if you use this option.

Whatever method you use, ‘LTDL_INIT’ will define the shell variable LIBLTDL to the link flag that you should use to link with libltdl, the shell variable LTDLDEPS to the files that can be used as a dependency in Makefile rules, and the shell variable LTDLINCL to the preprocessor flag that you should use to compile programs that include ltdl.h. So, when you want to link a program with libltdl, be it a convenience, installed or installable library, just use ‘$(LTDLINCL)’ for preprocessing and compilation, and ‘$(LIBLTDL)’ for linking.

You should probably also use the ‘dlopen’ option to LT_INIT in your configure.ac, otherwise libtool will assume no dlopening mechanism is supported, and revert to dlpreopening, which is probably not what you want. Avoid using the -static, -static-libtool-libs, or -all-static switches when linking programs with libltdl. This will not work on all platforms, because the dlopening functions may not be available for static linking.

The following example shows you how to embed an installable libltdl in your package. In order to use the convenience variant, just replace the LTDL_INIT option ‘installable’ with ‘convenience’. We assume that libltdl was embedded using ‘libtoolize --ltdl’.

configure.ac:

...
# Name the subdirectory that contains libltdl sources
LT_CONFIG_LTDL_DIR([libltdl])

# Configure libtool with dlopen support if possible
LT_INIT([dlopen])

# Enable building of the installable libltdl library
LTDL_INIT([installable])
...

Makefile.am:

...
SUBDIRS = libltdl

AM_CPPFLAGS = $(LTDLINCL)

myprog_LDFLAGS = -export-dynamic
myprog_LDADD = $(LIBLTDL) -dlopen self -dlopen foo1.la
myprog_DEPENDENCIES = $(LTDLDEPS) foo1.la
...
Macro: LTDL_INSTALLABLE
Macro: AC_LIBLTDL_INSTALLABLE

These macros are deprecated, the ‘installable’ option to LTDL_INIT should be used instead.

Macro: LTDL_CONVENIENCE
Macro: AC_LIBLTDL_CONVENIENCE

These macros are deprecated, the ‘convenience’ option to LTDL_INIT should be used instead.


Footnotes

(13)

We used to recommend adding the contents of ltdl.m4 to acinclude.m4, but with aclocal from a modern Automake (1.8 or newer) and this release of libltdl that is not only unnecessary but makes it easy to forget to upgrade acinclude.m4 if you move to a different release of libltdl.

(14)

Even if libltdl is installed, ‘LTDL_INIT’ may fail to detect it if libltdl depends on symbols provided by libraries other than the C library.