Next Up Previous Contents
Next: 2.1.3 Libtool
Up: 2.1 Overview of the Autotools
Previous: 2.1.1 Autoconf
[ID index][Keyword index]

2.1.2 Automake

The most typical use of autoconf is to configure a file Makefile.in. You can write this yourself, as described in the discussion of autoconf, but since so much of a typical makefile is boilerplate, automake exists to write this boilerplate for you. This has the additional advantage that we can support and enforce Starlink-specific conventions with a customised installation of automake. We (currently) use an adapted version of automake -- see automake --version for the version number, and Appendix B for a summary of the differences.

The file which controls automake is Makefile.am. Automake reads both this file and configure.ac, and based on these emits a Makefile.in. It is this latter file which you distribute, and which is substituted at build time by the ./configure script which autoconf generates in turn.

The resulting Makefile has rules to do all the required building and installation in a very portable fashion, as well as targets to make distributions (make dist), do tests (make check), clean up (make clean, make distclean and make maintainer-clean) and, in the case of Starlink automake, do an install along with an installation manifest.

The Makefile.am script consists, in its simplest form, of a sequence of declarations of the relationships between the source files in your distribution and the programs and libraries they are intended to produce. For example, here is the Makefile.am for the PAR library, slightly edited:


## Process this file with automake to produce Makefile.in

lib_LTLIBRARIES = libpar_adam.la
libpar_adam_la_SOURCES = $(F_ROUTINES)

include_HEADERS = $(PUBLIC_INCLUDES)

F_ROUTINES = \
     par1_menu.f \
     par_cancl.f \
     [blah...]

PUBLIC_INCLUDES = \
    PAR_ERR \
    PAR_PAR \
    par.h \
    parwrap.h \
    par_err.h \
    par_par.h

BUILT_SOURCES = PAR_ERR par_err.h

Overall, you can see that this automake source file is syntactically a makefile -- the statements in this example look like makefile variable settings, and it is possible to put makefile rules in the Makefile.am file, though that is not illustrated here. This is slightly deceptive, however, and while it was useful to think, above, of the configure.ac file as being the template of the eventual ./configure script, for automake you should think of the match between the input syntax and the makefile as a happy coincidence. You provide information to automake through the Makefile.am file, and based on that it then emits the Makefile.in it thinks you want (or need, at least).

The first line is a conventional comment. It starts with a doubled hash mark ##, which causes automake to discard the text after it; lines beginning with a single comment character are copied verbatim into the generated Makefile.in.

The next stanza declares that there is to be a library libpar_adam.la, and that the sources for this file are in the `makefile variable' F_ROUTINES.

Though the variables F_ROUTINES and PUBLIC_INCLUDES are specific to this makefile, and arbitrary, the other variable names have both structure and meaning for automake.

The variable lib_LTLIBRARIES consists of the `prefix' lib and the `primary' LTLIBRARIES. The primary tells automake that you wish to build the libtool library libpar_adam.la, and the prefix indicates that this is to be installed with the other libraries (the variable pkglib_LTLIBRARIES, for example, would tell automake that you wanted to install the result in a package-specific library). For each of the libraries listed in this variable, separated by spaces, there must be a corresponding _SOURCES variable, which has the `primary' SOURCES and a prefix formed from the library name, which lists the set of source files for that library. The prefix must be canonicalised by replacing with underscores everything other than letters and numbers. As well as declaring the files which are to be compiled into the library, this indicates to automake that these source files are to be distributed as part of the final tarball, and that it must emit makefile rules to install the library in the correct place, with the correct installation commands. For the list of such associated primaries, see section Program and Library Variables of the automake documentation.

By default, libtool builds both static and shared libraries. You can control this if necessary with the --enable-shared and --disable-shared options to ./configure, and with the AC_DISABLE_SHARED autoconf variable. For further details see the documentation for AC_PROG_LIBTOOL in the Libtool manual.

If we only wanted to build static libraries, we would replace this line with lib_LIBRARIES = libpar_adam.a, and the given library would be built in the usual way, without involving libtool.

The LIBRARIES and LTLIBRARIES primaries can have any one of the prefixes libdir, pkglibdir, check or noinst, with the latter indicating that the library should be built but not installed. Having non-installed libraries can be useful when you are building a library conditionally, or in stages. Libtool refers to these as `convenience libraries', and they are discussed in section Libtool Convenience Libraries of the automake manual.

The other very important primary (not shown here) is PROGRAMS, which describes programs which are to be built and installed (the special Starlink case of monoliths is described below). This can have the prefixes bin, sbin, libexec, pkglib, check or noinst: check is for tests, and is described in Section 4.4; noinst indicates that the program should be built but not installed, and is useful for programs which are used during the build -- for generating header files for example -- but which are not part of the final product. There is no single standard list of prefixes, since each primary supports only a subset of them (you cannot declare bin_LIBRARIES, for example), but several are mentioned in automake's What Gets Installed, and the directories in question are discussed in autoconf's 4.7.2 Installation Directory Variables.

The include_HEADERS line is similar: it indicates that the listed files are to be distributed, and are to be installed in the correct place for include files.

The final line which is significant to automake is the BUILT_SOURCES line. This says that, even though PAR_ERR and par_err.h are to be installed and distributed, they are not actually genuine source files, but must be built; adding the BUILT_SOURCES line forces automake to add a dependency for these files at an artificially early stage. It is only rather rarely necessary to include a line like this. If one of the source files were in this category, then it would naturally be built when it was required, without any need to add it to BUILT_SOURCES. As it happens, there is no rule in this file for building these targets; that is added automatically by automake when it spots that the STAR_MESSGEN macro has been used in the configure.ac file which partners this Makefile.am. In a more general case, however, you would add a make-style rule to the Makefile.am file to build these files from their (presumably undistributed) sources. See also Built sources in the automake manual.

For a second example, we can look at the Makefile.am for the sst application (this is a non-distributed application for building documentation).


## Process this file with automake to produce Makefile.in

bin_SCRIPTS = start

bin_MONOLITHS = sst_mon
sst_mon_SOURCES = \
    sst_mon.f \
    $(sst_mon_TASKS:=.f) \
    $(SUBSRC) \
    $(SUBCSRC) \
    $(PRIVATE_INCLUDES)
sst_mon_TASKS = forstats procvt prohlp prolat propak prohtml
sst_mon_LDADD = $(LDADD) `fio_link`


SUBSRC = sst_clean.f sst_fwild.f sst_latex.f sst_puts.f  sst_trcvt.f \
         sst_cntac.f sst_get.f sst_latp.f sst_rdad1.f sst_trhlp.f \
         [blah...]

SUBCSRC = find_file.c

PRIVATE_INCLUDES = SST_PAR SST_SCB

# special installation directory (but see discussion below)
sstsupportdir = $(bindir)
sstsupport_DATA = sun.tex sst.tex layout.tex forstats.dat html.sty

# The `start' script needs to have installation locations edited into it
edit = sed \
    -e 's,@bindir\@,$(bindir),g' \
    -e 's,@VERSION\@,$(VERSION),g'
start: start.in
    rm -f start.tmp start
    $(edit) \
        -e 's,@edited_input\@,start: produced from start.in by Makefile.am,' \
        $(srcdir)/start.in >start.tmp
    mv start.tmp start

EXTRA_DIST = start.in $(sstsupport_DATA)

This makefile configures and installs a script, builds and installs a monolith, and adds some supporting data files in a non-standard place.

The SCRIPTS primary indicates to automake where and how to install the start script. The start script must be generated, since it is to include the version number and installation location. Since it includes the installation location, it should not be generated at configure time or install time, but instead at make time, so that the user is free to specify one installation prefix at configure time (through ./configure --prefix=www), override this with another prefix at build time (through make prefix=xxx) and specify a different one -- presumably a staging location or something similar -- at installation time (through make prefix=yyy install). It is the prefix at build time that is to be baked into the code, if any such baking has to be done. This is one of the GNU conventions mentioned in Section 2.1, and is discussed in a little more detail in section 4.7.2 Installation Directory Variables of the autoconf manual. This is why we have to include a makefile-style rule for deriving the file start from its template start.in. This substitutes in the values of the makefile variables bindir and VERSION; these get their values, in the resulting Makefile, by having those values substituted in to the generated Makefile.in by the generated ./configure script; the careful escaping of the @-signs in the sed command is to match the @...@ in start.in while not matching this in Makefile.am or the resulting Makefile.in (yes, this can get a little confusing).

This Makefile.am also declares a single monolith (this and the TASKS primary below are obviously part of the Starlink extensions to automake) and its associated SOURCES, along with its component tasks. For fuller details of the monoliths support, see Section 3.4. This incidentally illustrates that automake allows variable reuse and rewriting very similar to that supported by make.

When we are linking this monolith, we need to add a couple of link options, and we do this with a LDADD primary associated with the sst_mon prefix. The extra link options we declare here are added to the eventual link command, replacing the default set of option options $(LDADD), so we include that variable in our version. We also add `fio_link`, because this monolith needs to be linked against the FIO library (automake constrains what can appear in the LDADD variable, and the `fio_link` is permissable only in Starlink automake -- see Appendix B for details).

The variables SUBSRC, SUBCSRC and PRIVATE_INCLUDES are purely user variables, with no special meaning to automake.

The next bit of magic in this file is sstsupport_DATA. In this particular case, we want to install data files in the same location as the binaries (why, and whether this is a good thing, is not for us to worry about here). The obvious thing would be to say bin_DATA = sun.tex ..., but automake forbids that particular combination of prefix and primary, precisely because it wouldn't generally make sense (see Architecture-independent data files in the automake manual). Instead, we can take advantage of an escape-hatch that automake provides: a given prefix, such as sstsupport, is valid if you also define a variable of the same name, but with dir appended. Thus we define sstsupport_DATA and sstsupportdir, and define the latter to have the same value as the $(bindir) makefile variable, as eventually substituted (see section The Uniform Naming Scheme in the automake manual).

If you look at the real sst component's Makefile.am file, you will see that it does in fact use bin_DATA rather than the sstsupport_DATA illustrated above. This is because the configure.ac in the sst component declares the option STAR_DEFAULTS(per-package-dirs) (see Appendix A.17) which, amongst a couple of other magic features, causes the variable bin_DATA to become legal.

This is a rather special case, and you should not have to do this sort of semi-licensed hacking very often. In particular, you do not need to do it in the case of the Starlink standard directories /star/docs, /star/etc, /star/examples and /star/help, since you can give these directories as prefixes to the DATA primary. As an example, the HDS makefile installs a file containing the information it has determined about the build machine's floating point model, and this is declared there as follows:


noinst_PROGRAMS = hds_machine
starhelp_DATA = hds_machine.txt

hds_machine_SOURCES = hds_machine.f
hds_machine_LDADD = libhds.la `ems_link` `chr_link` `cnf_link`

hds_machine.txt: hds_machine
        ./hds_machine >$@
This is enough to build the hds_machine application at install time, run it, and install the results in /star/help (with the obvious changes for prefixes stardocs, staretc and starexamples).

The remaining magic in this file is the EXTRA_DIST variable. For all its cleverness, automake cannot work out that the start.in source, nor any of the sstsupport_DATA files are to be distributed, and you need to declare that explicitly by setting the EXTRA_DIST variable. Though it is of course deterministic (see section What Goes in a Distribution of the manual), I find the most straightforward way to work out whether anything needs to go here is to build a distribution and spot what was missed out.


Next Up Previous Contents
Next: 2.1.3 Libtool
Up: 2.1 Overview of the Autotools
Previous: 2.1.1 Autoconf
[ID index][Keyword index]
The Starlink Build System
Starlink System Note 78
Norman Gray, Peter W Draper, Mark B Taylor, Steven E Rankin
11 April 2005. Release snapshot: $Revision: 1.116 $. Last updated 28 May 2006