[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10. Using libltdl

Libtool provides a small library, called `libltdl', that aims at hiding the various difficulties of dlopening libraries from programmers. It consists of a header-file and a small C source file that can be distributed with applications that need dlopening functionality. On some platforms, whose dynamic linkers are too limited for a simple implementation of `libltdl' services, it requires GNU DLD, or it will only emulate dynamic linking with libtool's dlpreopening mechanism.

libltdl supports currently the following dynamic linking mechanisms:

libltdl is licensed under the terms of the GNU Library General Public License, with the following exception:

As a special exception to the GNU Lesser General Public License, if you distribute this file as part of a program or library that is built using GNU libtool, you may include it under the same distribution terms that you use for the rest of that program.

10.1 How to use libltdl in your programs  
10.2 Creating modules that can be dlopened  
10.3 Using libtldl in a multi threaded environment  Registering callbacks for multi-thread safety.
10.4 Data associated with loaded modules  Associating data with loaded modules.
10.5 How to create and register new module loaders  Creating user defined module loaders.
10.6 How to distribute libltdl with your package  


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10.1 How to use libltdl in your programs

The libltdl API is similar to the dlopen interface of Solaris and Linux, which is very simple but powerful.

To use libltdl in your program you have to include the header file `ltdl.h':

 
#include <ltdl.h>

The last release of libltdl used some symbols that violated the POSIX namespace conventions. These symbols are now deprecated, and have been replaced by those described here. If you have code that relies on the old deprecated symbol names, defining `LT_NON_POSIX_NAMESPACE' before you include `ltdl.h' provides conversion macros. Whichever set of symbols you use, the new api is not binary compatible with the last, so you will need to recompile your application in order to use this version of libltdl.

Note that libltdl is not threadsafe, i.e. a multithreaded application has to use a mutex for libltdl. It was reported that GNU/Linux's glibc 2.0's dlopen with `RTLD_LAZY' (which libltdl uses by default) is not thread-safe, but this problem is supposed to be fixed in glibc 2.1. On the other hand, `RTLD_NOW' was reported to introduce problems in multi-threaded applications on FreeBSD. Working around these problems is left as an exercise for the reader; contributions are certainly welcome.

The following types are defined in `ltdl.h':

Type: lt_ptr
lt_ptr is a generic pointer.

Type: lt_dlhandle
lt_dlhandle is a module "handle". Every lt_dlopened module has a handle associated with it.

Type: lt_dlsymlist
lt_dlsymlist is a symbol list for dlpreopened modules. This structure is described in see section 9.2 Dlpreopening.

libltdl provides the following functions:

Function: int lt_dlinit (void)
Initialize libltdl. This function must be called before using libltdl and may be called several times. Return 0 on success, otherwise the number of errors.

Function: int lt_dlexit (void)
Shut down libltdl and close all modules. This function will only then shut down libltdl when it was called as many times as lt_dlinit has been successfully called. Return 0 on success, otherwise the number of errors.

Function: lt_dlhandle lt_dlopen (const char *filename)
Open the module with the file name filename and return a handle for it. lt_dlopen is able to open libtool dynamic modules, preloaded static modules, the program itself and native dynamic libraries.

Unresolved symbols in the module are resolved using its dependency libraries (not implemented yet) and previously dlopened modules. If the executable using this module was linked with the -export-dynamic flag, then the global symbols in the executable will also be used to resolve references in the module.

If filename is NULL and the program was linked with -export-dynamic or -dlopen self, lt_dlopen will return a handle for the program itself, which can be used to access its symbols.

If libltdl cannot find the library and the file name filename does not have a directory component it will additionally search in the following search paths for the module (in the order as follows):

  1. user-defined search path: This search path can be set by the program using the functions lt_dlsetsearchpath and lt_dladdsearchdir.

  2. libltdl's search path: This search path is the value of the environment variable LTDL_LIBRARY_PATH.

  3. system library search path: The system dependent library search path (e.g. on Linux it is LD_LIBRARY_PATH).

Each search path must be a colon-separated list of absolute directories, for example, "/usr/lib/mypkg:/lib/foo".

If the same module is loaded several times, the same handle is returned. If lt_dlopen fails for any reason, it returns NULL.

Function: lt_dlhandle lt_dlopenext (const char *filename)
The same as lt_dlopen, except that it tries to append different file name extensions to the file name. If the file with the file name filename cannot be found libltdl tries to append the following extensions:

  1. the libtool archive extension `.la'
  2. the extension used for native dynamic libraries on the host platform, e.g., `.so', `.sl', etc.

This lookup strategy was designed to allow programs that don't have knowledge about native dynamic libraries naming conventions to be able to dlopen such libraries as well as libtool modules transparently.

Function: int lt_dlclose (lt_dlhandle handle)
Decrement the reference count on the module handle. If it drops to zero and no other module depends on this module, then the module is unloaded. Return 0 on success.

Function: lt_ptr lt_dlsym (lt_dlhandle handle, const char *name)
Return the address in the module handle, where the symbol given by the null-terminated string name is loaded. If the symbol cannot be found, NULL is returned.

Function: {const char *}lt_dlerror (void)
Return a human readable string describing the most recent error that occurred from any of libltdl's functions. Return NULL if no errors have occurred since initialization or since it was last called.

Function: int lt_dlpreload (const lt_dlsymlist *preloaded)
Register the list of preloaded modules preloaded. If preloaded is NULL, then all previously registered symbol lists, except the list set by lt_dlpreload_default, are deleted. Return 0 on success.

Function: int lt_dlpreload_default (const lt_dlsymlist *preloaded)
Set the default list of preloaded modules to preloaded, which won't be deleted by lt_dlpreload. Note that this function does not require libltdl to be initialized using lt_dlinit and can be used in the program to register the default preloaded modules. Instead of calling this function directly, most programs will use the macro LTDL_SET_PRELOADED_SYMBOLS.

Return 0 on success.

Macro: LTDL_SET_PRELOADED_SYMBOLS()
Set the default list of preloaded symbols. Should be used in your program to initialize libltdl's list of preloaded modules.

 
#include <ltdl.h>

int main() {
  /* ... */
  LTDL_SET_PRELOADED_SYMBOLS();
  /* ... */
}

Function: int lt_dladdsearchdir (const char *search_dir)
Add the search directory search_dir to the user-defined library search path. Return 0 on success.

Function: int lt_dlsetsearchpath (const char *search_path)
Replace the current user-defined library search path with search_path, which must be a colon-separated list of absolute directories. Return 0 on success.

Function: {const char *}lt_dlgetsearchpath (void)
Return the current user-defined library search path.

Function: int lt_dlmakeresident (lt_dlhandle handle)
Mark a module so that it cannot be `lt_dlclose'd. This can be useful if a module implements some core functionality in your project, which would cause your code to crash if removed. Return 0 on success.

If you use `lt_dlopen (NULL)' to get a handle for the running binary, that handle will always be marked as resident, and consequently cannot be successfully `lt_dlclose'd.

Function: int lt_dlisresident (lt_dlhandle handle)
Check whether a particular module has been marked as resident, returning 1 if it has or 0 otherwise. If there is an error while executing this function, return -1 and set an error message for retrieval with lt_dlerror.

Variable: lt_ptr (*) (size_t size) lt_dlmalloc
Variable: void (*) (lt_ptr ptr) lt_dlfree
These variables are set to malloc and free, by default, but you can set them to any other functions that provides equivalent functionality. However, you must not modify their values after calling any libltdl function other than lt_dlpreopen_default or the macro LTDL_SET_PRELOADED_SYMBOLS.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10.2 Creating modules that can be dlopened

Libtool modules are like normal libtool libraries with a few exceptions:

You have to link the module with libtool's `-module' switch, and you should link any program that is intended to dlopen the module with `-dlopen modulename.la' so that libtool can dlpreopen the module on platforms which don't support dlopening. If the module depends on any other libraries, make sure you specify them either when you link the module or when you link programs that dlopen it. If you want to disable see section 6. Library interface versions for a specific module you should link it with the `-avoid-version' switch. Note that libtool modules don't need to have a "lib" prefix. However, automake 1.4 or higher is required to build such modules.

Usually a set of modules provide the same interface, i.e, exports the same symbols, so that a program can dlopen them without having to know more about their internals. In order to avoid symbol conflicts all exported symbols must be prefixed with "modulename_LTX_" (`modulename' is the name of the module). Internal symbols must be named in such a way that they won't conflict with other modules, for example, by prefixing them with "_modulename_". Although some platforms support having the same symbols defined more than once it is generally not portable and it makes it impossible to dlpreopen such modules. libltdl will automatically cut the prefix off to get the real name of the symbol. Additionally, it supports modules which don't use a prefix so that you can also dlopen non-libtool modules.

`foo1.c' gives an example of a portable libtool module. Exported symbols are prefixed with "foo1_LTX_", internal symbols with "_foo1_". Aliases are defined at the beginning so that the code is more readable.

 
/* aliases for the exported symbols */
#define foo	foo1_LTX_foo
#define bar	foo1_LTX_bar

/* a global variable definition */
int bar = 1;

/* a private function */
int _foo1_helper() {
  return bar;
}

/* an exported function */
int foo() {
  return _foo1_helper();
}

The `Makefile.am' contains the necessary rules to build the module `foo1.la':

 
...
lib_LTLIBRARIES = foo1.la

foo1_la_SOURCES = foo1.c
foo1_la_LDFLAGS = -module
...


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10.3 Using libtldl in a multi threaded environment

Using the lt_dlmutex_register() function, and by providing some appropriate callback function definitions, libltdl can be used in a multi-threaded environment.

Type: void lt_dlmutex_lock (void)
This is the type of a function pointer holding the address of a function which will be called at the start of parts of the libltdl implementation code which require a mutex lock.

Because libltdl is inherantly recursive, it is important that the locking mechanism employed by these callback functions are reentrant, or else strange problems will occur.

Type: void lt_dlmutex_unlock (void)
The type of a matching unlock function.

Type: void lt_dlmutex_seterror (const char *error);
Many of the functions in the libltdl API have a special return value to indicate to the client that an error has occured. Normally (in single threaded applications) a string describing that error can be retrieved from internal storage with lt_dlerror().

A function of this type must be registered with the library in order for it to work in a multi-threaded context. The function should store any error message passed in thread local storage.

Type: const char * lt_dlmutex_geterror (void)
The type of a matching callback function to retrieve the last stored error message from thread local storage.

When regeistered correctly this function will be used by lt_dlerror()) from all threads to retrieve error messages for the client.

Function: int lt_dlmutex_register (lt_dlmutex_lock *lock, lt_dlmutex_unlock *unlock, lt_dlmutex_set_error *seterror, lt_dlmutex_geterror *geterror)
Use this function to register one of each of function ttypes described above in preparation for multi-threaded use of libltdl. All arguments must be valid non-NULL function addresses, or else all NULL to return to single threaded operation.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10.4 Data associated with loaded modules

Some of the internal information about each loaded module that is maintained by libltdl is available to the user, in the form of this structure:

Type: struct lt_dlinfo { char *filename; char *name; int ref_count; }
lt_dlinfo is used to store information about a module. The filename attribute is a null-terminated character string of the real module file name. If the module is a libtool module then name is its module name (e.g. "libfoo" for "dir/libfoo.la"), otherwise it is set to NULL. The ref_count attribute is a reference counter that describes how often the same module is currently loaded.

The following function will return a pointer to libltdl's internal copy of this structure for the given handle:

Function: const lt_dlinfo * lt_dlgetinfo (lt_dlhandle handle)
Return a pointer to a struct that contains some information about the module handle. The contents of the struct must not be modified. Return NULL on failure.

Furthermore, in order to save you from having to keep a list of the handles of all the modules you have loaded, these functions allow you to iterate over libltdl's list of loaded modules:

Function: int lt_dlforeach (int (*func) (lt_dlhandle handle, lt_ptr data), lt_ptr data)
For each loaded module call the function func. The argument handle is the handle of one of the loaded modules, data is the data argument passed to lt_dlforeach. As soon as func returns a non-zero value for one of the handles, lt_dlforeach will stop calling func and immediately return 1. Otherwise 0 is returned.

Function: lt_dlhandle lt_dlhandle_next (lt_dlhandle place)
Iterate over the loaded module handles, returning the first handle in the list if place is NULL, and the next one on subsequent calls. If place is the last element in the list of loaded modules, this function returns NULL.

Of course, you would still need to maintain your own list of loaded module handles to parallel the list maintained by libltdl if there are any other data that you need to associate with each handle for the purposes of your application. However, if you use the following API calls to associate your application data with individual module handles as they are loaded there is actually no need to do that. You must first obtain a unique caller id from libltdl which you subsequently use to retrieve the data you stored earlier. This allows for different libraries that each wish to store their own data against loaded modules to do so without interfering with one another's data.

Type: lt_dlcaller_id
The opaque type used to hold individual data set keys.

Function: lt_dlcaller_id lt_dlcaller_register (void)
Use this to obtain a unique key to store and retrieve individual sets of per module data.

Function: lt_ptr lt_dlcaller_set_data (lt_dlcaller_id key, lt_dlhandle handle, lt_ptr data)
Set data as the set of data uniquely associated with key and handle for later retrieval. This function returns the data previously associated with key and handle if any. A result of 0, may indicate that a diagnostic for the last error (if any) is available from lt_dlerror().

For example, to correctly remove some associated data:

 
    lt_ptr stale = lt_dlcaller_set_data (key, handle, 0);
    if (stale == NULL)
      {
        char *error_msg = lt_dlerror ();

        if (error_msg != NULL)
          {
            my_error_handler (error_msg);
            return STATUS_FAILED;
          }
      }
    else
      {
        free (stale);
      }

Function: lt_ptr lt_dlcaller_get_data (lt_dlcaller_id key, lt_dlhandle handle)
Return the address of the data associated with key and handle, or else NULL if there is none.

The preceding functions can be combined with lt_dlforeach to implement search and apply operations without the need for your application to track the modules that have been loaded and unloaded:

 
int
my_dlcaller_callback (lt_dlhandle handle, lt_ptr key_ptr)
{
  struct my_module_data *my_data;

  my_data = lt_dlcaller_get_data (handle, (lt_dlcaller_id) *key_ptr);

  return process (my_data);
}

int
my_dlcaller_foreach (lt_dlcaller_id key)
{
  lt_dlforeach (my_dlcaller_callback, (lt_ptr) &key);
}


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10.5 How to create and register new module loaders

Sometimes libltdl's many ways of gaining access to modules are not sufficient for the purposes of a project. You can write your own loader, and register it with libltdl so that lt_dlopen will be able to use it.

Writing a loader involves writing at least three functions which can be called by lt_dlopen, lt_dlsym and lt_dlclose. Optionally, you can provide a finalisation function to perform any cleanup operations when lt_dlexit executes, and a symbol prefix string which will be prepended to any symbols passed to lt_dlsym. These functions must match the function pointer types below, after which they can be allocated to an instance of lt_user_dlloader and registered.

Registering the loader requires that you choose a name for it, so that it can be recognised by lt_dlloader_find and removed with lt_dlloader_remove. The name you choose must be unique, and not already in use by libltdl's builtin loaders:

"dlopen"
The system dynamic library loader, if one exists.
"dld"
The GNU dld loader, if `libdld' was installed when libltdl was built.
"dlpreload"
The loader for lt_dlopening of preloaded static modules.

The prefix "dl" is reserved for loaders supplied with future versions of libltdl, so you should not use that for your own loader names.

The following types are defined in `ltdl.h':

Type: lt_module
lt_module is a dlloader dependent module. The dynamic module loader extensions communicate using these low level types.

Type: lt_dlloader
lt_dlloader is a handle for module loader types.

Type: lt_dlloader_data
lt_dlloader_data is used for specifying loader instance data.

Type: struct lt_user_dlloader {const char *sym_prefix; lt_module_open *module_open;lt_module_close *module_close; lt_find_sym *find_sym; lt_dlloader_exit *dlloader_exit; lt_dlloader_data dlloader_data; }
If you want to define a new way to open dynamic modules, and have the lt_dlopen API use it, you need to instantiate one of these structures and pass it to lt_dlloader_add. You can pass whatever you like in the dlloader_data field, and it will be passed back as the value of the first parameter to each of the functions specified in the function pointer fields.

Type: lt_module lt_module_open (lt_user_data loader_data, const char *filename)
The type of the loader function for an lt_dlloader module loader. The value set in the dlloader_data field of the struct lt_user_dlloader structure will be passed into this function in the loader_data parameter. Implementation of such a function should attempt to load the named module, and return an lt_module suitable for passing in to the associated lt_module_close and lt_sym_find function pointers. If the function fails it should return NULL, and set the error message with lt_dlseterror.

Type: int lt_module_close (lt_dlloader_data loader_data, lt_module module)
The type of the unloader function for a user defined module loader. Implementatation of such a function should attempt to release any resources tied up by the module module, and then unload it from memory. If the function fails for some reason, set the error message with lt_dlseterror and return non-zero.

Type: lt_ptr lt_find_sym (lt_user_data loader_data, lt_module module, const char *symbol)
The type of the symbol lookup function for a user defined module loader. Implementation of such a function should return the address of the named symbol in the module module, or else set the error message with lt_dlseterror and return NULL if lookup fails.

Type: int lt_dlloader_exit (lt_user_data loader_data)
The type of the finalisation function for a user defined module loader. Implementation of such a function should free any resources associated with the loader, including any user specified data in the dlloader_data field of the lt_user_dlloader. If non-NULL, the function will be called by lt_dlexit, and lt_dlloader_remove.

For example:

 
int
register_myloader (void)
{
  lt_user_dlloader dlloader;

  /* User modules are responsible for their own initialisation. */
  if (myloader_init () != 0)
    return MYLOADER_INIT_ERROR;

  dlloader.sym_prefix    = NULL;
  dlloader.module_open   = myloader_open;
  dlloader.module_close  = myloader_close;
  dlloader.find_sym      = myloader_find_sym.
  dlloader.dlloader_exit = myloader_exit;
  dlloader.dlloader_data = (lt_user_data)myloader_function;

  /* Add my loader as the default module loader. */
  if (lt_dlloader_add (lt_dlloader_next (NULL), &dlloader, "myloader") != 0)
    return ERROR;

  return OK;
}

Note that if there is any initialisation required for the loader, it must be performed manually before the loader is registered -- libltdl doesn't handle user loader initialisation.

Finalisation is handled by libltdl however, and it is important to ensure the dlloader_exit callback releases any resources claimed during the initialisation phase.

libltdl provides the following functions for writing your own module loaders:

Function: int lt_dlloader_add (lt_dlloader *place, lt_user_dlloader *dlloader, const char *loader_name)
Add a new module loader to the list of all loaders, either as the last loader (if place is NULL), else immediately before the loader passed as place. loader_name will be returned by lt_dlloader_name if it is subsequently passed a newly registered loader. These loader_names must be unique, or lt_dlloader_remove and lt_dlloader_find cannot work. Returns 0 for success.

 
{
  /* Make myloader be the last one. */
  if (lt_dlloader_add (NULL, myloader) != 0)
    perror (lt_dlerror ());
}

Function: int lt_dlloader_remove (const char *loader_name)
Remove the loader identified by the unique name, loader_name. Before this can succeed, all modules opened by the named loader must have been closed. Returns 0 for success, otherwise an error message can be obtained from lt_dlerror.

 
{
  /* Remove myloader. */
  if (lt_dlloader_remove ("myloader") != 0)
    perror (lt_dlerror ());
}

Function: {lt_dlloader *}lt_dlloader_next (lt_dlloader *place)
Iterate over the module loaders, returning the first loader if place is NULL, and the next one on subsequent calls. The handle is for use with lt_dlloader_add.

 
{
  /* Make myloader be the first one. */
  if (lt_dlloader_add (lt_dlloader_next (NULL), myloader) != 0)
    return ERROR;
}

Function: {lt_dlloader *}lt_dlloader_find (const char *loader_name)
Return the first loader with a matching loader_name identifier, or else NULL, if the identifier is not found.

The identifiers which may be used by libltdl itself, if the host architecture supports them are dlopen(9), dld and dlpreload.

 
{
  /* Add a user loader as the next module loader to be tried if
     the standard dlopen loader were to fail when lt_dlopening. */
  if (lt_dlloader_add (lt_dlloader_find ("dlopen"), myloader) != 0)
    return ERROR;
}

Function: {const char *}lt_dlloader_name (lt_dlloader *place)
Return the identifying name of PLACE, as obtained from lt_dlloader_next or lt_dlloader_find. If this function fails, it will return NULL and set an error for retrieval with lt_dlerror.

Function: {lt_user_data *}lt_dlloader_data (lt_dlloader *place)
Return the address of the dlloader_data of PLACE, as obtained from lt_dlloader_next or lt_dlloader_find. If this function fails, it will return NULL and set an error for retrieval with lt_dlerror.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10.5.1 Error handling within user module loaders

Function: int lt_dladderror (const char *diagnostic)
This function allows you to integrate your own error messages into lt_dlerror. Pass in a suitable diagnostic message for return by lt_dlerror, and an error identifier for use with lt_dlseterror is returned.

If the allocation of an identifier fails, this function returns -1.

 
int myerror = lt_dladderror ("Doh!");
if (myerror < 0)
  perror (lt_dlerror ());

Function: int lt_dlseterror (int errorcode)
When writing your own module loaders, you should use this function to raise errors so that they are propogated through the lt_dlerror interface. All of the standard errors used by libltdl are declared in `ltdl.h', or you can add more of your own with lt_dladderror. This function returns 0 on success.

 
if (lt_dlseterror (LTDL_ERROR_NO_MEMORY) != 0)
  perror (lt_dlerror ());


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10.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. In this case, you must decide whether to manually add the ltdl objects to your package, or else which 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 the source files, `ltdl.c' and `ltdl.h', to a source directory withing 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 autoconf -- by appending the contents of `ltdl.m4' to `acinclude.m4', if you are using automake, or to `aclocal.m4' if you are not. Having made the macros available, you must add a call to the `AC_LIB_LTDL' macro to your package's `configure.in' to perform the configure time checks required to build `ltdl.o' correctly. This method has problems if you then try to link the package binaries with an installed libltdl, or a library which depends on libltdl: you may have problems with duplicate symbol definitions.

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 will not overwrite a pre-installed version of libltdl a user might have. 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 an 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 these libraries, because you may get duplicate symbols. In general you can safely use the convenience library in programs which don't depend on other libraries that might use libltdl too. In order to enable this flavor of libltdl, you should add the line `AC_LIBLTDL_CONVENIENCE' to your `configure.in', before `AC_PROG_LIBTOOL'.

In order to select the installable version of libltdl, you should add a call of the macro `AC_LIBLTDL_INSTALLABLE' to your `configure.in' before `AC_PROG_LIBTOOL'. This macro will check whether libltdl is already installed and, if not, request the libltdl embedded in your package to be built and installed. Note, however, that no version checking is performed. The user may override the test and determine that the libltdl embedded must be installed, regardless of the existence of another version, using the configure switch `--enable-ltdl-install'.

In order to embed libltdl into your package, just add `--ltdl' to the libtoolize command line. It will copy the libltdl sources to a subdirectory `libltdl' in your package. Both macros accept an optional argument to specify the location of the `libltdl' directory. By the default both macros assume that it is `${top_srcdir}/libltdl'.

Whatever macro you use, it is up to you to ensure that your `configure.in' will configure libltdl, using `AC_CONFIG_SUBDIRS', and that your `Makefile's will start sub-makes within libltdl's directory, using automake's SUBDIRS, for example. Both macros define the shell variables LIBLTDL, to the link flag that you should use to link with libltdl, and INCLTDL, to the preprocessor flag that you should use to compile with programs that include `ltdl.h'. It is up to you to use `AC_SUBST' to ensure that this variable will be available in `Makefile's, or add them to variables that are `AC_SUBST'ed by default, such as LIBS and CPPFLAGS.

If you're using the convenience libltdl, LIBLTDL will be the pathname for the convenience version of libltdl and INCLTDL will be `-I' followed by the directory that contains libltdl, both starting with `${top_builddir}/' or `${top_srcdir}/', respectively.

If you request an installed version of libltdl and one is found(10), LIBLTDL will be set to `-lltdl' and INCLTDL will be empty (which is just a blind assumption that `ltdl.h' is somewhere in the include path if libltdl is in the library path). If an installable version of libltdl must be built, its pathname, starting with `${top_builddir}/', will be stored in LIBLTDL, and INCLTDL will be set just like in the case of convenience library.

So, when you want to link a program with libltdl, be it a convenience, installed or installable library, just compile with `$(INCLTDL)' and link it with `$(LIBLTDL)', using libtool.

You should probably also add `AC_LIBTOOL_DLOPEN' to your `configure.in' before `AC_PROG_LIBTOOL', otherwise libtool will assume no dlopening mechanism is supported, and revert to dlpreopening, which is probably not what you want.

Avoid using the -static 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 the convenience libltdl in your package. In order to use the installable variant just replace `AC_LIBLTDL_CONVENIENCE' with `AC_LIBLTDL_INSTALLABLE'. We assume that libltdl was embedded using `libtoolize --ltdl'.

configure.in:
 
...
dnl Enable building of the convenience library
dnl and set LIBLTDL accordingly
AC_LIBLTDL_CONVENIENCE
dnl Substitute INCLTDL and LIBLTDL in the Makefiles
AC_SUBST(INCLTDL)
AC_SUBST(LIBLTDL)
dnl Check for dlopen support
AC_LIBTOOL_DLOPEN
dnl Configure libtool
AC_PROG_LIBTOOL
dnl Configure libltdl
AC_CONFIG_SUBDIRS(libltdl)
...

Makefile.am:
 
...
SUBDIRS = libltdl

INCLUDES = $(INCLTDL)

myprog_LDFLAGS = -export-dynamic
# The quotes around -dlopen below fool automake <= 1.4 into accepting it
myprog_LDADD = $(LIBLTDL) "-dlopen" self "-dlopen" foo1.la
myprog_DEPENDENCIES = $(LIBLTDL) foo1.la
...


[ << ] [ >> ]           [Top] [Contents] [Index] [ ? ]

This document was generated by Dirk Vermeir on May, 8 2002 using texi2html