autoconf-patches
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Avoid certain spurious `testsuite' rebuilds


From: Noah Misch
Subject: Re: Avoid certain spurious `testsuite' rebuilds
Date: Sat, 1 Apr 2006 10:49:16 -0800
User-agent: Mutt/1.5.6i

Hi Ralf,

On Sat, Apr 01, 2006 at 03:04:00PM +0200, Ralf Wildenhues wrote:
> * Noah Misch wrote on Fri, Mar 31, 2006 at 06:09:06PM CEST:

> > +stamp_tgat = $(srcdir)/stamp-tgat

> > +## Rebuild TESTSUITE_GENERATED_AT when their sources change.
> > +$(stamp_tgat): $(stamp_acm4)
> > +   test -f updated && mv -f updated $@; :
> 
> `updated' and `$(stamp_tgat)' aka `$(srcdir)/stamp-tgat' may not be on
> the same mount point.

Yes; good catch.  I moved `updated' into the source directory.

> > +$(stamp_acm4): mktests.sh $(AUTOCONF_FILES)
> > +   touch updated
> 
> If you want to be compatible to old BSDs, avoid touch for creating files
> or updating time stamps, see autoconf.texi.  I don't know if we can
> ignore this in practice, though.

>From that description in the manual, I take that one should not use `touch' to
update the mtime of an existing, empty file.  Using `touch' to update the mtime
of an existing file >0 bytes long is portable, as is using `touch' to create a
new, empty file with mtime = time().  Do you agree?

> > +   { ($(do_update)) && \
> > +       if test -f $(stamp_tgat); then rm -f updated; fi; } \
> > +     || test $$? -eq 55
> > +   touch $@
> 
> Likewise.

In light of the above analysis, I changed this.  The other use in this Makefile
should be safe, but I did change it, lest a user create `updated'.

> [ mktests ]
> > -    rm -f ac$base.tat ac$base.at
> > -    touch ac$base.at
> > +    rm -f ac$base.tat
> > +    if test -s ac$base.at; then
> > +   rm -f ac$base.at
> > +   touch ac$base.at
> 
> I guess the same applies here.

I left this as-is, since we just deleted the file we touch.


Thanks for the review.  Here is an updated patch (same ChangeLog):

diff -urp -X dontdiff ac-clean/tests/.cvsignore 
ac-test_ifchanged/tests/.cvsignore
--- ac-clean/tests/.cvsignore   2004-12-10 02:08:52.000000000 -0500
+++ ac-test_ifchanged/tests/.cvsignore  2006-04-01 12:52:10.000000000 -0500
@@ -14,4 +14,6 @@ autoreconf
 autom4te
 autoheader
 autoconf
+stamp-tgat
+stamp-acm4
 wrapper.in
diff -urp -X dontdiff ac-clean/tests/Makefile.am 
ac-test_ifchanged/tests/Makefile.am
--- ac-clean/tests/Makefile.am  2006-03-06 16:13:22.000000000 -0500
+++ ac-test_ifchanged/tests/Makefile.am 2006-04-01 13:00:59.000000000 -0500
@@ -1,7 +1,7 @@
 ## Process this file with automake to create Makefile.in. -*-Makefile-*-
 
 ## Makefile for Autoconf testsuite.
-## Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005
+## Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006
 ## Free Software Foundation, Inc.
 
 ## This program is free software; you can redistribute it and/or modify
@@ -79,6 +79,10 @@ $(wrappers): wrapper.in
 ## Test suite.  ##
 ## ------------ ##
 
+stamp_tgat = $(srcdir)/stamp-tgat
+stamp_acm4 = $(srcdir)/stamp-acm4
+EXTRA_DIST += $(stamp_tgat) $(stamp_acm4)
+
 TESTSUITE_GENERATED_AT = \
        $(srcdir)/aclang.at \
        $(srcdir)/acc.at \
@@ -112,7 +116,8 @@ TESTSUITE = ./testsuite
 AUTOTEST = ./autom4te --language=autotest
 $(TESTSUITE): $(srcdir)/package.m4 \
              local.at \
-             $(TESTSUITE_AT) \
+             $(TESTSUITE_HAND_AT) \
+             $(stamp_tgat) $(TESTSUITE_GENERATED_AT) \
              $(autotest_m4f_dependencies)
        cd $(top_builddir)/lib/autotest && $(MAKE) $(AM_MAKEFLAGS) autotest.m4f
        $(AUTOTEST) -I $(srcdir) suite.at -o address@hidden
@@ -161,9 +166,54 @@ AUTOCONF_FILES = $(autoconfdir)/general.
                 $(autoconfdir)/types.m4 \
                 $(autoconfdir)/programs.m4
 
-$(TESTSUITE_GENERATED_AT): mktests.sh $(AUTOCONF_FILES)
-       cd $(srcdir) && ./mktests.sh \
-         `echo " "$(AUTOCONF_FILES) | sed 's, [^ ]*/, ../lib/autoconf/,g'`
+# In this discussion, TGAT is short for $(TESTSUITE_GENERATED_AT) and ACM4 for
+# $(AUTOCONF_FILES).  A colon represents a Make dependency from left to right.
+#
+# testsuite : TGAT : ACM4 is natural, but it needlessly rebuilds `testsuite'
+# much of the time.  Only ACM4 changes that introduce a new public macro
+# actually affect TGAT.
+#
+# As a second try, one can keep the same dependencies but only touch the TGAT
+# that change.  One can then edit and test ACM4 without rebuilding testsuite,
+# but as soon as a TGAT is older than an ACM4, every `make check' will run
+# `mktests.sh' to possibly update TGAT.  That cost adds up.
+#
+# In this implementation, we use testsuite : stamp-tgat : stamp-acm4 : ACM4.
+# stamp-acm4 stands for the greatest mtime among ACM4 and stamp-tgat for the
+# greatest mtime among TGAT.  The stamp-tgat rules always run, but they simply
+# check a sentinel that the stamp-acm4 rules set when a TGAT changes.
+#
+# `testsuite' separately depends on TGAT, and TGAT depends on nothing but has
+# the same rebuild rule as stamp-acm4.  That serves to rebuild members of TGAT
+# if the user deletes one of them.
+#
+# This timing diagram shows the implementation in action.  Natural numbers
+# represent abstract time stamps.
+# COMMAND                    TIMESTAMP OF: testsuite stamp-tgat stamp-acm4 ACM4
+# $ rm testsuite stamp-tgat stamp-acm4  |                                     0
+# $ make check                          |  3          1           2           0
+# $ touch lib/autoconf/c.m4; make check |  3          1           5           4
+# $ rm acc.at; make check               |  8          6           7           4
+
+# Command to update TESTSUITE_GENERATED_AT from AUTOCONF_FILEs.  It should not
+# touch files that need no change.  It should return zero if it changed nothing
+# and 55 if it changed something.  Other exit values signify errors.
+do_update = cd $(srcdir) && ./mktests.sh \
+           `echo " "$(AUTOCONF_FILES) | sed 's, [^ ]*/, ../lib/autoconf/,g'`
+
+## Rebuild TESTSUITE_GENERATED_AT when their sources change.
+$(stamp_tgat): $(stamp_acm4)
+       test -f $(srcdir)/updated && mv -f $(srcdir)/updated $@; :
+$(stamp_acm4): mktests.sh $(AUTOCONF_FILES)
+       echo 'This file preserves a timestamp.' >$(srcdir)/updated
+       { ($(do_update)) && \
+           if test -f $(stamp_tgat); then rm -f $(srcdir)/updated; fi; } \
+         || test $$? -eq 55
+       echo 'This file preserves a timestamp.' >$@
+
+## Rebuild TESTSUITE_GENERATED_AT when the developer deletes one of them.
+$(TESTSUITE_GENERATED_AT):
+       $(do_update) || :
 
 
 ## maintainer-check ##
diff -urp -X dontdiff ac-clean/tests/mktests.sh 
ac-test_ifchanged/tests/mktests.sh
--- ac-clean/tests/mktests.sh   2006-04-01 10:57:02.000000000 -0500
+++ ac-test_ifchanged/tests/mktests.sh  2006-04-01 12:52:10.000000000 -0500
@@ -208,6 +208,7 @@ fi
 ## Creating the test files.  ##
 ## ------------------------- ##
 
+exit_val=0
 for file in $src
 do
   base=`echo "$file" | sed 's,.*[\\/],,;s/\..*//'`
@@ -262,18 +263,27 @@ MK_EOF
   # preserves the old version of the file.  If there is nothing to
   # check, output /rien du tout/[1].
   if grep AT_CHECK ac$base.tat >/dev/null 2>&1; then
-    mv -f ac$base.tat ac$base.at
-    # Help people not to update these files by hand.
-    chmod a-w ac$base.at
+    if diff ac$base.at ac$base.tat >/dev/null 2>&1; then
+       rm -f ac$base.tat
+    else
+       mv -f ac$base.tat ac$base.at
+       # Help people not to update these files by hand.
+       chmod a-w ac$base.at
+       exit_val=55
+    fi
   else
-    rm -f ac$base.tat ac$base.at
-    touch ac$base.at
+    rm -f ac$base.tat
+    if test -s ac$base.at; then
+       rm -f ac$base.at
+       touch ac$base.at
+       exit_val=55
+    fi
   fi
 done
 
 rm -f acdefuns audefuns requires
 
 trap 0
-exit 0
+exit $exit_val
 
 # [1] En franc,ais dans le texte.




reply via email to

[Prev in Thread] Current Thread [Next in Thread]