build: detect GNU/BSD date at configure time for SOURCE_DATE_EPOCH
The SOURCE_DATE_EPOCH -> date conversion previously relied on a runtime `date -u -d @EPOCH 2>/dev/null || date -u -r EPOCH` fallback. That is unreliable on macOS/*BSD: BSD `date -d` reads -d as a DST flag and silently prints the wrong time (exit 0), so the `-r` fallback is never reached. Decide at configure time instead: prefer coreutils `gdate` (GNU date, e.g. installed on macOS), else a native `date` that really is GNU (verified by the epoch-0 output containing 1970), else BSD `date -r`. configure substitutes the chosen invocation as @SOURCE_DATE_CMD@ and defs.mak appends the epoch. Verified on Linux (no gdate -> GNU `date -u -d @`): a fixed SOURCE_DATE_EPOCH yields a byte-identical buildinfo.o across builds; the no-epoch path still stamps the current local time. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
67d6a2ff5a
commit
25fa181200
|
|
@ -693,6 +693,8 @@ GREP
|
|||
PERL
|
||||
CCACHE_PREFIX_MAP_FLAG
|
||||
CCACHE
|
||||
SOURCE_DATE_CMD
|
||||
GDATE
|
||||
SED
|
||||
RANLIB
|
||||
INSTALL_DATA
|
||||
|
|
@ -4239,6 +4241,57 @@ $as_echo "$ac_cv_path_SED" >&6; }
|
|||
rm -f conftest.sed
|
||||
|
||||
|
||||
for ac_prog in gdate
|
||||
do
|
||||
# Extract the first word of "$ac_prog", so it can be a program name with args.
|
||||
set dummy $ac_prog; ac_word=$2
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
|
||||
$as_echo_n "checking for $ac_word... " >&6; }
|
||||
if ${ac_cv_prog_GDATE+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
if test -n "$GDATE"; then
|
||||
ac_cv_prog_GDATE="$GDATE" # Let the user override the test.
|
||||
else
|
||||
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
|
||||
for as_dir in $PATH
|
||||
do
|
||||
IFS=$as_save_IFS
|
||||
test -z "$as_dir" && as_dir=.
|
||||
for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
|
||||
ac_cv_prog_GDATE="$ac_prog"
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
|
||||
break 2
|
||||
fi
|
||||
done
|
||||
done
|
||||
IFS=$as_save_IFS
|
||||
|
||||
fi
|
||||
fi
|
||||
GDATE=$ac_cv_prog_GDATE
|
||||
if test -n "$GDATE"; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $GDATE" >&5
|
||||
$as_echo "$GDATE" >&6; }
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
fi
|
||||
|
||||
|
||||
test -n "$GDATE" && break
|
||||
done
|
||||
|
||||
if test -n "$GDATE"; then
|
||||
SOURCE_DATE_CMD="$GDATE -u -d @"
|
||||
elif date -u -d @0 2>/dev/null | grep -q 1970; then
|
||||
SOURCE_DATE_CMD="date -u -d @"
|
||||
else
|
||||
SOURCE_DATE_CMD="date -u -r "
|
||||
fi
|
||||
|
||||
|
||||
# Check whether --enable-ccache was given.
|
||||
if test "${enable_ccache+set}" = set; then :
|
||||
enableval=$enable_ccache;
|
||||
|
|
|
|||
|
|
@ -29,6 +29,23 @@ AC_PROG_INSTALL
|
|||
AC_PROG_RANLIB
|
||||
AC_PROG_SED
|
||||
|
||||
dnl SOURCE_DATE_EPOCH -> UTC date, for reproducible builds. GNU date (Linux, or
|
||||
dnl coreutils `gdate` on macOS) converts an epoch with `-d @EPOCH`; BSD date
|
||||
dnl (native macOS/*BSD) uses `-r EPOCH`. Decide here, at configure time, because
|
||||
dnl runtime probing is unreliable: BSD `date -d` silently mis-parses `@EPOCH` (it
|
||||
dnl reads -d as a DST flag) and prints the wrong time rather than failing. Prefer
|
||||
dnl `gdate`; else a `date` that really is GNU (verified by the epoch-0 output
|
||||
dnl containing 1970); else fall back to BSD `date -r`.
|
||||
AC_CHECK_PROGS([GDATE], [gdate])
|
||||
if test -n "$GDATE"; then
|
||||
SOURCE_DATE_CMD="$GDATE -u -d @"
|
||||
elif date -u -d @0 2>/dev/null | grep -q 1970; then
|
||||
SOURCE_DATE_CMD="date -u -d @"
|
||||
else
|
||||
SOURCE_DATE_CMD="date -u -r "
|
||||
fi
|
||||
AC_SUBST([SOURCE_DATE_CMD])
|
||||
|
||||
dnl Prefix the compilers with ccache when it is installed (autodetected; opt out
|
||||
dnl with --disable-ccache). Done after the AC_PROG_C* checks above so those
|
||||
dnl feature tests run with the plain compiler; only the substituted @CC@/@CXX@
|
||||
|
|
|
|||
|
|
@ -131,11 +131,13 @@ MAGIC_BUILDDATE_DEFS = @MAGIC_BUILDDATE_DEFS@
|
|||
# skipping it under --disable-magic-builddate avoids the parse-time date spawn.
|
||||
ifeq (${MAGIC_BUILDDATE_DEFS},)
|
||||
# Honor SOURCE_DATE_EPOCH (reproducible builds -- appimage/npm tarballs) when set,
|
||||
# else the current time. The SOURCE_DATE_EPOCH branch uses UTC so a reproducible
|
||||
# stamp does not depend on the builder's zone; the plain-`date` fallback is local.
|
||||
# else the current time. @SOURCE_DATE_CMD@ is the platform's epoch->UTC-date
|
||||
# invocation, chosen by configure (GNU `date -u -d @` / `gdate` vs BSD
|
||||
# `date -u -r `); the epoch is appended here. The SOURCE_DATE_EPOCH branch is
|
||||
# UTC so a reproducible stamp does not depend on the builder's zone; the plain
|
||||
# `date` fallback is local.
|
||||
MAGIC_BUILDDATE ?= $(shell if [ -n "$$SOURCE_DATE_EPOCH" ]; then \
|
||||
date -u -d "@$$SOURCE_DATE_EPOCH" 2>/dev/null \
|
||||
|| date -u -r "$$SOURCE_DATE_EPOCH" 2>/dev/null; \
|
||||
@SOURCE_DATE_CMD@$$SOURCE_DATE_EPOCH; \
|
||||
else date; fi | tr -d '\r\n')
|
||||
endif
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue