Without libtool, the programmer would invoke the ar
command to
create a static library:
burger$ ar cr libhello.a hello.o foo.o burger$
But of course, that would be too simple, so many systems require that
you run the ranlib
command on the resulting library in order to
generate a symbol table:
burger$ ranlib libhello.a burger$
It seems more natural to use the C compiler for this task, given
libtool’s “libraries are programs” approach. So, on platforms without
shared libraries, libtool simply acts as a wrapper for the system
ar
(and possibly ranlib
) commands.
Again, the libtool control file name (.la suffix) differs from the standard library name (.a suffix). The arguments to libtool are the same ones you would use to produce an executable named libhello.la with your compiler (see Link mode):
a23$ libtool --mode=link gcc -g -O -o libhello.la foo.o hello.o *** Warning: Linking the shared library libhello.la against the *** non-libtool objects foo.o hello.o is not portable! ar cr .libs/libhello.a ranlib .libs/libhello.a creating libhello.la (cd .libs && rm -f libhello.la && ln -s ../libhello.la libhello.la) a23$
Aha! Libtool caught a common error… trying to build a library from standard objects instead of special .lo object files. This doesn’t matter so much for static libraries, but on shared library systems, it is of great importance. (Note that you may replace libhello.la with libhello.a in which case libtool won’t issue the warning any more. But although this method works, this is not intended to be used because it makes you lose the benefits of using Libtool.)
So, let’s try again, this time with the library object files. Remember
also that we need to add -lm to the link command line because
foo.c uses the cos
math library function (see Using libtool).
Another complication in building shared libraries is that we need to specify the path to the directory where they will (eventually) be installed (in this case, /usr/local/lib)1:
a23$ libtool --mode=link gcc -g -O -o libhello.la foo.lo hello.lo \ -rpath /usr/local/lib -lm ar cr .libs/libhello.a foo.o hello.o ranlib .libs/libhello.a creating libhello.la (cd .libs && rm -f libhello.la && ln -s ../libhello.la libhello.la) a23$
Now, let’s try the same trick on the shared library platform:
burger$ libtool --mode=link gcc -g -O -o libhello.la foo.lo hello.lo \ -rpath /usr/local/lib -lm rm -fr .libs/libhello.a .libs/libhello.la ld -Bshareable -o .libs/libhello.so.0.0 .libs/foo.o .libs/hello.o -lm ar cr .libs/libhello.a foo.o hello.o ranlib .libs/libhello.a creating libhello.la (cd .libs && rm -f libhello.la && ln -s ../libhello.la libhello.la) burger$
Now that’s significantly cooler… Libtool just ran an obscure
ld
command to create a shared library, as well as the static
library.
Note how libtool creates extra files in the .libs subdirectory, rather than the current directory. This feature makes it easier to clean up the build directory, and helps ensure other programs fail horribly if you accidentally forget to use libtool when you should.
Again, you should look at the .la file to see what Libtool stores in it. You will see Libtool uses this file to remember the destination directory for the library (the argument to -rpath) as well as the dependency on the math library (‘-lm’).
If you don’t
specify an rpath
, then libtool builds a libtool convenience
archive, not a shared library (see Linking static libraries).