Notes on Autotools

Check out illustrations below in addition to perusing the links and the short text samples (not meant to replace actual reading of the source material).

Better comments on configure.in can be had here and Makefile.am here. To create an rpm specification, see here.


GNU autotools summary and random notes...

autoconf is m4 macros that...

automake produces makefile templates called Makefile.in in each build build directory; autoconf consumes these by means of Makefile.am, also in each subdirectory.

automake requires the presence and efforts of Autconf.

libtool does not require autoconf nor automake; it builds libraries in a portable way.

Autotools help produce code conforming to the GNU specification by generating boiler-plate sources before coding begins.

Autotools facilitate...

  • multidirectory builds of software packages
  • automatic configuration
  • automatic makefiles
  • support for test suites
  • shared libraries

(autoconf)
(automake)

(libtool)

How to set up and use autotools

The two most important and fundamental developer-controlled files are Makefile.am and configure.in (see them circled in red in the diagram below). They are created thus:

	-- Makefile.am -------------------------------------------------------------
	bin_PROGRAMS    = id         # (if creating a binary to install)
	nosint_PROGRAMS = id         # (if creating a binary that won’t be installed)
	hello_SOURCES   = id.c id.h
	hello_LDFLAGS   = -L/opt/quest/lib
	hello_LDADD     = -lvas

	lib_LTLIBRARIES = libid.a    # (if creating a library)
	(other macros as needed...)

	-- configure.in ------------------------------------------------------------
	AC_INIT(hello.c)
	AM_INIT_AUTOMAKE(hello,0.1)
	AM_CONFIG_HEADER(config.h)
	AM_PROG_LIBTOOL              # (initialize libtool if creating a library)
	AC_CHECK_CC                  # checks for gcc (?)
	AC_HEADER_STDC               # checks for headers
	AC_CHECK_HEADERS(errno.h stdio.h stdlib.h string.h vas.h)
	AC_CHECK_FUNCS(fprintf free)
	AC_PROG_CC
	AC_PROG_LIBTOOL              # (only if creating a library)
	AC_PROG_INSTALL              # (only if creating a binary to install)
	AC_OUTPUT(Makefile)

Useful note for reading configure.in: m4 macros abound. The comment-to-end-of-line symbol is dnl.


Building for debug...

...is done at configure time using an option before running make:

	./configure --enable-debug
	make

It requires the creation of some statements in configure.in nearer the top than the bottom:

	dnl This mechanism allows one to enable debug compilations...
	AC_ARG_ENABLE(debug,
	[  --enable-debug     enable debugging and disable optimization],
	[  if test "$enable_debug" = "yes"; then
	      DEBUG_CFLAGS="-g3 -DDEBUG"
	   else
	      DEBUG_CFLAGS="-O2 -DNDEBUG"
	   fi
	]
	)
	AM_CONDITIONAL(ENABLE_DEBUG, test "$enable_debug" = "yes")
	CFLAGS="$DEBUG_CFLAGS"

How it works: when autoconf is run, it sets up the state that, if defined on the configure commandline, the “--enable-debug” option will be reflected in the $enable_debug variable having value yes. This state being tested, DEBUG_CFLAGS, a macro, is established as being “-g3 -DDEBUG”.

Also, macro ENABLE_DEBUG is established for use by Makefile.am if needed (it doesn’t have to be used).

Finally, standard macro CFLAGS is established before Makefile is generated (this cannot apparently be done in Makefile.am—I know because I tried doing it and it leads to a complaint about CFLAGS already being set up).

So, when Makefile is run with make, it gets the flags as they were set up in configure.in, which will be the optimized ones if the debug option to configure isn’t present. Note that, by default, autotools like to set up CFLAGS as “-g -O2” for some, unexplained reason.

Then, run the following sequence of commands:

	aclocal
	autoconf
	automake                     # (tells us some files are missing...)
	touch NEWS README AUTHORS ChangeLog
	automake -a
	./configure
	make
	make install
	make distcheck
	make dist
	(etc.)

To cause automake to supply default versions of missing files, ...

	automake --add-missing

That will give you things like:

	russ@taliesin:~/php-vas> ll install-sh
	lrwxrwxrwx  1 russ users   34 2007-0308 install-sh -> /usr/share/automake-1.9/install-sh


Good links on autotools...

The version of the GNU tools that are in use presently (early 2006) include:


Diagram

User-controlled files are circled in red.





Flowchart




Fileset

In the illustrations on this page, some trouble has been gone to to illustrate that the .in files are inputs to autoconf. In one case, configure.in, it is manufactured by you. In other cases, it is the output of automake, autoheader, etc. In all cases, it is input to autoconf.

It is useful to think of the autotools as mere filters that massage a certain number of files created intelligently by the consumer dumbly into successively intermediate, then final files by autotools. Then, via make, all of the intermediate files are “filtered” into a final product, usually a binary and/or a set of other files.

aclocal, or local “auto-configuration” filter is another intermediary.

A script, usually named bootstrap.sh, is created to run all the intermediaries (aclocal, autoheader, automake, autoconf) preliminary to invoking ./configure and make.

The following files are explained. Unless otherwise noted, the location for the file is in the same directory as Makefile.am and configure.in.

The best tutorial on these questions seems to be http://seul.org/docs/autotut.

Makefile.am makefile macro and command source read by the automake tool.
configure.in macro source read by the autoconf tool; can contain Bourne shell script in addition to m4 macros; typically, you should not have a configure.in in each subdirectory, but only in the dominating one.
aclocal.m4 any m4 macro definitions of your own, however, this file also usually contains about 800 lines put there by autoconf for its own purposes; is it alright to create it before the first run of autoconf?
configure typically the output from autoconf and configure.in.
acinclude.m4 more m4 macros if using aclocal.
config.h great approach to avoiding long gcc command lines by collecting preprocessor defines in one place included in every module; configure.in need only define AM_CONFIG_HEADER plus a config.h.in with any additional definitions you desire must be created or autoconf will complain.
acconfig.h your chance to add yet more defines to config.h before it’s generated by autoconf.
INSTALL standard installation text; explains to downloading consumer how to install software including how to build it.
COPYING contains the GNU General Public License (GPL) if your software is GPL; automake doesn’t seem to insist upon it.
README for the tarball;
AUTHORS more complicated than mere list of authors involved, but mostly only that.
ChangeLog as name implies, contains whatever change you want to reveal to the consumer.
 

Getting macros out to the Makefile...

In order for a macro definition in configure.ac to reach the makefile, you have to use AC_SUBST:

	configure.ac:
	PHP_INCLUDE_PATH=/usr/include/php
	...
	AC_SUBST(PHP_INCLUDE_PATH)


	Makefile.am:
	INCLUDES = -I$(PHP_INCLUDE_PATH)


The problem of libraries...

To check for the existence of standard or extra-standard functions in the library, use:

	AC_CHECK_FUNCS(fprintf free)

On the other hand, to check for symbols consumed from third-party libraries, do:

	AC_CHECK_LIB(libbase-name, symbol, exists-action, doesn’t exist-action)

For example:

	AC_CHECK_LIB(vas, vas_id_get_name,,AC_MSG_ERROR(Where’s the VAS SDK library?))

(All arguments after the second are optional.) This won’t work unless the VAS SDK library is put onto /usr/lib. Using Linux construct, /etc/ld.so.conf, will solve this for the actual load from the executable (ELF) binary, but will not solve autoconf’s inability to find it. A symbolic link from /usr/lib to /opt/quest/lib/libvas.a and /opt/quest/lib/libvas.so will. This isn’t very satisfactory.

Bring in the howitzer...

Another way cool macro to use is AC_SEARCH_LIBS:

	AC_SEARCH_LIBS[ cos, m ]

This puts the library into $LIBS thus:

	$LIBS=-lm

However, no matter what you do, it cannot locate a symbol in a third-party library regardless of how you specify it (name, filename, full path) even if you add its parent directory to PATH. Bummer.


Don’t attempt to use [ or ]

A case in point (one experience). I know I’m not giving enough background here, but I make a useful point that cannot be mistaken.

So, I have to use shell commands to locate my library and version.

What blocks nice tricks like the grep -v ^[ld] is a fundamental problem I now feel I’ve accurately observed: Even though in configure.ac I’m not trying to do this stuff inside an m4 macro, you simply can NOT use brackets ( [ ] ) meaningfully. It appears to discard them without telling you.

So, led to believe that the shell invoked by autoconf is some rather poor relative of any I have ever worked in, I was finally reduced to the realization that everything I did in shell worked as long as it didn’t make use of brackets.

For me, at least, this is some kind of quantum leap through this mess.

My solution? Distribute a script, libvas-info.sh, callable from configure.ac that works this out and gives the full analysis back to configure.ac.

It works perfectly.