This tutorial looks at the GNU Build System. From an end-user's perspective, it first describes how to build the binary executable of a GNU free and open source software package from the available source code and install it on your system. Then, from a programmer's perspective it looks at the GNU Build System for generating the scripts and makefiles which provide the infrastructure that enables the end user to build and install the GNU software executables.
BUILDING AND INSTALLING A GNU SOFTWARE PACKAGE
GNU software packages come as compressed archives with file names in one of the two forms, either package-name.version.tar.gz, or package-name.version.tar.bz2. In both cases, the archives have been made using tar. The difference between the two is that the former has been compressed using the gzip utility whereas the latter has been compressed using bzip2. The .gz archive can be unpacked into the relevant directory structure by giving the command,
tar -xvzf package-name.version.tar.gz
whereas the .bz2 archive can be unpacked by the command,
tar -xvjf package-name.version.tar.bz2
The package is unpacked in the directory package-name.version. You can go to the directory,
You will find files like README and INSTALL which give instructions for further work. Broadly, you need to carry out three steps to build and install the software,
./configure make sudo make install
configure finds out about the local environment, checks whether other packages required for this package are already installed and, if everything is OK, writes the relevant makefiles. make builds the binary executable file(s). make install installs the executable files on your system. You normally need superuser access for installing the executable files; hence sudo make install is required.
Figure 1: Major steps in building a GNU software package
Apart from the above-mentioned three commands, you can give other commands too. For example, in between make and make install, you can give the command,
This runs the regression test-suites, assuming these were provided in your package by the developers. Also, let's say you have built the software once and wish to re-build, you can clean the directories of all the in-process files by giving one of the commands,
make clean # or, make distclean # or, make maintainer-clean
make clean removes all the files made by make and make check, but not the files written by configure. If the intent was to to remove the files written by configure as well and start afresh, one has to use make distclean. make maintainer-clean should not normally be required by end-users installing the package. It removes all the files that make distclean removes and also removes files that developers had automatically generated using the GNU build system. It may be useful for maintainers to remove those automatically generated files and make these files again.
To make the discussion complete, there are some more targets. make uninstall uninstalls the software, make dist makes the compressed archive distribution package, package-name.version.tar.gz and make distcheck makes the distribution, unpacks it in a sub-directory, configures, makes the executables and runs the regression test-suites to check if everything is OK.
THE GNU BUILD SYSTEM
In the above paragraphs, two problems are quite clear. First, a given GNU package has to be built in different hardware and software environments. Second, there are a number of targets that the makefiles should be capable of building. Then, there is a third problem, though not mentioned above, that the software sources may be organized in different directories. These problems appear to be formidable. But, there is nothing to worry as the GNU Build System comprising of programs, Autoconf, Automake and Libtool have abstracted the complexity out of this work. These programs are also known as Autotools. Using Autotools, it becomes quite simple for the package developer to provide the required infrastructure for the end-user to build and install the software.
Figure 2: The GNU Build System
The prerequisites of the GNU Build System are the GNU gcc compiler, GNU make, GNU m4 macro processor version 1.4.5 or later and GNU tar programs. Also, you need to ensure that autoconf, automake, and libtool programs are available on your system.
One of the major objectives of GNU software packages is that the software may be distributed as source code and it should possible to make the executable under various Posix-like systems. Normally, it would be a gigantic task for each programmer to write makefiles for each conceivable Posix-like environment. autoconf makes this a straightforward task. The input to autoconf is a text file named configure.ac, or configure.in (configure.in is the older name). autoconf produces configure, which is a shell script to to create makefile(s), customized to build the software executables as per the local environment. The input file, configure.ac, contains macros to check a system for features that a software package might use. autoconf invokes the m4 macro processor to generate the configure script.
Some of the important autoconf macros are AC_INIT, AC_OUTPUT, AC_PROG_CC, AC_PROG_INSTALL, AC_CONFIG_SRCDIR, AC_CONFIG_HEADERS, AC_CONFIG_FILES, etc. Some of the macros accept arguments. When a macro takes arguments, there should not be any whitespace between macro name and the open parenthesis. The arguments should be enclosed in m4 quote characters
] and should be separated by commas. If an argument can not be a macro call, the quotes may be omitted. We can write these in our configure.ac file,
AC_INIT([hello], [1.0]) AC_CONFIG_SRCDIR([hello.c]) AC_CONFIG_HEADERS(config.h) AC_PROG_CC AC_CONFIG_FILES(Makefile) AC_PROG_INSTALL AC_OUTPUT
Each configure.ac must start with an AC_INIT. The parameters, here, are the package name hello and version, 1.0. AC_CONFIG_HEADERS ensures that -D options to the compiler are not passed on the commandline. Instead, a file config.h would be created, containing all the #defines that were being passed as -D option on command line. A single -DHAVE_CONFIG_H would be passed on the command line for compilation. Programmers can put the following code in all source files,
#if HAVE_CONFIG_H #include <config.h> #endif
right at the beginning. AC_CONFIG_SRCDIR makes autoconf check for the presence of given file, in this case hello.c. AC_PROG_CC determines the
C compiler to use. AC_CONFIG_FILES makes AC_OUTPUT create the given files. AC_PROG_INSTALL checks for the presence of BSD compatible install program in the current path. If it is found, its path is set to output variable INSTALL, otherwise INSTALL is set to
install-sh -c. The last call in configure.ac is AC_OUTPUT. It performs all the configuration actions, which includes writing all output files.
automake is a tool for generating the file Makefile.in from a template file Makefile.am. For example, we have a Makefile.am as given below,
bin_PROGRAMS = hello
hello_SOURCES = hello.c
There are a few autoconf macros related to automake. The most important one is AM_INIT_AUTOMAKE, which, in turn runs does some initializations related to automake. We add this macro to our configure.ac to get,
AC_INIT([hello], [1.0]) AC_CONFIG_SRCDIR([hello.c]) AC_CONFIG_HEADERS(config.h) AM_INIT_AUTOMAKE AC_PROG_CC AC_CONFIG_FILES(Makefile) AC_PROG_INSTALL AC_OUTPUT
autoheader program scans the configure.ac and generates a file config.h.in containing information about all the preprocessor macros that need to be defined.
aclocal program creates the file aclocal.m4, containing macro definitions required by autoconf.
Creating the build infrastructure
Using the above mentioned configure.ac and Makefile.am, execute the following commands,
aclocal autoconf autoheader touch NEWS README AUTHORS ChangeLog automake -a ./configure make make dist
After make dist, you should have the package-version.tar.gz file created which can be distributed to end-users.