libtool: Linking executables

1 
1 3.3 Linking executables
1 =======================
1 
1 If you choose at this point to "install" the library (put it in a
1 permanent location) before linking executables against it, then you
1 don't need to use libtool to do the linking.  Simply use the appropriate
1 '-L' and '-l' flags to specify the library's location.
1 
1    Some system linkers insist on encoding the full directory name of
1 each shared library in the resulting executable.  Libtool has to work
1 around this misfeature by special magic to ensure that only permanent
1 directory names are put into installed executables.
1 
1    The importance of this bug must not be overlooked: it won't cause
1 programs to crash in obvious ways.  It creates a security hole, and
1 possibly even worse, if you are modifying the library source code after
1 you have installed the package, you will change the behaviour of the
1 installed programs!
1 
1    So, if you want to link programs against the library before you
1 install it, you must use libtool to do the linking.
1 
1    Here's the old way of linking against an uninstalled library:
1 
1      burger$ gcc -g -O -o hell.old main.o libhello.a -lm
1      burger$
1 
1    Libtool's way is almost the same(1) (⇒Link mode):
1 
1      a23$ libtool --mode=link gcc -g -O -o hell main.o libhello.la
1      gcc -g -O -o hell main.o  ./.libs/libhello.a -lm
1      a23$
1 
1    That looks too simple to be true.  All libtool did was transform
1 'libhello.la' to './.libs/libhello.a', but remember that 'a23' has no
1 shared libraries.  Notice that Libtool also remembered that
1 'libhello.la' depends on '-lm', so even though we didn't specify '-lm'
1 on the libtool command line(2) Libtool has added it to the 'gcc' link
1 line for us.
1 
1    On 'burger' Libtool links against the uninstalled shared library:
1 
1      burger$ libtool --mode=link gcc -g -O -o hell main.o libhello.la
1      gcc -g -O -o .libs/hell main.o -L./.libs -R/usr/local/lib -lhello -lm
1      creating hell
1      burger$
1 
1    Now assume 'libhello.la' had already been installed, and you want to
1 link a new program with it.  You could figure out where it lives by
1 yourself, then run:
1 
1      burger$ gcc -g -O -o test test.o -L/usr/local/lib -lhello -lm
1 
1    However, unless '/usr/local/lib' is in the standard library search
1 path, you won't be able to run 'test'.  However, if you use libtool to
1 link the already-installed libtool library, it will do The Right Thing
1 (TM) for you:
1 
1      burger$ libtool --mode=link gcc -g -O -o test test.o \
1                      /usr/local/lib/libhello.la
1      gcc -g -O -o .libs/test test.o -Wl,--rpath \
1              -Wl,/usr/local/lib /usr/local/lib/libhello.a -lm
1      creating test
1      burger$
1 
1    Note that libtool added the necessary run-time path flag, as well as
1 '-lm', the library libhello.la depended upon.  Nice, huh?
1 
1    Notice that the executable, 'hell', was actually created in the
1 '.libs' subdirectory.  Then, a wrapper script (or, on certain platforms,
1 a wrapper executable ⇒Wrapper executables) was created in the
1 current directory.
1 
1    Since libtool created a wrapper script, you should use libtool to
1 install it and debug it too.  However, since the program does not depend
1 on any uninstalled libtool library, it is probably usable even without
1 the wrapper script.
1 
1    On NetBSD 1.2, libtool encodes the installation directory of
1 'libhello', by using the '-R/usr/local/lib' compiler flag.  Then, the
1 wrapper script guarantees that the executable finds the correct shared
1 library (the one in './.libs') until it is properly installed.
1 
1    Let's compare the two different programs:
1 
1      burger$ time ./hell.old
1      Welcome to GNU Hell!
1      ** This is not GNU Hello.  There is no built-in mail reader. **
1              0.21 real         0.02 user         0.08 sys
1      burger$ time ./hell
1      Welcome to GNU Hell!
1      ** This is not GNU Hello.  There is no built-in mail reader. **
1              0.63 real         0.09 user         0.59 sys
1      burger$
1 
1    The wrapper script takes significantly longer to execute, but at
1 least the results are correct, even though the shared library hasn't
1 been installed yet.
1 
1    So, what about all the space savings that shared libraries are
1 supposed to yield?
1 
1      burger$ ls -l hell.old libhello.a
1      -rwxr-xr-x  1 gord  gord  15481 Nov 14 12:11 hell.old
1      -rw-r--r--  1 gord  gord   4274 Nov 13 18:02 libhello.a
1      burger$ ls -l .libs/hell .libs/libhello.*
1      -rwxr-xr-x  1 gord  gord  11647 Nov 14 12:10 .libs/hell
1      -rw-r--r--  1 gord  gord   4274 Nov 13 18:44 .libs/libhello.a
1      -rwxr-xr-x  1 gord  gord  12205 Nov 13 18:44 .libs/libhello.so.0.0
1      burger$
1 
1    Well, that sucks.  Maybe I should just scrap this project and take up
1 basket weaving.
1 
1    Actually, it just proves an important point: shared libraries incur
1 overhead because of their (relative) complexity.  In this situation, the
1 price of being dynamic is eight kilobytes, and the payoff is about four
1 kilobytes.  So, having a shared 'libhello' won't be an advantage until
1 we link it against at least a few more programs.
1 

Menu