GNU Autoconf, Automake and Libtool


1. Introduction

Philosophy


2. How it all fits together

Processing the Files


3. A Simple Project


3.1. The Makefile.am file

# Define sub-directories of the project
SUBDIRS = man

# noinst_PROGRAMS are programs that should be compiled but not installed
noinst_PROGRAMS = test_rwlock
# Source files for test_rwlock
test_rwlock_SOURCES = test_rwlock.c
# Libraries to link against
test_rwlock_LDADD = libpthread_rwlock_fcfs.la

# Libraries that are built using libtool
lib_LTLIBRARIES = libpthread_rwlock_fcfs.la
# Where to install the headers
libpthread_rwlock_fcfsincludedir=$(includedir)/pthread
# The source files of the library
libpthread_rwlock_fcfs_la_SOURCES = rwlock.c queue.c
# A libtool library version numbers
libpthread_rwlock_fcfs_la_LDFLAGS = -version-info 0:0:0
# The headers of the library
libpthread_rwlock_fcfsinclude_HEADERS = rwlock_fcfs.h rwlock_fcfs_queue.h

# Extra files in the distribution
EXTRA_DIST += Docs/FCFS_RWLock_Scheme.txt Docs/FCFS_RWLock_Scheme_RLE.txt
EXTRA_DIST += test_rwlock.c
EXTRA_DIST += test_queue.cpp

EXTRA_DIST += pthread/rwlock_fcfs.h pthread/rwlock_fcfs_queue.h

EXTRA_DIST += TODO

3.2. The configure.in file

dnl Process this file with autoconf to produce a configure script.

dnl AC_INIT is the first macro that should be called in an Autoconf
dnl script. It should be called with one argument that exhibits one
dnl of the source files
AC_INIT(rwlock.c)

dnl Initialize Automake
dnl The first parameter is the project name
dnl The second is the version
AM_INIT_AUTOMAKE(pthread_rwlock_fcfs, 0.4.0)

dnl Initialize libtool
AM_PROG_LIBTOOL

dnl Checks for programs.
AC_PROG_CC


dnl Checks for libraries.
AC_CHECK_LIB(pthread, pthread_create)

dnl Checks for header files.
AC_HEADER_STDC
AC_CHECK_HEADERS(sys/time.h unistd.h)

dnl Set the debug flag to no by default
debug_rwlock=no

dnl Set a command line option to set it otherwise
AC_ARG_ENABLE(debug-rwlock,
 [  --enable-debug-rwlock  Enable an RWLock that prints debug notices on the screen. This is a debugging feature which should not be usually enabled],
 [ debug_rwlock=yes
 ])

dnl If debug_rwlock is set
if test "x$debug_rwlock" = "xyes" ; then
    dnl Define the macro PTHREAD_RWLOCK_FCFS_DEBUG
    AC_DEFINE(PTHREAD_RWLOCK_FCFS_DEBUG)
fi

dnl Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST
AC_HEADER_TIME

dnl Checks for library functions.
AC_CHECK_FUNCS(gettimeofday)

dnl Output the files
AC_OUTPUT([Makefile man/Makefile])

4. Commonly Used configure.in macros

This section will cover some commonly used Autoconf Macros.


4.1. AC_DEFINE

AC_DEFINE(HELLO)

AC_DEFINE(VERSION, "5.6")

myvar="foo"
othervar="bar"
AC_DEFINE_UNQUOTED(TEST, "${myvar}${othervar}")

4.2. AC_CHECK_LIB

AC_CHECK_LIB(m, pow)

if test "x$requires_libavl" = "xyes" ; then
    AC_CHECK_LIB(avl, avl_create, [], [
        echo "Error! You need to have libavl around."
        exit -1
        ])
fi

4.3. AC_ARG_ENABLE

AC_ARG_ENABLE(debug-rwlock,
 [  --enable-debug-rwlock  Enable an RWLock that prints debug notices \
  on the screen. This is a debugging feature which should not be \
  usually enabled],
 [ debug_rwlock=yes
 ])

AC_ARG_ENABLE(states-type,
 [  --enable-states-type[=state type] Specify the states type:
                      compact [default]: Compact States
                      debug: Debug States (very slow)
                      indirect: Indirect Stack States],
 [ if   test "x$enableval" = "xcompact" ; then
      states_type=compact
   elif test "x$enableval" = "xdebug" ; then
      states_type=debug
   elif test "x$enableval" = "xindirect" ; then
      states_type=indirect
   else
      echo
      echo "Error!"
      echo "Unknown states' type"
      exit -1
   fi
 ])

4.4. AC_OUTPUT

AC_OUTPUT([Makefile freecell-solver-config freecell-solver.spec], [chmod +x freecell-solver-config])

4.5. AC_CHECK_FUNCS


4.6. AC_CHECK_HEADERS


5. Using changequote

AC_ARG_ENABLE(max-num-stacks,
[  --enable-max-num-stacks[=stacks num] Set the maximal number of Stacks],
[ if   test "x$enableval" = "x" ; then
     max_num_stacks=8
  else
      changequote(, )
      # Check if it's indeed a number
      if echo "0$enableval" | grep '[^0-9]' > /dev/null ; then
          echo
          echo "Error!"
          echo "max-num-stacks should be a number!"
          exit -1
      elif expr $enableval \< 8 > /dev/null ; then
          echo
          echo "Error!"
          echo "max-num-stacks cannot be lower than 8"
          exit -1
      elif expr $enableval \> 20 > /dev/null ; then
          echo
          echo "Error!"
          echo "max-num-stacks cannot be greater than 20"
          exit -1
      else
          max_num_stacks="$enableval"
      fi
      changequote([, ])
  fi])

6. Format of the Makefile.am File


6.1. Super Targets


6.2. Specifying the source files

lib_LTLIBRARIES = libpthread_rwlock_fcfs.la
libpthread_rwlock_fcfs_la_SOURCES = rwlock.c queue.c

6.3. Linking with internal libraries


6.4. Library Headers


6.5. EXTRA_DIST


6.6. Plain Rules


6.7. Libtool Library Versioning


7. Format of acconfig.h


7.1. Example

/*
    config.h - Configuration file for Freecell Solver

    Written by Shlomi Fish, 2000

    This file is distributed under the public domain.
    (It is not copyrighted).
*/

#ifndef FC_SOLVE__CONFIG_H
#define FC_SOLVE__CONFIG_H

#ifdef __cplusplus
extern "C" {
#endif

#undef DEBUG_STATES
#undef COMPACT_STATES
#undef INDIRECT_STACK_STATES

#undef CARD_DEBUG_PRES

/*
 * Define this macro if the C compiler supports the keyword inline or
 * a similar keyword that was found by Autoconf (and defined as inline).
 * */
#undef HAVE_C_INLINE


/*
    The sort margin size for the previous states array.
*/
#define PREV_STATES_SORT_MARGIN 32
/*
    The amount prev_states grow by each time it each resized.
    Should be greater than 0 and in order for the program to be
    efficient, should be much bigger than
    PREV_STATES_SORT_MARGIN.
*/
#define PREV_STATES_GROW_BY 128

/*
    The amount the pack pointers array grows by. Shouldn't be too high
    because it doesn't happen too often.
*/
#define IA_STATE_PACKS_GROW_BY 32

/*
 * The maximal number of Freecells. For efficiency's sake it should be a
 * multiple of 4.
 * */

#define MAX_NUM_FREECELLS 4

/*
 * The maximal number of Stacks. For efficiency's sake it should be a
 * multiple of 4.
 * */

#define MAX_NUM_STACKS 10
/*
 * The maximal number of initial cards that can be found in a stack.
 * */
#define MAX_NUM_INITIAL_CARDS_IN_A_STACK 8

#define MAX_NUM_DECKS 2


#define FCS_STATE_STORAGE_INDIRECT 0
#define FCS_STATE_STORAGE_INTERNAL_HASH 1
#define FCS_STATE_STORAGE_LIBAVL_AVL_TREE 2
#define FCS_STATE_STORAGE_LIBAVL_REDBLACK_TREE 3
#define FCS_STATE_STORAGE_LIBREDBLACK_TREE 4
#define FCS_STATE_STORAGE_GLIB_TREE 5
#define FCS_STATE_STORAGE_GLIB_HASH 6
#define FCS_STATE_STORAGE_DB_FILE 7

#define FCS_STACK_STORAGE_INTERNAL_HASH 0
#define FCS_STACK_STORAGE_LIBAVL_AVL_TREE 1
#define FCS_STACK_STORAGE_LIBAVL_REDBLACK_TREE 2
#define FCS_STACK_STORAGE_LIBREDBLACK_TREE 3
#define FCS_STACK_STORAGE_GLIB_TREE 4
#define FCS_STACK_STORAGE_GLIB_HASH 5

#undef FCS_STATE_STORAGE
#undef FCS_STACK_STORAGE

#ifdef __cplusplus
}
#endif

#endif

8. Various Issues


8.1. Creating a Sub-Directory with a Different Configuration


8.2. mylibrary-config program


8.3. Creating an RPM Spec


Manuals

The Autoconf Manual

The Automake Manual

The Libtool Manual

GNU m4

Other Sources of Information

Autoconf, Automake and Libtool
Autobook - an online book about the GNU Autotools
An Autoconf Tutorial
Autotut - an Autotools tutorial

Autoconf Macros Archive

Contains a lot of predefined macros which are free for use.