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