-static do not do any dynamic linking of libtool libraries
-version-info CURRENT[:REVISION[:AGE]]
specify library version info [each variable defaults to 0]
+ -weak LIBNAME declare that the target provides the LIBNAME interface
All other options (arguments beginning with \`-') are ignored.
thread_safe=no
vinfo=
vinfo_number=no
+ weak_libs=
func_infer_tag $base_compile
prev=
continue
;;
- inst_prefix)
- inst_prefix_dir="$arg"
- prev=
- continue
- ;;
- precious_regex)
- precious_files_regex="$arg"
+ framework)
+ case $host in
+ *-*-darwin*)
+ case "$deplibs " in
+ *" $qarg.ltframework "*) ;;
+ *) deplibs="$deplibs $qarg.ltframework" # this is fixed later
+ ;;
+ esac
+ ;;
+ esac
prev=
continue
;;
- release)
- release="-$arg"
+ inst_prefix)
+ inst_prefix_dir="$arg"
prev=
continue
;;
prev=
continue
;;
+ precious_regex)
+ precious_files_regex="$arg"
+ prev=
+ continue
+ ;;
+ release)
+ release="-$arg"
+ prev=
+ continue
+ ;;
rpath | xrpath)
# We need an absolute path.
case $arg in
prev=
continue
;;
- xcompiler)
- compiler_flags="$compiler_flags $qarg"
+ shrext)
+ shrext_cmds="$arg"
prev=
- compile_command="$compile_command $qarg"
- finalize_command="$finalize_command $qarg"
continue
;;
- xlinker)
- linker_flags="$linker_flags $qarg"
- compiler_flags="$compiler_flags $wl$qarg"
+ weak)
+ weak_libs="$weak_libs $arg"
prev=
- compile_command="$compile_command $wl$qarg"
- finalize_command="$finalize_command $wl$qarg"
continue
;;
xcclinker)
finalize_command="$finalize_command $qarg"
continue
;;
- framework)
- case $host in
- *-*-darwin*)
- case "$deplibs " in
- *" $qarg.ltframework "*) ;;
- *) deplibs="$deplibs $qarg.ltframework" # this is fixed later
- ;;
- esac
- ;;
- esac
+ xcompiler)
+ compiler_flags="$compiler_flags $qarg"
prev=
+ compile_command="$compile_command $qarg"
+ finalize_command="$finalize_command $qarg"
continue
;;
- shrext)
- shrext_cmds="$arg"
+ xlinker)
+ linker_flags="$linker_flags $qarg"
+ compiler_flags="$compiler_flags $wl$qarg"
prev=
+ compile_command="$compile_command $wl$qarg"
+ finalize_command="$finalize_command $wl$qarg"
continue
;;
*)
continue
;;
+ -framework)
+ prev=framework
+ continue
+ ;;
+
-inst-prefix-dir)
prev=inst_prefix
continue
continue
;;
- -shrext)
- prev=shrext
- continue
- ;;
-
-no-fast-install)
fast_install=no
continue
continue
;;
+ -shrext)
+ prev=shrext
+ continue
+ ;;
+
-static)
# The effects of -static are defined in a previous loop.
# We used to do the same as -all-static on platforms that
prev=vinfo
continue
;;
+
-version-number)
prev=vinfo
vinfo_number=yes
continue
;;
+ -weak)
+ prev=weak
+ continue
+ ;;
+
-Wc,*)
args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wc,//'`
arg=
continue
;;
- -framework)
- prev=framework
- continue
- ;;
-
# Some other compiler flag.
-* | +*)
# Unknown arguments in both finalize_command and compile_command need
# Collect and forward deplibs of preopened libtool libs
for lib in $dlprefiles; do
# Ignore non-libtool-libs
+ dependency_libs=
case $lib in
- */*.la | *\\*.la)
- . $lib
- deplibs="$deplibs $dependency_libs"
- ;;
- *.la)
- . ./$lib
- deplibs="$deplibs $dependency_libs"
- ;;
+ *[\\/]*.la) . $lib ;;
+ *.la) . ./$lib ;;
esac
+
+ # Collect preopened libtool deplibs, except any this library
+ # has declared as weak libs
+ for deplib in $dependency_libs; do
+ deplib_base=`echo "$deplib" |$SED "$basename"`
+ case " $weak_libs " in
+ *" $deplib_base "*) ;;
+ *) deplibs="$deplibs $deplib" ;;
+ esac
+ done
done
libs="$dlprefiles"
fi
# Libraries that this one depends upon.
dependency_libs='$dependency_libs'
+# Names of additional weak libraries provided by this library
+weak_library_names='$weak_libs'
+
# Version information for $libname.
current=$current
age=$age
* Building modules:: Creating dlopenable objects and libraries.
* Dlpreopening:: Dlopening that works on static platforms.
+* Linking with dlopened modules:: Using dlopenable modules in libraries.
* Finding the dlname:: Choosing the right file to @code{dlopen}.
* Dlopen issues:: Unresolved problems that need your attention.
operating systems. New projects should use the @samp{-version-info} flag
instead.
+@item -weak @var{libname}
+if @var{output-file} is a libtool library, declare that it provides a
+weak @var{libname} interface. This is a hint to libtool that there is
+no need to append @var{libname} to the list of dependency libraries of
+@var{output-file}, because linking against @var{output-file} already
+supplies the same interface (@pxref{Linking with dlopened modules}).
+
@item -Wl,@var{flag}
@itemx -Xlinker @var{flag}
Pass a linker specific flag directly to the linker.
@menu
* Building modules:: Creating dlopenable objects and libraries.
* Dlpreopening:: Dlopening that works on static platforms.
+* Linking with dlopened modules:: Using dlopenable modules in libraries.
* Finding the dlname:: Choosing the right file to @code{dlopen}.
* Dlopen issues:: Unresolved problems that need your attention.
@end menu
@end deftypefun
+@node Linking with dlopened modules
+@section Linking with dlopened modules
+@cindex linking, dlopen
+@cindex linking, dlpreopen
+
+When, say, an interpreter application uses dlopened modules to extend
+the list of methods it provides, an obvious abstraction for the
+maintainers of the interpreter is to have all methods (including the
+built in ones supplied with the interpreter) accessed through
+dlopen. For one thing, the dlopening functionality will be tested
+even during routine invocations. For another, only one subsystem has
+to be written for getting methods into the interpreter.
+
+The downside of this abstraction is, of course, that environments that
+provide only static linkage can't even load the intrinsic interpreter
+methods. Not so! We can statically link those methods by
+@strong{dlpreopening} them.
+
+Unfortunately, since platforms such as @sc{aix} and cygwin require
+that all library symbols must be resolved at compile time, the
+interpreter maintainers will need to provide a library to both its own
+dlpreopened modules, and third-party modules loaded by dlopen. In
+itself, that is not so bad, except that the interpreter too must
+provide those same symbols otherwise it will be impossible to resolve
+all the symbols required by the modules as they are loaded. Things
+are even worse if the code that loads the modules for the interpreter
+is itself in a library -- and that is usually the case for any
+non-trivial application. Modern platforms take care of this by
+automatically loading all of a module's dependency libraries as the
+module is loaded (libltdl can do this even on platforms that can't do
+it by themselves). In the end, this leads to problems with duplicated
+symbols and prevents modules from loading, and prevents the
+application from compiling when modules are preloaded.
+
+@example
+,-------------. ,------------------. ,-----------------.
+| Interpreter |----> Module------------> Third-party |
+`-------------' | Loader | |Dlopened Modules |
+ | | | `-----------------'
+ |,-------v--------.| |
+ || Dlpreopened || |
+ || Modules || |
+ |`----------------'| |
+ | | | |
+ |,-------v--------.| ,--------v--------.
+ ||Module Interface|| |Module Interface |
+ || Library || | Library |
+ |`----------------'| `-----------------'
+ `------------------'
+@end example
+
+Libtool has the concept of @dfn{weak library interfaces} to circumvent
+this problem. Recall that the code that dlopens method-provider
+modules for the interpreter application resides in a library: All of
+the modules and the dlopener library itself should be linked against
+the common library that resolves the module symbols at compile time.
+To guard against duplicate symbol definitions, and for dlpreopened
+modules to work at all in this scenario, the dlopener library must
+declare that it provides a weak library interface to the common
+symbols in the library it shares with the modules. That way, when
+@command{libtool} links the @strong{Module Loader} library with some
+@strong{Dlpreopened Modules} that were in turn linked against the
+@strong{Module Interface Library}, it knows that the @strong{Module
+Loader} provides an already loaded @strong{Module Interface Library}
+to resolve symbols for the @strong{Dlpreopened Modules}, and doesn't
+ask the compiler driver to link an identical @strong{Module Interface
+Library} dependency library too.
+
+In conjunction with Automake, the @file{Makefile.am} for the
+@strong{Module Loader} might look like this:
+
+@example
+lib_LTLIBRARIES = libinterface.la libloader.la
+
+libinterface_la_SOURCES = interface.c interface.h
+libinterface_la_LDFLAGS = -version-info 3:2:1
+
+libloader_la_SOURCES = loader.c
+libloader_la_LDFLAGS = -weak libinterface.la \
+ -version-info 3:2:1 \
+ -dlpreopen ../modules/intrinsics.la
+libloader_la_LIBADD = $(libinterface_la_OBJECTS)
+@end example
+
+And the @file{Makefile.am} for the @file{intrinsics.la} module in a
+sibling @file{modules} directory might look like this:
+
+@example
+AM_CPPFLAGS = -I$(srcdir)/../libloader
+AM_LDFLAGS = -no-undefined -module -avoid-version \
+ -export-dynamic
+
+noinst_LTLIBRARIES = intrinsics.la
+
+intrinsics_la_LIBADD = ../libloader/libinterface.la
+
+../libloader/libinterface.la:
+ cd ../libloader; $(MAKE) $(AM_MAKEFLAGS) libinterface.la
+@end example
+
+@cindex -weak option
+For a more complex example, see the sources of @file{libltdl} in the
+Libtool distribution, which is built with the help of the @samp{-weak}
+option.
+
+
@node Finding the dlname
@section Finding the correct name to dlopen
@cindex names of dynamic modules