build: man page generation: degrade gracefully when perl is lacking

Since commit v8.19-118-g57da212, our 'dist-hook' rule tweaked the
distributed Makefile.in to make each man page 'man/foo.1' depend
on the corresponding source 'src/foo.c' rather than the corresponding
program 'src/foo'.  That was done to accommodate systems without
perl, which cannot run help2man to regenerate the manpage after
its corresponding program has been built.

This seems a right and proper graceful degradation, in that the
man pages dependencies are still 100% correct in a git checkout,
while being more lax but "more portable" in a distribution tarball.
Alas, that is not the case in practice, as it turns out the tweaked
Makefile makes the building of man pages unreliable and potentially
incorrect!

In fact, assume that instead of the correct a dependency:

    man/ls.1: src/ls

we have the laxer one:

    man/ls.1: src/ls.c

and think of what happens if a user modifies, say, 'src/ls.c', and then
runs "make -j4" to rebuild everything.  The make process will see that
it has to rebuild the man page 'man/ls.1' (because its prerequisite
'src/ls.c' has changed), but won't see that it has to rebuild 'src/ls'
*before* re-running 'help2man' to generate that man page; so, if
'man/ls.1' is rebuilt before 'src/ls' (which can happen with concurrent
make), our user will get either a build error (if 'src/ls' did non
exist) or, worse, a man page with an up-to-date timestamp but an
out-of-date content.  And what's even worse in all of this is that
this problem will be present also for users who have perl installed:
this is not a "graceful degradation" at all!

In our situation, the best and simplest way to implement a graceful
degradation it to keep the correct dependencies for man pages (that
is, "man/ls.1: src/ls"), and if perl is not present, just generate
dummy man pages reporting that built-time issue and redirecting the
user back to either the info documentation or the '--help' output.

As a consequence of this change, we also stop distributing man pages,
since they will now be generated unconditionally.

* Makefile.am (do-not-require-help2man): Remove.
(dist-hook): Don't depend on it.
* man/local.mk: Remove an obsolete comment.
(EXTRA_DIST): Stop distributing generated man pages.
($(EXTRA_MANS)): This no longer needs to depend on $(all_programs).
(MAINTAINERCLEANFILES): $(ALL_MANS) Do not list it here, and ...
(CLEANFILES): ... list it here, instead.
(.x.1): Instead of warning if perl is missing, but then trying to run
'help2man' unconditionally, simply run ...
(run_help2man): ... the command referenced by this new variable, that
expands to a proper invocation of 'help2man' if perl is present, and
to an invocation of a shell script generating a dummy manpage if it
is not.
(EXTRA_DIST): Distribute that shell script.
* man/dummy-man: New shell script.
* NEWS (Build-related): Mention this.
Fixes coreutils http://bugs.gnu.org/12715.
This commit is contained in:
Stefano Lattarini 2012-09-11 20:54:30 +02:00 committed by Jim Meyering
parent 74da4c8047
commit 48536bfe8f
4 changed files with 99 additions and 31 deletions

View File

@ -93,29 +93,11 @@ BUILT_SOURCES = .version
.version:
$(AM_V_GEN)echo $(VERSION) > $@-t && mv $@-t $@
# In general, we run help2man to build a man page from the binary's --help
# output, but when building from a just-unpacked distribution tarball, we
# must not do that, since help2man uses perl. We don't want to depend on
# perl in that case. In general, the .1 file does indeed depend on the
# binary. I.e., for cat, we have this Makefile dependency:
# man/cat.1: src/cat
# That means that once we build src/cat, we would trigger the .x.1
# rule which runs help2man. The trick is simply to change the RHS to
# "src/cat.c" in the $(distdir) that we're about to tar and compress.
# Also handle the three exceptions corresponding to the three binaries
# for which there is no like-named .c file: dir, vdir, ginstall.
.PHONY: do-not-require-help2man
do-not-require-help2man:
perl -pi -e 's,^(man/.+?\.1:\s*src/.+?)$$,$$1.c,;' \
-e 's,^(man/.+?\.1:\s*src)/ginstall\.c$$,$$1/install.c,;' \
-e 's,^(man/.+?\.1:\s*src)/v?dir\.c$$,$$1/ls.c,;' \
$(distdir)/Makefile.in
# Arrange so that .tarball-version appears only in the distribution
# tarball, and never in a checked-out repository.
# The perl substitution is to change some key uses of "rm" to "/bin/rm".
# See the rm_subst comment for details.
dist-hook: gen-ChangeLog do-not-require-help2man
dist-hook: gen-ChangeLog
$(AM_V_GEN)echo $(VERSION) > $(distdir)/.tarball-version
$(AM_V_at)perl -pi -e '$(rm_subst)' $(distdir)/Makefile.in

13
NEWS
View File

@ -8,6 +8,19 @@ GNU coreutils NEWS -*- outline -*-
consistently padded with spaces, rather than with zeros for certain widths.
[bug introduced in TEXTUTILS-1_22i]
** Build-related
Perl is now more of a prerequisite. It has long been required in order
to run (not skip) a significant percentage of the tests. Now, it is
also required in order to generate proper man pages, via help2man. The
generated man/*.1 man pages are no longer distributed. Building without
perl, you would create stub man pages. Thus, while perl is not an
official prerequisite (build and "make check" will still succeed), any
resulting man pages would be inferior. In addition, this fixes a bug
in distributed (not from clone) Makefile.in that could cause parallel
build failure when building from modified sources, as is common practice
for a patched distribution package.
* Noteworthy changes in release 8.20 (2012-10-23) [stable]

72
man/dummy-man Executable file
View File

@ -0,0 +1,72 @@
#!/bin/sh
# Poor man's placeholder for help2man invocation on systems lacking perl;
# it generates a dummy man page stating that a proper one could not be
# generated, and redirecting the user back to either the info
# documentation or the '--help' output.
set -e; set -u
fatal_ ()
{
printf '%s: %s\n' "$0" "$*" >&2
exit 1
}
basename_ ()
{
printf '%s\n' "$1" | sed 's,.*/,,'
}
output=
source="GNU coreutils"
while test $# -gt 0; do
case $1 in
# Help2man options we recognize and handle.
--output=*) output=`expr x"$1" : x'--output=\(.*\)'`;;
--output) shift; output=$1;;
--source=*) source=`expr x"$1" : x'--source=\(.*\)'`;;
--source) shift; source=$1;;
# Recognize (as no-op) other help2man options that might be used
# in the makefile.
--include=*);;
--include) shift;;
-*) fatal_ "invalid or unrecognized help2man option '$1'";;
--) shift; break;;
*) break;;
esac
shift
done
test $# -gt 0 || fatal_ "missing argument"
test $# -le 1 || fatal_ "too many non-option arguments"
baseout=`basename_ "$output"`
sed 's/^/WARNING: /' >&2 <<END
Cannot create proper '$baseout' man page, since perl is missing or
inadequate on this system. Creating a stub man page instead.
END
progname=`basename_ "$1"`
year=`LC_ALL=C date +%Y`
bs='\'
cat >"$output" <<END
.TH "$progname" 1 "$year" "$source" "User Commands"
.SH NAME
$progname $bs- a $source program
.SH DESCRIPTION
.B OOOPS!
Due to the lack of perl on the build system, we were
unable to create a proper manual page for
.B $progname.
For concise option descriptions, run
.IP
.B env $progname --help
.PP
The full documentation for
.B $progname
is maintained as a Texinfo manual, which should be accessible
on your system via the command
.IP
.B info coreutils $bs(aq$progname invocation$bs(aq
END

View File

@ -16,17 +16,24 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
EXTRA_DIST += man/help2man
EXTRA_DIST += man/help2man man/dummy-man
## Graceful degradation for systems lacking perl.
if HAVE_PERL
run_help2man = $(PERL) -- $(srcdir)/man/help2man
else
run_help2man = $(SHELL) $(srcdir)/man/dummy-man
endif
man1_MANS = @man1_MANS@
EXTRA_DIST += $(man1_MANS) $(man1_MANS:.1=.x)
EXTRA_DIST += $(man1_MANS:.1=.x)
EXTRA_MANS = @EXTRA_MANS@
EXTRA_DIST += $(EXTRA_MANS) $(EXTRA_MANS:.1=.x)
EXTRA_DIST += $(EXTRA_MANS:.1=.x)
ALL_MANS = $(man1_MANS) $(EXTRA_MANS)
MAINTAINERCLEANFILES += $(ALL_MANS)
CLEANFILES += $(ALL_MANS)
# This is required because we have subtle inter-directory dependencies:
# in order to generate all man pages, even those for which we don't
@ -161,13 +168,7 @@ man/whoami.1: src/whoami
man/yes.1: src/yes
.x.1:
$(AM_V_GEN)case '$(PERL)' in \
*"/missing "*) \
echo 'WARNING: cannot update man page $@ since perl is missing' \
'or inadequate' 1>&2 \
exit 0;; \
esac; \
name=`echo $@ | sed -e 's|.*/||' -e 's|\.1$$||'` || exit 1; \
$(AM_V_GEN)name=`echo $@ | sed 's|.*/||; s|\.1$$||'` || exit 1; \
## Ensure that help2man runs the 'src/ginstall' binary as 'install' when
## creating 'install.1'. Similarly, ensure that it uses the 'src/[' binary
## to create 'test.1'.
@ -184,7 +185,7 @@ man/yes.1: src/yes
&& rm -rf $$t \
&& $(MKDIR_P) $$t \
&& (cd $$t && $(LN_S) '$(abs_top_builddir)/src/'$$prog $$name) \
&& $(PERL) -- $(srcdir)/man/help2man \
&& $(run_help2man) \
--source='$(PACKAGE_STRING)' \
--include=$(srcdir)/man/$$name.x \
--output=$$t/$$name.1 $$t/$$name \