When you have a project that needs to be compiled under all the Linux, BSD, Unix, and all the other junk OS outside here you’ll soon end up with a tons of block of source code that need conditional compiling, i.e. #ifdef – #endif
Writing a Makefile by hand that automatically detect your OS and the configuration of wich compiler and libraries are installed and located is an impossible task nowadays.
Using some GNU tool you can automatically generate scripts that those this job for you: those tools are autoconf and automake.
How they work, quick summary:
- you’ll write a set of rules in a file called Makefile.am
- automake will translate this in Makefile.in
- you’ll write a set of rules in a file called configure.in
- autoconf will translate this in configure
- you need to generate a template config.h.in using autoheader
- a developer will just run the script ./configure
- configure will translate any Makefile.in into the finale Makefile
- the developer will just run make now
So you just need to learn how to:
- the syntax to create a Makefile.am file for every directory that needs a final Makefile
- the syntax to create a configure.in that will generate later all the final Makefiles
A skeleton configuration
A simple Makefile.am for a small project:
AUTOMAKE_OPTIONS = gnits bin_PROGRAMS = hello hello_CFLAGS= -Wall -Os hello_SOURCES = test-ansi.c hello_LDADD = ../lib/libbadpenguin.a hello_LDFLAGS = -static hello_HEADERS = hello.h
The key variable here is “bin_PROGRAMS” that specify with program this Makefile will generate. At each program name you can add an additional “_PARAM”. The most important is ofc the “_SOURCES” that will handle compilation of source code and dependencie handling withing the Makefile when generated.
A simple configure.in for a small project:
AC_INIT(hello.c) AM_INIT_AUTOMAKE(hello,1.0.0) AM_CONFIG_HEADER(config.h) AC_PROG_AWK AC_PROG_CC AC_PROG_CPP AC_PROG_INSTALL AC_PROG_LN_S AC_CHECK_LIB(z,zlibVersion,,AC_MSG_ERROR([Cannot find libz])) AC_CHECK_HEADERS([alloca.h langinfo.h libintl.h]) AC_CHECK_FUNCS([nl_langinfo]) AC_OUTPUT(Makefile)
Withing this file the lines starting with dnl are indicating a comment.
The important lines here are:
- AC_INIT that points to our main source file that is used to initialize autoconf
- AM_INIT_AUTOMAKE that specify a project name and a version that is used to initialize usage of automake withing autoconf
- AM_CONFIG_HEADER that specify config.h as the header where to write all the scanned/parsed output
- AC_PROG_* that check the presence of the compiler and other tools
- AC_CHECK_* that check the presence of libraries, headers and functions within the system and will automatically gererate #define withing config.h that you need to include withing your source files
- AC_OUTPUT specify the location of all the Makefile to generate
We’re missing config.h.in that will be generated below by autoheader.
If you don’t want to learn all by yourself all the checks that you can use withing configure.in you can use the tool autoscan that will try to generate automatically a configure.in file for you scanning your entire project source files and headers. You can find the output of this tool in configure.scan file and compare it against your configure.in
When you’ve finished to create your templates you can try to compile everything:
aclocal autoconf autoheader automake "“add-missing "“foreign ./configure make