An Internationalized Software Project With Auto Tools
Prev Adding Auto Tool Support Next

Adding Auto Tool Support

The first step to "autotoolize" the project is to find the correct gnu auto tool versions. Some installations select one version (probably the latest) and name them 'automake' and 'autoconf'. On FreeBSD, several autotool versions can be installed parallel and none is selected. Therefore the latest version are (currently) called 'automake19' and 'autoconf259'. So if automake is called here, 'automake19' has to be typed. While just typing slightly different command names is not a big deal, there is a subtile detail: 'configure' stores the names of the used auto tools in the generated Makefiles so that they can be started again later, if necessary. Therefore the exact names of the gnu auto tools should be set before they are used and before each call of 'configure', 'make' or ' '. This step can be omitted, if commands with the default names (e.g. 'automake' instead of 'automake19') exist and are used.

Therefore on FreeBSD each development session starts with:
# setenv ACLOCAL aclocal19
# setenv AUTOMAKE automake19
# setenv AUTOCONF autoconf259
# setenv AUTOHEADER autoheader259
To automatize this, a small script (setEnvironment) may be created, which sets all these variables and starts a new shell. Starting a new shell is necessary, as child processes can not set variables in the parent environment! Alternatively these variables can also be set in the users shells init script.
# touch setEnvironment.freebsd
# chmod a+x setEnvironment.freebsd

setEnvironment.freebsd

#!/bin/csh
setenv ACLOCAL aclocal19
setenv AUTOMAKE automake19
setenv AUTOCONF autoconf259
setenv AUTOHEADER autoheader259
csh
Note, that this is done on csh. On other shells, the syntax is different, e.g.

ACLOCAL=aclocal19 ; export ACLOCAL

in bash.

Now it's time to create the necessary configuration files. First 'configure.ac'. There exists a tool, to create a template automatically:
# autoscan259
autom4te259: configure.ac: no such file or directory
autoscan259: /usr/local/bin/autom4te259 failed with exit status: 1
Despite the error message, the template has been created and can now be edited:
# mv configure.scan configure.ac

configure.ac

#                                               -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.

AC_PREREQ(2.59)
AC_INIT(testproj, 0.1, j.t.kirk@ncc-1701.ufp)
AC_CONFIG_SRCDIR([src/main.cpp])
AC_CONFIG_HEADER([config.h])
AM_INIT_AUTOMAKE

# Checks for programs.
AC_PROG_CXX
AC_PROG_CC

# Checks for libraries.

# Checks for header files.

# Checks for typedefs, structures, and compiler characteristics.

# Checks for library functions.
AC_CONFIG_FILES([Makefile src/Makefile])
AC_OUTPUT
Some comments have been deleted and a few lines (bold) have been added. What do these configure lines mean? Next, that Makefile.in's have to be created:
# touch Makefile.am
# touch src/Makefile.am

Makefile.am

SUBDIRS = src
The top level Makefile.in is quite simple. It just points to the src directory and instructs 'make', to execute a Makefile in here.

src/Makefile.am

bin_PROGRAMS = testproj
testproj_SOURCES = main.cpp
noinst_HEADERS = testproj.h
This Makefile.am contains more data. The first line (bin_PROGRAMS) defines the executables, which are created in this directory. Here the executable 'testproj' is created. Now some variables might start with 'testproj', like 'testproj_SOURCES'. 'testproj_SOURCES' lists all source files, which have to be compiled and linked into 'testproj'. Here it is 'main.cpp' only. testproj_SOURCES are compiled and are part of the source tarball but are not installed on 'make install'.

Finally noinst_HEADERS lists header files. These are not directly compiled and not installed but are part of the source tarball.

These information are sufficent to create a source tarball, compile the project and to install it. Note, that the dependencies between the source and header files are not specified! It will be calculated lateron.

Now all necessary files have been created and the gnu auto tools can start its work. First some scripts are created, necessary to run configure lateron on the users computer without the need to have gnu auto tools installed:
# ${ACLOCAL}
... lots of warnings
There are plenty of warnings, which can be ignored. Next a template for config.h, which will take the result of 'configure's tests as c #defines has to be created. It must contain an #undef for each variable, 'configure' will set lateron. Fortunately, such a template can be created automatically:
# ${AUTOHEADER}
Now config.h.in should exist. Next the Makefile.in's are created. 'automake' requires some files to exist, so they have to be created fist:
# touch NEWS
# touch README
# touch AUTHORS
# touch ChangeLog
These files should obviously filled with some usefull information.

Now 'automake' can run. It requires some more input files, but the switch '--add-missing' will create them.
# ${AUTOMAKE} --add-missing
configure.ac: installing `./install-sh'
configure.ac: installing `./missing'
src/Makefile.am: installing `./depcomp'
Makefile.am: installing `./INSTALL'
Makefile.am: installing `./COPYING'
Now Makefile.in and src/Makefile.in should be there. Finally 'configure' itself can be created:
# ${AUTOCONF}
That's it. Now all scripts, necessary for the developer and end user have been set up. As long as the files created above, especially configure.ac and the Makefile.am's are not touched, the gnu auto tools are no longer necessary.

'Configuring' the Project

To go ahead with the compilation of the test project, 'configure' has to be run:
# ./configure
checking for a BSD-compatible install... /usr/bin/install -c

...

checking dependency style of gcc... gcc3
configure: creating ./config.status
config.status: creating Makefile
config.status: creating src/Makefile
config.status: creating config.h
config.status: executing depfiles commands
It runs several tests and writes the results in config.h. Furthermore it finally creates the Makefile's. config.h so far contains some defines with project name and version:
# cat config.h
/* config.h.  Generated by configure.  */
/* config.h.in.  Generated from configure.ac by autoheader.  */

/* Name of package */
#define PACKAGE "testproj"

...

/* Version number of package */
#define VERSION "0.1"

Some 'make' Targets

Now the project is in a state, that it can be compiled. Note, that on FreeBSD, 'gmake' should be used. On linux 'make' and 'gmake' are usually identical.
# gmake
gmake  all-recursive
gmake[1]: Entering directory `/usr/home/he/develop/testproj'
Making all in src
gmake[2]: Entering directory `/usr/home/he/develop/testproj/src'
if g++ -DHAVE_CONFIG_H -I. -I. -I..     -g -O2 -MT main.o -MD -MP -MF ".deps/main.Tpo" -c -o main.o main.cpp; \
then mv -f ".deps/main.Tpo" ".deps/main.Po"; else rm -f ".deps/main.Tpo"; exit 1; fi
g++  -g -O2   -o testproj  main.o
gmake[2]: Leaving directory `/usr/home/he/develop/testproj/src'
gmake[2]: Entering directory `/usr/home/he/develop/testproj'
gmake[2]: Nothing to be done for `all-am'.
gmake[2]: Leaving directory `/usr/home/he/develop/testproj'
gmake[1]: Leaving directory `/usr/home/he/develop/testproj'
'make' without an argument (which is the same as 'make all') here just triggers the target 'all-recursive'. This was first done in the testproj directory. As there is nothing to do, 'make' changed into the 'src' sub-directory and runs 'make all' here as well. Here it invokes the c++ compiler (g++ on this machine) and compiles main.cpp. The output is the main.o object file and .deps/main.Tpo, which tracks the dependencies between the source and header files. This dependency is kept and renamed to .deps/main.Po on sucess or deleted, if the compilation failes. This file is used on any later 'make's, to rebuild only the necessary files, if e.g. just a header has been changed.

Afterwards the object file is linked into the executable 'testproj'. This might now be installed:
# gmake install
Making install in src
gmake[1]: Entering directory `/usr/home/he/develop/testproj/src'
gmake[2]: Entering directory `/usr/home/he/develop/testproj/src'
test -z "/usr/local/bin" || /usr/home/he/develop/testproj/install-sh -d "/usr/local/bin"
  /usr/bin/install -c 'testproj' '/usr/local/bin/testproj'
gmake[2]: Nothing to be done for `install-data-am'.
gmake[2]: Leaving directory `/usr/home/he/develop/testproj/src'
gmake[1]: Leaving directory `/usr/home/he/develop/testproj/src'
gmake[1]: Entering directory `/usr/home/he/develop/testproj'
gmake[2]: Entering directory `/usr/home/he/develop/testproj'
gmake[2]: Nothing to be done for `install-exec-am'.
gmake[2]: Nothing to be done for `install-data-am'.
gmake[2]: Leaving directory `/usr/home/he/develop/testproj'
gmake[1]: Leaving directory `/usr/home/he/develop/testproj'
# rehash
# testproj
Hello world!
rehash is required in csh only. If missed, testproj will not found. Obviously testproj works as it sould!

Also uninstall will work now:
# gmake uninstall
Making uninstall in src
gmake[1]: Entering directory `/usr/home/he/develop/testproj/src'
 rm -f '/usr/local/bin/testproj'
gmake[1]: Leaving directory `/usr/home/he/develop/testproj/src'
gmake[1]: Entering directory `/usr/home/he/develop/testproj'
gmake[1]: Nothing to be done for `uninstall-am'.
gmake[1]: Leaving directory `/usr/home/he/develop/testproj'
To change the installation directory, the used compiler or whatever, 'configure' has to be invoked again. Here is a list of all possible switches and variables:
# ./configure --help
`configure' configures testproj 0.1 to adapt to many kinds of systems.

...

Installation directories:
  --prefix=PREFIX         install architecture-independent files in PREFIX
                          [/usr/local]
  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
                          [PREFIX]

By default, `make install' will install all the files in
`/usr/local/bin', `/usr/local/lib' etc.  You can specify
an installation prefix other than `/usr/local' using `--prefix',
for instance `--prefix=$HOME'.

...

Some influential environment variables:
  CXX         C++ compiler command
  CXXFLAGS    C++ compiler flags

...
To build a source tarball, the dist-bzip2 (or other) target can be used:
# gmake dist-bzip2

...
testproj.tar.bz2 is now in the project directory. To delete all files created by 'make', the 'clean' target can be used:
# gmake clean

...
The target 'distclean' additionally removes all files created by 'configure' as well:
# gmake distclean

...
Afterwards, 'make' will no longer work, as the Makefile's are removed. 'configure' has to be run again to recreate them.
# ./configure

...
Now the simple program is fully armed with gnu auto tools. The result source code can be downloaded here.

Next the revision control is shortly discussed.
Prev Home Next
Auto Tools Overview Revision Control