When using Linux software, it is quite common to compile source code in the classical 3 phases : configure, make and make install. This process relies on GNU autotools.
If you develop a Linux software, you must be aware that users who want to recompile this software will certainly not have the same development environment as yours. They might have a different distribution, different versions of tools and libraries.
So the Makefile delivered with the software must make no assumptions at all that it will run in the same environment as yours. To deal with these potential discrepencies between developer and user, Makefile will be dynamically built by the configuration phase run by configure.
When configure runs, a lot of controls are performed on the current environment, to check if the software will be able to successfully compile in this environment. The configuration phase also detects includes and libraries locations, in order to dynamically build the Makefile that will be adapted to the current environment.
Makefile is built by configure from a Makefile template : Makefile.am.
As a developer you write the Makefile.am template, and let the user generate the final Makefile during the configuration phase. Of course if you are the developer, you generate the Makefile using the same mechanism. The only difference is that this Makefile and the Makefile from another user can be different, each one adapted to its particular situation.
As Makefile is built from Makefile.am, configure is a very complex script automatically built from a configuration template called configure.ac. configure.ac is written by the developer to define what control must be performed, and what variables must be defined in accordance with the local environment.
Let’s take an example : we will make a little Hello World program with autotools.
First let’s make a working directory, and a subdirectory src for sources :
~$ mkdir -p ~/autohello/src
~$ cd ~/autohello/src
The first version of the source code autohello.c is quite classic :
~/autohello/src$ cat autohello.c
/** * @file autohello.c * * This file implements simple hello world program. * * @author Xxx Yyy */ #include #include #include "config.h" #include "autohello-version.h" int main(int argc, char **argv) { printf("Hello world version %s\n", AUTOHELLO_VERSION_STRING); exit(0); }
Now let us write the Makefile template Makefile.am in ~/autohello/src :
~/autohello/src$ cat Makefile.am
bin_PROGRAMS = autohello autohello_SOURCES = autohello.c CLEANFILES = *~ AM_CPPFLAGS = -D_GNU_SOURCE AM_CFLAGS = -Wall -Werror
and Makefile.am in ~/autohello :
~/autohello/src$ cd ~/autohello
~/autohello$ cat Makefile.am
SUBDIRS = src
Now we have Makefile templates in base directory and in src subdirectory. We need to create the template for configure script, configure.ac :
~/autohello$ cat configure.ac
# -*- Autoconf -*- # Process this file with autoconf to produce a configure script. # Define version major, minor and micro number m4_define([autohello_version_major], [1]) m4_define([autohello_version_minor], [0]) m4_define([autohello_version_micro], [0]) m4_define([autohello_version], [autohello_version_major.autohello_version_minor.autohello_version_micro]) AC_PREREQ([2.63]) AC_INIT([autohello], [autohello_version], [xxx dot yyy at company dot com]) AC_CONFIG_SRCDIR([src/autohello.c]) AC_CONFIG_HEADERS([config.h]) AC_CONFIG_MACRO_DIR([m4]) AM_INIT_AUTOMAKE([foreign]) AUTOHELLO_VERSION_MAJOR=autohello_version_major AUTOHELLO_VERSION_MINOR=autohello_version_minor AUTOHELLO_VERSION_MICRO=autohello_version_micro AUTOHELLO_VERSION=autohello_version AC_SUBST(AUTOHELLO_VERSION_MAJOR) AC_SUBST(AUTOHELLO_VERSION_MINOR) AC_SUBST(AUTOHELLO_VERSION_MICRO) AC_SUBST(AUTOHELLO_VERSION) # Checks for programs. AC_PROG_CC # Checks for header files. AC_CHECK_HEADERS([stdio.h stdlib.h]) # Generate files AC_CONFIG_FILES([Makefile src/Makefile src/autohello-version.h]) AC_OUTPUT
The file ~/autohello/src/autohello-version.h is automatically generated during configuration, based on a template called autohello-version.h.in. Its role is to automatically define the software version in various ways useable in C source code, from versionning numbers specified in configure.ac .
~/autohello$ cd ~/autohello/src
~/autohello/src$ cat autohello-version.h.in :
/** * @file autohello-version.h * * This header files defines parts if the software version. * * @author Xxx Yyy */ #ifndef _AUTOHELLO_VERSION_H_ #define _AUTOHELLO_VERSION_H_ /** The major version, (1, if %AUTOHELLO_VERSION is 1.2.3) */ #define AUTOHELLO_VERSION_MAJOR (@AUTOHELLO_VERSION_MAJOR@) /** The minor version (2, if %AUTOHELLO_VERSION is 1.2.3) */ #define AUTOHELLO_VERSION_MINOR (@AUTOHELLO_VERSION_MINOR@) /** The micro version (3, if %AUTOHELLO_VERSION is 1.2.3) */ #define AUTOHELLO_VERSION_MICRO (@AUTOHELLO_VERSION_MICRO@) /** The full version, like 1.2.3 */ #define AUTOHELLO_VERSION @AUTOHELLO_VERSION@ /** The full version, in string form (suited for string concatenation) */ #define AUTOHELLO_VERSION_STRING "@AUTOHELLO_VERSION@" /** Numerically encoded version, like 0x010203 */ #define AUTOHELLO_VERSION_HEX ((AUTOHELLO_MAJOR_VERSION << 24) | \ (AUTOHELLO_MINOR_VERSION << 16) | \ (AUTOHELLO_MICRO_VERSION << 8)) /** Evaluates to True if the version is greater than @major, @minor and @micro */ #define AUTOHELLO_VERSION_CHECK(major,minor,micro) \ (AUTOHELLO_VERSION_MAJOR > (major) || \ (AUTOHELLO_VERSION_MAJOR == (major) && \ AUTOHELLO_VERSION_MINOR > (minor)) || \ (AUTOHELLO_VERSION_MAJOR == (major) && \ AUTOHELLO_VERSION_MINOR == (minor) && \ AUTOHELLO_VERSION_MICRO >= (micro))) #endif /* _AUTOHELLO_VERSION_H_ */
The following table summarizes the files we have written, and their role :
Directory | File | Role |
autohello | configure.ac | Template for configure script |
Makefile.am | Template for Makefile (mainly relay to src) | |
autohello/src | Makefile.am | Template for Makefile |
autohello-version.h.in | Template for version definition header | |
autohello.c | C source code |
In the next article we will configure and compile the software.
CIO Systèmes Embarqués – 1 Rue de la Presse, 42 000 Saint-Étienne – contact@ciose.fr – 04 77 93 34 32
CIO Systèmes Embarqués est le nom commercial de la SAS CIO Informatique Industrielle
CIO Informatique Industrielle © 1991-2020 v3.0