From: Ralf Wildenhues Date: Sun, 7 Sep 2008 07:59:52 +0000 (+0200) Subject: Reliable multi-file install for man pages. X-Git-Tag: v1.10b~110 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2cfd4806452c2b206b0d77c57ec6129bf2fc0118;p=thirdparty%2Fautomake.git Reliable multi-file install for man pages. * lib/am/mans.am: Include inst-vars.am. (install-man%SECTION%): Gather lists of man pages to install, and install up to 40 of those that do not have to be renamed at once. Fail if installation of any file fails. (uninstall-man%SECTION%): Rewrite to use fewer sed invocations. * doc/automake.texi (Man pages): Hint the user to the fast path. Indentation fix. * tests/instmany-mans.test: New test. * tests/Makefile.am: Update. Signed-off-by: Ralf Wildenhues --- diff --git a/ChangeLog b/ChangeLog index 4266e4dc6..e5b4eb652 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2008-09-07 Ralf Wildenhues + Jim Meyering + + Reliable multi-file install for man pages. + * lib/am/mans.am: Include inst-vars.am. + (install-man%SECTION%): Gather lists of man pages to install, + and install up to 40 of those that do not have to be renamed + at once. Fail if installation of any file fails. + (uninstall-man%SECTION%): Rewrite to use fewer sed invocations. + * doc/automake.texi (Man pages): Hint the user to the fast path. + Indentation fix. + * tests/instmany-mans.test: New test. + * tests/Makefile.am: Update. + 2008-09-07 Ralf Wildenhues Faster `make uninstall'; fast install for JAVA. diff --git a/doc/automake.texi b/doc/automake.texi index 0ea578097..263d1b638 100644 --- a/doc/automake.texi +++ b/doc/automake.texi @@ -7644,6 +7644,7 @@ For instance, consider this example: man1_MANS = rename.man thesame.1 alsothesame.1c @end example +@noindent In this case, @file{rename.man} will be renamed to @file{rename.1} when installed, but the other files will keep their names. @@ -7661,6 +7662,10 @@ not expend effort to keep the man pages up to date. In these cases, the installed by default. The user can still explicitly install them via @samp{make install-man}. +For fast installation, with many files it is preferable to use +@samp{man@var{SECTION}_MANS} over @samp{man_MANS} as well as files that +do not need to be renamed. + Man pages are not currently considered to be source, because it is not uncommon for man pages to be automatically generated. Therefore they are not automatically included in the distribution. However, this can diff --git a/lib/am/mans.am b/lib/am/mans.am index 338b43c51..803a89227 100644 --- a/lib/am/mans.am +++ b/lib/am/mans.am @@ -15,6 +15,7 @@ ## You should have received a copy of the GNU General Public License ## along with this program. If not, see . +include inst-vars.am man%SECTION%dir = $(mandir)/man%SECTION% ## ------------ ## @@ -34,62 +35,69 @@ install-man%SECTION%: %DEPS% if %?NOTRANS_MANS% ## Handle MANS with notrans_ prefix @list='%NOTRANS_SECT_LIST%'; \ + { for i in $$list; do echo "$$i"; done; \ ## Extract all items from notrans_man_MANS that should go in this section. ## This must be done dynamically to support conditionals. -?HAVE_NOTRANS? l2='%NOTRANS_LIST%'; \ -?HAVE_NOTRANS? for i in $$l2; do \ -?HAVE_NOTRANS? case "$$i" in \ -## Have to accept files like `foo.1c'. -?HAVE_NOTRANS? *.%SECTION%*) list="$$list $$i" ;; \ -?HAVE_NOTRANS? esac; \ +?HAVE_NOTRANS? l2='%NOTRANS_LIST%'; for i in $$l2; do \ +## Accept files like `foo.1c'. +?HAVE_NOTRANS? case $$i in *.%SECTION%*) echo "$$i";; esac; \ ?HAVE_NOTRANS? done; \ - for i in $$list; do \ +## Extract basename of manpage, change the extension if needed. + } | while read p; do \ ## Find the file. - if test -f $$i; then file=$$i; \ - else file=$(srcdir)/$$i; fi; \ -## Change the extension if needed. - ext=`echo $$i | sed -e 's/^.*\\.//'`; \ - case "$$ext" in \ - %SECTION%*) ;; \ - *) ext='%SECTION%' ;; \ - esac; \ -## Extract basename of man page and append extension. - inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ - inst=`echo $$inst | sed -e 's/^.*\///'`.$$ext; \ - echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man%SECTION%dir)/$$inst'"; \ - $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man%SECTION%dir)/$$inst"; \ - done + if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; echo "$$p"; \ + done | \ +## Extract the basename of the man page and change the extension if needed. + sed 'n;s,.*/,,;p;s,\.[^%SECTION%][0-9a-z]*$$,.%SECTION%,' | \ + sed 'N;N;s,\n, ,g' | { \ +## We now have a list "sourcefile basename installed-name". + list=; while read file base inst; do \ + if test "$$base" = "$$inst"; then list="$$list $$file"; else \ + echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man%SECTION%dir)/$$inst'"; \ + $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man%SECTION%dir)/$$inst" || exit $$?; \ + fi; \ + done; \ + for i in $$list; do echo "$$i"; done | $(am__base_list) | \ + while read files; do \ + test -z "$$files" || { \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man%SECTION%dir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(man%SECTION%dir)" || exit $$?; }; \ + done; } endif %?NOTRANS_MANS% if %?TRANS_MANS% ## Handle MANS without notrans_ prefix @list='%TRANS_SECT_LIST%'; \ -## Extract all items from man_MANS that should go in this section. + { for i in $$list; do echo "$$i"; done; \ +## Extract all items from notrans_man_MANS that should go in this section. ## This must be done dynamically to support conditionals. -?HAVE_TRANS? l2='%TRANS_LIST%'; \ -?HAVE_TRANS? for i in $$l2; do \ -?HAVE_TRANS? case "$$i" in \ -## Have to accept files like `foo.1c'. -?HAVE_TRANS? *.%SECTION%*) list="$$list $$i" ;; \ -?HAVE_TRANS? esac; \ +?HAVE_TRANS? l2='%TRANS_LIST%'; for i in $$l2; do \ +## Accept files like `foo.1c'. +?HAVE_TRANS? case $$i in *.%SECTION%*) echo "$$i";; esac; \ ?HAVE_TRANS? done; \ - for i in $$list; do \ +## Extract basename of manpage, change the extension if needed. + } | while read p; do \ ## Find the file. - if test -f $$i; then file=$$i; \ - else file=$(srcdir)/$$i; fi; \ -## Change the extension if needed. - ext=`echo $$i | sed -e 's/^.*\\.//'`; \ - case "$$ext" in \ - %SECTION%*) ;; \ - *) ext='%SECTION%' ;; \ - esac; \ -## Extract basename of man page and run it through the program rename -## transform. - inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ - inst=`echo $$inst | sed -e 's/^.*\///'`; \ - inst=`echo $$inst | sed '$(transform)'`.$$ext; \ - echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man%SECTION%dir)/$$inst'"; \ - $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man%SECTION%dir)/$$inst"; \ - done + if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; echo "$$p"; \ + done | \ +## Extract the basename of the man page and change the extension if needed. + sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^%SECTION%][0-9a-z]*$$,%SECTION%,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ + sed 'N;N;s,\n, ,g' | { \ +## We now have a list "sourcefile basename installed-name". + list=; while read file base inst; do \ + if test "$$base" = "$$inst"; then list="$$list $$file"; else \ + echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man%SECTION%dir)/$$inst'"; \ + $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man%SECTION%dir)/$$inst" || exit $$?; \ + fi; \ + done; \ + for i in $$list; do echo "$$i"; done | $(am__base_list) | \ + while read files; do \ + test -z "$$files" || { \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man%SECTION%dir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(man%SECTION%dir)" || exit $$?; }; \ + done; } endif %?TRANS_MANS% @@ -97,7 +105,6 @@ endif %?TRANS_MANS% ## Uninstalling. ## ## -------------- ## -## This is just completely gross. .PHONY: uninstall-man ?INSTALL-MAN?uninstall-am: uninstall-man .PHONY uninstall-man: uninstall-man%SECTION% @@ -106,54 +113,34 @@ uninstall-man%SECTION%: if %?NOTRANS_MANS% ## Handle MANS with notrans_ prefix @list='%NOTRANS_SECT_LIST%'; \ + files=`{ for i in $$list; do echo "$$i"; done; \ ## Extract all items from notrans_man_MANS that should go in this section. ## This must be done dynamically to support conditionals. -?HAVE_NOTRANS? l2='%NOTRANS_LIST%'; \ -?HAVE_NOTRANS? for i in $$l2; do \ -?HAVE_NOTRANS? case "$$i" in \ -## Have to accept files like `foo.1c'. -?HAVE_NOTRANS? *.%SECTION%*) list="$$list $$i" ;; \ -?HAVE_NOTRANS? esac; \ +?HAVE_NOTRANS? l2='%NOTRANS_LIST%'; for i in $$l2; do \ +## Accept files like `foo.1c'. +?HAVE_NOTRANS? case $$i in *.%SECTION%*) echo "$$i";; esac; \ ?HAVE_NOTRANS? done; \ - for i in $$list; do \ -## Change the extension if needed. - ext=`echo $$i | sed -e 's/^.*\\.//'`; \ - case "$$ext" in \ - %SECTION%*) ;; \ - *) ext='%SECTION%' ;; \ - esac; \ -## Extract basename of man page and append extension. - inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ - inst=`echo $$inst | sed -e 's/^.*\///'`.$$ext; \ - echo " rm -f '$(DESTDIR)$(man%SECTION%dir)/$$inst'"; \ - rm -f "$(DESTDIR)$(man%SECTION%dir)/$$inst"; \ - done +## Extract basename of manpage, change the extension if needed. + } | sed 's,.*/,,;s,\.[^%SECTION%][0-9a-z]*$$,.%SECTION%,'`; \ + test -n "$$files" || exit 0; \ + echo " ( cd '$(DESTDIR)$(man%SECTION%dir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(man%SECTION%dir)" && rm -f $$files endif %?NOTRANS_MANS% if %?TRANS_MANS% ## Handle MANS without notrans_ prefix @list='%TRANS_SECT_LIST%'; \ + files=`{ for i in $$list; do echo "$$i"; done; \ ## Extract all items from man_MANS that should go in this section. ## This must be done dynamically to support conditionals. -?HAVE_TRANS? l2='%TRANS_LIST%'; \ -?HAVE_TRANS? for i in $$l2; do \ -?HAVE_TRANS? case "$$i" in \ -## Have to accept files like `foo.1c'. -?HAVE_TRANS? *.%SECTION%*) list="$$list $$i" ;; \ -?HAVE_TRANS? esac; \ +?HAVE_TRANS? l2='%TRANS_LIST%'; for i in $$l2; do \ +## Accept files like `foo.1c'. +?HAVE_TRANS? case $$i in *.%SECTION%*) echo "$$i";; esac; \ ?HAVE_TRANS? done; \ - for i in $$list; do \ -## Change the extension if needed. - ext=`echo $$i | sed -e 's/^.*\\.//'`; \ - case "$$ext" in \ - %SECTION%*) ;; \ - *) ext='%SECTION%' ;; \ - esac; \ -## Extract basename of man page and run it through the program rename -## transform. - inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ - inst=`echo $$inst | sed -e 's/^.*\///'`; \ - inst=`echo $$inst | sed '$(transform)'`.$$ext; \ - echo " rm -f '$(DESTDIR)$(man%SECTION%dir)/$$inst'"; \ - rm -f "$(DESTDIR)$(man%SECTION%dir)/$$inst"; \ - done +## Extract basename of manpage, run it through the program rename +## transform, and change the extension if needed. + } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^%SECTION%][0-9a-z]*$$,%SECTION%,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ + test -n "$$files" || exit 0; \ + echo " ( cd '$(DESTDIR)$(man%SECTION%dir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(man%SECTION%dir)" && rm -f $$files endif %?TRANS_MANS% diff --git a/tests/Makefile.am b/tests/Makefile.am index 7a6b2865a..a9e995eb8 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -311,6 +311,7 @@ insthook.test \ instman.test \ instman2.test \ instmany.test \ +instmany-mans.test \ instmany-python.test \ instspc.test \ interp.test \ diff --git a/tests/Makefile.in b/tests/Makefile.in index 914ebf84f..d5559b646 100644 --- a/tests/Makefile.in +++ b/tests/Makefile.in @@ -462,6 +462,7 @@ insthook.test \ instman.test \ instman2.test \ instmany.test \ +instmany-mans.test \ instmany-python.test \ instspc.test \ interp.test \ diff --git a/tests/instmany-mans.test b/tests/instmany-mans.test new file mode 100755 index 000000000..3f331a665 --- /dev/null +++ b/tests/instmany-mans.test @@ -0,0 +1,147 @@ +#! /bin/sh +# Copyright (C) 2008 Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Installing many files should not exceed the command line length limit. + +# This is the mans sister test of instmany.test, see there for details. + +required=non-root # hope to catch 'chmod a-r'-challenged file systems. +. ./defs || Exit 1 + +set -e + +# In order to have a useful test on modern systems (which have a high +# limit, if any), use a fake install program that errors out for more +# than 2K characters in a command line. The POSIX limit is 4096, but +# that may include space taken up by the environment. + +limit=2500 +subdir=long_subdir_name_with_many_characters +nfiles=81 + +# Let's use `seq' if available, it's faster than the loop. +list=`(seq 1 $nfiles) 2>/dev/null || { + i=1 + while test $i -le $nfiles; do + echo $i + i=\`expr $i + 1\` + done; }` + +sed "s|@limit@|$limit|g" >myinstall.in <<'END' +#! /bin/sh +# Fake install script. This doesn't really install +# (the INSTALL path below would be wrong outside this directory). +limit=@limit@ +INSTALL='@INSTALL@' +len=`expr "$INSTALL $*" : ".*" 2>/dev/null || echo $limit` +if test $len -ge $limit; then + echo "$0: safe command line limit of $limit characters exceeded" >&2 + exit 1 +fi +exit 0 +END + +# Creative quoting in the next line to please maintainer-check. +sed "s|@limit@|$limit|g" >'rm' <<'END' +#! /bin/sh +limit=@limit@ +PATH=$save_PATH +export PATH +RM='rm -f' +len=`expr "$RM $*" : ".*" 2>/dev/null || echo $limit` +if test $len -ge $limit; then + echo "$0: safe command line limit of $limit characters exceeded" >&2 + exit 1 +fi +exec $RM "$@" +exit 1 +END + +chmod +x rm + +cat >>configure.in <Makefile.am <Makefile.am <<'END' +man_MANS = +man3_MANS = +notrans_man_MANS = +notrans_man3_MANS = +END + +for n in $list; do + cat >>Makefile.am <page$n.1 + echo >page$n.man + echo >npage$n.1 + echo >npage$n.man +done + +cd .. +$ACLOCAL +$AUTOCONF +$AUTOMAKE --add-missing + +instdir=`pwd`/inst +mkdir build +cd build +../configure --prefix="$instdir" +$MAKE +# Try whether native install (or install-sh) works. +$MAKE install +$MAKE uninstall +test `find "$instdir" -type f -print | wc -l` = 0 + +# Try whether we don't exceed the low limit. +INSTALL='$(SHELL) $(top_builddir)/myinstall' $MAKE -e install +env save_PATH="$PATH" PATH="`pwd`/..:$PATH" $MAKE uninstall + +cd $subdir +srcdir=../../$subdir + +# Ensure 'make install' fails when 'install' fails. + +# We cheat here, for efficiency, knowing the internal rule names. +# For correctness, one should `$MAKE install' here always, or at +# least use install-exec or install-data. + +for file in page3.1 page$nfiles.1 npage3.1 npage$nfiles.1; do + chmod a-r $srcdir/$file + $MAKE install-man1 && Exit 1 + chmod u+r $srcdir/$file +done + +for file in page3.man page$nfiles.man npage3.man npage$nfiles.man; do + chmod a-r $srcdir/$file + $MAKE install-man3 && Exit 1 + chmod u+r $srcdir/$file +done +: