$SOURCE_DATE_EPOCH support for build date stamp
authorPhil Pennock <pdp@exim.org>
Thu, 13 Apr 2017 03:22:36 +0000 (23:22 -0400)
committerPhil Pennock <pdp@exim.org>
Thu, 13 Apr 2017 03:28:09 +0000 (23:28 -0400)
If, and _only_ if, $SOURCE_DATE_EPOCH is found in environ during build,
use it to set the timestamp embedded in the binary instead of using
__DATE__ and __TIME__ cpp directives.

This per <https://reproducible-builds.org/specs/source-date-epoch/>
spec.  It's sane and sensible, without removing date stamping which
matters.  The examples encourage packagers to use timestamps which
do change when they backport patches, so that the date remains useful
for distinguishing builds instead of claiming one date forever across
multiple patchlevels.

This change written so that the old behaviour and code is used if the
environment variable is not found, to better continue to support ancient
platforms with other variants of date(1).

Built with and without an override, on macOS.

doc/doc-txt/ChangeLog
doc/doc-txt/NewStuff
src/scripts/reversion
src/src/version.c

index 5dfc9b5bb00ceda7c9d74c56c38876100c8542cd..b6c9e3986284c2c07de8c5f6a7fc4f9028655a5c 100644 (file)
@@ -46,6 +46,9 @@ JH/06 Default openssl_options to include +no_ticket, to reduce load on peers.
       by default on recent versions (3.1.3 +) unless the PFS priority string
       is used (3.2.4 +).
 
+PP/03 Add $SOURCE_DATE_EPOCH support for reproducible builds, per spec at
+      <https://reproducible-builds.org/specs/source-date-epoch/>.
+
 
 Exim version 4.89
 -----------------
index c0d07b4463a6ae455febfb2a856e846f20956003..5f446f7927ebbb1acc09ddaf505ee70db2e99948 100644 (file)
@@ -26,6 +26,9 @@ Version 4.90
  5. An option for recipient verify callouts to hold the connection open for
     further recipients and for delivery.
 
+ 6. The reproducible build $SOURCE_DATE_EPOCH environment variable is now
+    supported.
+
 
 Version 4.89
 ------------
index 9707b9c1c680911372d4b209d6132c28a5882f14..45755c0848944e53fe81438e98cdcb492ec46219 100755 (executable)
@@ -71,10 +71,41 @@ EXIM_COMPILE_NUMBER=$(expr "${EXIM_COMPILE_NUMBER:-0}" + 1)
 
 echo "$EXIM_COMPILE_NUMBER" >cnumber.h
 
+# Reproducible builds, accept a build timestamp override from environ per
+# <https://reproducible-builds.org/specs/source-date-epoch/>.
+# We require a fairly modern date(1) command here, which is not portable
+# to some of the systems Exim is built on.  That's okay, because the scenarios
+# are:
+#  1) Local postmaster building, not using $SOURCE_DATE_EPOCH, doesn't matter
+#  2) Packaging folks who don't care about reproducible builds
+#  3) Packaging folks who care but are using systems where date Just Works
+#  3) Packaging folks who care and can put a modern date(1) in $PATH
+#  4) Packaging folks who care and can supply us with a clean patch to support
+#     their requirements
+#  5) Packaging folks who care but won't do any work to support their strange
+#     old systems and want us to do the work for them.  We don't care either,
+#     they're SOL and have to live without reproducible builds.
+#
+exim_build_date_override=''
+if [ ".${SOURCE_DATE_EPOCH:-}" != "." ]; then
+  fmt='+%d-%b-%Y %H:%M:%S'
+  # Non-reproducible, we use __DATE__ and __TIME__ in C, which respect timezone
+  # (think localtime, not gmtime); for reproduction between systems, UTC makes
+  # more sense and the examples available use UTC without explicitly mandating
+  # it.  I think that we can switch behavior and use UTC for reproducible
+  # builds without it causing any problems: nothing really cares about timezone.
+  # GNU date: "date -d @TS"
+  # BSD date: "date -r TS"
+  exim_build_date_override="$(date -u -d "@${SOURCE_DATE_EPOCH}" "$fmt" 2>/dev/null | date -u -r "${SOURCE_DATE_EPOCH}" "$fmt" 2>/dev/null)"
+fi
+
 ( echo '# automatically generated file - see ../scripts/reversion'
   echo EXIM_RELEASE_VERSION='"'"$EXIM_RELEASE_VERSION"'"'
   echo EXIM_VARIANT_VERSION='"'"$EXIM_VARIANT_VERSION"'"'
   echo EXIM_COMPILE_NUMBER='"'"$EXIM_COMPILE_NUMBER"'"'
+  if [ ".${exim_build_date_override:-}" != "." ]; then
+    echo EXIM_BUILD_DATE_OVERRIDE='"'"${exim_build_date_override}"'"'
+  fi
 ) >version.sh
 
 if [ ! -f version.h ]
@@ -83,6 +114,9 @@ then
   echo '#define EXIM_RELEASE_VERSION "'"$EXIM_RELEASE_VERSION"'"'
   echo '#define EXIM_VARIANT_VERSION "'"$EXIM_VARIANT_VERSION"'"'
   echo '#define EXIM_VERSION_STR EXIM_RELEASE_VERSION EXIM_VARIANT_VERSION'
+  if [ ".${exim_build_date_override:-}" != "." ]; then
+    echo '#define EXIM_BUILD_DATE_OVERRIDE "'"${exim_build_date_override}"'"'
+  fi
 ) >version.h
 fi
 
index 04a2d07337f8d185c9bc41950e91d83d3ea681c1..f27cc3cde679cca06a5fa5acdef3fbd63804c7c7 100644 (file)
@@ -40,6 +40,16 @@ version_cnumber_format = US"%d\0<<eximcnumber>>";
 sprintf(CS version_cnumber, CS version_cnumber_format, cnumber);
 version_string = US EXIM_VERSION_STR "\0<<eximversion>>";
 
+#ifdef EXIM_BUILD_DATE_OVERRIDE
+/* Reproducible build support; build tooling should have given us something looking like
+ * "25-Feb-2017 20:15:40" in EXIM_BUILD_DATE_OVERRIDE based on $SOURCE_DATE_EPOCH in environ
+ * per <https://reproducible-builds.org/specs/source-date-epoch/>
+ */
+version_date = date_buffer;
+version_date[0] = 0;
+Ustrncat(version_date, EXIM_BUILD_DATE_OVERRIDE, sizeof(date_buffer));
+
+#else
 Ustrcpy(today, __DATE__);
 if (today[4] == ' ') today[4] = '0';
 today[3] = today[6] = '-';
@@ -51,6 +61,7 @@ Ustrncat(version_date, today, 4);
 Ustrncat(version_date, today+7, 4);
 Ustrcat(version_date, " ");
 Ustrcat(version_date, __TIME__);
+#endif
 }
 
 /* End of version.c */