Subject: bug#61867: dirstamp pattern rule kills buildability with FreeBSD make, NetBSD make, AIX make

From: Bruno Haible <[email-masked]>
Date: Tue, 28 Feb 2023 13:47:06 +0100

Hi,

FreeBSD 13.1 'make', NetBSD 9.0 'make', AIX 7.1 and 7.2 'make' are perfectly
fine for building many GNU packages, even as VPATH builds.

Jim Meyering has now put out a tarball for testing, that uses bleeding-edge
Automake:
https://lists.gnu.org/archive/html/platform-testers/2023-02/msg00012.html

When I build this tarball on FreeBSD, NetBSD, or AIX — in srcdir or as a
VPATH build, does not matter —, the build fails, like this:

 ------------------------------------------------------
...
  CC       libgreputils_a-getopt1.o
  CC       libgreputils_a-getprogname.o
make: 1254-002 Cannot find a rule to create target malloc/.dirstamp from dependencies.
Stop.
make: 1254-004 The error code from the last command is 2.

Stop.
make: 1254-004 The error code from the last command is 1.

Stop.
make: 1254-004 The error code from the last command is 2.

Stop.
 ------------------------------------------------------

This is a regression, caused by the bleeding-edge Automake, because when I
unpack the tarball and then (with Automake 1.16.5 in $PATH) do
  aclocal -I m4
  automake
  touch configure
  touch config.hin
it does not exhibit this build failure any more.

Find attached the diff between lib/Makefile (that fails) and lib/Makefile
(that comes from Automake 1.16.5 and works fine). You can see that with
individual rules for malloc/$(am__dirstamp), glthread/$(am__dirstamp),
unistr/$(am__dirstamp), uniwidth/$(am__dirstamp) the build works fine,
whereas with the pattern rule
  %/$(am__dirstamp)
it fails.

I guess that the commit "dirstamp: switch to a pattern rule" is the culprit.
https://git.savannah.gnu.org/gitweb/?p=automake.git;a=commitdiff;h=55f8fcfd08cbf15d65d61dd2db934b6c3171cf06

Bruno

--- grep-3.8.35-c860/build/lib/Makefile	2023-02-28 10:01:18.623558000 +0100
+++ grep-3.8.35-c860-fixed/build/lib/Makefile	2023-02-28 13:26:12.610679000 +0100
@@ -1,7 +1,7 @@
-# Makefile.in generated by automake 1.16i from Makefile.am.
+# Makefile.in generated by automake 1.16.5 from Makefile.am.
 # lib/Makefile.  Generated from Makefile.in by configure.
 
-# Copyright (C) 1994-2023 Free Software Foundation, Inc.
+# Copyright (C) 1994-2021 Free Software Foundation, Inc.
 
 # This Makefile.in is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -203,8 +203,6 @@
   test $$has_opt = yes
 am__make_dryrun = (target_option=n; $(am__make_running_with_option))
 am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
-am__rm_f = rm -f $(am__rm_f_notfound)
-am__rm_rf = rm -rf $(am__rm_f_notfound)
 am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
 install_sh_DATA = $(install_sh) -c -m 644
 install_sh_PROGRAM = $(install_sh) -c
@@ -446,7 +444,6 @@
 am__v_AR_0 = @echo "  AR      " $@;
 am__v_AR_1 = 
 libgreputils_a_AR = $(AR) $(ARFLAGS)
-libgreputils_a_RANLIB = $(RANLIB)
 am__DEPENDENCIES_1 =
 LIBOBJDIR = ../gnulib-tests/
 am__dirstamp = $(am__leading_dot)dirstamp
@@ -951,7 +948,7 @@
 pkgincludedir = ${includedir}/${PACKAGE}
 pkglibdir = ${libdir}/${PACKAGE}
 pkglibexecdir = ${libexecdir}/${PACKAGE}
-ACLOCAL = ${SHELL} '/home/bruno/grep-3.8.35-c860/build-aux/missing' aclocal-1.16
+ACLOCAL = ${SHELL} '/home/bruno/grep-3.8.35-c860-fixed/build-aux/missing' aclocal-1.16
 ALLOCA = 
 ALLOCA_H = alloca.h
 AMTAR = $${TAR-tar}
@@ -960,9 +957,9 @@
 AR = ar
 ARFLAGS = cr
 ASSERT_H = assert.h
-AUTOCONF = ${SHELL} '/home/bruno/grep-3.8.35-c860/build-aux/missing' autoconf
-AUTOHEADER = ${SHELL} '/home/bruno/grep-3.8.35-c860/build-aux/missing' autoheader
-AUTOMAKE = ${SHELL} '/home/bruno/grep-3.8.35-c860/build-aux/missing' automake-1.16
+AUTOCONF = ${SHELL} '/home/bruno/grep-3.8.35-c860-fixed/build-aux/missing' autoconf
+AUTOHEADER = ${SHELL} '/home/bruno/grep-3.8.35-c860-fixed/build-aux/missing' autoheader
+AUTOMAKE = ${SHELL} '/home/bruno/grep-3.8.35-c860-fixed/build-aux/missing' automake-1.16
 AWK = nawk
 BITSIZEOF_PTRDIFF_T = 
 BITSIZEOF_SIG_ATOMIC_T = 
@@ -985,6 +982,7 @@
 ECHO_C = 
 ECHO_N = -n
 ECHO_T = 
+EGREP = @EGREP@
 EMULTIHOP_HIDDEN = 
 EMULTIHOP_VALUE = 
 ENOLINK_HIDDEN = 
@@ -1803,7 +1801,7 @@
 LTLIBOBJS = 
 LTLIBSIGSEGV = 
 LTLIBTHREAD = 
-MAKEINFO = ${SHELL} '/home/bruno/grep-3.8.35-c860/build-aux/missing' makeinfo
+MAKEINFO = ${SHELL} '/home/bruno/grep-3.8.35-c860-fixed/build-aux/missing' makeinfo
 MBRTOWC_LIB = 
 MKDIR_P = mkdir -p
 MSGFMT = /home/bruno/bin/msgfmt
@@ -2216,19 +2214,17 @@
 XGETTEXT = /home/bruno/bin/xgettext
 XGETTEXT_015 = /home/bruno/bin/xgettext
 XGETTEXT_EXTRA_OPTIONS =  --flag=error:3:c-format --flag=error_at_line:5:c-format --keyword='proper_name:1,"This is a proper name. See the gettext manual, section Names."' --keyword='proper_name_utf8:1,"This is a proper name. See the gettext manual, section Names."'
-abs_aux_dir = /home/bruno/grep-3.8.35-c860/build-aux
-abs_builddir = /home/bruno/grep-3.8.35-c860/build/lib
-abs_srcdir = /home/bruno/grep-3.8.35-c860/build/../lib
-abs_top_builddir = /home/bruno/grep-3.8.35-c860/build
-abs_top_srcdir = /home/bruno/grep-3.8.35-c860/build/..
+abs_aux_dir = /home/bruno/grep-3.8.35-c860-fixed/build-aux
+abs_builddir = /home/bruno/grep-3.8.35-c860-fixed/build/lib
+abs_srcdir = /home/bruno/grep-3.8.35-c860-fixed/build/../lib
+abs_top_builddir = /home/bruno/grep-3.8.35-c860-fixed/build
+abs_top_srcdir = /home/bruno/grep-3.8.35-c860-fixed/build/..
 ac_ct_CC = cc -ferror-limit=0
 am__include = include
 am__leading_dot = .
 am__quote = 
-am__rm_f_notfound = 
 am__tar = $${TAR-tar} chof - "$$tardir"
 am__untar = $${TAR-tar} xf -
-am__xargs_n = xargs -n
 bindir = ${exec_prefix}/bin
 bindir_c = "/home/bruno/bin"
 bindir_c_make = \"$(bindir)\"
@@ -2274,7 +2270,7 @@
 infodir = ${datarootdir}/info
 infodir_c = "/home/bruno/share/info"
 infodir_c_make = \"$(infodir)\"
-install_sh = ${SHELL} /home/bruno/grep-3.8.35-c860/build-aux/install-sh
+install_sh = ${SHELL} /home/bruno/grep-3.8.35-c860-fixed/build-aux/install-sh
 libdir = ${exec_prefix}/lib
 libdir_c = "/home/bruno/lib"
 libdir_c_make = \"$(libdir)\"
@@ -2564,11 +2560,17 @@
 $(am__aclocal_m4_deps):
 
 clean-noinstLIBRARIES:
-	-$(am__rm_f) $(noinst_LIBRARIES)
-%/$(am__dirstamp):
-	@$(MKDIR_P) $(@D)
-	@: >>$@
+	-test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+../gnulib-tests/$(am__dirstamp):
+	@$(MKDIR_P) ../gnulib-tests/
+	@: > ../gnulib-tests/$(am__dirstamp)
 ../gnulib-tests/alloca.$(OBJEXT): ../gnulib-tests/$(am__dirstamp)
+malloc/$(am__dirstamp):
+	@$(MKDIR_P) malloc
+	@: > malloc/$(am__dirstamp)
+malloc/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) malloc/$(DEPDIR)
+	@: > malloc/$(DEPDIR)/$(am__dirstamp)
 malloc/libgreputils_a-dynarray_at_failure.$(OBJEXT):  \
 	malloc/$(am__dirstamp) malloc/$(DEPDIR)/$(am__dirstamp)
 malloc/libgreputils_a-dynarray_emplace_enlarge.$(OBJEXT):  \
@@ -2579,16 +2581,34 @@
 	malloc/$(am__dirstamp) malloc/$(DEPDIR)/$(am__dirstamp)
 malloc/libgreputils_a-dynarray_resize_clear.$(OBJEXT):  \
 	malloc/$(am__dirstamp) malloc/$(DEPDIR)/$(am__dirstamp)
+glthread/$(am__dirstamp):
+	@$(MKDIR_P) glthread
+	@: > glthread/$(am__dirstamp)
+glthread/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) glthread/$(DEPDIR)
+	@: > glthread/$(DEPDIR)/$(am__dirstamp)
 glthread/libgreputils_a-lock.$(OBJEXT): glthread/$(am__dirstamp) \
 	glthread/$(DEPDIR)/$(am__dirstamp)
 glthread/libgreputils_a-threadlib.$(OBJEXT): glthread/$(am__dirstamp) \
 	glthread/$(DEPDIR)/$(am__dirstamp)
+unistr/$(am__dirstamp):
+	@$(MKDIR_P) unistr
+	@: > unistr/$(am__dirstamp)
+unistr/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) unistr/$(DEPDIR)
+	@: > unistr/$(DEPDIR)/$(am__dirstamp)
 unistr/libgreputils_a-u8-mbtoucr.$(OBJEXT): unistr/$(am__dirstamp) \
 	unistr/$(DEPDIR)/$(am__dirstamp)
 unistr/libgreputils_a-u8-uctomb.$(OBJEXT): unistr/$(am__dirstamp) \
 	unistr/$(DEPDIR)/$(am__dirstamp)
 unistr/libgreputils_a-u8-uctomb-aux.$(OBJEXT): unistr/$(am__dirstamp) \
 	unistr/$(DEPDIR)/$(am__dirstamp)
+uniwidth/$(am__dirstamp):
+	@$(MKDIR_P) uniwidth
+	@: > uniwidth/$(am__dirstamp)
+uniwidth/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) uniwidth/$(DEPDIR)
+	@: > uniwidth/$(DEPDIR)/$(am__dirstamp)
 uniwidth/libgreputils_a-width.$(OBJEXT): uniwidth/$(am__dirstamp) \
 	uniwidth/$(DEPDIR)/$(am__dirstamp)
 malloc/libgreputils_a-dynarray-skeleton.$(OBJEXT):  \
@@ -2597,7 +2617,7 @@
 libgreputils.a: $(libgreputils_a_OBJECTS) $(libgreputils_a_DEPENDENCIES) $(EXTRA_libgreputils_a_DEPENDENCIES) 
 	$(AM_V_at)-rm -f libgreputils.a
 	$(AM_V_AR)$(libgreputils_a_AR) libgreputils.a $(libgreputils_a_OBJECTS) $(libgreputils_a_LIBADD)
-	$(AM_V_at)$(libgreputils_a_RANLIB) libgreputils.a
+	$(AM_V_at)$(RANLIB) libgreputils.a
 
 mostlyclean-compile:
 	-rm -f *.$(OBJEXT)
@@ -2789,7 +2809,7 @@
 
 $(am__depfiles_remade):
 	@$(MKDIR_P) $(@D)
-	@: >>$@
+	@echo '# dummy' >$@-t && $(am__mv) $@-t $@
 
 am--depfiles: $(am__depfiles_remade)
 
@@ -5384,36 +5404,36 @@
 	    "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
 	fi
 mostlyclean-generic:
-	-$(am__rm_f) $(MOSTLYCLEANFILES)
-	-$(am__rm_f) ../gnulib-tests/alloca.$(OBJEXT)
+	-rm -f ../gnulib-tests/alloca.$(OBJEXT)
+	-test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
 
 clean-generic:
-	-$(am__rm_f) $(CLEANFILES)
+	-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
 
 distclean-generic:
-	-$(am__rm_f) $(CONFIG_CLEAN_FILES)
-	-test . = "$(srcdir)" || $(am__rm_f) $(CONFIG_CLEAN_VPATH_FILES)
-	-$(am__rm_f) ../gnulib-tests/$(am__dirstamp)
-	-$(am__rm_f) glthread/$(DEPDIR)/$(am__dirstamp)
-	-$(am__rm_f) glthread/$(am__dirstamp)
-	-$(am__rm_f) malloc/$(DEPDIR)/$(am__dirstamp)
-	-$(am__rm_f) malloc/$(am__dirstamp)
-	-$(am__rm_f) unistr/$(DEPDIR)/$(am__dirstamp)
-	-$(am__rm_f) unistr/$(am__dirstamp)
-	-$(am__rm_f) uniwidth/$(DEPDIR)/$(am__dirstamp)
-	-$(am__rm_f) uniwidth/$(am__dirstamp)
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+	-rm -f ../gnulib-tests/$(am__dirstamp)
+	-rm -f glthread/$(DEPDIR)/$(am__dirstamp)
+	-rm -f glthread/$(am__dirstamp)
+	-rm -f malloc/$(DEPDIR)/$(am__dirstamp)
+	-rm -f malloc/$(am__dirstamp)
+	-rm -f unistr/$(DEPDIR)/$(am__dirstamp)
+	-rm -f unistr/$(am__dirstamp)
+	-rm -f uniwidth/$(DEPDIR)/$(am__dirstamp)
+	-rm -f uniwidth/$(am__dirstamp)
 
 maintainer-clean-generic:
 	@echo "This command is intended for maintainers to use"
 	@echo "it deletes files that may require special tools to rebuild."
-	-$(am__rm_f) $(BUILT_SOURCES)
-	-$(am__rm_f) $(MAINTAINERCLEANFILES)
+	-test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+	-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
 clean: clean-am
 
 clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am
 
 distclean: distclean-am
-	-rm -f ../gnulib-tests/$(DEPDIR)/alloca.Po
+		-rm -f ../gnulib-tests/$(DEPDIR)/alloca.Po
 	-rm -f ./$(DEPDIR)/libgreputils_a-argmatch.Po
 	-rm -f ./$(DEPDIR)/libgreputils_a-at-func.Po
 	-rm -f ./$(DEPDIR)/libgreputils_a-basename-lgpl.Po
@@ -5635,7 +5655,7 @@
 installcheck-am:
 
 maintainer-clean: maintainer-clean-am
-	-rm -f ../gnulib-tests/$(DEPDIR)/alloca.Po
+		-rm -f ../gnulib-tests/$(DEPDIR)/alloca.Po
 	-rm -f ./$(DEPDIR)/libgreputils_a-argmatch.Po
 	-rm -f ./$(DEPDIR)/libgreputils_a-at-func.Po
 	-rm -f ./$(DEPDIR)/libgreputils_a-basename-lgpl.Po