[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

23. When Automake Isn't Enough

In some situations, where Automake is not up to one task, one has to resort to handwritten rules or even handwritten `Makefile's.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

23.1 Extending Automake Rules

With some minor exceptions (for example _PROGRAMS variables, TESTS, or XFAIL_TESTS) being rewritten to append `$(EXEEXT)'), the contents of a `Makefile.am' is copied to `Makefile.in' verbatim.

These copying semantics mean that many problems can be worked around by simply adding some make variables and rules to `Makefile.am'. Automake will ignore these additions.

Since a `Makefile.in' is built from data gathered from three different places (`Makefile.am', `configure.ac', and automake itself), it is possible to have conflicting definitions of rules or variables. When building `Makefile.in' the following priorities are respected by automake to ensure the user always has the last word:

These overriding semantics make it possible to fine tune some default settings of Automake, or replace some of its rules. Overriding Automake rules is often inadvisable, particularly in the topmost directory of a package with subdirectories. The `-Woverride' option (see section Creating a `Makefile.in') comes in handy to catch overridden definitions.

Note that Automake does not make any distinction between rules with commands and rules that only specify dependencies. So it is not possible to append new dependencies to an automake-defined target without redefining the entire rule.

However, various useful targets have a `-local' version you can specify in your `Makefile.am'. Automake will supplement the standard target with these user-supplied targets.

The targets that support a local version are all, info, dvi, ps, pdf, html, check, install-data, install-dvi, install-exec, install-html, install-info, install-pdf, install-ps, uninstall, installdirs, installcheck and the various clean targets (mostlyclean, clean, distclean, and maintainer-clean).

Note that there are no uninstall-exec-local or uninstall-data-local targets; just use uninstall-local. It doesn't make sense to uninstall just data or just executables.

For instance, here is one way to erase a subdirectory during `make clean' (see section What Gets Cleaned).

 
clean-local:
        -rm -rf testSubDir

You may be tempted to use install-data-local to install a file to some hard-coded location, but you should avoid this (see section Installing to Hard-Coded Locations).

With the -local targets, there is no particular guarantee of execution order; typically, they are run early, but with parallel make, there is no way to be sure of that.

In contrast, some rules also have a way to run another rule, called a hook; hooks are always executed after the main rule's work is done. The hook is named after the principal target, with `-hook' appended. The targets allowing hooks are install-data, install-exec, uninstall, dist, and distcheck.

For instance, here is how to create a hard link to an installed program:

 
install-exec-hook:
        ln $(DESTDIR)$(bindir)/program$(EXEEXT) \
           $(DESTDIR)$(bindir)/proglink$(EXEEXT)

Although cheaper and more portable than symbolic links, hard links will not work everywhere (for instance, OS/2 does not have ln). Ideally you should fall back to `cp -p' when ln does not work. An easy way, if symbolic links are acceptable to you, is to add AC_PROG_LN_S to `configure.ac' (see (autoconf)Particular Programs section `Particular Program Checks' in The Autoconf Manual) and use `$(LN_S)' in `Makefile.am'.

For instance, here is how you could install a versioned copy of a program using `$(LN_S)':

 
install-exec-hook:
        cd $(DESTDIR)$(bindir) && \
          mv -f prog$(EXEEXT) prog-$(VERSION)$(EXEEXT) && \
          $(LN_S) prog-$(VERSION)$(EXEEXT) prog$(EXEEXT)

Note that we rename the program so that a new version will erase the symbolic link, not the real binary. Also we cd into the destination directory in order to create relative links.

When writing install-exec-hook or install-data-hook, please bear in mind that the exec/data distinction is based on the installation directory, not on the primary used (see section The Two Parts of Install). So a foo_SCRIPTS will be installed by install-data, and a barexec_SCRIPTS will be installed by install-exec. You should define your hooks consequently.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

23.2 Third-Party `Makefile's

In most projects all `Makefile's are generated by Automake. In some cases, however, projects need to embed subdirectories with handwritten `Makefile's. For instance, one subdirectory could be a third-party project with its own build system, not using Automake.

It is possible to list arbitrary directories in SUBDIRS or DIST_SUBDIRS provided each of these directories has a `Makefile' that recognizes all the following recursive targets.

When a user runs one of these targets, that target is run recursively in all subdirectories. This is why it is important that even third-party `Makefile's support them.

all

Compile the entire package. This is the default target in Automake-generated `Makefile's, but it does not need to be the default in third-party `Makefile's.

distdir

Copy files to distribute into `$(distdir)', before a tarball is constructed. Of course this target is not required if the `no-dist' option (see section Changing Automake's Behavior) is used.

The variables `$(top_distdir)' and `$(distdir)' (see section The dist Hook) will be passed from the outer package to the subpackage when the distdir target is invoked. These two variables have been adjusted for the directory that is being recursed into, so they are ready to use.

install
install-data
install-exec
uninstall

Install or uninstall files (see section What Gets Installed).

install-dvi
install-html
install-info
install-ps
install-pdf

Install only some specific documentation format (see section Texinfo).

installdirs

Create install directories, but do not install any files.

check
installcheck

Check the package (see section Support for test suites).

mostlyclean
clean
distclean
maintainer-clean

Cleaning rules (see section What Gets Cleaned).

dvi
pdf
ps
info
html

Build the documentation in various formats (see section Texinfo).

tags
ctags

Build `TAGS' and `CTAGS' (see section Interfacing to etags).

If you have ever used Gettext in a project, this is a good example of how third-party `Makefile's can be used with Automake. The `Makefile's gettextize puts in the `po/' and `intl/' directories are handwritten `Makefile's that implement all these targets. That way they can be added to SUBDIRS in Automake packages.

Directories that are only listed in DIST_SUBDIRS but not in SUBDIRS need only the distclean, maintainer-clean, and distdir rules (see section Conditional Subdirectories).

Usually, many of these rules are irrelevant to the third-party subproject, but they are required for the whole package to work. It's OK to have a rule that does nothing, so if you are integrating a third-party project with no documentation or tag support, you could simply augment its `Makefile' as follows:

 
EMPTY_AUTOMAKE_TARGETS = dvi pdf ps info html tags ctags
.PHONY: $(EMPTY_AUTOMAKE_TARGETS)
$(EMPTY_AUTOMAKE_TARGETS):

Another aspect of integrating third-party build systems is whether they support VPATH builds (see section Parallel Build Trees (a.k.a. VPATH Builds)). Obviously if the subpackage does not support VPATH builds the whole package will not support VPATH builds. This in turns means that `make distcheck' will not work, because it relies on VPATH builds. Some people can live without this (actually, many Automake users have never heard of `make distcheck'). Other people may prefer to revamp the existing `Makefile's to support VPATH. Doing so does not necessarily require Automake, only Autoconf is needed (see (autoconf)Build Directories section `Build Directories' in The Autoconf Manual). The necessary substitutions: `@srcdir@', `@top_srcdir@', and `@top_builddir@' are defined by `configure' when it processes a `Makefile' (see (autoconf)Preset Output Variables section `Preset Output Variables' in The Autoconf Manual), they are not computed by the Makefile like the aforementioned `$(distdir)' and `$(top_distdir)' variables.

It is sometimes inconvenient to modify a third-party `Makefile' to introduce the above required targets. For instance, one may want to keep the third-party sources untouched to ease upgrades to new versions.

Here are two other ideas. If GNU make is assumed, one possibility is to add to that subdirectory a `GNUmakefile' that defines the required targets and includes the third-party `Makefile'. For this to work in VPATH builds, `GNUmakefile' must lie in the build directory; the easiest way to do this is to write a `GNUmakefile.in' instead, and have it processed with AC_CONFIG_FILES from the outer package. For example if we assume `Makefile' defines all targets except the documentation targets, and that the check target is actually called test, we could write `GNUmakefile' (or `GNUmakefile.in') like this:

 
# First, include the real Makefile
include Makefile
# Then, define the other targets needed by Automake Makefiles.
.PHONY: dvi pdf ps info html check
dvi pdf ps info html:
check: test

A similar idea that does not use include is to write a proxy `Makefile' that dispatches rules to the real `Makefile', either with `$(MAKE) -f Makefile.real $(AM_MAKEFLAGS) target' (if it's OK to rename the original `Makefile') or with `cd subdir && $(MAKE) $(AM_MAKEFLAGS) target' (if it's OK to store the subdirectory project one directory deeper). The good news is that this proxy `Makefile' can be generated with Automake. All we need are `-local' targets (see section Extending Automake Rules) that perform the dispatch. Of course the other Automake features are available, so you could decide to let Automake perform distribution or installation. Here is a possible `Makefile.am':

 
all-local:
        cd subdir && $(MAKE) $(AM_MAKEFLAGS) all
check-local:
        cd subdir && $(MAKE) $(AM_MAKEFLAGS) test
clean-local:
        cd subdir && $(MAKE) $(AM_MAKEFLAGS) clean

# Assuming the package knows how to install itself
install-data-local:
        cd subdir && $(MAKE) $(AM_MAKEFLAGS) install-data
install-exec-local:
        cd subdir && $(MAKE) $(AM_MAKEFLAGS) install-exec
uninstall-local:
        cd subdir && $(MAKE) $(AM_MAKEFLAGS) uninstall

# Distribute files from here.
EXTRA_DIST = subdir/Makefile subdir/program.c ...

Pushing this idea to the extreme, it is also possible to ignore the subproject build system and build everything from this proxy `Makefile.am'. This might sound very sensible if you need VPATH builds but the subproject does not support them.


[ << ] [ >> ]           [Top] [Contents] [Index] [ ? ]

This document was generated on July, 20 2009 using texi2html 1.76.