User Tools

Site Tools


doc:appunti:prog:autotools

Autotools nano-HOWTO

http://juha.vierinen.net/files/autotools-nano-howto.html

© 2005,2007 Juha Vierinen jPARSE@THISsgo.fi

Introduction

One often gets a warm fuzzy feeling seeing the autoconf generated configure file after unpacking a source tarball – this is because your chances of easily compiling the piece of software have grown significantly. This doesn't mean that you won't have any problems – you will have problems with compiling software sooner or later – it just means that things tend to go more smoothly when autoconf and automake (referred to as autotools in this text) are involved. The main purpose of these tools is ease the pain of compiling software on different platforms, but automake can additionally automate many other aspects of software configuration management.</p>

Building autotools managed software

The end user never needs to use autoconf or automake, as these tools create a plain vanilla sh script called configure. This way the platform used for compiling doesn't need to have a working autotools, just a regular bourne shell. The normal way to proceed after untarring a source package is this:

./configure ; make ; make install

Usually there are also many custom options provided by the package maintainer. The help option usually lists these.

./configure --help

For example, –prefix will install the software into the home directory of the user instead of the default location (/usr or /usr/local).

./configure --prefix=/home/user

Common environment variables are CFLAGS, CXXFLAGS, FFLAGS, FCFLAGS, LIBS and LDFLAGS. These are processed and tested by configure and added to the flags that configure comes up with. On more obscure (e.g., AIX) platforms, you will often have to come up with CFLAGS and LDFLAGS that will find the right headers and libraries. For example:

> export CFLAGS="-O42 -g --funny-compiler-flag -I/hard/to/guess/directory"
> ./configure ; make # will usually use your CFLAGS for compiling</span>

Sometimes, a package might also include custom arguments to do this as well eg.:

> ./configure --with-blas="-L/home/user -lblas"
> ./configure --with-blas="/opt/supafastblaswithstripesandachrometailpipe.a"

Automake default targets

The commonly used targets are:

make           # Compile everything.
make clean     # Remove all objects, temporary files and such.
make distclean # Remove automatically generated autoconf/automake files.

make dist      # Create a tar.gz file containing source ready for distribution.
make install   # Install software to you kit.

Other useful targets:

<a name="flags">make tags      <span class="comment"># Generate etags files for the source.</span>
make dist-zip  <span class="comment"># Create a zip file (great for windows people)</span>

make uninstall <span class="comment"># Uninstall the files installed with make install</span>
make check     <span class="comment"># Run tests bundled with the project</span>
</a></pre>

===== The anatomy of a automake and autoconf governed project =====

<p><a name="flags">Automake operates on a high abstraction level. You define the
source files that are needed to build an executable or a
library and automake generates the necessary make rules --
also rules for packaging and installing are automatically
created. Automake reads <code>Makefile.am

and

configure.in

as input.</a></p>

<p><a name=“flags”>Autoconf is on the abstraction level of a normal Makefile. The main purpose of autoconf is create a configure script that finds necessary compilers and compiler flags. Autoconf also reads it's input from

configure.in

(or sometimes

configure.ac

). Automake depends on autoconf for generating the

configure

script. Autoconf can also be used stand-alone by creating a Makefile template in

Makefile.in

. When the

configure

script is run by the user, placeholders for compilers and compiler flags in

Makefile.in

are replaced with the platform specific values to create a

Makefile

.</a></p>

<pre><a name=“flags”>autogen.sh <span class=“comment”># Semi-standard script for generating the configure

         # script and possibly the Makefile.in files
         # by running automake and autoconf.</span>

configure.[in,ac] <span class=“comment”># Definitions used for producing configure</span> Makefile.in <span class=“comment”># Autoconf makefile template</span> Makefile.am <span class=“comment”># Automake project description file.</span> </a></pre>

Maintaining an autoconf project

<p> <a name=“flags”>If only autoconf is used, then Makefile.in is the file to edit. Autoconf variables appear as

@VARIABLE@

like definitions (these are replaced with values found by the configure script). It is also possible to use autoconf definitions in Makefile.am files, this is especially useful for situations where automake functionality runs short. A snippet of Makefile.in can look like: </a></p>

<pre><a name=“flags”>screensave.@OBJEXT@: screensave.c<br> @CC@ @CFLAGS@ -c -o $@ $&lt;<br></a></pre>

<p><a name=“flags”>Here,

@OBJEXT@

,

@CC@

, and

@CFLAGS@

are replaced with values found by the configure script to create a normal makefile.</a></p>

<h2><a name=“flags”>Maintaining an autoconf+automake project</a></h2>

<p> <a name=“flags”>If automake is used, the file to edit is Makefile.am. You can also mix custom Makefile directives in here, but stick with automake definitions whenever possible, as it will save a lot of time. A simple Makefile.am could look like this: </a></p>

<pre><a name=“flags”>bin_PROGRAMS=hello<br>hello_SOURCES=hello.c hello.h someotherfile.f manylanguages.cpp<br></a></pre>

<p><a name=“flags”>This example will create a

configure

that looks for working C, Fortran 77 and C++ compilers, ending up with a working Makefile that will compile the executable <bold>hello</bold>, which will be copmiled from a mix of C, fortran and C++.</a></p>

Commands

<pre><a name=“flags”>autoscan <span class=“comment”># Scan your source code to detect which tests might be needed and

          # create a configure.scan, which can be used as a basis of 
    # configure.in.</span>

autoheader <span class=“comment”># Scan configure.in and create a config.h.in file, that will

          # be used as a basis of your config.h (if you use one)</span>

automake <span class=“comment”># Go through configure.in and Makefile.am files and create

          # Makefile.in files.</span>

autoconf <span class=“comment”># Go through configure.in and create the configure script.</span> </a></pre>

<p> <a name=“flags”>Still can't figure out what to run and in which order? Try running automake, aclocal, autoconf and autoheader in random combinations, and you'll usually end up with something useful after a couple of iterations. When you get a feeling of what is needed, write it down into autogen.sh, so you'll remember it next time. </a></p>

Writing custom tests

<p> <a name=“flags”>You can write tests directly into configure.in. The language is a macro-language called <a href=“http://www.gnu.org/software/m4/”>M4</a>, which is used to generate Bourne shell script. So you basically write in a mixture of sh and M4. Eg. </a></p>

<pre><a name=“flags”>AC_MSG_CHECKING([for answer to meaning of life]) <span class=“comment”># M4 function call</span><br>answer=“42” <span class=“comment”># sh variable assignment</span><br>AC_MSG_RESULT($answer) <span class=“comment”># M4 function call</span><br></a></pre>

<p> <a name=“flags”>Even writing modular and reusable M4+sh is possible, just take a look at the autoconf source for the default AC_* macros. </a></p>

<p> <a name=“flags”>If you intend to write a lot of tests, it is beneficial to write them into separate .m4 files. This has an advantage of keeping configure.in more understandable. Eg. you might have a file acx_blas.m4 that contains a routine that gives a BLAS library as an argument to

./configure

: </a></p>

<pre><a name=“flags”>AC_DEFUN([ACX_BLAS], <br>[<br>acx_blas_ok=no<br><br>AC_ARG_WITH(blas,<br> [AC_HELP_STRING([–with-blas=&lt;lib&gt;], [use BLAS library &lt;lib&gt;])])<br>case $with_blas in<br> yes | “”) ;;<br> no) acx_blas_ok=disable ;;<br> -* | */* | *.a | *.so | *.so.* | *.o) BLAS_LIBS=“$with_blas” ;;<br> *) BLAS_LIBS=“-l$with_blas” ;;<br>esac<br><br><span class=“comment”># Get fortran symbol name of sgemm (a blas routine).</span><br>AC_FC_FUNC(sgemm)<br><br>acx_blas_save_LIBS=“$LIBS”<br>LIBS=“$LIBS $FCLIBS $FLIBS”<br><br><span class=“comment”># First, check BLAS_LIBS environment variable</span><br>if test “x$BLAS_LIBS” != x; then<br> save_LIBS=“$LIBS”; LIBS=“$BLAS_LIBS $LIBS”<br> AC_MSG_CHECKING([for $sgemm in $BLAS_LIBS])<br> AC_TRY_LINK_FUNC($sgemm, [acx_blas_ok=yes], [BLAS_LIBS=“”])<br> AC_MSG_RESULT($acx_blas_ok)<br> LIBS=“$save_LIBS”<br>fi<br><span class=“comment”># restore the libs variable</span><br>LIBS=$acx_blas_save_LIBS<br>])<br></a></pre>

<p> <a name=“flags”>This can be then added to

configure.in

like this: </a></p>

<pre><a name=“flags”>sinclude([acx_blas.m4])<br>ACX_BLAS<br>LIBS=“$BLAS_LIBS $FLIBS”<br></a></pre>

CVS and autotools

<p>

<a name=“flags”>CVS and autotools is an evil combination. AM_MAINTAINER_MODE is the key many of the problems with mixed up timestamps, but there are other things to know as well. </a></p>

<p> <a name=“flags”>CVS updates often break autotools managed files files beyond repair. This can be seen as weird errors in while using make. One way to proceed might be to re-run configure to create everything – or if even configure is broken a </a></p>

<pre><a name=“flags”>rm configure ; cvs update configure ; ./configure <br></a></pre>

<p><a name=“flags”>will be a sure fix.</a></p>

<p> <a name=“flags”>Alternatively, you can regenerate the configure yourself, if you have autotools installed: </a></p>

<pre><a name=“flags”>sh autogen.sh ; ./configure <br></a></pre>

Troubleshooting

<p> <a name=“flags”>When a test fails and configure fails to give a reasonable explanation of what went wrong (the usual case), searching config.log will often give more detailed information about what went wrong. </a></p>

More information

<p> <a name=“flags”>The best way to learn is to study (i.e., steal) code from others – just search for projects that use the same libraries and programming languages that you do. The documentation that comes with automake and autoconf is extremely good: </a></p>

<p><a href=“http://www.gnu.org/software/autoconf/manual/index.html”>Autoconf manual</a></p>

<p><a href=“http://www.gnu.org/software/automake/manual/index.html”>Automake manual</a></p>

<p> There is also a semi-official autoconf macro index contains a wide range of tests. They might not be perfect, but usually are a good starting point. </p>

<p><a href=“http://autoconf-archive.cryp.to/macros-by-category.html”>Autoconf macro archive</a></p>

<p> Another useful reference is the code itself. Need to know a shell variable that is produced by some test? Look it up from the autoconf/lib/autoconf directory of autoconf source. </p>

<p>Libtool is another useful tool to learn, for making cross-platform libraries, but libtool is not discussed here.</p>

<p><a href=“http://directory.fsf.org/All_Packages_in_Directory/autoproject.html”>Autoproject</a> is a tool that creates a skeleton automake and autoconf managed project.</p>

doc/appunti/prog/autotools.txt · Last modified: 2008/04/16 16:02 by 127.0.0.1