My Avatar

Shilong ZHAO

Autoconf Automake Notes

2016-04-15 00:00:00 +0200

In case you have any questions or suggestions, you can leave comments HERE . Thanks!

 

PART I. Autoconf

Autoconf common macros

AC_SUBST(variable, [macro])

The first argument variable represents a shell variable whose value you want to substitute into all files generated by config.status from templates (e.g. in the eventual Makefile there will be variable).

The substitution variable will have the same name as the shell variable except that it will be bracketed with two @ signs in the template files.

autoconf

in: configure.ac

out: config.h.in configure

automake

in: Makefile.am configure.ac

out: Makefile.h.in

configure

in: Makefile.in , config.h.in

out: config.h, Makefile

AC_DEFINE

 

Initialize

AC_CONFIG_HEADERS([header-file-list])

generate the configure header files, usually config.h

AC_INIT([package_name], [version])

generate macros related to the package name and version inside the header files.

 

Finalize

AC_OUTPUT

will replace the instances of substitution variable @variable@ in all the template files?

 

Check required programs

AC_PROG_CC([compiler-search-list])

check C compilers.

output: set variable CC to the name of the compiler found, and also the substitution variable @CC@.  

AC_PROG_AWK will check if awk is available

output: set variable AWK to the name of the awk found.

AC_CHECK_PROG(variable, prog-to-check, value-if-found, [value-if-not-found], [path=`$PATH`],[reject])

perform generic program checks

output: if program prog-to-check is found, set variable to value-found

 

Check headers and libraries

AC_CHECK_LIB(library, function, [action-if-found], [action-if-not-found], [other-libraries])

Test whether the library library is available by trying to link a test program that calls function function  with the library. function  should be a function provided by the library. Use the base name of the library.

output: If action-if-found is not specified, the default action prepends -llibrary  to @LIBS@(used in Makefile.in) and defines HAVE_LIBlibrary (in all capitals).

AC_SEARCH_LIBS(function, search-libs, [action-if-found], [action-if-not-found], [other-libraries])

an enhanced version of AC_CHECK_LIB,

AC_CHECK_HEADERS(header-file..., [action-if-found], [action-if-not-found], [includes])

For each given system header file header-file in the blank-separated argument list that exists, define HAVE_header-file (in all capitals) in configuration header file (e.g. config.h). If action-if-found is given, it is additional shell code to execute when one of the header files is found. You can give it a value of ‘break’ to break out of the loop on the first match. If action-if-not-found is given, it is executed when one of the header files is not found.  

 

Support optional packages or features

AC_ARG_WITH (package, help-string, [action-if-given], [action-if-not-given])

If the user gave configure the option --with-package or --without-package, run shell commands action-if-given. If neither option was given, run shell commands action-if-not-given. The name package indicates another software package that this program should work with. It should consist only of alphanumeric characters, dashes, plus signs, and dots.

The option’s argument is available to the shell commands action-if-given  in the shell variable withval, which is actually just the value of the shell variable named with_package, with any non-alphanumeric characters in package changed into ‘_’.

AC_ARG_ENABLE(feature, help-string, [action-if-given], [action-if-not-given])

If the user gave configure the option --enable-feature or --disable-feature, run shell commands action-if-given. If neither option was given, run shell commands action-if-not-given

The option’s argument is available to the shell commands action-if-given in the shell variable enableval, which is actually just the value of the shell variable named enable_feature, with any non-alphanumeric characters in feature changed into ‘_’ .

  > output: set environmental variable ${enableval} and ${enable_feature}

suppose there’s a feature named async-exec and we need it be disabled by default, then use

AC_ARG_ENABLE([async-exec],
    [--enable-async-exec    enable asynchronous execution],
    [async_exec=${enableval}], [async_exec=no])

or if we want it to be enabled by default

AC_ARG_ENABLE([async-exec],
    [--disable-async-exec    disable asynchronous execution],
    [async_exec=${enableval}], [async_exec=yes])

AS_HELP_STRING()

 

AC_MSG_ERROR

AC_MSG_WARN

 

Define functions

AC_DEFUN  

 

Example

configure.ac

AC_INIT([testpackage], [1.0])
AC_CONFIG_HEADERS([config.h])
AC_ARG_WITH([openssl], [--with-openssl use OpenSSL],
            [with_openssl=${withval}],[with_openssl=no])

openssl_lib=crypto
if test x$with_openssl = xyes; then
    AC_CHECK_LIB([$openssl_lib], [main], [LIBS="$LIBS"],
                 [AC_MSG_ERROR([OpenSSL lib$openssl_lib not found!])])
    AC_CHECK_HEADERS([openssl/evp.h],,
                     [AC_MSG_ERROR([OpenSSL header openssl/evp.h not found!])])
fi

AC_PROG_CC
AC_OUTPUT

 

PART II. Automake

 

Enable Automake

AM_INIT_AUTOMAKE: Enable Automake within the build system.

Adding AM_INIT_AUTOMAKE macro into configure.ac causes autoreconf -i to call automake -i and Automake now generates Makefile.in from Makefile.am

 

Define directories to build

The top level Makefile.am simply has only one line:

SUBDIRS = src

The Makefile.am files in the SUBDIRS list will be recursively processed.

 

Enable plugin/feature with Automake

related macros:

AM_CONDITIONAL

AM_COND_IF

 

AM_CPPFLAGS is a global flag that will apply to all the targets. If a target-specific flag is needed, use targetname_CPPFLAGS. According to the Automake manual, if the target-specific flag is defined, the target will be compiled with that target-specific flag and the user variable CPPFLAGS, no global AM_CPPFLAGS will be used.

 

in the top level configure.ac

AC_INIT([testpackage], [1.0])
AC_CONFIG_HEADERS([config.h])
AC_PROG_CC
AM_PROG_CC_C_O
AM_INIT_AUTOMAKE
# with openssl
AC_ARG_WITH([openssl], [--with-openssl use OpenSSL],
            [with_openssl=${withval}],[with_openssl=no])
openssl_lib=crypto
if test x$with_openssl = xyes; then
    AC_CHECK_LIB([$openssl_lib], [main], [LIBS="$LIBS"],
                 [AC_MSG_ERROR([OpenSSL lib$openssl_lib not found!])])
    AC_CHECK_HEADERS([openssl/evp.h],,
                     [AC_MSG_ERROR([OpenSSL header openssl/evp.h not found!])])
fi
# enable debug 
AC_ARG_ENABLE([debug], [--enable-debug  Turn on debug],
              [case "${enableval}" in
               yes) debug=true ;;
               no)  debug=false ;;
               *)   AC_MSG_ERROR([bad value ${enableval} for --enable-debug])
               esac], [debug=false])
AM_CONDITIONAL([DEBUG],[test x$debug = xtrue])
AC_CONFIG_FILES([Makefile src/Makefile])
AC_OUTPUT

 

In src/Makefile.am, suppose we want to build a target named sushi, depending on if DEBUG is defined, the sushi_CPPFLAGS will be set accordingly:

bin_PROGRAMS = sushi
sushi_SOURCES = main.c
sushi_CPPFLAGS = $(AM_CPPFLAGS)
if DEBUG
sushi_CPPFLAGS += -DDEBUG
endif

Note that there are no spaces or tabs before sushi_CPPFLAGS+= -DDEBUG!

in your C source code or header files, you can define the debug function according to if macro DEBUG is defined or not.

#ifdef DEBUG // note this DEBUG is the one in the sushi_CPPFLAGS, NOT the one generated from AM_CONDITIONAL 
#define DBG(M, ...) \
        printf("**file %s line %d, function %s: " M "\n", \
                __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__)
#else
#define DBG(M, ...)
#endif

Now you can run:

$ autoreconf -i
$ ./configure --enable-debug
$ make

to have a debug-enabled sushi.

 

Example enable plugin

conditional sub-directories (from StrongSwan)

configure.ac

249  ARG_ENABL_SET([tnc-imv],        [enable TNC IMV module.])

1558 AM_CONDITIONAL([USE_TNC_IMV], [test x$tnc_imv = xtrue])

1688 AC_CONFIG_FILES([
     Makefile
    ...
    src/libtnccs/plugins/tnc_imv/Makefile
    ...]) 

 

Makefile.am

SUBDIRS = src man conf init testing 

 

 

src/libtnccs/plugins/Makefiles.am

if USE_TNC_IMV
    SUBDIRS += plugin/tnc_imv
endif