If you have read Using Automake and Autoconf with C++ then you should already know how to use automake and autoconf to build your C++ programs. This document will show you how to use the same tools to build a reusable library. I have included an example which demonstrates these ideas.
You may also wish to read Using C/C++ libraries with automake and autoconf to see what users of your library will expect.
Why use libtool?
Each platform has its own way of implementing the shared (or 'dynamic') library idea, and there are various tools needed to build these libraries. Libtool delegates to these platform-specific tools and presents the developer with a simpler set of options. Automake and autoconf can use libtool to build libraries for many OS and development environments using the same build files.
Libtool also makes it easy to build a static library or a dynamic library from the same project.
libtoolize
When you start your project files you need to issue the 'libtoolize' command to add libtool support files to your project.
AM_LIBTOOL
You need to call AM_PROG_LIBTOOL in your configure.ac file.
libtool variables
When building an executable you use something like this in your Makefile.am:
PROGRAMS = someapp someapp_SOURCES = main.ccTo build a library you use the LTLIBRARIES set of variables instead:
lib_LTLIBRARIES = something-1.0.la something_la_SOURCES = something.h something.ccParallel installs
Notice that the library is called something-1.0.la, including the version number in its name. This will allow the next version, libsomething-2.0, to be installed alongside, without preventing use of the previous version.
Don't use 'src'
When the library is installed, its headers will be installed in their own directory in the 'include' directory. Code that uses the library should #include them like so:
#include <something/something.h> #include <something/extrabits.h>If you put your source files in a 'src' directory then the #include lines in your own headers will not work when they are installed, and the #includes in your examples (in the 'examples' directory') will be misleading. At best, they will include like so:
#include <something.h> #include <extrabits.h>I suggest that you put your sources in a directory that has the same name as your library. Then the examples inside your distribution and any external examples will use the same path in their #include directives.
Sources in sub directories
In Using automake and autoconf with C++ I explained how to build intermediate static libraries in each sub directory. The idea is very similar when building a library, but the syntax is slightly different.
- Libtool libraries have the .la suffix, instead of .a
- We need to use _LIBADD instead of_ LDADD.
For instance
lib_LTLIBRARIES = something.la something_la_SOURCES = main.cc something_la_LIBADD = sub/libsubstuff.laThis technique is demonstrated in the downloadable example.Note that, at the time of writing, there are two problems with libtool that you should be aware of:
- Libtool will not add libtool libraries recursively. Therefore you need to list all of the convenience libraries in one place. For instance:
something_la_LIBADD = sub/libsub.la sub/subsub/libsubsub.la- Libtool will not differentiate between two libraries with the same name in different directories. Therefore you should probably include the full path in the name of your convenience libraries. For instance:
something_la_LIBADD = foo/libfoo.la foo/sub/libfoo_sub.la goo/libgoo.la goo/sub/libgoo_sub.laHopefully these problems will be fixed in the next version of libtool. Please tell me when they have been fixed, so that I can update this page.
When the user types 'make install' the library's header files should be installed as well as the library itself. You can make this happen by using these variables in your Makefile.am files:
library_includedir=$(includedir)/something-1.0/something library_include_HEADERS = something.h foo.hThis will put something.h and foo.h in include/something-1.0/something/
Users of the library would then #include your headers like so:#include <something/something.h>Parallel installs
Notice that the headers should be installed in a version-specific directory. This will allow the next version's headers to be installed alongside in something-2.0, without preventing use of the previous version's headers.
config.h
The generated config.h header should be installed in the lib directory, because it is architecture-dependent. Actually, I'd like a better explanation than that to put here.
For example, in your Makefile,am file:
something_configdir = $(libdir)/something-1.0/include something_config_DATA = config.h
Your library should have two numbers - the 'release number' and the 'version number'.
The release number uses a scheme of your own devising. Generally it indicates how much functionality has been added since the last version, and how many bugs were fixed.
The version number uses an established scheme to indicate what type of changes happened to your library's interface. The following diagram can be found in many configure.ac files:
EXAMPLE_RELEASE=2:1:3 EXAMPLE_LIBRARY_VERSION=3:0:0 | | | +------+ | +---+ | | | current:revision:age | | | | | +- increment if interfaces have been added | | set to zero if interfaces have been removed | | or changed | +- increment if source code has changed | set to zero if current is incremented +- increment if interfaces have been added, removed or changedUse this version number in your Makefile.am file:
libsomething_la_LDFLAGS= -version-info $(EXAMPLE_LIBRARY_VERSION) -release $(EXAMPLE_RELEASE)
Experts can use your library if they are given just the headers and the library, but you can make life much easier for people who are using automake and autoconf. In my opinion, your library will appear more complete, and will be used by more people if you use pkg-config. This tool was created relatively recently to improve upon the old method, described here. It allows you to install details about your library, specifically the linker and include options that should be used with it. Developers can add a line to their configure.ac files that reads this infomation back, along with the options required for your library's dependencies.
The .pc.in file
Your library should install a .pc file, describing the linker and include options for your library. But those are dependent on the --prefix given to the configure script, so you'll need to crate a .pc.in file. For instance:
prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: something Description: Some library. Requires: somethingelse-2.0 somethingmore-1.0 Version: @VERSION@ Libs: -L${libdir} -lsomething-1.0 Cflags: -I${includedir}/something-1.0 -I${libdir}/something-1.0/includeYou'll need to mention this new .in file in your configure.ac script, like so:
AC_OUTPUT( Makefile \ something/Makefile \ something/sub/Makefile \ something-1.0.pc )And you'll need to mention it in your Makefile.am file, so that it gets installed and distributed. For instance:
pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = something-1.0.pc
Read Using C/C++ libraries with automake and autoconf to see how this pkg-config file would be used.
Parallel Installs
The .pc.in file should include the version number in its name. For instance, something-1.0.pc.in. This will allow the next version of the library to install its own something-2.0.pc file alongside, without preventing use of the previous version.
If you are writing a C++ library, I strongly suggest that you put all the classes in a namespace. For instance, in the header file:
namespace Something {class Example { Example(); ... };} /* namespace Something */And in the implementation file:
namespace Something {Example::Example() { ... } ...} /* namespace Something */This will prevent name clashes and make it more obvious when other code is using the library.
You may download this example which demonstrates how to put all these ideas together.
This example uses some 'generic' variables instead of repeating the library name several times. This should make the project files easier to maintain, and it is used to generate the examplelib-config script automatically. Thanks to Cedric Gustin for this idea.
The document Using C/C++ libraries with automake and autoconf contains an example which links to this library.
Copyright © Murray Cumming, Openismus GmbH.
