automake: recognize all-numeric MAJ.MIN.MICROa.ALPHA versions better.
[automake.git] / m4 / sanity.m4
blobc7f32daf850c06ec04595bcd759c5bc9309d3356
1 # Check to make sure that the build environment is sane.    -*- Autoconf -*-
3 # Copyright (C) 1996-2024 Free Software Foundation, Inc.
5 # This file is free software; the Free Software Foundation
6 # gives unlimited permission to copy and/or distribute it,
7 # with or without modifications, as long as this notice is preserved.
9 # _AM_SLEEP_FRACTIONAL_SECONDS
10 # ----------------------------
11 AC_DEFUN([_AM_SLEEP_FRACTIONAL_SECONDS], [dnl
12 AC_CACHE_CHECK([whether sleep supports fractional seconds],
13                am_cv_sleep_fractional_seconds, [dnl
14 AS_IF([sleep 0.001 2>/dev/null], [am_cv_sleep_fractional_seconds=yes],
15                                  [am_cv_sleep_fractional_seconds=no])
16 ])])
18 # _AM_FILESYSTEM_TIMESTAMP_RESOLUTION
19 # -----------------------------------
20 # Determine the filesystem's resolution for file modification
21 # timestamps.  The coarsest we know of is FAT, with a resolution
22 # of only two seconds, even with the most recent "exFAT" extensions.
23 # The finest (e.g. ext4 with large inodes, XFS, ZFS) is one
24 # nanosecond, matching clock_gettime.  However, it is probably not
25 # possible to delay execution of a shell script for less than one
26 # millisecond, due to process creation overhead and scheduling
27 # granularity, so we don't check for anything finer than that. (See below.)
28 AC_DEFUN([_AM_FILESYSTEM_TIMESTAMP_RESOLUTION], [dnl
29 AC_REQUIRE([_AM_SLEEP_FRACTIONAL_SECONDS])
30 AC_CACHE_CHECK([filesystem timestamp resolution],
31                am_cv_filesystem_timestamp_resolution, [dnl
32 # Default to the worst case.
33 am_cv_filesystem_timestamp_resolution=2
35 # Only try to go finer than 1 sec if sleep can do it.
36 # Don't try 1 sec, because if 0.01 sec and 0.1 sec don't work,
37 # - 1 sec is not much of a win compared to 2 sec, and
38 # - it takes 2 seconds to perform the test whether 1 sec works.
39
40 # Instead, just use the default 2s on platforms that have 1s resolution,
41 # accept the extra 1s delay when using $sleep in the Automake tests, in
42 # exchange for not incurring the 2s delay for running the test for all
43 # packages.
45 am_try_resolutions=
46 if test "$am_cv_sleep_fractional_seconds" = yes; then
47   # Even a millisecond often causes a bunch of false positives,
48   # so just try a hundredth of a second. The time saved between .001 and
49   # .01 is not terribly consequential.
50   am_try_resolutions="0.01 0.1 $am_try_resolutions"
53 # In order to catch current-generation FAT out, we must *modify* files
54 # that already exist; the *creation* timestamp is finer.  Use names
55 # that make ls -t sort them differently when they have equal
56 # timestamps than when they have distinct timestamps, keeping
57 # in mind that ls -t prints the *newest* file first.
58 rm -f conftest.ts?
59 : > conftest.ts1
60 : > conftest.ts2
61 : > conftest.ts3
63 # Make sure ls -t actually works.  Do 'set' in a subshell so we don't
64 # clobber the current shell's arguments. (Outer-level square brackets
65 # are removed by m4; they're present so that m4 does not expand
66 # <dollar><star>; be careful, easy to get confused.)
67 if (
68      set X `[ls -t conftest.ts[12]]` &&
69      {
70        test "$[]*" != "X conftest.ts1 conftest.ts2" ||
71        test "$[]*" != "X conftest.ts2 conftest.ts1";
72      }
73 ); then :; else
74   # If neither matched, then we have a broken ls.  This can happen
75   # if, for instance, CONFIG_SHELL is bash and it inherits a
76   # broken ls alias from the environment.  This has actually
77   # happened.  Such a system could not be considered "sane".
78   _AS_ECHO_UNQUOTED(
79     ["Bad output from ls -t: \"`[ls -t conftest.ts[12]]`\""],
80     [AS_MESSAGE_LOG_FD])
81   AC_MSG_FAILURE([ls -t produces unexpected output.
82 Make sure there is not a broken ls alias in your environment.])
85 for am_try_res in $am_try_resolutions; do
86   # Any one fine-grained sleep might happen to cross the boundary
87   # between two values of a coarser actual resolution, but if we do
88   # two fine-grained sleeps in a row, at least one of them will fall
89   # entirely within a coarse interval.
90   echo alpha > conftest.ts1
91   sleep $am_try_res
92   echo beta > conftest.ts2
93   sleep $am_try_res
94   echo gamma > conftest.ts3
96   # We assume that 'ls -t' will make use of high-resolution
97   # timestamps if the operating system supports them at all.
98   if (set X `ls -t conftest.ts?` &&
99       test "$[]2" = conftest.ts3 &&
100       test "$[]3" = conftest.ts2 &&
101       test "$[]4" = conftest.ts1); then
102     #
103     # Ok, ls -t worked. If we're at a resolution of 1 second, we're done,
104     # because we don't need to test make.
105     make_ok=true
106     if test $am_try_res != 1; then
107       # But if we've succeeded so far with a subsecond resolution, we
108       # have one more thing to check: make. It can happen that
109       # everything else supports the subsecond mtimes, but make doesn't;
110       # notably on macOS, which ships make 3.81 from 2006 (the last one
111       # released under GPLv2). https://bugs.gnu.org/68808
112       # 
113       # We test $MAKE if it is defined in the environment, else "make".
114       # It might get overridden later, but our hope is that in practice
115       # it does not matter: it is the system "make" which is (by far)
116       # the most likely to be broken, whereas if the user overrides it,
117       # probably they did so with a better, or at least not worse, make.
118       # https://lists.gnu.org/archive/html/automake/2024-06/msg00051.html
119       #
120       # Create a Makefile (real tab character here):
121       rm -f conftest.mk
122       echo 'conftest.ts1: conftest.ts2' >conftest.mk
123       echo '    touch conftest.ts2' >>conftest.mk
124       #
125       # Now, running
126       #   touch conftest.ts1; touch conftest.ts2; make
127       # should touch ts1 because ts2 is newer. This could happen by luck,
128       # but most often, it will fail if make's support is insufficient. So
129       # test for several consecutive successes.
130       #
131       # (We reuse conftest.ts[12] because we still want to modify existing
132       # files, not create new ones, per above.)
133       n=0
134       make=${MAKE-make}
135       until test $n -eq 3; do
136         echo one > conftest.ts1
137         sleep $am_try_res
138         echo two > conftest.ts2 # ts2 should now be newer than ts1
139         if $make -f conftest.mk | grep 'up to date' >/dev/null; then
140           make_ok=false
141           break # out of $n loop
142         fi
143         n=`expr $n + 1`
144       done
145     fi
146     #
147     if $make_ok; then
148       # Everything we know to check worked out, so call this resolution good.
149       am_cv_filesystem_timestamp_resolution=$am_try_res
150       break # out of $am_try_res loop
151     fi
152     # Otherwise, we'll go on to check the next resolution.
153   fi
154 done
155 rm -f conftest.ts?
156 # (end _am_filesystem_timestamp_resolution)
157 ])])
159 # AM_SANITY_CHECK
160 # ---------------
161 AC_DEFUN([AM_SANITY_CHECK],
162 [AC_REQUIRE([_AM_FILESYSTEM_TIMESTAMP_RESOLUTION])
163 # This check should not be cached, as it may vary across builds of
164 # different projects.
165 AC_MSG_CHECKING([whether build environment is sane])
166 # Reject unsafe characters in $srcdir or the absolute working directory
167 # name.  Accept space and tab only in the latter.
168 am_lf='
170 case `pwd` in
171   *[[\\\"\#\$\&\'\`$am_lf]]*)
172     AC_MSG_ERROR([unsafe absolute working directory name]);;
173 esac
174 case $srcdir in
175   *[[\\\"\#\$\&\'\`$am_lf\ \    ]]*)
176     AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);;
177 esac
179 # Do 'set' in a subshell so we don't clobber the current shell's
180 # arguments.  Must try -L first in case configure is actually a
181 # symlink; some systems play weird games with the mod time of symlinks
182 # (eg FreeBSD returns the mod time of the symlink's containing
183 # directory).
184 am_build_env_is_sane=no
185 am_has_slept=no
186 rm -f conftest.file
187 for am_try in 1 2; do
188   echo "timestamp, slept: $am_has_slept" > conftest.file
189   if (
190     set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null`
191     if test "$[]*" = "X"; then
192       # -L didn't work.
193       set X `ls -t "$srcdir/configure" conftest.file`
194     fi
195     test "$[]2" = conftest.file
196   ); then
197     am_build_env_is_sane=yes
198     break
199   fi
200   # Just in case.
201   sleep "$am_cv_filesystem_timestamp_resolution"
202   am_has_slept=yes
203 done
205 AC_MSG_RESULT([$am_build_env_is_sane])
206 if test "$am_build_env_is_sane" = no; then
207   AC_MSG_ERROR([newly created file is older than distributed files!
208 Check your system clock])
211 # If we didn't sleep, we still need to ensure time stamps of config.status and
212 # generated files are strictly newer.
213 am_sleep_pid=
214 AS_IF([test -e conftest.file || grep 'slept: no' conftest.file >/dev/null 2>&1],, [dnl
215   ( sleep "$am_cv_filesystem_timestamp_resolution" ) &
216   am_sleep_pid=$!
218 AC_CONFIG_COMMANDS_PRE(
219   [AC_MSG_CHECKING([that generated files are newer than configure])
220    if test -n "$am_sleep_pid"; then
221      # Hide warnings about reused PIDs.
222      wait $am_sleep_pid 2>/dev/null
223    fi
224    AC_MSG_RESULT([done])])
225 rm -f conftest.file