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-base 5.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++6 6.1.1-1 ii zlib1g 1: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 <none> pn gcc-5-locales <none> pn gcc-5-multilib <none> pn libasan2-dbg <none> pn libatomic1-dbg <none> pn libcilkrts5-dbg <none> pn libgcc1-dbg <none> pn libgomp1-dbg <none> pn libitm1-dbg <none> pn liblsan0-dbg <none> pn libmpx0-dbg <none> pn libquadmath0-dbg <none> pn libtsan0-dbg <none> pn libubsan0-dbg <none> -- 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__ and __TIME__ macro + usage if SOURCE_DATE_EPOCH is defined. */ + if (pfile->source_date_epoch != (time_t) -1) + tb = gmtime (&pfile->source_date_epoch); + else + { + /* (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); + } if (tb) {
signature.asc
Description: PGP signature