Previous: Extending, Up: Not Enough


23.2 Third-Party Makefiles

In most projects all Makefiles are generated by Automake. In some cases, however, projects need to embed subdirectories with handwritten Makefiles. 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 Makefiles support them.

all
Compile the entire package. This is the default target in Automake-generated Makefiles, but it does not need to be the default in third-party Makefiles.
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 Options) is used.

The variables ‘$(top_distdir)’ and ‘$(distdir)’ (see Dist) 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 Install).
install-dvi
install-html
install-info
install-ps
install-pdf
Install only some specific documentation format (see Texinfo).
installdirs
Create install directories, but do not install any files.
check
installcheck
Check the package (see Tests).
mostlyclean
clean
distclean
maintainer-clean
Cleaning rules (see Clean).
dvi
pdf
ps
info
html
Build the documentation in various formats (see Texinfo).
tags
ctags
Build TAGS and CTAGS (see Tags).

If you have ever used Gettext in a project, this is a good example of how third-party Makefiles can be used with Automake. The Makefiles gettextize puts in the po/ and intl/ directories are handwritten Makefiles 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 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 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 Makefiles to support VPATH. Doing so does not necessarily require Automake, only Autoconf is needed (see Build Directories). The necessary substitutions: ‘@srcdir@’, ‘@top_srcdir@’, and ‘@top_builddir@’ are defined by configure when it processes a Makefile (see Preset Output Variables), 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 include 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 Extending) 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 sounds very sensible if you need VPATH builds but the subproject does not support them.