build systems with autoconf, automake and libtool [updated]

43
Build Systems with autoconf and libtool Benny Siegert ‹[email protected]The MirOS Project (http://www.mirbsd.org) FOSDEM 2010

Upload: benny-siegert

Post on 14-May-2015

4.897 views

Category:

Technology


2 download

DESCRIPTION

Talk held at FOSDEM 2010

TRANSCRIPT

Page 1: Build Systems with autoconf, automake and libtool [updated]

Build Systems with autoconf and libtool

Benny Siegert ‹[email protected]›The MirOS Project (http://www.mirbsd.org)

FOSDEM 2010

Page 2: Build Systems with autoconf, automake and libtool [updated]

Contents1. Theory

a) Introduction: a history lesson

b) Presentation of components

2. Practice

a) A concrete example

b) Bad practices

3. Conclusion

Page 3: Build Systems with autoconf, automake and libtool [updated]

Make!les‣ since Version 7 AT&T Unix (ca 1977)

‣ Targets = !lenameswith dependencies and compiler commands

‣ “Phony” !lenames like “install”

# extremely simple Makefilefoo: foo.o cc -o foo foo.o

foo.o: foo.c cc -c -o foo.o foo.c

install: foo install -m 555 foo /usr/local/bin

Page 4: Build Systems with autoconf, automake and libtool [updated]

… end of story?

Problem: Options

‣ compiler "ags, conditionals

‣ paths: headers, installation directory?

‣ user must be able to adjust these

‣ manually editing Make!les today?unacceptable!

Page 5: Build Systems with autoconf, automake and libtool [updated]

Other build systems‣ imake (X11): Imake!le + cpp ➝ Make!le

‣ a nightmare in practice

‣ Xorg now uses autotools, they know why

‣ Schily make (J?rg Schilling, cdrtools)

‣ >300 Make!le fragments, one per platform

‣ does not work with BSD make

‣ bsd.prog.mk etc (BSD): platform dependent

Page 6: Build Systems with autoconf, automake and libtool [updated]

The GNU build system‣ almost everywhere today (good!)

‣ easy to use:

% ./configure ; make ; make install

‣ But: few developers understand it

‣ more and more “easier” alternatives (cmake)

‣ Is it really too complicated?

— No, because a portable build system is difficult!

Page 7: Build Systems with autoconf, automake and libtool [updated]

Introducingautotools

Page 8: Build Systems with autoconf, automake and libtool [updated]

con!gure

‣ gets options:target dir, compiler "ags, paths, modules, etc.

‣ searches for libraries, headers, paths

‣ creates con!g.status

‣ con!g.status handles replacement variables(e.g. CC, CFLAGS, LIBS)

con!g.statusMake!le.incon!g.h.in

*.in

Make!lecon!g.h

*

Page 9: Build Systems with autoconf, automake and libtool [updated]

autoconf

‣ you don‘t actually write con!gure yourself

‣ con!gure.ac contains macro calls to be converted into a shell script

‣ Macros that are not part of autoconfcome from aclocal.m4

‣ Documentation: info autoconf (read it!)

m4con!gure.acaclocal.m4

con!gure

Page 10: Build Systems with autoconf, automake and libtool [updated]

autoheader

‣ creates a template for con!g.h

‣ con!g.h contains C preprocessor symbolsfor options, e.g. HAVE_FOO_H

‣ Source code: #include “con!g.h”at the start of each !le

‣ Documentation: info autoheader

con!gure.ac con!g.h.in

Page 11: Build Systems with autoconf, automake and libtool [updated]

automake

‣ creates a portable Make!lefrom a simpli!ed description

‣ Make!le.am is short and simple

‣ Make!le.in looks horrendously complex(don‘t touch it then)

‣ Documentation: info automake

Make!le.am Make!le.in

Page 12: Build Systems with autoconf, automake and libtool [updated]

aclocal

‣ part of automake

‣ tells autoconf about local macros,like those from automake

‣ only those actually used are put into aclocal.m4

‣ acinclude.m4 is for your own macros

‣ Documentation: info aclocal

*.m4 aclocal.m4

Page 13: Build Systems with autoconf, automake and libtool [updated]

pkgcon!g

‣ makes !nding and using shared libs easier

‣ replaces *-con!g scripts (gtk-con!g etc.)

‣ PKG_CHECK_MODULES(FOO, glib2.0 >= 2.8.0)sets FOO_CFLAGS, FOO_LIBS

‣ if you are writing a library, consider distributing a .pc !le for it

‣ Dokumentation: man pkgcon!g

CFLAGS LIBS

*.pc

Page 14: Build Systems with autoconf, automake and libtool [updated]

libtool

‣ shared library support for all platforms

‣ encapsulates platform-speci!c commands

‣ you pretend you are building a static library with .la suffix (so-called libtool library)

‣ you pre!x commands with libtool --mode=foo,libtool executes different, adapted commands

‣ Documentation: info libtool (except Mac OS)

command different command

Page 15: Build Systems with autoconf, automake and libtool [updated]

Others

autom4te: m4 wrapper used by autoconf

‣ Weird problems: delete autom4te.cache

autoscan: automatically create con!gure.ac

libtoolize, gettextize: add !les for libtool or gettext

autoreconf: regenerate necessary !les

Page 16: Build Systems with autoconf, automake and libtool [updated]

Part 2Practice

Page 17: Build Systems with autoconf, automake and libtool [updated]

Example source code#include <stdio.h>#include "hello.h"

void hello(){ printf("Hello World!\n");}

void hello();

#include "hello.h"

int main(int argc, char **argv){ hello(); return 0;}

hello.c

hello.h

main.c

Page 18: Build Systems with autoconf, automake and libtool [updated]

Traditional Make!le

hw: main.o libhello.a cc -o hw main.o libhello.a

libhello.a: hello.o ar cru libhello.a hello.o ranlib libhello.a

.SUFFIXES: .c .o

.c.o: cc -c -o $@ $<

clean: rm -f hw main.o hello.o libhello.a

Page 19: Build Systems with autoconf, automake and libtool [updated]

Make!le using libtoolhw: main.lo libhello.la ./libtool --mode=link cc -o hw main.lo libhello.la

libhello.la: hello.lo ./libtool --mode=link cc -rpath /usr/local/lib \ -o libhello.la hello.lo

.SUFFIXES: .c .lo

.c.lo: ./libtool --mode=compile cc -c -o $@ $<

clean: ./libtool --mode=clean rm -f hw main.lo hello.lo \ libhello.la

Page 20: Build Systems with autoconf, automake and libtool [updated]

autoconf + automake‣ here: source code moved to src/

‣ call autoreconf -v -i

AC_INIT(hw, 0.1)AM_INIT_AUTOMAKE(foreign)

AC_PROG_CCAC_STDC_HEADERS

AC_CONFIG_FILES([Makefile src/Makefile])AC_OUTPUT

bin_PROGRAMS = hwhw_SOURCES = main.c hello.c hello.h

SUBDIRS = src

con!gure.ac

Make!le.am

src/Make!le.am

Page 21: Build Systems with autoconf, automake and libtool [updated]

Using con!g.h

‣ call autoheader (done by autoreconf)

‣ To use con!g.h:add this to the top of every .c !le

AC_INIT(hw, 0.1)AM_INIT_AUTOMAKEAC_CONFIG_HEADERS(config.h)

[…]

con!gure.ac

#ifdef HAVE_CONFIG_H#include "config.h"#endif

Page 22: Build Systems with autoconf, automake and libtool [updated]

Features we have‣ uses user‘s CC and CFLAGS

‣ can be built outside the sources

‣ installation (via make install), uninstall

‣ user can specify target directory

‣ dependency tracking (can be disabled)

‣ create a tarball (make dist)

‣ make clean

Page 23: Build Systems with autoconf, automake and libtool [updated]

libtool!

‣ goal (as before): make libhello a shared library

‣ libtool is created by con!gure (AC_PROG_LIBTOOL macro)

‣ copy libtool.m4 and ltmain.sh from the libtool sources (or use libtoolize --copy)

‣ !nally call autoreconf -v -i

Page 24: Build Systems with autoconf, automake and libtool [updated]

bin_PROGRAMS = hwhw_SOURCES = main.chw_LDADD = libhello.la

lib_LTLIBRARIES = libhello.lalibhello_la_SOURCES = hello.c hello.h

src/Makefile.am

[…]AC_PROG_CCAC_STDC_HEADERSAC_PROG_LIBTOOL[…]

configure.ac

ACLOCAL_AMFLAGS = -I .

SUBDIRS = srcMakefile.am

Page 25: Build Systems with autoconf, automake and libtool [updated]

Replacement variables‣ a variable is set to a value in con!gure

‣ AC_SUBST(variable) replaces @variable@by its value in output !les

‣ automake de!nes variable for us in Make!les

‣ Goal here: version info for libhello should be set by con!gure

‣ add -version-info to libhello‘s LDFLAGS

Page 26: Build Systems with autoconf, automake and libtool [updated]

current:revision:age‣ version info for libtool libraries

‣ three numbers ∈ ℕ

‣ current: current API revision

‣ revision: bug!xes etc. without any API changes

‣ age: to how many API revisions are we backwards compatible?

Page 27: Build Systems with autoconf, automake and libtool [updated]

‣ If you don‘t touch any function prototypes:

increment revision

‣ a function was added:

increment current and age, set revision to 0

‣ function prototype changed or removed:

increment current, set age and revision to 0

Page 28: Build Systems with autoconf, automake and libtool [updated]

[…]LIBHELLO_CURRENT=1LIBHELLO_REVISION=0LIBHELLO_AGE=1

LIBHELLO_VER=$LIBHELLO_CURRENT:\$LIBHELLO_REVISION:$LIBHELLO_AGEAC_SUBST(LIBHELLO_VER)

AC_CONFIG_FILES([Makefile src/Makefile])AC_OUTPUT

con!gure.ac

lib_LTLIBRARIES = libhello.lalibhello_la_SOURCES = hello.clibhello_la_LDFLAGS = \ -version-info ${LIBHELLO_VER}

src/Make!le.am

Page 29: Build Systems with autoconf, automake and libtool [updated]

Advanced stuff

Page 30: Build Systems with autoconf, automake and libtool [updated]

Checking headers‣ AC_CHECK_HEADERS checks if a header !le is

found and if it works

‣ If another header must be included before, use the fourth parameter

‣ ex: sys/mount.h depends on sys/param.h[…]AC_CHECK_HEADERS([sys/param.h sys/mount.h], [], [], [#ifdef HAVE_SYS_PARAM_H#include <sys/param.h>#endif]) […]

con!gure.ac

Page 31: Build Systems with autoconf, automake and libtool [updated]

arguments to con!gure

‣ additional features (--enable-feature) or

use of external packages (--with-package)

‣ AC_ARG_ENABLE and AC_ARG_WITH,work the same way

‣ Arguments: name, help string, and twoshell fragments (if arg given, if omitted)

‣ AS_HELP_STRING formats the help string

Page 32: Build Systems with autoconf, automake and libtool [updated]

Example

‣ AC_DEFINE: sets a preprocessor symbol(in con!g.h)

[…]AC_ARG_ENABLE([debug], AS_HELP_STRING([--enable-debug], [Enable debugging code (default=no)]), [enable_debug=$enableval], [enable_debug=no])if test "x$enable_debug" = xyes; then AC_DEFINE(DEBUG, 1, [Enable debugging code])fi[…]

con!gure.ac

Page 33: Build Systems with autoconf, automake and libtool [updated]

More complex exampleAC_ARG_WITH([glib2], AS_HELP_STRING([--with-glib2], [Enable support for glib 2.0 @<:@default=auto@:>@]), [with_glib2=$withval], [with_glib2=auto])if test "x$with_glib2" != xno; then PKG_CHECK_MODULES(GLIB, [glib-2.0 >= 2.8], [have_glib2=yes], [have_glib2=no])else have_glib2=nofiif test "x$with_glib2" = xyes -a "x$have_glib2" = xno; then AC_MSG_ERROR([Library requirements (glib-2.0 >= 2.8) not met; consider adjusting the PKG_CONFIG_PATH environment variable if your libraries are in a nonstandard prefix so pkg-config can find them.])fiif test "x$have_glib2" = xyes; then AC_DEFINE([HAVE_GLIB2], [1], [Define if you have the glib2 library.])fi

Page 34: Build Systems with autoconf, automake and libtool [updated]

Conditional compile‣ No portable “if” statement in Make!les,

use automake conditionals

‣ decision is taken at con!gure timeusing the test from the second argument

[…]AM_CONDITIONAL(DEBUG,

[test "x$enable_debug" = xyes]) […]

con!gure.ac

[…]if DEBUGhw_SOURCES += debugging.celse# something elseendif

src/Make!le.am

Page 35: Build Systems with autoconf, automake and libtool [updated]

How not to do it

Page 36: Build Systems with autoconf, automake and libtool [updated]

‣ automake replacement, used by wxWidgets

‣ pkgsrc has patched wxWidgets Make!les so that they use libtool. The patch is 3 MiB.

‣ example Bake!le, from the tutorial:

Bake!le

<?xml version="1.0"?>

<makefile> <include file="presets/simple.bkl"/>

<exe id="hello" template="simple"> <sources>hello.c</sources> </exe></makefile>

Page 37: Build Systems with autoconf, automake and libtool [updated]

wx-con!g‣ very complex con!g script instead of a .pc !le

‣ has to clean up behind con!gure:# We evidently can't trust people not to duplicate things in# configure, or to keep them in any sort of sane order overall,# so only add unique new fields here even if it takes us a while.[…]# This is not a licence# for sloppy work elsewhere though and @GUI_TK_LIBRARY should# be fixed.[…]# of course, this duplication is bad but I'll leave to somebody else the care# of refactoring this as I don't see any way to do it - VZ.

# This (and the other cruft to support it) should be removed with# reference to the FIXME above when configure stops piping us a slurry# of options that need to be decomposed again for most practical uses - RL.

Page 38: Build Systems with autoconf, automake and libtool [updated]

“List of platforms“‣ autoconf‘s goal is to help you get rid of long

lists of platforms and corresponding options.

‣ Yet, some con!gures manage to do this.case "${host}" in[…] *-*-openbsd*) USE_BSD=1 USE_OPENBSD=1 AC_DEFINE(__OPENBSD__) AC_DEFINE(__BSD__) DEFAULT_DEFAULT_wxUSE_GTK=1 ;;

*) AC_MSG_ERROR(unknown system type ${host}.)esac

Page 39: Build Systems with autoconf, automake and libtool [updated]

a2ps Make!les‣ Last release (2.13b) in 2000

‣ uses autoconf 2.14a that was never officially released

‣ does not use aclocal but:

‣ comes with its own version of automakein 17 (!) m4 !les

## I use special autoconf/make macrosACLOCAL_AMFLAGS = --version >/dev/null && cat m4/*.m4 >aclocal.m4

Page 40: Build Systems with autoconf, automake and libtool [updated]

Conclusion

Page 41: Build Systems with autoconf, automake and libtool [updated]

‣ It is a good thing that so many projects use autotools – only one build system to learn

‣ you cannot write a portable build systemfrom scratch – so don‘t try

‣ writing Make!les with automake is notthat complicated

‣ automake replacements complicate lifefor porters and contributors

‣ a good build system even runs on an “unknown” system

Page 42: Build Systems with autoconf, automake and libtool [updated]

1. Don‘t try to reinvent the wheel.

2. Not everyone uses Linux i386 with gccand GNU make.

3. Don‘t hardcode things that can be tested.

4. The user must be able to regenerateyour autoconf infrastructure.

5. Don‘t change any generated !les.

My golden rules

Page 43: Build Systems with autoconf, automake and libtool [updated]

Thank youfor your attention!

‣ slides on http://www.slideshare.net/bsiegert

‣ info pages

‣ ”autotools mythbuster“:http://www."ameeyes.eu/autotools-mythbuster/

Further Reading