[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
A Libtool library is built from Libtool objects in the same way
that a native (non-Libtool) library is built from native objects.
Building a Libtool library with libtool
is as easy as building
an old style static archive. Generally, each of the sources is compiled
to a Libtool object, and then these objects are combined to create
the library.
If you want to try this to see what
libtool
does on your machine, put the following code in a file ‘hello.c’, in a directory of its own, and run the example shell commands from there:
#include <stdio.h> void hello (char *who) { printf ("Hello, %s!\n", who); }
The traditional way to make a (native) static library is as follows:
$ gcc -c hello.c $ ls hello.c hello.o $ ar cru libhello.a hello.o $ ranlib libhello.a $ ls hello.c hello.o libhello.a |
Notice that even when I just want to build an old static archive, I need
to know that, in common with most Unices, I have to
bless(14) my library with ranlib
to make it work optimally on
HP-UX.
Essentially, Libtool supports the building of three types of library: shared libraries; static libraries; and convenience libraries. In the following sections I will talk about each in turn, but first you will need to understand how to create and use position independent code, as explained in the next section.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
On most architectures, when you compile source code to object code, you need to specify whether the object code should be position independent or not. There are occasional architectures which don’t make the distinction, usually because all object code is position independent by virtue of the ABI(15), or less often because the load address of the object is fixed at compile time (which implies that shared libraries are not supported by such a platform). If an object is compiled as position independent code (PIC), then the operating system can load the object at any address in preparation for execution. This involves a time overhead, in replacing direct address references with relative addresses at compile time, and a space overhead, in maintaining information to help the runtime loader fill in the unresolved addresses at runtime. Consequently, PIC objects are usually slightly larger and slower at runtime than the equivalent non-PIC object. The advantage of sharing library code on disk and in memory outweigh these problems as soon as the PIC object code in shared libraries is reused.
PIC compilation is exactly what is required for objects which will
become part of a shared library. Consequently, libtool
builds
PIC objects for use in shared libraries and non-PIC objects
for use in static libraries. Whenever libtool
instructs the
compiler to generate a PIC object, it also defines the preprocessor
symbol, ‘PIC’, so that assembly code can be aware of whether it
will reside in a PIC object or not.
Typically, as libtool
is compiling sources, it will generate a
‘.lo’ object, as PIC, and a ‘.o’ object, as non-PIC,
and then it will use the appropriate one of the pair when linking
executables and libraries of various sorts. On architectures where
there is no distinction, the ‘.lo’ file is just a soft link to the
‘.o’ file.
In practice, you can link PIC objects into a static archive for a
small overhead in execution and load speed, and often you can similarly
link non-PIC objects into shared archives. If you find that you
need to do this, libtool
provides several ways to override the
default behavior (see section Creating libtool
).
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
From Libtool’s point of view, the term ‘shared library’ is somewhat of a misnomer. Since Libtool is intended to abstract away the details of library building, it doesn’t matter whether Libtool is building a shared library or a static archive. Of course, Libtool will always try to build a shared library by default on the platforms to which it has been ported (see section PLATFORMS), but will equally fall back to building a static archive if the host architecture does not support shared libraries, or if the project developer deliberately configures Libtool to always build static archives only. These libraries are more properly called ‘Libtool libraries’; the underlying native library will usually be a shared library, except as described above.
To create a Libtool library on my HP-UX host, or indeed anywhere
else that libtool
works, run the following commands:
$ rm hello.o libhello.a $ libtool gcc -c hello.c mkdir .libs 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 $ ls hello.c hello.lo hello.o $ libtool gcc -rpath /usr/local/lib -o libhello.la hello.lo rm -fr .libs/libhello.la .libs/libhello.* .libs/libhello.* /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.lo hello.o libhello.la |
This example illustrates several features of libtool
. Compare
the command line syntax with the previous example (see section The Libtool Library). They are both very similar. Notice, however, that when
compiling the ‘hello.c’ source file, libtool
creates
two objects. The first, ‘hello.lo’, is the Libtool
object which we use for Libtool libraries, and the second,
‘hello.o’ is a standard object. On HP-UX, libtool
knows that Libtool objects should be compiled with position
independent code, hence the extra switches when creating the first
object.
When you run
libtool
from the command line, you must also specify a compiler for it to call. Similarly when you create alibtool
script withltconfig
, a compiler is chosen and interrogated to discover what characteristics it has. See section Creatinglibtool
.Prior to release 1.4 of Libtool,
ltconfig
probed the build machine for a suitable compiler, by searching first forgcc
and thencc
. The functionality ofltconfig
is being migrated into the ‘AC_PROG_LIBTOOL’ macro, such that there will be noltconfig
script in Libtool release 1.5. The current release is part way between the two. In all cases, you can specify a particular compiler by setting the ‘CC’ environment variable.It is important to continue to use the same compiler when you run
libtool
as the compiler that was used when you created thelibtool
script. If you create the script with ‘CC’ set togcc
, and subsequently try to compile using, say:
$ libtool c89 -rpath /usr/local/lib -c hello.c
libtool
will try to callc89
using the options it discovered forgcc
. Needless to say, that doesn’t work!
The link command specifies a Libtool library target, ‘libhello.la’,
compiled from a single Libtool object, ‘hello.lo’. Even so,
libtool
knows how to build both static and shared archives on
HP-UX – underneath the libtool
abstraction both are
created. libtool
also understands the particulars of library
linking on HP-UX: the static archive, ‘libhello.a’, is
blessed; the system (and compiler) dependent compiler and linker
flags, versioning scheme and .sl
extension are utilised for the
shared archive, ‘libhello.sl’. On another host, all of these
details may be completely different, yet with exactly the same
invocation, libtool
will call the native tools with the
appropriate options to achieve the same result. Try it on your own
machines to see any differences.
It is the ‘-rpath’ switch that tells libtool
that you
want to build a Libtool library (with both the shared and static
components where possible). If you omit the ‘-rpath’ switch,
libtool
will build a convenience library instead,
see Creating convenience Libraries. The ‘-rpath’ switch is doubly
important, because it tells libtool
that you intend to install
‘libhello.la’ in ‘/usr/local/lib’. This allows
libtool
to finalize the library correctly after installation
on the architectures that need it, see Installing a Library.
Finally, notice that only the Libtool library, ‘libhello.la’, is visible after a successful link. The various files which form the local implementation details of the Libtool library are in a hidden subdirectory, but in order for the abstraction to work cleanly you shouldn’t need to worry about these too much.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
In contrast, libtool
will create a static library if either
the ‘-static’ or ‘-all-static’ switches are specified on
the link line for a Libtool library:
$ libtool gcc -static -o libhello.la hello.lo rm -fr .libs/libhello.la .libs/libhello.* .libs/libhello.* 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) |
Note that since libtool
will only create a static archive, the
‘-rpath’ switch is not required: once a static library has been
installed, there is no need to perform additional finalization for the
library to be used from the installed location(16), or
to track runtime search paths when installing a static archive.
When you link an executable against this ‘libhello.la’, the objects from the static archive will be statically linked into the executable. The advantage of such a library over the traditional native static archive is that all of the dependency information from the Libtool library is used. For an example, See section Creating Convenience Libraries.
libtool
is useful as a general library building toolkit, yet people still seem to regress to the old way of building libraries whenever they want to use static archives. You should exploit the consistent interface oflibtool
even for static archives. If you don’t want to use shared archives, use the ‘-static’ switch to build a static Libtool library.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
The third type of library which can be built with libtool
is the
convenience library. Modern compilers are able to create
partially linked objects: intermediate compilation units which
comprise several compiled objects, but are neither an executable or a
library. Such partially linked objects must be subsequently linked
into a library or executable to be useful. Libtool convenience
libraries are partially linked objects, but are emulated by
libtool
on platforms with no native implementation.
If you want to try this to see what
libtool
does on your machine, put the following code in a file ‘trim.c’, in the same directory as ‘hello.c’ and ‘libhello.la’, and run the example shell commands from there:
#include <string.h> #define WHITESPACE_STR " \f\n\r\t\v" /** * Remove whitespace characters from both ends of a copy of * '\0' terminated STRING and return the result. **/ char * trim (char *string) { char *result = 0; /* Ignore NULL pointers. */ if (string) { char *ptr = string; /* Skip leading whitespace. */ while (strchr (WHITESPACE_STR, *ptr)) ++ptr; /* Make a copy of the remainder. */ result = strdup (ptr); /* Move to the last character of the copy. */ for (ptr = result; *ptr; ++ptr) /* NOWORK */; --ptr; /* Remove trailing whitespace. */ for (--ptr; strchr (WHITESPACE_STR, *ptr); --ptr) *ptr = '\0'; } return result; }
To compile the convenience library with libtool
, you would do
this:
$ 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 -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) |
Additionally, you can use a convenience library as an alias for a set of zero or more object files and some dependent libraries. If you need to link several objects against a long list of libraries, it is much more convenient to create an alias:
$ libtool gcc -o libgraphics.la -lpng -ltiff -ljpeg -lz rm -fr .libs/libgraphics.la .libs/libgraphics.* .libs/libgraphics.* ar cru .libs/libgraphics.al ranlib .libs/libgraphics.al creating libgraphics.la (cd .libs && rm -f libgraphics.la && \ ln -s ../libgraphics.la libgraphics.la) |
Having done this, whenever you link against ‘libgraphics.la’ with
libtool
, all of the dependent libraries will be linked too.
In this case, there are no actual objects compiled into the convenience
library, but you can do that too, if need be.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] |
This document was generated by Ben Elliston on July 10, 2015 using texi2html 1.82.