Fixes automake bug https://bugs.gnu.org/10828.
Delete the configure check that would abort if `rm -f` does not work, and delete the plans to make this a hard requirement in the future. Instead, test to see if `rm -f` fails w/out arguments. If it does, define am__rm_f such that it always passes at least the "" argument when deleting files. If it doesn't fail, then we can omit the "". Then go through lib/am/ and update places where we use the pattern `test -z ... || rm -f ...` and replace with $(am__rm_f). * NEWS: Mention support for `rm -f` w/out arguments. * PLANS/rm-f-without-args.txt: Remove. * lib/am/check.am: Use new $(am__rm_f) helper. * lib/am/clean.am: Likewise. * lib/am/header-vars.am: Likewise. * lib/am/inst-vars.am: Likewise. * lib/am/libs.am: Likewise. * lib/am/ltlib.am: Likewise. * lib/am/progs.am: Likewise. * lib/am/texinfos.am: Likewise. * m4/init.m4: Delete `rm -f` checks and call _AM_PROG_RM_F. * m4/rmf.m4: Define new _AM_PROG_RM_F macro. * t/rm-f-probe.sh: Update test. --- NEWS | 4 ++++ PLANS/rm-f-without-args.txt | 40 ------------------------------------ lib/am/check.am | 8 ++++---- lib/am/clean.am | 4 ++-- lib/am/header-vars.am | 4 ++++ lib/am/inst-vars.am | 8 +++----- lib/am/libs.am | 2 +- lib/am/ltlib.am | 8 +++----- lib/am/progs.am | 5 ++--- lib/am/texinfos.am | 8 +++----- m4/init.m4 | 41 +------------------------------------ m4/rmf.m4 | 16 +++++++++++++++ t/rm-f-probe.sh | 26 +++++++++++------------ 13 files changed, 55 insertions(+), 119 deletions(-) delete mode 100644 PLANS/rm-f-without-args.txt create mode 100644 m4/rmf.m4 diff --git a/NEWS b/NEWS index 74ad6d612560..fbb3f758ce52 100644 --- a/NEWS +++ b/NEWS @@ -22,6 +22,10 @@ New in 1.17: - Generated file timestamp checks now handle filesystems with sub-second timestamp granularity dynamically. + - Systems with non-POSIX "rm -f" behavior are now supported, and intent to + drop support for them has been reversed. The ACCEPT_INFERIOR_RM_PROGRAM + setting no longer exists. + * Obsolescent features: - py-compile no longer supports Python 0.x or 1.x versions. Python 2.0, diff --git a/PLANS/rm-f-without-args.txt b/PLANS/rm-f-without-args.txt deleted file mode 100644 index b940fc3e9000..000000000000 --- a/PLANS/rm-f-without-args.txt +++ /dev/null @@ -1,40 +0,0 @@ -Summary -------- - -POSIX will say in a future version that calling "rm -f" with no argument -is OK; and this sensible behaviour seem to be already very widespread in -"the wild" (and possibly lacking only on those systems that are well on -their way to obsolescence). - -Se we'd like to simplify several automake-generated "cleaning" rules -accordingly, to get rid of the awful idiom: - - test -z "$(VAR)" || rm -f $(VAR) - -See automake bug#10828. - -For Automake 1.14 (DONE) ------------------------- - -Add a temporary "probe check" in AM_INIT_AUTOMAKE that verifies that -the no-args "rm -f" usage is supported on the system configure is -being run on; complain loudly if this is not the case, and tell the -user to report the situation to us. - -For Automake 2.0 ----------------- - -Make any failure in the configure-time probe check introduced by the -previous point fatal; and in case of failure, also suggest to the user -to install an older version of GNU coreutils to work around the -limitation of his system (this version should be old enough not to -be bootstrapped with Automake 2.0, otherwise the user will face a -bootstrapping catch-22). - -In all our recipes, start assuming "rm -f" with no argument is OK; -simplify and de-uglify the recipes accordingly. - -For Automake 3.0 ----------------- - -Remove the runtime probe altogether. diff --git a/lib/am/check.am b/lib/am/check.am index a7201af76bc0..6648c011d721 100644 --- a/lib/am/check.am +++ b/lib/am/check.am @@ -405,8 +405,8 @@ RECHECK_LOGS = $(TEST_LOGS) ## ------------------------------------------ ## check-TESTS: %CHECK_DEPS% - @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list - @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list + @list='$(RECHECK_LOGS)'; $(am__rm_f) $$list + @list='$(RECHECK_LOGS:.log=.trs)'; $(am__rm_f) $$list ## We always have to remove $(TEST_SUITE_LOG), to ensure its rule is run ## in any case even in lazy mode: otherwise, if no test needs rerunning, ## or a prior run plus reruns all happen within the same timestamp (can @@ -414,7 +414,7 @@ check-TESTS: %CHECK_DEPS% ## OTOH, this means that, in the rule for '$(TEST_SUITE_LOG)', we ## cannot use '$?' to compute the set of lazily rerun tests, lest ## we rely on .PHONY to work portably. - @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + @$(am__rm_f) $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ log_list=`for i in $$bases; do echo $$i.log; done`; \ trs_list=`for i in $$bases; do echo $$i.trs; done`; \ @@ -432,7 +432,7 @@ check-TESTS: %CHECK_DEPS% recheck: all %CHECK_DEPS% ## See comments above in the check-TESTS recipe for why remove ## $(TEST_SUITE_LOG) here. - @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + @$(am__rm_f) $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ ## We must only consider tests that had an unexpected outcome (FAIL ## or XPASS) in the earlier run. diff --git a/lib/am/clean.am b/lib/am/clean.am index 987e825ba77f..bf7eb81789fe 100644 --- a/lib/am/clean.am +++ b/lib/am/clean.am @@ -27,8 +27,8 @@ clean-generic: distclean-am: distclean-generic clean-am distclean-generic: - -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) - -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -$(am__rm_f) $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || $(am__rm_f) $(CONFIG_CLEAN_VPATH_FILES) %DISTCLEAN_RMS% ## Makefiles and their dependencies cannot be cleaned by diff --git a/lib/am/header-vars.am b/lib/am/header-vars.am index cfc330e6506b..0256faed6d2b 100644 --- a/lib/am/header-vars.am +++ b/lib/am/header-vars.am @@ -140,6 +140,10 @@ am__make_dryrun = (target_option=n; $(am__make_running_with_option)) ## subdirectories, and decide whether to stop at the first error or not. am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +## Helper to handle `rm -f` failing with no arguments. +am__rm_f = rm -f $(am__rm_f_notfound) +am__rm_rf = rm -rf $(am__rm_f_notfound) + ## Some derived variables that have been found to be useful. pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ diff --git a/lib/am/inst-vars.am b/lib/am/inst-vars.am index c17dd625d96f..fd35a7de1a16 100644 --- a/lib/am/inst-vars.am +++ b/lib/am/inst-vars.am @@ -59,15 +59,13 @@ am__base_list = \ ## to the directory where the files to be removed are, and to the list of ## such files. am__uninstall_files_from_dir = { \ -## Some rm implementations complain if 'rm -f' is used without arguments. - test -z "$$files" \ ## At least Solaris /bin/sh still lacks 'test -e', so we use the multiple ## tests below instead. We expect $dir to be either non-existent or a ## directory, so the failure we'll experience if it is a regular file ## is indeed desired and welcome (better to fail loudly thasn silently). - || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ - || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ - $(am__cd) "$$dir" && rm -f $$files; }; \ + { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && $(am__rm_f) $$files; }; \ } endif %?FIRST% diff --git a/lib/am/libs.am b/lib/am/libs.am index 52413521a088..a5e175e93160 100644 --- a/lib/am/libs.am +++ b/lib/am/libs.am @@ -103,4 +103,4 @@ endif %?INSTALL% .PHONY clean-am: clean-%DIR%LIBRARIES clean-%DIR%LIBRARIES: - -test -z "$(%DIR%_LIBRARIES)" || rm -f $(%DIR%_LIBRARIES) + -$(am__rm_f) $(%DIR%_LIBRARIES) diff --git a/lib/am/ltlib.am b/lib/am/ltlib.am index 6e3c065f4300..032f88169bda 100644 --- a/lib/am/ltlib.am +++ b/lib/am/ltlib.am @@ -109,7 +109,7 @@ endif %?INSTALL% .PHONY clean-am: clean-%DIR%LTLIBRARIES clean-%DIR%LTLIBRARIES: - -test -z "$(%DIR%_LTLIBRARIES)" || rm -f $(%DIR%_LTLIBRARIES) + -$(am__rm_f) $(%DIR%_LTLIBRARIES) ## 'so_locations' files are created by some linkers (IRIX, OSF) when ## building a shared object. Libtool places these files in the ## directory where the shared object is created. @@ -117,7 +117,5 @@ clean-%DIR%LTLIBRARIES: locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ - test -z "$$locs" || { \ - echo rm -f $${locs}; \ - rm -f $${locs}; \ - } + echo rm -f $${locs}; \ + $(am__rm_f) $${locs} diff --git a/lib/am/progs.am b/lib/am/progs.am index 8b99ec5a8c54..db3fd9585761 100644 --- a/lib/am/progs.am +++ b/lib/am/progs.am @@ -93,9 +93,8 @@ uninstall-%DIR%PROGRAMS: -e 's/$$/$(EXEEXT)/' \ ?!BASE? -e 'x;s,[^/]*$$,,;G;s,\n,,' \ `; \ - test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(%NDIR%dir)' && rm -f" $$files ")"; \ - cd "$(DESTDIR)$(%NDIR%dir)" && rm -f $$files + cd "$(DESTDIR)$(%NDIR%dir)" && $(am__rm_f) $$files endif %?INSTALL% @@ -105,7 +104,7 @@ endif %?INSTALL% .PHONY clean-am: clean-%DIR%PROGRAMS clean-%DIR%PROGRAMS: -?!LIBTOOL? -test -z "$(%DIR%_PROGRAMS)" || rm -f $(%DIR%_PROGRAMS) +?!LIBTOOL? -$(am__rm_f) $(%DIR%_PROGRAMS) ## Under Cygwin, we build 'program$(EXEEXT)'. However, if this ## program uses a Libtool library, Libtool will move it in ## '_libs/program$(EXEEXT)' and create a 'program' wrapper (without diff --git a/lib/am/texinfos.am b/lib/am/texinfos.am index 4284b1ea76d5..896a2a007b76 100644 --- a/lib/am/texinfos.am +++ b/lib/am/texinfos.am @@ -386,14 +386,13 @@ mostlyclean-aminfo: ## Use '-rf', not just '-f', because the %*CLEAN% substitutions can also ## contain any directory created by "makeinfo --html", as well as the ## '*.t2d' and '*.t2p' directories used by texi2dvi and texi2pdf. - -rm -rf %MOSTLYCLEAN% + -$(am__rm_rf) %MOSTLYCLEAN% .PHONY clean-am: clean-aminfo clean-aminfo: ## Use '-rf', not just '-f'; see comments in 'mostlyclean-aminfo' ## above for details. -?TEXICLEAN? -test -z "%TEXICLEAN%" \ -?TEXICLEAN? || rm -rf %TEXICLEAN% +?TEXICLEAN? -$(am__rm_rf) %TEXICLEAN% .PHONY maintainer-clean-am: maintainer-clean-aminfo maintainer-clean-aminfo: @@ -405,7 +404,6 @@ maintainer-clean-aminfo: done ## Use '-rf', not just '-f'; see comments in 'mostlyclean-aminfo' ## above for details. -?MAINTCLEAN? -test -z "%MAINTCLEAN%" \ -?MAINTCLEAN? || rm -rf %MAINTCLEAN% +?MAINTCLEAN? -$(am__rm_rf) %MAINTCLEAN% endif %?LOCAL-TEXIS% diff --git a/m4/init.m4 b/m4/init.m4 index 6ef46d6692e7..e576b935d2a2 100644 --- a/m4/init.m4 +++ b/m4/init.m4 @@ -142,47 +142,8 @@ AC_CONFIG_COMMANDS_PRE(dnl [m4_provide_if([_AM_COMPILER_EXEEXT], [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl -# POSIX will say in a future version that running "rm -f" with no argument -# is OK; and we want to be able to make that assumption in our Makefile -# recipes. So use an aggressive probe to check that the usage we want is -# actually supported "in the wild" to an acceptable degree. -# See automake bug#10828. -# To make any issue more visible, cause the running configure to be aborted -# by default if the 'rm' program in use doesn't match our expectations; the -# user can still override this though. -if rm -f && rm -fr && rm -rf; then : OK; else - cat >&2 <<'END' -Oops! +AC_REQUIRE([_AM_PROG_RM_F]) -Your 'rm' program seems unable to run without file operands specified -on the command line, even when the '-f' option is present. This is contrary -to the behaviour of most rm programs out there, and not conforming with -the upcoming POSIX standard: <http://austingroupbugs.net/view.php?id=542> - -Please tell bug-automake@gnu.org about your system, including the value -of your $PATH and any error possibly output before this message. This -can help us improve future automake versions. - -END - if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then - echo 'Configuration will proceed anyway, since you have set the' >&2 - echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 - echo >&2 - else - cat >&2 <<'END' -Aborting the configuration process, to ensure you take notice of the issue. - -You can download and install GNU coreutils to get an 'rm' implementation -that behaves properly: <https://www.gnu.org/software/coreutils/>. - -If you want to complete the configuration process using your problematic -'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM -to "yes", and re-run configure. - -END - AC_MSG_ERROR([Your 'rm' program is bad, sorry.]) - fi -fi dnl The trailing newline in this macro's definition is deliberate, for dnl backward compatibility and to allow trailing 'dnl'-style comments dnl after the AM_INIT_AUTOMAKE invocation. See automake bug#16841. diff --git a/m4/rmf.m4 b/m4/rmf.m4 new file mode 100644 index 000000000000..2437a9f76a6d --- /dev/null +++ b/m4/rmf.m4 @@ -0,0 +1,16 @@ +## -*- Autoconf -*- +# Copyright (C) 2022 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_PROG_RM_F +# --------------- +# Check whether 'rm -f' without any arguments works. +# https://bugs.gnu.org/10828 +AC_DEFUN([_AM_PROG_RM_F], +[am__rm_f_notfound= +AS_IF([(rm -f && rm -fr && rm -rf) 2>/dev/null], [], [am__rm_f_notfound='""']) +AC_SUBST(am__rm_f_notfound) +]) diff --git a/t/rm-f-probe.sh b/t/rm-f-probe.sh index 9cd3e8814b7d..8463f4fb63c5 100644 --- a/t/rm-f-probe.sh +++ b/t/rm-f-probe.sh @@ -14,8 +14,8 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see <https://www.gnu.org/licenses/>. -# Verify our probe that checks that "rm -f" doesn't complain if called -# without file operands works as expected. See automake bug#10828. +# Verify our probe that checks that "rm -f" behavior works. +# https://bugs.gnu.org/10828 . test-init.sh @@ -40,8 +40,8 @@ while test $# -gt 0; do shift done if test $# -eq 0; then - echo "Oops, fake rm called without arguments" >&2 - exit 1 + echo "Oops, fake rm called without arguments" >&2 #DELETE + exit 1 #CHANGE else exec rm $rm_opts "$@" fi @@ -54,19 +54,17 @@ export PATH original_PATH rm -f && exit 99 # Sanity check. -./configure 2>stderr && { cat stderr >&2; exit 1; } -cat stderr >&2 - -grep "'rm' program.* unable to run without file operands" stderr -$FGREP "tell bug-automake@gnu.org about your system" stderr -$FGREP "install GNU coreutils" stderr -$EGREP "(^| |')ACCEPT_INFERIOR_RM_PROGRAM($| |')" stderr +# Check that `rm -f` is detected as broken. +./configure +grep '^am__rm_f_notfound = ""$' Makefile -ACCEPT_INFERIOR_RM_PROGRAM=yes; export ACCEPT_INFERIOR_RM_PROGRAM +# Chagne the `rm -f` behavior to work. +sed -e '/#DELETE/d' -e '/#CHANGE/s:1:0:' bin/rm > bin/rm.tmp +cat bin/rm.tmp > bin/rm +# Check that `rm -f` is detected as working. ./configure -$MAKE -$MAKE distcheck +grep '^am__rm_f_notfound = *$' Makefile # For the sake of our exit trap. PATH=$original_PATH; export PATH -- 2.34.1