manpagez: man pages & more
info libtool
Home | html | info | man

File: libtool.info,  Node: Linking executables,  Next: Debugging executables,  Prev: Linking libraries,  Up: Using libtool

3.3 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 --mode=link gcc -g -O -o hell main.o libhello.la
     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.  Notice Libtool also remembered ‘libhello.la’ depends
on ‘-lm’, so even though we didn't specify ‘-lm’ on the libtool command
line(2) Libtool has added it to the ‘gcc’ link line for us.

   On ‘burger’ Libtool links against the uninstalled shared library:

     burger$ libtool --mode=link gcc -g -O -o hell main.o libhello.la
     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 -lm

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

     burger$ libtool --mode=link 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?

   Notice the executable, ‘hell’, was actually created in the ‘.libs’
subdirectory.  Then, a wrapper script (or, on certain platforms, a
wrapper executable *note Wrapper executables::) was created in the
current directory.

   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.

   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 the executable finds the correct shared
library (the one in ‘./.libs’) so it can be 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.

* Menu:

* Wrapper executables::         Wrapper executables for some platforms.

   ---------- 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.

   (2) And why should we?  ‘main.o’ doesn't directly depend on ‘-lm’
after all.

© manpagez.com 2000-2025
Individual documents may contain additional copyright information.