GNU Info

Info Node: (libtool.info)Linking executables

(libtool.info)Linking executables


Next: Debugging executables Prev: Linking libraries Up: Using libtool
Enter node , (file) or (file)node

Linking executables
===================

   If you choose at this point to "install" the library (put it in a
permanent location) before linking executables against it, then you
don't need to use libtool to do the linking.  Simply use the appropriate
`-L' and `-l' flags to specify the library's location.

   Some system linkers insist on encoding the full directory name of
each shared library in the resulting executable.  Libtool has to work
around this misfeature by special magic to ensure that only permanent
directory names are put into installed executables.

   The importance of this bug must not be overlooked: it won't cause
programs to crash in obvious ways.  It creates a security hole, and
possibly even worse, if you are modifying the library source code after
you have installed the package, you will change the behaviour of the
installed programs!

   So, if you want to link programs against the library before you
install it, you must use libtool to do the linking.

   Here's the old way of linking against an uninstalled library:

     burger$ gcc -g -O -o hell.old main.o libhello.a -lm
     burger$

   Libtool's way is almost the same(1) (Note: Link mode):

     a23$ libtool gcc -g -O -o hell main.o libhello.la -lm
     gcc -g -O -o hell main.o ./.libs/libhello.a -lm
     a23$

   That looks too simple to be true.  All libtool did was transform
`libhello.la' to `./.libs/libhello.a', but remember that `a23' has no
shared libraries.

   On `burger' the situation is different:

     burger$ libtool gcc -g -O -o hell main.o libhello.la -lm
     gcc -g -O -o .libs/hell main.o -L./.libs -R/usr/local/lib -lhello -lm
     creating hell
     burger$

   Now assume `libhello.la' had already been installed, and you want to
link a new program with it.  You could figure out where it lives by
yourself, then run:

     burger$ gcc -g -O -o test test.o -L/usr/local/lib -lhello

   However, unless `/usr/local/lib' is in the standard library search
path, you won't be able to run `test'.  However, if you use libtool to
link the already-installed libtool library, it will do The Right Thing
(TM) for you:

     burger$ libtool gcc -g -O -o test test.o /usr/local/lib/libhello.la
     gcc -g -O -o .libs/test test.o -Wl,--rpath
     -Wl,/usr/local/lib /usr/local/lib/libhello.a -lm
     creating test
     burger$

   Note that libtool added the necessary run-time path flag, as well as
`-lm', the library libhello.la depended upon.  Nice, huh?

   Since libtool created a wrapper script, you should use libtool to
install it and debug it too.  However, since the program does not depend
on any uninstalled libtool library, it is probably usable even without
the wrapper script.  Libtool could probably be made smarter to avoid the
creation of the wrapper script in this case, but this is left as an
exercise for the reader.

   Notice that the executable, `hell', was actually created in the
`.libs' subdirectory.  Then, a wrapper script was created in the
current directory.

   On NetBSD 1.2, libtool encodes the installation directory of
`libhello', by using the `-R/usr/local/lib' compiler flag.  Then, the
wrapper script guarantees that the executable finds the correct shared
library (the one in `./.libs') until it is properly installed.

   Let's compare the two different programs:

     burger$ time ./hell.old
     Welcome to GNU Hell!
     ** This is not GNU Hello.  There is no built-in mail reader. **
             0.21 real         0.02 user         0.08 sys
     burger$ time ./hell
     Welcome to GNU Hell!
     ** This is not GNU Hello.  There is no built-in mail reader. **
             0.63 real         0.09 user         0.59 sys
     burger$

   The wrapper script takes significantly longer to execute, but at
least the results are correct, even though the shared library hasn't
been installed yet.

   So, what about all the space savings that shared libraries are
supposed to yield?

     burger$ ls -l hell.old libhello.a
     -rwxr-xr-x  1 gord  gord  15481 Nov 14 12:11 hell.old
     -rw-r--r--  1 gord  gord   4274 Nov 13 18:02 libhello.a
     burger$ ls -l .libs/hell .libs/libhello.*
     -rwxr-xr-x  1 gord  gord  11647 Nov 14 12:10 .libs/hell
     -rw-r--r--  1 gord  gord   4274 Nov 13 18:44 .libs/libhello.a
     -rwxr-xr-x  1 gord  gord  12205 Nov 13 18:44 .libs/libhello.so.0.0
     burger$

   Well, that sucks.  Maybe I should just scrap this project and take up
basket weaving.

   Actually, it just proves an important point: shared libraries incur
overhead because of their (relative) complexity.  In this situation, the
price of being dynamic is eight kilobytes, and the payoff is about four
kilobytes.  So, having a shared `libhello' won't be an advantage until
we link it against at least a few more programs.

   ---------- Footnotes ----------

   (1) However, you should avoid using `-L' or `-l' flags to link
against an uninstalled libtool library.  Just specify the relative path
to the `.la' file, such as `../intl/libintl.la'.  This is a design
decision to eliminate any ambiguity when linking against uninstalled
shared libraries.


automatically generated by info2www version 1.2.2.9