[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Libraries often rely on code in other libraries. Traditionally the way to deal with this is to know what the dependencies are and, when linking an executable, be careful to list all of the dependencies on the link line in the correct order. If you have ever built an X Window application using a widget library, you will already be familiar with this notion.
Even though you only use the functions in the widget library directly, a typical link command would need to be:
$ gcc -o Xtest -I/usr/X11R6/include Xtest.c -L/usr/X11R6/lib \ -lXm -lXp -lXaw -lXmu -lX11 -lnsl -lsocket |
With modern architectures, this problem has been solved by allowing libraries to be linked into other libraries, but this feature is not yet particularly portable. If you are trying to write a portable project, it is not safe to rely on native support for inter-library dependencies, especially if you want to have dependencies between static and shared archives. Some of the features discussed in this section were not fully implemented before Libtool 1.4, so you should make sure that you are using this version or newer if you need these features.
If you want to try the examples in this section to see what
libtool
does on your machine, you will first need to modify the source of ‘hello.c’ to introduce a dependency on ‘trim.c’:
#include <stdio.h> extern char *trim (); extern void free (); void hello (char *who) { char *trimmed = trim (who); printf ("Hello, %s!\n", trimmed); free (trimmed); }You might also want to modify the ‘main.c’ file to exercise the new ‘trim’ functionality to prove that the newly linked executable is working:
void hello (); int main (int argc, char *argv[]) { hello ("\tWorld \r\n"); exit (0); }
Suppose I want to make two libraries, ‘libtrim’ and ‘libhello’. ‘libhello’ uses the ‘trim’ function in ‘libtrim’ but the code in ‘main’ uses only the ‘hello’ function in ‘libhello’. Traditionally, the two libraries are built like this:
$ rm hello *.a *.la *.o *.lo $ gcc -c trim.c $ ls hello.c main.c trim.c trim.o $ ar cru libtrim.a trim.o $ ranlib libtrim.a $ gcc -c hello.c $ ls hello.c hello.o libtrim.a main.c trim.c trim.o $ ar cru libhello.a hello.o $ ranlib libhello.a $ ls hello.c libhello.a main.c trim.o hello.o libtrim.a trim.c |
Notice that there is no way to specify that ‘libhello.a’ won’t work unless it is also linked with ‘libtrim.a’. Because of this I need to list both libraries when I link the application. What’s more, I need to list them in the correct order:
$ gcc -o hello main.c libtrim.a libhello.a /usr/bin/ld: Unsatisfied symbols: trim (code) collect2: ld returned 1 exit status $ gcc -o hello main.c libhello.a libtrim.a $ ls hello hello.o libtrim.a trim.c hello.c libhello.a main.c trim.o $ ./hello Hello, World! |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
libtool
’s inter-library dependency support will use the native
implementation if there is one available. If there is no native
implementation, or if the native implementation is broken or incomplete,
libtool
will use an implementation of its own.
To build ‘libtrim’ as a standard Libtool library (see section The Libtool Library), as follows:
$ rm hello *.a *.o $ ls hello.c main.c trim.c $ libtool gcc -c trim.c rm -f .libs/trim.lo gcc -c -fPIC -DPIC trim.c -o .libs/trim.lo gcc -c trim.c -o trim.o >/dev/null 2>&1 mv -f .libs/trim.lo trim.lo $ libtool gcc -rpath /usr/local/lib -o libtrim.la trim.lo rm -fr .libs/libtrim.la .libs/libtrim.* .libs/libtrim.* /opt/gcc-lib/hp821/2.7.0/ld -b +h libtrim.sl.0 +b /usr/local/lib \ -o .libs/libtrim.sl.0.0 trim.lo (cd .libs && rm -f libtrim.sl.0 && ln -s libtrim.sl.0.0 libtrim.sl.0) (cd .libs && rm -f libtrim.sl && ln -s libtrim.sl.0.0 libtrim.sl) ar cru .libs/libtrim.a trim.o ranlib .libs/libtrim.a creating libtrim.la (cd .libs && rm -f libtrim.la && ln -s ../libtrim.la libtrim.la) |
When you build ‘libhello’, you can specify the libraries it depends on at the command line, like so:
$ libtool gcc -c hello.c rm -f .libs/hello.lo gcc -c -fPIC -DPIC hello.c -o .libs/hello.lo gcc -c hello.c -o hello.o >/dev/null 2>&1 mv -f .libs/hello.lo hello.lo $ libtool gcc -rpath /usr/local/lib -o libhello.la hello.lo libtrim.la rm -fr .libs/libhello.la .libs/libhello.* .libs/libhello.* *** Warning: inter-library dependencies are not known to be supported. *** All declared inter-library dependencies are being dropped. *** The inter-library dependencies that have been dropped here will be *** automatically added whenever a program is linked with this library *** or is declared to -dlopen it. /opt/gcc-lib/hp821/2.7.0/ld -b +h libhello.sl.0 +b /usr/local/lib \ -o .libs/libhello.sl.0.0 hello.lo (cd .libs && rm -f libhello.sl.0 && ln -s libhello.sl.0.0 libhello.sl.0) (cd .libs && rm -f libhello.sl && ln -s libhello.sl.0.0 libhello.sl) ar cru .libs/libhello.a hello.o ranlib .libs/libhello.a creating libhello.la (cd .libs && rm -f libhello.la && ln -s ../libhello.la libhello.la) $ ls hello.c hello.o libtrim.la trim.c trim.o hello.lo libhello.la main.c trim.lo |
Although, on HP-UX, libtool
warns that it doesn’t know
how to use the native inter-library dependency implementation, it will
track the dependencies and make sure they are added to the final link
line, so that you only need to specify the libraries that you use
directly.
Now, you can rebuild ‘hello’ exactly as in the earlier example (see section Linking an Executable), as in:
$ libtool gcc -o hello main.c libhello.la libtool: link: warning: this platform does not like uninstalled libtool: link: warning: shared libraries libtool: link: hello will be relinked during installation gcc -o .libs/hello main.c /tmp/intro-hello/.libs/libhello.sl \ /tmp/intro-hello/.libs/libtrim.sl \ -Wl,+b -Wl,/tmp/intro-hello/.libs:/usr/local/lib creating hello $ ./hello Hello, World! |
Notice that even though you only specified the ‘libhello.la’
library at the command line, libtool
remembers that
‘libhello.sl’ depends on ‘libtrim.sl’ and links that library
too.
You can also link a static executable, and the dependencies are handled similarly:
$ libtool gcc -o hello-again -static main.c libhello.la gcc -o hello main.c ./.libs/libhello.a /tmp/intro-hello/.libs/libtrim.a $ ./hello-again Hello, World! |
For your own projects, provided that you use libtool
, and that
you specify the libraries you wish to link using the ‘.la’
pseudo-libraries, these dependencies can be nested as deeply as you
like. You can also register dependencies on native libraries, though
you will of course need to specify any dependencies that the native
library itself has at the same time.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
To rebuild ‘libtrim’ as a convenience library (see section Creating Convenience Libraries), use the following commands:
$ rm hello *.la $ ls hello.c hello.lo hello.o main.c trim.c trim.lo trim.o $ libtool gcc -o libtrim.la trim.lo rm -fr .libs/libtrim.la .libs/libtrim.* .libs/libtrim.* ar cru .libs/libtrim.al trim.lo ranlib .libs/libtrim.al creating libtrim.la (cd .libs && rm -f libtrim.la && ln -s ../libtrim.la libtrim.la) |
Then, rebuild ‘libhello’, with an inter-library dependency on ‘libtrim’ (see section Inter-library Dependencies), like this:
$ libtool gcc -rpath `pwd`/_inst -o libhello.la hello.lo libtrim.la rm -fr .libs/libhello.la .libs/libhello.* .libs/libhello.* *** Warning: inter-library dependencies are not known to be supported. *** All declared inter-library dependencies are being dropped. *** The inter-library dependencies that have been dropped here will be *** automatically added whenever a program is linked with this library *** or is declared to -dlopen it. rm -fr .libs/libhello.lax mkdir .libs/libhello.lax rm -fr .libs/libhello.lax/libtrim.al mkdir .libs/libhello.lax/libtrim.al (cd .libs/libhello.lax/libtrim.al && ar x /tmp/./.libs/libtrim.al) /opt/gcc-lib/hp821/2.7.0/ld -b +h libhello.sl.0 +b /tmp/hello/_inst \ -o .libs/libhello.sl.0.0 hello.lo .libs/libhello.lax/libtrim.al/trim.lo (cd .libs && rm -f libhello.sl.0 && ln -s libhello.sl.0.0 libhello.sl.0) (cd .libs && rm -f libhello.sl && ln -s libhello.sl.0.0 libhello.sl) rm -fr .libs/libhello.lax mkdir .libs/libhello.lax rm -fr .libs/libhello.lax/libtrim.al mkdir .libs/libhello.lax/libtrim.al (cd .libs/libhello.lax/libtrim.al && ar x /tmp/hello/./.libs/libtrim.al) ar cru .libs/libhello.a hello.o .libs/libhello.lax/libtrim.al/trim.lo ranlib .libs/libhello.a rm -fr .libs/libhello.lax .libs/libhello.lax creating libhello.la (cd .libs && rm -f libhello.la && ln -s ../libhello.la libhello.la) $ ls hello.c hello.o libtrim.la trim.c trim.o hello.lo libhello.la main.c trim.lo |
Compare this to the previous example of building ‘libhello’ and you
can see that things are rather different. On HP-UX, partial
linking is not known to work, so libtool
extracts the objects
from the convenience library, and links them directly into
‘libhello’. That is, ‘libhello’ is comprised of its own
objects and the objects in ‘libtrim’. If ‘libtrim’ had
had any dependencies, ‘libhello’ would have inherited them too.
This technique is especially useful for grouping source files into
subdirectories, even though all of the objects compiled in the
subdirectories must eventually reside in a big library: compile the
sources in each into a convenience library, and in turn link
all of these into a single library which will then contain all of the
constituent objects and dependencies of the various convenience
libraries.
When you relink the hello
executable, notice that
‘libtrim’ is not linked, because the ‘libtrim’
objects are already present in ‘libhello’:
$ libtool gcc -o hello main.c libhello.la libtool: link: warning: this platform does not like uninstalled libtool: link: warning: shared libraries libtool: link: hello will be relinked during installation gcc -o .libs/hello main.c /tmp/intro-hello/.libs/libhello.sl \ -Wl,+b -Wl,/tmp/intro-hello/.libs:/usr/local/lib creating hello $ ./hello Hello, World! |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] |
This document was generated by Ben Elliston on July 10, 2015 using texi2html 1.82.