distclean
¶As explained in the section above (see Checking the Distribution), ‘make distcheck’ attempts to build and check your package for errors. One such error you might see is:
ERROR: files left in build directory after distclean:
The file(s) left in the build directory after ‘make distclean’ has run are listed after this error message. This can happen in two ways:
In the first case of simple left-over files not intended to be distributed, the fix is to include them for cleaning (see What Gets Cleaned); this is straightforward and doesn’t need more explanation.
The second case, however, is not always easy to understand and fix, so
let’s proceed with an example. Suppose our package contains a program
for which we want to build a man page using help2man
. GNU
help2man
produces simple manual pages from the
--help and --version output of other commands
(see The Help2man Manual). Because we don’t want to
force our users to install help2man
, we distribute the
generated man page using the following setup.
# This Makefile.am is bogus. bin_PROGRAMS = foo foo_SOURCES = foo.c dist_man_MANS = foo.1 foo.1: foo$(EXEEXT) help2man --output=foo.1 ./foo$(EXEEXT)
This will effectively distribute the man page. However, ‘make distcheck’ will fail with:
ERROR: files left in build directory after distclean: ./foo.1
Why was foo.1 rebuilt? Because although distributed, foo.1 depends on a non-distributed built file: foo$(EXEEXT). foo$(EXEEXT) is built by the user, so it will always appear to be newer than the distributed foo.1.
In other words, ‘make distcheck’ caught an inconsistency in our
package. Our intent was to distribute foo.1 so users do not
need to install help2man
, but since this rule causes this
file to be always rebuilt, users do need help2man
.
Either we should ensure that foo.1 is not rebuilt by users, or
there is no point in distributing foo.1.
More generally, the rule is that distributed files should never depend on non-distributed built files. If you distribute something generated, distribute all its sources.
One way to fix the above example, while still distributing
foo.1, is to not depend on foo$(EXEEXT), but instead on
relevant source files. For instance, assuming foo --version
and foo --help
do not change unless foo.c or
configure.ac change, we could write the following
Makefile.am:
bin_PROGRAMS = foo foo_SOURCES = foo.c dist_man_MANS = foo.1 foo.1: foo.c $(top_srcdir)/configure.ac $(MAKE) $(AM_MAKEFLAGS) foo$(EXEEXT) help2man --output=foo.1 ./foo$(EXEEXT)
This way, foo.1 will not get rebuilt every time
foo$(EXEEXT) changes. The make
call makes sure
foo$(EXEEXT) is up-to-date before help2man
.
Another step towards ensuring this would be to use separate
directories for binaries and man pages, and set SUBDIRS
so that
binaries are built before man pages. Unfortunately, this alone is, in
general, not sufficient. In order to avoid to avoid concurrency bugs,
it may be necessary to include wrappers; this is done by GNU Autoconf,
as mentioned below.
We could also decide not to distribute foo.1. In this case
it’s fine to have foo.1 dependent upon foo$(EXEEXT),
since both will have to be rebuilt. However, it might be impossible
to build the package in a cross-compilation, because building
foo.1 involves an execution of foo$(EXEEXT). The
exception would be if foo is a platform-independent script,
such as help2man
.
Another context where such errors are common is when distributed files are built by tools that are built by the package. The pattern is similar:
distributed-file: built-tools distributed-sources build-command
should be changed to
distributed-file: distributed-sources $(MAKE) $(AM_MAKEFLAGS) built-tools build-command
or you could choose not to distribute distributed-file, if cross-compilation does not matter.
The points made through these examples are worth summarizing:
|
Real-world examples for help2man
:
autoconf/man/local.mk
, which has
a good discussion of the necessary additional details.
help2man
script, which is plausible
because help2man
is small, self-contained, and
platform-independent. See the source file
automake/doc/local.mk
.
If you’re desperate, it’s possible to disable this check completely by
setting distcleancheck_listfiles
(see distcleancheck
).
Make sure you understand the reason why ‘make distcheck’
complains first. distcleancheck_listfiles
is a way to
hide errors, not to fix them. You can always do better.