From 23e69f6e6d29b0f9aa5aa3aab2464b3cf38a59bf Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Mon, 27 May 2024 12:34:35 -0700 Subject: [PATCH] test: check that subsecond mtime works with make. Trying to fix https://bugs.gnu.org/68808. * m4/sanity.m4 (_AM_FILESYSTEM_TIMESTAMP_RESOLUTION): check that make works with subsecond mtimes, as well as sleep and ls. (Known to fail with the make 3.81 that ships with macOS.) * configure.ac (MTIME_RESOLUTION): notice if it erroneously expands to the empty string, i.e., fall back to 1 if $am_cv_filesystem_timestamp_resolution ended up being unset. * t/ax/test-defs.in (MTIME_RESOLUTION): also fall back to 1 if the variable to not set, with a message. Fix other typos en passant. * HACKING: tweak. --- HACKING | 10 ++++----- configure.ac | 4 ++++ m4/sanity.m4 | 57 ++++++++++++++++++++++++++++++++++++++++------- t/ax/test-defs.in | 28 ++++++++++++++++++----- 4 files changed, 80 insertions(+), 19 deletions(-) diff --git a/HACKING b/HACKING index ed644ea9f..c0b7702e9 100644 --- a/HACKING +++ b/HACKING @@ -204,10 +204,10 @@ * To get a faithful and correct rebuild, run: ./bootstrap && ./config.status --recheck && make clean all -* Usually, it is best to run again latest stable versions of Autoconf, - Libtool, etc., since that is what most users will do. Sometimes it may - be necessary to use the development versions due to bugs fixed, - etc. Whatever is first in PATH wins. +* Usually, it is best to run against the latest stable versions of + Autoconf, Libtool, etc., since that is what most users will + do. However, sometimes it may be necessary to use the development + versions due to bugs fixed, etc. Whatever is first in PATH wins. (Some background: https://bugs.gnu.org/11347) * The Automake git tree currently carries three basic branches: @@ -281,7 +281,7 @@ to follow. See the further points below for clarifications and minor corrections. - topic: brief description (this is the "summary line") + topic: brief description (this is the "summary line"). diff --git a/configure.ac b/configure.ac index eb5383324..062db9935 100644 --- a/configure.ac +++ b/configure.ac @@ -191,6 +191,10 @@ AC_PROG_FGREP # supported by the filesystem hosting the build. The value # will be acceptable to 'sleep' on this system. MTIME_RESOLUTION=$am_cv_filesystem_timestamp_resolution +if test -z "$MTIME_RESOLUTION"; then + AC_MSG_NOTICE(am_cv_filesystem_timestamp_resolution strangely not set; using 1) + MTIME_RESOLUTION=1 +fi AC_SUBST([MTIME_RESOLUTION]) dnl FIXME: could we extract this in a simpler way through autoconf diff --git a/m4/sanity.m4 b/m4/sanity.m4 index 59afa7b15..4504ef878 100644 --- a/m4/sanity.m4 +++ b/m4/sanity.m4 @@ -24,16 +24,20 @@ AS_IF([sleep 0.001 2>/dev/null], [am_cv_sleep_fractional_seconds=true], # nanosecond, matching clock_gettime. However, it is probably not # possible to delay execution of a shell script for less than one # millisecond, due to process creation overhead and scheduling -# granularity, so we don't check for anything finer than that. +# granularity, so we don't check for anything finer than that. (See below.) AC_DEFUN([_AM_FILESYSTEM_TIMESTAMP_RESOLUTION], [dnl AC_REQUIRE([_AM_SLEEP_FRACTIONAL_SECONDS]) -AC_CACHE_CHECK([filesystem timestamp resolution], am_cv_filesystem_timestamp_resolution, [dnl +AC_CACHE_CHECK([filesystem timestamp resolution], + am_cv_filesystem_timestamp_resolution, [dnl # Default to the worst case. am_cv_filesystem_timestamp_resolution=2 # Only try to go finer than 1s if sleep can do it. am_try_resolutions=1 if $am_cv_sleep_fractional_seconds; then + # Even a millisecond often causes a bunch of false positives, + # so just try a hundredth of a second. The time saved between .001 and + # .01 is not terribly consequential. am_try_resolutions="0.01 0.1 $am_try_resolutions" fi @@ -48,12 +52,13 @@ rm -f conftest.ts? : > conftest.ts3 # Make sure ls -t actually works. Do 'set' in a subshell so we don't -# clobber the current shell's arguments. +# clobber the current shell's arguments. (Outer-level square brackets +# are for m4; be careful, it's easy to get confused.) if ( set X `[ls -t conftest.ts[12]]` && { - test "$[*]" != "X conftest.ts1 conftest.ts2" || - test "$[*]" != "X conftest.ts2 conftest.ts1"; + test "$[]*" != "X conftest.ts1 conftest.ts2" || + test "$[]*" != "X conftest.ts2 conftest.ts1"; } ); then :; else # If neither matched, then we have a broken ls. This can happen @@ -64,7 +69,7 @@ if ( ["Bad output from ls -t: \"`[ls -t conftest.ts[12]]`\""], [AS_MESSAGE_LOG_FD]) AC_MSG_FAILURE([ls -t produces unexpected output. -Make sure there is not a broken alias in your environment.]) +Make sure there is not a broken ls alias in your environment.]) fi for am_try_res in $am_try_resolutions; do @@ -84,11 +89,47 @@ for am_try_res in $am_try_resolutions; do test "$[]2" = conftest.ts3 && test "$[]3" = conftest.ts2 && test "$[]4" = conftest.ts1); then - am_cv_filesystem_timestamp_resolution=$am_try_res - break + # + # Ok, ls -t worked. We have one more thing to check: make. + # It can happen that everything else supports the subsecond mtimes, + # but make doesn't, notably on macOS, which ships make 3.81 from + # 2006 (the last one released under GPLv2). https://bugs.gnu.org/68808 + # + # So, first let's create a Makefile: + rm -f conftest.mk + echo 'conftest.ts1: conftest.ts2' >conftest.mk + echo ' touch conftest.ts2' >>conftest.mk + # + # Now, running + # touch conftest.ts1; touch conftest.ts2; make + # should touch ts1 because ts2 is newer. This could happen by luck, + # but most often, it will fail if make's support is insufficient. So + # test for several consecutive successes. + # + # (We reuse conftest.ts[12] because we still want to modify existing + # files, not create new ones, per above.) + n=0 + make_ok=true + until test $n -eq 4; do + echo one > conftest.ts1 + sleep $am_try_res + echo two > conftest.ts2 # ts2 should now be newer than ts1 + if make -f conftest.mk | grep 'up to date' >/dev/null; then + make_ok=false + break # out of $n loop + fi + n=`expr $n + 1` + done + if $make_ok; then + # Everything we know to check worked out, so call this resolution good. + am_cv_filesystem_timestamp_resolution=$am_try_res + break # out of resolution loop + fi + # Otherwise, we'll go on to check the next resolution. fi done rm -f conftest.ts? +# (end _am_filesystem_timestamp_resolution) ])]) # AM_SANITY_CHECK diff --git a/t/ax/test-defs.in b/t/ax/test-defs.in index c1ead418e..275cfb2dc 100644 --- a/t/ax/test-defs.in +++ b/t/ax/test-defs.in @@ -64,7 +64,7 @@ case ${am_running_installcheck:=no} in am_system_acdir="" ;; *) - echo "$me: variable 'am_running_installcheck' has invalid" + echo "$me: variable 'am_running_installcheck' has invalid" \ "value '$am_running_installcheck'" >&2 exit 99 ;; @@ -172,7 +172,7 @@ GNU_CFLAGS=${AM_TESTSUITE_GNU_CFLAGS-${GNU_CFLAGS-'@GNU_CFLAGS@'}} GNU_GCJ=${AM_TESTSUITE_GNU_GCJ-${GNU_GCJ-'@GNU_GCJ@'}} GNU_GCJFLAGS=${AM_TESTSUITE_GNU_GCJFLAGS-${GNU_GCJFLAGS-'@GNU_GCJFLAGS@'}} -# No all versions of Tex support '--version', so we use a configure +# Not all versions of Tex support '--version', so we use a configure # check to decide if tex is available. This decision is embodied in # this variable. TEX=${AM_TESTSUITE_TEX-'@TEX@'} @@ -190,8 +190,24 @@ case $MTIME_RESOLUTION in grep 'Features:.*subsecond-mtime' > /dev/null 2>&1 && $AUTOM4TE --version 2>&1 | grep 'Features:.*subsecond-mtime' > /dev/null 2>&1; then - : + # subsecond-mtime should be supported; use the timestamp + # resolution that we determined. If it hasn't been determined, + # that's a bug somewhere. + if test -n "$am_cv_filesystem_timestamp_resolution"; then + #echo "$me: got $am_cv_filesystem_timestamp_resolution" >&2 + MTIME_RESOLUTION=$am_cv_filesystem_timestamp_resolution + else + # ends up in test-suite.log. + echo "$me: subsecond-mtime supported per automake and auto4mte" \ + "--version, but am_cv_filesystem_timestamp_resolution not set;" \ + "that's an error somewhere. Proceeding with value 1." >&2 + MTIME_RESOLUTION=1 + fi else + #echo "$me: --version doesn't support subsecond-mtime" >&2 + #$AUTOMAKE --version >&2 + #$AUTOM4TE --version >&2 + # MTIME_RESOLUTION=1 # we must not sleep for fractional seconds when autom4te does not # support subsecond-mtimes, even when sleep supports it. See bug#67670. @@ -202,10 +218,10 @@ case $MTIME_RESOLUTION in esac # This sleep variable is used explicitly in some tests to avoid -# too-quick creation. I (Karl) believe that was an incomplete workaround +# too-quick creation. Seems likely this was an incomplete workaround # for this whole subsecond-mtime problem. With this set to "sleep 1", -# there were still random parallelization failures, without also setting -# am_cv_sleep_fractional_seconds=false as above. +# there were still random parallelization failures; setting +# am_cv_sleep_fractional_seconds=false as above was still needed. # sleep="sleep $MTIME_RESOLUTION" -- 2.47.3