Building C/C++ libraries with Automake and Autoconf

29 篇文章 0 订阅
12 篇文章 0 订阅

From: http://www.openismus.com/documents/linux/building_libraries/building_libraries


Building C/C++ libraries with Automake and Autoconf

Contents

Introduction

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. An example is included 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.

libtool

Why use libtool?

Each platform has its own way of implementing the shared (or "dynamically loaded") 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 unified set of options. Automake and autoconf can use libtool to build libraries for many operating systems 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.

LT_INIT

Modern versions of autoconf and automake have optional built-in support for libtool. Once the libtool package is installed, you can call LT_INIT in your configure.ac file. The next time that you run autoreconf, the necessary libtool support files will be copied to your project.

libtool variables

When building an executable you use something like this in your Makefile.am:

PROGRAMS = someapp
someapp_SOURCES = main.cc

To build a library you use the LTLIBRARIES set of variables instead:

lib_LTLIBRARIES = libsomething-1.0.la
libsomething_1_0_la_SOURCES = something.cc
Parallel installs

Notice that the library is called libsomething-1.0.la, including a 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. This API version number is distinct from the actual library version. It should change only when incompatible changes have been made to the library interface.

Directory structure

Installing headers

When the library is installed, its header files should be installed into their own subdirectory of the common include directory. This practise avoids namespace pollution, and avoids the need to prefix the filenames themselves in order to avoid conflicts with other libraries' header files.

For this to work, the subdirectory which contains the header files must not be in the include search path of the compiler. Instead, code that uses the library should include the headers like so:

#include <something/something.h>
#include <something/extrabits.h>

Often, there is also a single central header file which does not live in the subdirectory, and is included without the directory prefix. This header file usually has the same name as the library itself.

If you put your source files in a "src/" subdirectory, or any directory named differently than the installation subdirectory, it will be difficult for a public header file to include other headers files of the library without putting all header files directly on the include path. The same also applies to code examples which are built using the uninstalled header files from the source tree.

For this reason, we recommend to place all public source files in the tree into subdirectories with the same name and relative location as used for the installation.

Sources in subdirectories

In Using automake and autoconf with C++, it is explained how to build several source files from different subdirectories together into one binary. The idea is very similar when building a library, but the syntax is slightly different. For example, libtool target names should have a "lib" prefix and must have the ".la" file extension.

For instance:

lib_LTLIBRARIES = libsomething-1.0.la
libsomething_1_0_la_SOURCES = something/main.cc something/sub/sub.cc

The downloadable example demonstrates this technique, alongside with detailed explanations of what each declaration does.

Installing headers

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/foo.h something/bar.h

This will put foo.h and bar.h in <prefix>/include/something-1.0/something/. Users of the library would then include your headers like so:

#include <something/foo.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

Many non-trivial libraries have a public configuration header file which provides compile-time information about the target platform the library was built for. This header file is usually named somethingconfig.h for a library called "something". It must only define macros with a namespace prefix to prevent clashes with user code.

The public configuration header should be installed in a subdirectory of $(libdir) rather than$(includedir), since its contents are architecture-dependent. For example, in your Makefile.am:

something_libincludedir = $(libdir)/something-1.0/include
nodist_something_libinclude_HEADERS = config.h

Version numbers

Your library should have a 'version number' to identify it. This is not the same as the version number of the package as a whole. For example, gtkmm-2.20.2 has a package version of 2.20.2 but a library (sometimes called SO for 'shared object') version of 2:0:1.

The library version number uses an established scheme to indicate what type of changes happened to your library's interface. The scheme is documented in the Libtool's versioning system section of the libtool manual, and consists of three numbers, separated by colons. For example:

EXAMPLE_LIBRARY_VERSION=3:0:0

Use this version number in your Makefile.am file:

libsomething_1_0_la_LDFLAGS = -version-info $(EXAMPLE_LIBRARY_VERSION)

Making your library easy to use

A library can be used if just the headers and the shared library object are provided. However, in an environment where software is usually made available as source packages, authors usually do not provide the compiled binaries for most of their end users. This work is done either by the end user directly, or by packagers of distributions to provide integrated systems build from many independently developed components.

In such an environment, it is very important for your library to integrate well with the platforms it is installed on. If installation paths, features, etc are variable dependending on the target platform or build-time settings, there should be a means for an application developer to query configuration information about the library using automated tools. This way, the application developer is able to provide a single source package which will automatically configure itself to build with your library on all supported target platforms.

These days, the best way to make this configuration information available is the pkg-config tool. This tool was created to improve upon the old method of manually written shell scripts, describedhere. 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. However, those are dependent on the --prefix given to the configure script, so you will need to create a .pc.in file, which is used to create a .pc file that is updated each time configure is run. 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: @PACKAGE_VERSION@
Libs: -L${libdir} -lsomething-1.0
Cflags: -I${includedir}/something-1.0 -I${libdir}/something-1.0/include

You will need to mention this new .pc file that should be created in your configure.ac file, like so:

AC_CONFIG_FILES([Makefile something-1.0.pc])

And you will need to mention it in your Makefile.am file, so that it gets installed. For instance:

pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = something-1.0.pc

The .pc.in file is automatically marked for distribution by the AC_CONFIG_FILES call.

Read Using C/C++ libraries with automake and autoconf to see how this pkg-config file would be used.

Parallel Installs

The .pc file should include the version number in its name. For instance, something-1.0.pc. 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.

The example library package demonstrates a way to include the version number in the generated .pc file's name without having to also include it in the name of the .pc.in template file.

C++ namespaces

If you are writing a C++ library, you should you put all of 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.

Example Files

You may download this example which demonstrates how to put all these ideas together, or you can browse the source on the Gitorious project page.

The document Using C/C++ libraries with automake and autoconf contains an example which links to this library.


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值