automake: Errors with distclean
1
1 27.5 Errors with distclean
1 ==========================
1
1 This is a diagnostic you might encounter while running ‘make distcheck’.
1
1 As explained in ⇒Checking the Distribution, ‘make distcheck’
1 attempts to build and check your package for errors like this one.
1
11 ‘make distcheck’ will perform a ‘VPATH’ build of your package (⇒
VPATH Builds), and then call ‘make distclean’. Files left in the
1 build directory after ‘make distclean’ has run are listed after this
1 error.
1
1 This diagnostic really covers two kinds of errors:
1
1 • files that are forgotten by distclean;
1 • distributed files that are erroneously rebuilt.
1
1 The former left-over files are not distributed, so the fix is to mark
1 them for cleaning (⇒Clean), this is obvious and doesn’t deserve
1 more explanations.
1
1 The latter bug is not always easy to understand and fix, so let’s
1 proceed with an example. Suppose our package contains a program for
1 which we want to build a man page using ‘help2man’. GNU ‘help2man’
1 produces simple manual pages from the ‘--help’ and ‘--version’ output of
1 other commands (⇒Overview (help2man)Top.). Because we don’t want
1 to force our users to install ‘help2man’, we decide to distribute the
1 generated man page using the following setup.
1
1 # This Makefile.am is bogus.
1 bin_PROGRAMS = foo
1 foo_SOURCES = foo.c
1 dist_man_MANS = foo.1
1
1 foo.1: foo$(EXEEXT)
1 help2man --output=foo.1 ./foo$(EXEEXT)
1
1 This will effectively distribute the man page. However, ‘make
1 distcheck’ will fail with:
1
1 ERROR: files left in build directory after distclean:
1 ./foo.1
1
1 Why was ‘foo.1’ rebuilt? Because although distributed, ‘foo.1’
1 depends on a non-distributed built file: ‘foo$(EXEEXT)’. ‘foo$(EXEEXT)’
1 is built by the user, so it will always appear to be newer than the
1 distributed ‘foo.1’.
1
1 ‘make distcheck’ caught an inconsistency in our package. Our intent
1 was to distribute ‘foo.1’ so users do not need to install ‘help2man’,
1 however since this rule causes this file to be always rebuilt, users
1 _do_ need ‘help2man’. Either we should ensure that ‘foo.1’ is not
1 rebuilt by users, or there is no point in distributing ‘foo.1’.
1
1 More generally, the rule is that distributed files should never
1 depend on non-distributed built files. If you distribute something
1 generated, distribute its sources.
1
1 One way to fix the above example, while still distributing ‘foo.1’ is
1 to not depend on ‘foo$(EXEEXT)’. For instance, assuming ‘foo --version’
1 and ‘foo --help’ do not change unless ‘foo.c’ or ‘configure.ac’ change,
1 we could write the following ‘Makefile.am’:
1
1 bin_PROGRAMS = foo
1 foo_SOURCES = foo.c
1 dist_man_MANS = foo.1
1
1 foo.1: foo.c $(top_srcdir)/configure.ac
1 $(MAKE) $(AM_MAKEFLAGS) foo$(EXEEXT)
1 help2man --output=foo.1 ./foo$(EXEEXT)
1
1 This way, ‘foo.1’ will not get rebuilt every time ‘foo$(EXEEXT)’
1 changes. The ‘make’ call makes sure ‘foo$(EXEEXT)’ is up-to-date before
1 ‘help2man’. Another way to ensure this would be to use separate
1 directories for binaries and man pages, and set ‘SUBDIRS’ so that
1 binaries are built before man pages.
1
1 We could also decide not to distribute ‘foo.1’. In this case it’s
1 fine to have ‘foo.1’ dependent upon ‘foo$(EXEEXT)’, since both will have
1 to be rebuilt. However it would be impossible to build the package in a
1 cross-compilation, because building ‘foo.1’ involves an _execution_ of
1 ‘foo$(EXEEXT)’.
1
1 Another context where such errors are common is when distributed
1 files are built by tools that are built by the package. The pattern is
1 similar:
1
1 distributed-file: built-tools distributed-sources
1 build-command
1
1 should be changed to
1
1 distributed-file: distributed-sources
1 $(MAKE) $(AM_MAKEFLAGS) built-tools
1 build-command
1
1 or you could choose not to distribute ‘distributed-file’, if
1 cross-compilation does not matter.
1
1 The points made through these examples are worth a summary:
1
1 • Distributed files should never depend upon non-distributed built
1 files.
1 • Distributed files should be distributed with all their
1 dependencies.
1 • If a file is _intended_ to be rebuilt by users, then there is no
1 point in distributing it.
1
1 For desperate cases, it’s always possible to disable this check by
11 setting ‘distcleancheck_listfiles’ as documented in ⇒Checking the
Distribution. Make sure you do understand the reason why ‘make
1 distcheck’ complains before you do this. ‘distcleancheck_listfiles’ is
1 a way to _hide_ errors, not to fix them. You can always do better.
1