Build tools

It is desirable to keep the released software independent to the computer systems where it will be finally used. The simple make command using a makefile comes to its limits when dealing with such requirements. Additionally writing a makefile for a complex project from scratch becomes tricky and its maintenance even more tricky.

Autotools is the most common tool for that, but alternatives to autotools are available:

  1. cmake

  2. scons

  3. distutils

  4. ant

  5. jam

Autotools

If the project gets split in many different modules and if the program should run under various operating systems, maintaining the makefile manually gets complex. Here a set of gnu tools and scripts to build are called autotools will help. https://devmanual.gentoo.org/general-concepts/autotools/index.html

However if the program is just for Linux and quite simple the autotools might be too much and requires much more compilation time than having just a makefile.

The concept is easy, the project contains per directory a Makefile.am and pre project a config.ac file.

With the command ./configure, scripts are started that create makefiles and config.h files and more. Then make can be used as if the makefile would have been created manually.

Unfortunately dealing with autotools increases the complexity of developing software immense since autotools can do much more than compiling a simple programs, the documentation is broadly available but often has just the effect of heating up your brain rather than helping you to solve a simple problem. The following is an attempt to bring in some light in the topic, since autotools are broadly used in the world of Linux and Gentoo.

For small little programs autotools might be a overshoot, just compare your code size to the size of that what autotools creates to compile it. Writing the makefile manually will probably be faster and you even know what you do!

The first complexity increase is, autotools is not a program, it is a collection of different individual programs that somehow fit together. The most commonly known are:

autoconf, automake, autoheader, and libtool

To know what is really going on, you need a flowchart to see what is going on.

Try to read the documentation from http://www.gnu.org/manual/.

The following explains how to use autotools using the single file program hello.c. First create a directory for the program and change to it ./ create a sub-directory ./src and put hello.c inside.

Makefile.am

Every directory has to have a file called Makefile.am. It serves to create the Makefile for each directory. Its contents look very different to a normal Makefile. Instead of listing dependencies one by one, just the files are listed and defined what they are.

The Makefile.am on the top directory contains usually just a line pointing where the source files are:

SUBDIRS=src

The Makefile.am in the src directory could look as follows:

helloprgdir=/usr/local/bin/
helloprg_PROGRAMS=hello
hello_SOURCES=hello.c
  1. The first line tells where to install

  2. The second line what to build

  3. The third line the source files required

To have the standard math library

<Program name>_LDADD= -lm

To add a man page and have it even distributed with the tar.gz file add the following:

dist_man_MANS = <mymanpage>.1

configure.ac

The file configure.ac contains gnu m4 macros to define what has to be done to configure the project. M4 is a scripting language with its own syntax (Perl like), see:

Start the program autoscan in the top directory of the project. Among other stuff, the file configure.scan is created that can serve as configure.ac example. This way it can be avoided to deal too much with the m4 syntax. The configure.scan has to be customized and saved as configure.ac:

  1. To be user friendly consider to lower the version number so users not very up to date can deal with it AC_PREREQ(2.61)

  2. Put the line AC_INIT(FULL-PACKAGE-NAME, VERSION, BUG-REPORT-ADDRESS) something useful as AC_INIT(hello, 1.0, urs@linurs.org)

  3. Add AM_INIT_AUTOMAKE directive to tell Autoconf that our configure script should produce Makefiles.

  4. Change AC_CONFIG_HEADER([config.h]) to AM_CONFIG_HEADER([config.h]) because the AM macro does some additional setting up for Automake that the AC macro doesn't do.

Note: Older versions of autotools called the configure.ac file configure.in.

Steps to get an autotool package

  1. Run aclocal to get all the stuff configure.ac needs to run (autom4te.cache directory and aclocal.m4 file)

  2. Run autoheader to get config.h.in

  3. Run automake -ac to convert all the Makefile.am to Makifile.in that look closer then a regular Makefile additional additional files are copied and added with the -ac option others can not be created automatically so automake just complains about. So create those dummy files, they can be empty (NEWS, README, AUTHORS, ChangeLog).

  4. Run autoconf to get the configure script

Now the autotools package is finished and is ready to be compiled and installed using the following commands:

./configure creates the makefile and config.h

make

make install

Important

make install as root writes it to the system and getting track of what has been done is easily lost and so it will be hard to make the changes undone. Linux Distributions as gentoo install first into a sandbox and have then copied it over to the real system writing down every change in a database. To avoid any harm run make install just as regular user and even better install it into a temporary directory instead of the root directory make DESTDIR=<tempdir> install

And to start:

/usr/local/bin/hello

Make can do more as:

make uninstall to remove everything put outside

make clean to clean up all stuff necessary for the compilation

make dist to clean up the directories and makes a tar.gz archive ready for shipping.

After modifying the above it would be painful to repeat the steps. Therefore the command:

autoreconf --install --force

will do the update. To not typing so much some packages have a bash script for that, e.g.:

./autogen.sh

Autotools and libraries

Using autotools the source is in ./src and the library source in ./lib. Therefore create the ./lib directory and copy printhello.c there. Create a Makefile.am with the following contents:

lib_LIBRARIES = libhello.a
libhello_a_SOURCES=printhello.c

start autoscan and create configure.ac considering configure.scan make sure the following shows the lib directory:

AC_CONFIG_FILES([Makefile

lib/Makefile

src/Makefile])

Additionally to get a statically library add to configure.ac

AC_PROG_RANLIB

If you use libtool in your package you must run libtoolize

  1. If required the libraries have to be considered by adding

    AC_PROG_LIBTOOL this uses libtool to create them. If there is AC_PROG_RANLIB in an existing file remove it, since libtool does this work.

For libraries add

lib_LIBRARIES = lib<name>.a
lib<name>_a_SOURCES = <objec1>.c <object2>.c

or if you use libtool

lib_LTLIBRARIES = lib<name>.la
lib<name>_la_SOURCES = <object1>.c <object2>.c

la stands for library archive. Different systems have different format of shared libraries or not even support them.

Gnu offers libtool that automates the creation of libraries, it is called as

libtool gcc <options>

As autotools, libtool creates intermediate files .al for .a and .ol for o files. Libtool can also be used by autotools. Libtool can offer both static and dynamic libraries.

Static libraries Add AC_PROG_RANLIB to configure.ac

Scons

Is a python based build tool and uses a SConstruct python file instead of a Makefile. A project can consists of different targets. Each target has its sub directory containing a SConscript file defining how those targets are built.

Build and install using scons

To build scons

To install to /usr/local scons install

To install somewhere else scons prefix=</path>

To install in a temporary directory, from where it than can be copied to the right directory when installation was successful. Gentoo does exactly this it installs first somewhere in /var/tmp/portage and then merges it (copies it):

scons install prefix=/usr destdir=/var/tmp/

Debug scons

Since it is python, the build process can easily be debugged. However since this file is not called directly you need a debugger with embedded debugging support as winpdb. Add the following line to the SConstruct file.

import rpdb2; rpdb2.start_embedded_debugger_interactive_password()

Then start your build command as usual, however this time SConstruct will prompt for a password and wait for an external debugger. More info can be found in the python embedded debugging section.

cmake

cmake can build makefiles that then are used for the build.

cmake --help-module-list to see what modules cmake uses

cmake --help-module FindGit to get help for a module

pkg-config

pkg-config is used to find installed libraries. Build tools make use of pkq-config

pkg-config --list-all

Waf

Waf is an other build tool using python and having a nice wiki and documentation see https://github.com/waf-project/waf


Linurs startpage