Add a test to simulate a failure visible on systems which

need a library prefix like 'lib', such as BeOS.  Fix a number
of bugs exposed by this test in order for it to pass.
Currently the prefix is hardcoded as 'lib', as I am not aware
of systems that require a different prefix:

* libltdl/loaders/preopen.c (lt_dlpreload_open):  Move error
condition out of test loop to be sure that each originator is
tried, instead of erroring out if the first doesn't match.
Support passing NULL as the originator to load all preloaded
modules originating in the program itself.
* libltdl/lt_dlloader.c (lt_dlloader_dump): New debug function.
* libltdl/libltdl/lt_dlloader.h (lt_dlloader_dump): Declare it
when LT_DEBUG_LOADERS is defined at compile time.
* libltdl/ltdl.c (lt_dlinit): Dump loader list after successful
initialisation.
(tryall_dlopen): Add a new VTABLE parameter to force use of a
specific loader in preference to trying every loader in turn.
Adjust all callers.
(try_dlopen): Always see whether a module was preloaded for
module names with no directory component before searching the
filesystem for a match.
* libltdl/m4/libtool.m4 (_LT_CMD_GLOBAL_SYMBOLS): Declare
a new global_symbol_to_c_name_address_lib_prefix variable.
(global_symbol_to_c_name_address_lib_prefix): The sed
expressions to use when a lib prefix is enforced need to be
slightly different to work with preloaded modules.
* libltdl/config/ltmain.m4sh (func_generate_dlsyms): In order
to name preloaded symbols correctly for the lookup algorithm
to work when the loaded module file must be prefixed with lib.
Use global_symbol_to_c_name_address_lib_prefix when
need_lib_prefix is other than no.
* tests/need_lib_prefix.at: New test to check for breakage on
hosts where need_lib_prefix is unknown.
* Makefile.am (TESTSUITE_AT): Add new test.
* tests/TODO: Note missing tests that would have caught some
of the latent bugs fixed by this patch.
* HACKING: Document libltdl keyword.
* NEWS: Updated.
This commit is contained in:
Gary V. Vaughan 2007-06-24 20:46:47 +00:00
parent e6e96742ef
commit a894e3baee
12 changed files with 402 additions and 69 deletions

View File

@ -1,3 +1,45 @@
2007-06-24 Gary V. Vaughan <gary@gnu.org>
Add a test to simulate a failure visible on systems which
need a library prefix like 'lib', such as BeOS. Fix a number
of bugs exposed by this test in order for it to pass.
Currently the prefix is hardcoded as 'lib', as I am not aware
of systems that require a different prefix:
* libltdl/loaders/preopen.c (lt_dlpreload_open): Move error
condition out of test loop to be sure that each originator is
tried, instead of erroring out if the first doesn't match.
Support passing NULL as the originator to load all preloaded
modules originating in the program itself.
* libltdl/lt_dlloader.c (lt_dlloader_dump): New debug function.
* libltdl/libltdl/lt_dlloader.h (lt_dlloader_dump): Declare it
when LT_DEBUG_LOADERS is defined at compile time.
* libltdl/ltdl.c (lt_dlinit): Dump loader list after successful
initialisation.
(tryall_dlopen): Add a new VTABLE parameter to force use of a
specific loader in preference to trying every loader in turn.
Adjust all callers.
(try_dlopen): Always see whether a module was preloaded for
module names with no directory component before searching the
filesystem for a match.
* libltdl/m4/libtool.m4 (_LT_CMD_GLOBAL_SYMBOLS): Declare
a new global_symbol_to_c_name_address_lib_prefix variable.
(global_symbol_to_c_name_address_lib_prefix): The sed
expressions to use when a lib prefix is enforced need to be
slightly different to work with preloaded modules.
* libltdl/config/ltmain.m4sh (func_generate_dlsyms): In order
to name preloaded symbols correctly for the lookup algorithm
to work when the loaded module file must be prefixed with lib.
Use global_symbol_to_c_name_address_lib_prefix when
need_lib_prefix is other than no.
* tests/need_lib_prefix.at: New test to check for breakage on
hosts where need_lib_prefix is unknown.
* Makefile.am (TESTSUITE_AT): Add new test.
* tests/TODO: Note missing tests that would have caught some
of the latent bugs fixed by this patch.
* HACKING: Document libltdl keyword.
* NEWS: Updated.
2007-06-24 Gary V. Vaughan <gary@gnu.org>
Reenable compilation of libltdl with C++:

View File

@ -51,6 +51,10 @@ and is not part of a release distribution.
3. Test Suite
=============
* When writing tests, make sure the link invocation (first argument to
AT_CHECK) is on a single line so that 'testsuite -x' displays the
whole thing.
* Use
make check TESTSUITEFLAGS=-V
make check-local
@ -60,6 +64,7 @@ and is not part of a release distribution.
* The new Autotest testsuite uses keywords to denote test features:
autoconf needs Autoconf
automake needs Automake
libltdl exercises the `libltdl' library
libtool exercises the `libtool' script
libtoolize exercises the `libtoolize' script
recursive runs the suite recursively, with a modified

View File

@ -447,6 +447,7 @@ TESTSUITE_AT = tests/testsuite.at \
tests/am-subdir.at \
tests/lt_dlexit.at \
tests/lt_dladvise.at \
tests/need_lib_prefix.at \
tests/standalone.at \
tests/subproject.at \
tests/nonrecursive.at \

6
NEWS
View File

@ -2,12 +2,6 @@ NEWS - list of user-visible changes between releases of GNU Libtool
New in 2.1a: 2007-??-??; CVS version 2.1a, Libtool team:
* Regressions over 1.5.x that may be fixed later:
- On systems which need a library prefix like `lib', such as BeOS,
libltdl currently does not build. The new structure of libltdl with
preopened modules exposes some long-lived bugs here.
* Important incompatible changes and obsoleted features:
- Removed deprecated APIs from libltdl: lt_dlcaller_register,

View File

@ -1020,8 +1020,14 @@ lt_${my_prefix}_LTX_preloaded_symbols[] =
{\
{ \"$my_originator\", (void *) 0 },"
eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms"
case $need_lib_prefix in
no)
eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms"
;;
*)
eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms"
;;
esac
$ECHO >> "$output_objdir/$my_dlsyms" "\
{0, (void *) 0}
};

View File

@ -81,6 +81,10 @@ LT_SCOPE const lt_dlvtable *lt_dlloader_get (lt_dlloader loader);
/* Type of a function to get a loader's vtable: */
typedef const lt_dlvtable *lt_get_vtable (lt_user_data data);
#ifdef LT_DEBUG_LOADERS
LT_SCOPE void lt_dlloader_dump (void);
#endif
LT_END_C_DECLS
#endif /*!defined(LT_DLLOADER_H)*/

View File

@ -322,7 +322,8 @@ lt_dlpreload (const lt_dlsymlist *preloaded)
/* Open all the preloaded modules from the named originator, executing
a callback for each one. */
a callback for each one. If ORIGINATOR is NULL, then call FUNC for
each preloaded module from the program itself. */
int
lt_dlpreload_open (const char *originator, lt_dlpreload_callback_func *func)
{
@ -334,7 +335,8 @@ lt_dlpreload_open (const char *originator, lt_dlpreload_callback_func *func)
for (list = preloaded_symlists; list; list = list->next)
{
/* ...that was preloaded by the requesting ORIGINATOR... */
if (streq (list->symlist->name, originator))
if ((originator && streq (list->symlist->name, originator))
|| (!originator && streq (list->symlist->name, "@PROGRAM@")))
{
const lt_dlsymlist *symbol;
unsigned int idx = 0;
@ -360,12 +362,12 @@ lt_dlpreload_open (const char *originator, lt_dlpreload_callback_func *func)
}
}
}
}
if (!found)
{
LT__SETERROR(CANNOT_OPEN);
++errors;
}
if (!found)
{
LT__SETERROR(CANNOT_OPEN);
++errors;
}
return errors;

View File

@ -97,6 +97,33 @@ lt_dlloader_add (const lt_dlvtable *vtable)
return RETURN_SUCCESS;
}
#ifdef LT_DEBUG_LOADERS
static void *
loader_dump_callback (SList *item, void *userdata)
{
const lt_dlvtable *vtable = (const lt_dlvtable *) item->userdata;
fprintf (stderr, ", %s", (vtable && vtable->name) ? vtable->name : "(null)");
return 0;
}
void
lt_dlloader_dump (void)
{
fprintf (stderr, "loaders: ");
if (!loaders)
{
fprintf (stderr, "(empty)");
}
else
{
const lt_dlvtable *head = (const lt_dlvtable *) loaders->userdata;
fprintf (stderr, "%s", (head && head->name) ? head->name : "(null)");
if (slist_tail (loaders))
slist_foreach (slist_tail (loaders), loader_dump_callback, NULL);
}
fprintf (stderr, "\n");
}
#endif
/* An iterator for the global loader list: if LOADER is NULL, then
return the first element, otherwise the following element. */

View File

@ -1,7 +1,7 @@
/* ltdl.c -- system independent dlopen wrapper
Copyright (C) 1998, 1999, 2000, 2004, 2005, 2006,
2007 Free Software Foundation, Inc.
2007 Free Software Foundation, Inc.
Written by Thomas Tanner, 1998
NOTE: The canonical source of this file is maintained with the
@ -120,7 +120,8 @@ static int try_dlopen (lt_dlhandle *handle,
lt_dladvise advise);
static int tryall_dlopen (lt_dlhandle *handle,
const char *filename,
lt_dladvise advise);
lt_dladvise advise,
const lt_dlvtable *vtable);
static int unload_deplibs (lt_dlhandle handle);
static lt__advise *advise_dup (lt__advise *advise);
static int lt_argz_insert (char **pargz, size_t *pargz_len,
@ -239,6 +240,10 @@ lt_dlinit (void)
#endif /* HAVE_LIBDLLOADER */
}
#ifdef LT_DEBUG_LOADERS
lt_dlloader_dump();
#endif
return errors;
}
@ -332,17 +337,23 @@ lt_dlexit (void)
}
/* Try all dlloaders for FILENAME. If the library is not successfully
loaded, return non-zero. Otherwise, the dlhandle is stored at the
address given in PHANDLE. */
/* Try VTABLE or, if VTABLE is NULL, all available loaders for FILENAME.
If the library is not successfully loaded, return non-zero. Otherwise,
the dlhandle is stored at the address given in PHANDLE. */
static int
tryall_dlopen (lt_dlhandle *phandle, const char *filename,
lt_dladvise advise)
lt_dladvise advise, const lt_dlvtable *vtable)
{
lt__handle * handle = (lt__handle *) handles;
const char * saved_error = 0;
int errors = 0;
#ifdef LT_DEBUG_LOADERS
fprintf (stderr, "tryall_dlopen (%s, %s)\n",
filename ? filename : "(null)",
vtable ? vtable->name : "(ALL)");
#endif
LT__GETERROR (saved_error);
/* check whether the module was already opened */
@ -391,42 +402,60 @@ tryall_dlopen (lt_dlhandle *phandle, const char *filename,
}
{
const lt_dlvtable *vtable = 0;
lt_dlloader *loader = 0;
lt_dlloader loader = lt_dlloader_next (0);
const lt_dlvtable *loader_vtable;
while ((loader = (lt_dlloader *) lt_dlloader_next (loader)))
do
{
lt__advise *advise_taken = 0;
if (advise)
advise_taken = advise_dup ((lt__advise *) advise);
vtable = lt_dlloader_get (loader);
handle->module = (*vtable->module_open) (vtable->dlloader_data,
filename, advise_taken);
if (vtable)
loader_vtable = vtable;
else
loader_vtable = lt_dlloader_get (loader);
#ifdef LT_DEBUG_LOADERS
fprintf (stderr, "Calling %s->module_open (%s)\n",
(loader_vtable && loader_vtable->name) ? loader_vtable->name : "(null)",
filename ? filename : "(null)");
#endif
handle->module = (*loader_vtable->module_open) (loader_vtable->dlloader_data,
filename, advise_taken);
#ifdef LT_DEBUG_LOADERS
fprintf (stderr, " Result: %s\n",
handle->module ? "Success" : "Failed");
#endif
if (handle->module != 0)
{
if (advise_taken)
{
handle->info.is_resident = advise_taken->is_resident;
handle->info.is_symglobal = advise_taken->is_symglobal;
handle->info.is_symlocal = advise_taken->is_symlocal;
handle->info.is_resident = advise_taken->is_resident;
handle->info.is_symglobal = advise_taken->is_symglobal;
handle->info.is_symlocal = advise_taken->is_symlocal;
}
break;
}
FREE (advise_taken);
}
while (!vtable && (loader = lt_dlloader_next (loader)));
if (!loader)
/* If VTABLE was given but couldn't open the module, or VTABLE wasn't
given but we exhausted all loaders without opening the module, bail
out! */
if ((vtable && !handle->module)
|| (!vtable && !loader))
{
FREE (handle->info.filename);
++errors;
goto done;
}
handle->vtable = vtable;
handle->vtable = loader_vtable;
}
LT__SETERRORSTR (saved_error);
@ -474,9 +503,9 @@ tryall_dlopen_module (lt_dlhandle *handle, const char *prefix,
if (prefix)
{
error += tryall_dlopen_module (handle, (const char *) 0,
prefix, filename, advise);
prefix, filename, advise);
}
else if (tryall_dlopen (handle, filename, advise) != 0)
else if (tryall_dlopen (handle, filename, advise, 0) != 0)
{
++error;
}
@ -493,7 +522,7 @@ find_module (lt_dlhandle *handle, const char *dir, const char *libdir,
/* Try to open the old library first; if it was dlpreopened,
we want the preopened version of it, even if a dlopenable
module is available. */
if (old_name && tryall_dlopen (handle, old_name, advise) == 0)
if (old_name && tryall_dlopen (handle, old_name, advise, 0) == 0)
{
return 0;
}
@ -513,14 +542,14 @@ find_module (lt_dlhandle *handle, const char *dir, const char *libdir,
if (!installed)
{
if (tryall_dlopen_module (handle, dir, objdir,
dlname, advise) == 0)
dlname, advise) == 0)
return 0;
}
/* maybe it was moved to another directory */
{
if (dir && (tryall_dlopen_module (handle, (const char *) 0,
dir, dlname, advise) == 0))
dir, dlname, advise) == 0))
return 0;
}
}
@ -737,7 +766,7 @@ find_handle_callback (char *filename, void *data, void *data2)
/* Try to dlopen the file, but do not continue searching in any
case. */
if (tryall_dlopen (handle, filename, advise) != 0)
if (tryall_dlopen (handle, filename, advise, 0) != 0)
*handle = 0;
return 1;
@ -1093,7 +1122,7 @@ cleanup:
/* Try to open FILENAME as a module. */
static int
try_dlopen (lt_dlhandle *phandle, const char *filename, const char *ext,
lt_dladvise advise)
lt_dladvise advise)
{
const char * saved_error = 0;
char * canonical = 0;
@ -1107,6 +1136,12 @@ try_dlopen (lt_dlhandle *phandle, const char *filename, const char *ext,
assert (phandle);
assert (*phandle == 0);
#ifdef LT_DEBUG_LOADERS
fprintf (stderr, "try_dlopen (%s, %s)\n",
filename ? filename : "(null)",
ext ? ext : "(null)");
#endif
LT__GETERROR (saved_error);
/* dlopen self? */
@ -1121,7 +1156,7 @@ try_dlopen (lt_dlhandle *phandle, const char *filename, const char *ext,
/* lt_dlclose()ing yourself is very bad! Disallow it. */
((lt__handle *) newhandle)->info.is_resident = 1;
if (tryall_dlopen (&newhandle, 0, advise) != 0)
if (tryall_dlopen (&newhandle, 0, advise, 0) != 0)
{
FREE (*phandle);
return 1;
@ -1210,6 +1245,35 @@ try_dlopen (lt_dlhandle *phandle, const char *filename, const char *ext,
name[ext - base_name] = LT_EOS_CHAR;
}
/* Before trawling through the filesystem in search of a module,
check whether we are opening a preloaded module. */
if (!dir)
{
const lt_dlvtable *vtable = lt_dlloader_find ("lt_preopen");
if (vtable)
{
*phandle = (lt_dlhandle) lt__zalloc (sizeof (lt__handle));
if (*phandle == NULL)
{
++errors;
goto cleanup;
}
newhandle = *phandle;
if (tryall_dlopen (&newhandle, filename, advise, vtable) == 0)
{
goto register_handle;
}
/* If we're still here, there was no matching preloaded module,
so put things back as we found them, and continue searching. */
FREE (*phandle);
newhandle = NULL;
}
}
/* Check whether we are opening a libtool module (.la extension). */
if (ext && streq (ext, archive_ext))
{
@ -1225,16 +1289,14 @@ try_dlopen (lt_dlhandle *phandle, const char *filename, const char *ext,
of libtool */
int installed = 1;
/* Now try to open the .la file. If there is no directory name
component, try to find it first in user_search_path and then other
prescribed paths. Otherwise (or in any case if the module was not
yet found) try opening just the module name as passed. */
component, try to find it first in user_search_path and then other
prescribed paths. Otherwise (or in any case if the module was not
yet found) try opening just the module name as passed. */
if (!dir)
{
const char *search_path;
const char *search_path = user_search_path;
search_path = user_search_path;
if (search_path)
file = find_file (user_search_path, base_name, &dir);
@ -1277,7 +1339,7 @@ try_dlopen (lt_dlhandle *phandle, const char *filename, const char *ext,
/* read the .la file */
if (parse_dotla_file(file, &dlname, &libdir, &deplibs,
&old_name, &installed) != 0)
errors++;
++errors;
fclose (file);
@ -1303,7 +1365,7 @@ try_dlopen (lt_dlhandle *phandle, const char *filename, const char *ext,
newhandle = *phandle;
/* find_module may replace newhandle */
if (find_module (&newhandle, dir, libdir, dlname, old_name,
installed, advise))
installed, advise))
{
unload_deplibs (*phandle);
++errors;
@ -1347,7 +1409,7 @@ try_dlopen (lt_dlhandle *phandle, const char *filename, const char *ext,
Otherwise (or in any case if the module was not yet found) try
opening just the module name as passed. */
if ((dir || (!find_handle (user_search_path, base_name,
&newhandle, advise)
&newhandle, advise)
&& !find_handle (getenv (LTDL_SEARCHPATH_VAR), base_name,
&newhandle, advise)
#if defined(LT_MODULE_PATH_VAR)
@ -1356,14 +1418,14 @@ try_dlopen (lt_dlhandle *phandle, const char *filename, const char *ext,
#endif
#if defined(LT_DLSEARCH_PATH)
&& !find_handle (sys_dlsearch_path, base_name,
&newhandle, advise)
&newhandle, advise)
#endif
)))
{
if (tryall_dlopen (&newhandle, filename, advise) != 0)
{
newhandle = NULL;
}
if (tryall_dlopen (&newhandle, filename, advise, 0) != 0)
{
newhandle = NULL;
}
}
if (!newhandle)
@ -1420,8 +1482,8 @@ file_not_found (void)
static int
has_library_ext (const char *filename)
{
char * ext = 0;
size_t len;
char * ext = 0;
size_t len;
assert (filename);
@ -1430,7 +1492,7 @@ has_library_ext (const char *filename)
if (ext && ((streq (ext, archive_ext))
#if defined(LT_MODULE_EXT)
|| (streq (ext, shlib_ext))
|| (streq (ext, shlib_ext))
#endif
))
{
@ -1528,7 +1590,7 @@ lt_dlhandle
lt_dlopenadvise (const char *filename, lt_dladvise advise)
{
lt_dlhandle handle = 0;
int errors = 0;
int errors = 0;
/* Can't have symbols hidden and visible at the same time! */
if (advise
@ -1545,9 +1607,9 @@ lt_dlopenadvise (const char *filename, lt_dladvise advise)
|| has_library_ext (filename))
{
/* Just incase we missed a code path in try_dlopen() that reports
an error, but forgot to reset handle... */
an error, but forgot to reset handle... */
if (try_dlopen (&handle, filename, NULL, advise) != 0)
return 0;
return 0;
return handle;
}
@ -1559,21 +1621,21 @@ lt_dlopenadvise (const char *filename, lt_dladvise advise)
errors += try_dlopen (&handle, filename, archive_ext, advise);
/* If we found FILENAME, stop searching -- whether we were able to
load the file as a module or not. If the file exists but loading
failed, it is better to return an error message here than to
report FILE_NOT_FOUND when the alternatives (foo.so etc) are not
in the module search path. */
load the file as a module or not. If the file exists but loading
failed, it is better to return an error message here than to
report FILE_NOT_FOUND when the alternatives (foo.so etc) are not
in the module search path. */
if (handle || ((errors > 0) && !file_not_found ()))
return handle;
return handle;
#if defined(LT_MODULE_EXT)
/* Try appending SHLIB_EXT. */
errors = try_dlopen (&handle, filename, shlib_ext, advise);
/* As before, if the file was found but loading failed, return now
with the current error message. */
with the current error message. */
if (handle || ((errors > 0) && !file_not_found ()))
return handle;
return handle;
#endif
}
@ -2170,9 +2232,9 @@ lt_dlinterface_register (const char *id_string, lt_dlhandle_interface *iface)
{
interface_id->id_string = lt__strdup (id_string);
if (!interface_id->id_string)
FREE (interface_id);
FREE (interface_id);
else
interface_id->iface = iface;
interface_id->iface = iface;
}
return (lt_dlinterface_id) interface_id;

View File

@ -3222,6 +3222,7 @@ lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p'
# Transform an extracted symbol line into symbol name and symbol address
lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p'"
lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \(lib[[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"lib\2\", (void *) \&\2},/p'"
# Handle CRLF in mingw tool chain
opt_cr=
@ -3375,6 +3376,9 @@ _LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1],
_LT_DECL([global_symbol_to_c_name_address],
[lt_cv_sys_global_symbol_to_c_name_address], [1],
[Transform the output of nm in a C name address pair])
_LT_DECL([global_symbol_to_c_name_address_lib_prefix],
[lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1],
[Transform the output of nm in a C name address pair when lib prefix is needed])
]) # _LT_CMD_GLOBAL_SYMBOLS

7
tests/TODO Normal file
View File

@ -0,0 +1,7 @@
Please write the following testcases and submit to libtool-patches@gnu.org:
- ensure each libtool library 'originator' is tried.
- check that passing NULL as the 'originator' correctly loads all
preloaded modules originating from "self" (program itself).
- test whether a preloaded library will open without the matching
.la file.

179
tests/need_lib_prefix.at Normal file
View File

@ -0,0 +1,179 @@
# need-lib-prefix.at -- test libltdl functionality -*- Autotest -*-
#
# Copyright (C) 2007 Free Software Foundation, Inc.
# Written by Gary V. Vaughan, 2007
#
# This file is part of GNU Libtool.
#
# GNU Libtool is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of
# the License, or (at your option) any later version.
#
# GNU Libtool is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with GNU Libtool; see the file COPYING. If not, a copy
# can be downloaded from http://www.gnu.org/licenses/gpl.html,
# or obtained by writing to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
####
AT_SETUP([enforced lib prefix])
AT_KEYWORDS([libltdl libtool])
AT_DATA([main.c],
[[#include <ltdl.h>
#include <stdio.h>
typedef int fun (int);
static int errors = 0;
static void
complain (const char *msg)
{
const char *errmsg = lt_dlerror ();
fprintf (stderr, "%s", msg);
if (errmsg)
fprintf (stderr, ": %s\n", errmsg);
else
fprintf (stderr, ".\n");
++errors;
}
static lt_dlhandle
moduleopen (const char *filename)
{
lt_dlhandle handle;
handle = lt_dlopen (filename);
if (!handle)
{
fprintf (stderr, "can't open the module %s!\n", filename);
complain ("error was");
}
return handle;
}
static int
moduletest (lt_dlhandle handle)
{
const lt_dlinfo *info = lt_dlgetinfo (handle);
fun *f = (fun *) lt_dlsym (handle, "f");
int *v = (int *) lt_dlsym (handle, "i");
if (!f)
{
complain ("function `f' not found");
return 1;
}
if (!v)
{
complain ("variable `i' not found");
return 1;
}
printf ("%s: %d\n", info->name, f (*v));
return 0;
}
int
main (int argc, char **argv)
{
lt_dlhandle handle;
LTDL_SET_PRELOADED_SYMBOLS();
if (lt_dlinit() != 0)
{
fprintf (stderr, "error during initialization: %s\n", lt_dlerror());
return 1;
}
if (lt_dlpreload_open (0, moduletest) != 0)
complain ("error during preloading");
if (lt_dlexit () != 0)
complain ("error during exit");
return (errors != 0);
}
]])
AT_DATA([foo1.c],
[[#define f foo1_LTX_f
#define i foo1_LTX_i
#ifdef __cplusplus
extern "C" {
#endif
int f (int x) { return x / 3; }
int i = 7;
#ifdef __cplusplus
}
#endif
]])
AT_DATA([foo2.c],
[[#define f libfoo2_LTX_f
#define i libfoo2_LTX_i
#ifdef __cplusplus
extern "C" {
#endif
int f (int x) { return (x * x) / 10; }
int i = 6;
#ifdef __cplusplus
}
#endif
]])
AT_DATA([expout],
[[libfoo1: 2
libfoo2: 3
]])
: ${LTDLINCL="-I$abs_top_srcdir/libltdl"}
: ${LIBLTDL="$abs_builddir/../libltdl/libltdlc.la"}
CPPFLAGS="$CPPFLAGS $LTDLINCL"
LDFLAGS="$LDFLAGS"
# Create our own libtool, forcing need_lib_prefix setting
sed 's,^\(need_lib_prefix\)=.*$,\1=unknown,' $LIBTOOL > ./libtool
LIBTOOL="$SHELL ./libtool"
# Installation directory:
instdir=`pwd`/_inst
$CC $CPPFLAGS $CFLAGS -c main.c
for file in foo1 foo2; do
$LIBTOOL --mode=compile $CC $CPPFLAGS $CFLAGS -c $file.c
done
AT_CHECK([$LIBTOOL --mode=link $CC -module -avoid-version $CFLAGS $LDFLAGS -o foo1.la foo1.lo -rpath $instdir/lib],
[], [ignore], [ignore])
AT_CHECK([$LIBTOOL --mode=link $CC -module -avoid-version $CFLAGS $LDFLAGS -o libfoo2.la foo2.lo -rpath $instdir/lib],
[], [ignore], [ignore])
AT_CHECK([$LIBTOOL --mode=link $CC $CFLAGS $LDFLAGS -o main main.$OBJEXT -dlpreopen foo1.la -dlpreopen libfoo2.la $LIBLTDL],
[], [ignore], [ignore])
LT_AT_NOINST_EXEC_CHECK([./main], [-dlopen foo1.la -dlopen libfoo2.la],
[], [expout], [])
# Install the libraries.
mkdir $instdir
mkdir $instdir/lib
$LIBTOOL --mode=install cp foo1.la $instdir/lib/foo1.la
$LIBTOOL --mode=install cp libfoo2.la $instdir/lib/libfoo2.la
# Install the binary
mkdir $instdir/bin
$LIBTOOL --mode=install cp main $instdir/bin/main
LT_AT_EXEC_CHECK([$instdir/bin/main], [], [expout], [])
AT_CLEANUP