Package: gcc-5
Version: 5.3.1-17
Severity: normal
Tags: upstream patch
Control: clone -1 -2
Control: reassign -2 gcc-6 6.1.1-1
Hi,
With the SOURCE_DATE_EPOCH patch from upstream, the __DATE__ and
__TIME__ macros always give Jan 1 1970 00:00:00 when running the
preprocessor on its own with gcc -E[1]. I believe this is because
c_lex_with_flags is not called when just preprocessing (no C code needs
to be lexed), so pfile->source_date_epoch stays initialised to 0, and
subsequent __DATE__/__TIME__ expansions believe that the timestamp has
been set to epoch 0. I have attached an alternative implementation of
gcc-SOURCE_DATE_EPOCH.diff which fixes this, by initialising
pfile->source_date_epoch inside libcpp when pfile is initially created.
[1] https://paste.debian.net/683081/
-- System Information:
Debian Release: stretch/sid
APT prefers unstable-debug
APT policy: (500, 'unstable-debug'), (500, 'unstable'), (1,
'experimental-debug'), (1, 'experimental')
Architecture: amd64 (x86_64)
Kernel: Linux 4.5.0-2-amd64 (SMP w/4 CPU cores)
Locale: LANG=en_GB.UTF-8, LC_CTYPE=en_GB.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
Init: systemd (via /run/systemd/system)
Versions of packages gcc-5 depends on:
ii binutils 2.26-8
ii cpp-5 5.3.1-17
ii gcc-5-base5.3.1-17
ii libc6 2.22-7
ii libcc1-0 6.1.1-1
ii libgcc-5-dev 5.3.1-17
ii libgcc1 1:6.1.1-1
ii libgmp10 2:6.1.0+dfsg-2
ii libisl15 0.16.1-1
ii libmpc3 1.0.3-1
ii libmpfr4 3.1.4-1
ii libstdc++66.1.1-1
ii zlib1g1:1.2.8.dfsg-2+b1
Versions of packages gcc-5 recommends:
ii libc6-dev 2.22-7
Versions of packages gcc-5 suggests:
pn gcc-5-doc
pn gcc-5-locales
pn gcc-5-multilib
pn libasan2-dbg
pn libatomic1-dbg
pn libcilkrts5-dbg
pn libgcc1-dbg
pn libgomp1-dbg
pn libitm1-dbg
pn liblsan0-dbg
pn libmpx0-dbg
pn libquadmath0-dbg
pn libtsan0-dbg
pn libubsan0-dbg
-- no debconf information
--- a/src/libcpp/init.c
+++ b/src/libcpp/init.c
@@ -36,6 +36,7 @@
static void init_library (void);
static void mark_named_operators (cpp_reader *, int);
+static void cpp_init_source_date_epoch (cpp_reader *);
static void read_original_filename (cpp_reader *);
static void read_original_directory (cpp_reader *);
static void post_options (cpp_reader *);
@@ -264,6 +265,9 @@
_cpp_init_hashtable (pfile, table);
+ /* Initialize the source_date_epoch value. */
+ cpp_init_source_date_epoch (pfile);
+
return pfile;
}
@@ -530,6 +534,46 @@
_cpp_define_builtin (pfile, "__OBJC__ 1");
}
+/* Read SOURCE_DATE_EPOCH from environment to have a deterministic
+ timestamp to replace embedded current dates to get reproducible
+ results. Returns -1 if SOURCE_DATE_EPOCH is not defined. */
+static time_t
+get_source_date_epoch (cpp_reader *pfile)
+{
+ char *source_date_epoch;
+ long long epoch;
+ char *endptr;
+
+ source_date_epoch = getenv ("SOURCE_DATE_EPOCH");
+ if (!source_date_epoch)
+return (time_t) -1;
+
+ errno = 0;
+ epoch = strtoll (source_date_epoch, &endptr, 10);
+ if ((errno == ERANGE && (epoch == LLONG_MAX || epoch == LLONG_MIN))
+ || (errno != 0 && epoch == 0))
+cpp_error (pfile, CPP_DL_FATAL, "environment variable $SOURCE_DATE_EPOCH: "
+ "strtoll: %s\n", xstrerror(errno));
+ if (endptr == source_date_epoch)
+cpp_error (pfile, CPP_DL_FATAL, "environment variable $SOURCE_DATE_EPOCH: "
+ "no digits were found: %s\n", endptr);
+ if (*endptr != '\0')
+cpp_error (pfile, CPP_DL_FATAL, "environment variable $SOURCE_DATE_EPOCH: "
+ "trailing garbage: %s\n", endptr);
+ if (epoch < 0)
+cpp_error (pfile, CPP_DL_FATAL, "environment variable $SOURCE_DATE_EPOCH: "
+ "value must be nonnegative: %lld \n", epoch);
+
+ return (time_t) epoch;
+}
+
+/* Initialize the source_date_epoch value. */
+static void
+cpp_init_source_date_epoch (cpp_reader *pfile)
+{
+ pfile->source_date_epoch = get_source_date_epoch (pfile);
+}
+
/* Sanity-checks are dependent on command-line options, so it is
called as a subroutine of cpp_read_main_file (). */
#if ENABLE_CHECKING
--- a/src/libcpp/internal.h
+++ b/src/libcpp/internal.h
@@ -502,6 +502,10 @@
const unsigned char *date;
const unsigned char *time;
+ /* Externally set timestamp to replace current date and time useful for
+ reproducibility. */
+ time_t source_date_epoch;
+
/* EOF token, and a token forcing paste avoidance. */
cpp_token avoid_paste;
cpp_token eof;
--- a/src/libcpp/macro.c
+++ b/src/libcpp/macro.c
@@ -350,13 +350,20 @@
time_t tt;
struct tm *tb = NULL;
- /* (time_t) -1 is a legitimate value for "number of seconds
- since the Epoch", so we have to do a little dance to
- distinguish that from a genuine error. */
- errno = 0;
- tt = time(NULL);
- if (tt != (time_t)-1 || errno == 0)
- tb = localtime (&tt);
+ /* Set a reproducible timestamp for __DATE_