The "GNU build system" has a solution for _building_ shared libraries portably, namely libtool. As paradoxical as it sounds, it does not yet have a solution for _using_ shared libraries portably.
The linker command line for using a shared library is fortunately the same everywhere on Unix, namely -lfoo. But when this simple approach is used, the resulting executables on many platforms need additional measures to be taken in order to run: the user needs to set an environment variable like LD_LIBRARY_PATH, LIBPATH or SHLIB_PATH, or needs to register the directory in a file like /etc/ld.so.config. Quite painful in practice. Most systems nowadays have a way to hardwire a shared library search path (or the precise location of each required shared library) in the executable. Let me call it the "rpath facility". This solves the LD_LIBRARY_PATH problem, but has two disadvantages: 1) It hardcodes pathnames. But this is not a problem for packages built using autoconf: they cannot be relocatabled in the filesystem anyway. (The $prefix is used in the Makefile and hardwired in various places, from -DLOCALEDIR=$localedir to #!@INTERPRETER@...) 2) The syntax used to specify a shared library's search path is platform dependent. libtool 1.4 and newer is using the rpath facility, so that when libtool is used to create an executable, the resulting executable runs out of the box and does not have the LD_LIBRARY_PATH problem. I suggested last year that every package that uses a shared library (for example, -lintl for internationalization) use libtool to create its executables. There was consensus that this is not the right approach, mostly for practical reasons: it increases a package's size by 500 KB (120 KB once for libtool.m4, once again for aclocal.m4, once more for configure, and finally 140 KB for ltmain.sh). Also the configure script then spends time checking for irrelevant features, like the output syntax of "nm". So I set out and realized in gettext-0.11.2 a solution of the LD_LIBRARY_PATH problem that: 1) is lightweight to use, and integrates well with autoconf and automake, 2) integrates well with libtool, i.e. can be equally well used in projects that use libtool as in projects that don't, 3) copes with dependencies between shared libraries (example: -lintl depends on -liconv), even on systems where these dependencies are not explicit 4) handles all kinds of libraries, whether shared or static, whether built with or without libtool (example: zlib). 5) works when cross-compiling, 6) is easy to port to new platforms, 7) allows support for new platforms to be added without rebuilding 'configure'. You find it in gettext-0.11.2, contained in the files m4/lib-ld.m4 m4/lib-link.m4 m4/lib-prefix.m4 config.rpath tests/rpath* portions of tests/Makefile.am and Makefile.am related to tests/rpath* The solution seems mature now. I have gotten no bug report about it since the release of gettext-0.11.2. I would propose this facility for inclusion in GNU autoconf. The reason is that although it has been developed to deal with -lintl and -liconv, the macros are generally useful and can equally well be used to locate libz or libxml. Of course you can rewrite the entire facility the way you like, but first let me explain more details. - There is a single autoconf macro: AC_LIB_LINKFLAGS(name [, dependencies]) searches for libname and the libraries corresponding to explicit and implicit dependencies. Sets and AC_SUBSTs the LIB${NAME} and LTLIB${NAME} variables and augments the CPPFLAGS variable. - Goal 1 is achieved by defining an autoconf macro which sets and AC_SUBSTs some variables. I made some experiments with a libtool like wrapper script for the link command line. It turns out that it is too intrusive (the programmer needs to look at all his link command line invocations, and automake would need modifications), and its size is still one third of libtool.m4. I also considered shell scripts of the form foo-config, but found that - they don't observe a standard pattern (some can give you CPPFLAGS, some can give you CFLAGS, some give you -L$libdir without rpath option, some with rpath option), - even if they were standardized, there would be the problem that the -rpath option is compiler and linker dependent: the ones contained in the foo-config script have been determined for the compiler that compiled libfoo, not for the compiler that uses it. - libtool and "gcc -shared" create libraries without creating foo-config scripts, therefore there are many more shared libraries around than foo-config scripts. - Goal 2 is achieved by defining variables for use with libtool and variables for use without libtool. The first will contain "-Rdirectory" whereas the second one will contain "-Wl,-rpath,directory". This is needed because we cannot use the same variable for both cases: the linker does not accept "-Rdirectory", and libtool does not recognize "-Wl,-rpath,directory" and its variants with spaces. - Goal 3: Dependencies between libraries. If libtool .la files are present, there is no need to specify the dependencies as argument of AC_LIB_LINKFLAGS. Only when the .la files are not there, it is needed to put a-priori knowledge into the AC_LIB_LINKFLAGS invocation. (It's needed for the case with static libraries, or platforms without implicit shared library dependencies.) - Goal 4: Look into the macro :-) - Goal 5: The autoconf test does not run any program, it only looks for files. Therefore a database of system capabilities, based on the canonical triple, is used. - Goal 6: Porting to new platforms is made easy by a script rpathcfg.sh which infers the values which can be put into that database of system capabilities. - Goal 7: The database of system capabilities has been put into a separate file, config.rpath, which is called from configure, not included in it. This way, when someone ports to a new platform and builds dozens of packages for it, he needs to patch all the config.rpath files the same way; he doesn't need to rerun aclocal and autoconf. - Why does the macro modify CPPFLAGS? It could also define a variable INC${NAME} that the programmer would add to his DEFS Makefile variable. The reasons are: - So that later tests in the configure script can use the added library. - A set of Makefiles is more robust if all source files are compiled with the same -I options. (Just imagine one file being compiled with GNU libintl.h and another file with Solaris libintl.h... Messy.) - On systems like OSF/1, where rpath options are not cumulative, the facility has the limitation that no more than one library directory can be used. I.e. --with-libiconv-prefix=/opt/gnu1 --with-libintl-prefix=/opt/gnu2 will not solve the LD_LIBRARY_PATH problem. There are three workarounds: a) The user can use the same --prefix for all his packages. b) The user can create symlinks for the installed libraries, so that they become accessible from a single directory. c) The programmer could use libtool to create his executables. - On systems like SCO 3.2.5, there is no rpath facility in the system at all. I haven't seen such systems for the last couple of years, but I believe that in this case the use of AC_LIB_LINKFLAGS will not harm (and have no positive effect either). Bruno