From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 97843 invoked by alias); 26 Apr 2016 21:29:31 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 97829 invoked by uid 89); 26 Apr 2016 21:29:30 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.0 required=5.0 tests=AWL,BAYES_00,RP_MATCHES_RCVD,SPF_PASS autolearn=ham version=3.3.2 spammy=klose, Klose, macro.c, macroc X-HELO: smtp5.openmailbox.org Received: from smtp5.openmailbox.org (HELO smtp5.openmailbox.org) (62.4.1.39) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-GCM-SHA256 encrypted) ESMTPS; Tue, 26 Apr 2016 21:29:16 +0000 Received: by mail2.openmailbox.org (Postfix, from userid 1004) id C44DC2AC8818; Tue, 26 Apr 2016 23:29:13 +0200 (CEST) Date: Tue, 26 Apr 2016 21:29:00 -0000 From: Dhole To: Bernd Schmidt Cc: gcc-patches@gcc.gnu.org Subject: Re: Allow embedded timestamps by C/C++ macros to be set externally (3) Message-ID: <20160426212803.GB11894@panther> References: <20160418122636.GR3248@panther> <571DEE56.6090406@redhat.com> MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha512; protocol="application/pgp-signature"; boundary="TiqCXmo5T1hvSQQg" Content-Disposition: inline In-Reply-To: <571DEE56.6090406@redhat.com> User-Agent: Mutt/1.5.24 (2015-08-30) X-IsSubscribed: yes X-SW-Source: 2016-04/txt/msg01557.txt.bz2 --TiqCXmo5T1hvSQQg Content-Type: multipart/mixed; boundary="7iMSBzlTiPOCCT2k" Content-Disposition: inline --7iMSBzlTiPOCCT2k Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: quoted-printable Content-length: 2701 Hi Bernd, On 16-04-25 12:15:50, Bernd Schmidt wrote: > On 04/18/2016 02:26 PM, Dhole wrote: > >A few months ago I submited a patch to allow the embedded timestamps by > >C/C++ macros to be set externally [2], which was already an improvement > >over [1]. I was told to wait until the GCC 7 stage 1 started to send > >this patch again. >=20 > >+/* 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. */ > >+long long > >+get_source_date_epoch() >=20 > Always have a space before open-paren. Maybe this should return time_t. S= ee > below. >=20 > >+/* 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. */ > >+extern long long get_source_date_epoch(); >=20 > Double space after the end of a sentence. Space before open paren. >=20 > >+ source_date_epoch =3D get_source_date_epoch(); > >+ cpp_init_source_date_epoch(parse_in, source_date_epoch); >=20 > Spaces. >=20 > >+/* Initialize the source_date_epoch value. */ > >+extern void cpp_init_source_date_epoch (cpp_reader *, long long); >=20 > Also thinking we should be using time_t here. >=20 > > /* Sanity-checks are dependent on command-line options, so it is > > called as a subroutine of cpp_read_main_file (). */ >=20 > We don't write () to mark function names. >=20 > >+ tb =3D gmtime ((time_t*) &pfile->source_date_epoch); >=20 > Space before the "*". But this cast looks ugly and unreliable (think > big-endian). This is why I would prefer to move to a time_t representation > sooner. >=20 > >2016-04-18 Eduard Sanou > > Matthias Klose > > * c-common.c (get_source_date_epoch): New function, gets the environment > > variable SOURCE_DATE_EPOCH and parses it as long long with error > > handling. > > * c-common.h (get_source_date_epoch): Prototype. > > * c-lex.c (c_lex_with_flags): set parse_in->source_date_epoch. >=20 > Add blank lines after the end of the names in ChangeLogs. Thanks for the review! I've fixed all the spaces issues. I've also changed the "unsigned long lon= g" to "time_t" as you suggested. Also, to improve reliability I'm now using strtoll rather than strtoull, so that negative values can be detected in SOURCE_DATE_EPOCH, which are treated as errors. This way the variable pfile->source_date_epoch can't be set to -1 (which is the default value) when SOURCE_DATE_EPOCH is defined. I'm attaching the improved patch with the ChangeLog. Cheers, --=20 Dhole --7iMSBzlTiPOCCT2k Content-Type: text/plain; charset=utf-8 Content-Disposition: attachment; filename="gcc-SOURCE_DATE_EPOCH-patch-2016_04_26.diff.txt" Content-Transfer-Encoding: quoted-printable Content-length: 6492 diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index f2846bb..6ef63b1 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -12741,4 +12741,37 @@ valid_array_size_p (location_t loc, tree type, tre= e name) return true; } =20 +/* 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. */ +time_t +get_source_date_epoch () +{ + char *source_date_epoch; + long long epoch; + char *endptr; + + source_date_epoch =3D getenv ("SOURCE_DATE_EPOCH"); + if (!source_date_epoch) + return (time_t) -1; + + errno =3D 0; + epoch =3D strtoll (source_date_epoch, &endptr, 10); + if ((errno =3D=3D ERANGE && (epoch =3D=3D LLONG_MAX || epoch =3D=3D LLON= G_MIN)) + || (errno !=3D 0 && epoch =3D=3D 0)) + fatal_error (UNKNOWN_LOCATION, "environment variable $SOURCE_DATE_EPOC= H: " + "strtoll: %s\n", xstrerror(errno)); + if (endptr =3D=3D source_date_epoch) + fatal_error (UNKNOWN_LOCATION, "environment variable $SOURCE_DATE_EPOC= H: " + "No digits were found: %s\n", endptr); + if (*endptr !=3D '\0') + fatal_error (UNKNOWN_LOCATION, "environment variable $SOURCE_DATE_EPOC= H: " + "Trailing garbage: %s\n", endptr); + if (epoch < 0) + fatal_error (UNKNOWN_LOCATION, "environment variable $SOURCE_DATE_EPOC= H: " + "Value must be nonnegative: %lld \n", epoch); + + return (time_t) epoch; +} + #include "gt-c-family-c-common.h" diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index fa3746c..656bc75 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -1467,4 +1467,9 @@ extern bool reject_gcc_builtin (const_tree, location_= t =3D UNKNOWN_LOCATION); extern void warn_duplicated_cond_add_or_warn (location_t, tree, vec = **); extern bool valid_array_size_p (location_t, tree, tree); =20 +/* 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. */ +extern time_t get_source_date_epoch (void); + #endif /* ! GCC_C_COMMON_H */ diff --git a/gcc/c-family/c-lex.c b/gcc/c-family/c-lex.c index 96da4fc..753e8b8 100644 --- a/gcc/c-family/c-lex.c +++ b/gcc/c-family/c-lex.c @@ -385,6 +385,10 @@ c_lex_with_flags (tree *value, location_t *loc, unsign= ed char *cpp_flags, enum cpp_ttype type; unsigned char add_flags =3D 0; enum overflow_type overflow =3D OT_NONE; + time_t source_date_epoch =3D (time_t) -1; + + source_date_epoch =3D get_source_date_epoch (); + cpp_init_source_date_epoch (parse_in, source_date_epoch); =20 timevar_push (TV_CPP); retry: diff --git a/gcc/doc/cppenv.texi b/gcc/doc/cppenv.texi index 22c8cb3..e958e93 100644 --- a/gcc/doc/cppenv.texi +++ b/gcc/doc/cppenv.texi @@ -79,4 +79,21 @@ main input file is omitted. @ifclear cppmanual @xref{Preprocessor Options}. @end ifclear + +@item SOURCE_DATE_EPOCH + +If this variable is set, its value specifies a UNIX timestamp to be +used in replacement of the current date and time in the @code{__DATE__} +and @code{__TIME__} macros, so that the embedded timestamps become +reproducible. + +The value of @env{SOURCE_DATE_EPOCH} must be a UNIX timestamp, +defined as the number of seconds (excluding leap seconds) since +01 Jan 1970 00:00:00 represented in ASCII, identical to the output of +@samp{@command{date +%s}}. + +The value should be a known timestamp such as the last modification +time of the source or package and it should be set by the build +process. + @end vtable diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h index 35b0375..4998b3a 100644 --- a/libcpp/include/cpplib.h +++ b/libcpp/include/cpplib.h @@ -784,6 +784,9 @@ extern void cpp_init_special_builtins (cpp_reader *); /* Set up built-ins like __FILE__. */ extern void cpp_init_builtins (cpp_reader *, int); =20 +/* Initialize the source_date_epoch value. */ +extern void cpp_init_source_date_epoch (cpp_reader *, time_t); + /* This is called after options have been parsed, and partially processed. */ extern void cpp_post_options (cpp_reader *); diff --git a/libcpp/init.c b/libcpp/init.c index 4343075..f5ff85b 100644 --- a/libcpp/init.c +++ b/libcpp/init.c @@ -533,8 +533,15 @@ cpp_init_builtins (cpp_reader *pfile, int hosted) _cpp_define_builtin (pfile, "__OBJC__ 1"); } =20 +/* Initialize the source_date_epoch value. */ +void +cpp_init_source_date_epoch (cpp_reader *pfile, time_t source_date_epoch) +{ + pfile->source_date_epoch =3D source_date_epoch;=20 +} + /* Sanity-checks are dependent on command-line options, so it is - called as a subroutine of cpp_read_main_file (). */ + called as a subroutine of cpp_read_main_file. */ #if CHECKING_P static void sanity_checks (cpp_reader *); static void sanity_checks (cpp_reader *pfile) diff --git a/libcpp/internal.h b/libcpp/internal.h index 9ce8707..e3eb26b 100644 --- a/libcpp/internal.h +++ b/libcpp/internal.h @@ -502,6 +502,10 @@ struct cpp_reader const unsigned char *date; const unsigned char *time; =20 + /* 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; diff --git a/libcpp/macro.c b/libcpp/macro.c index c251553..c2a8376 100644 --- a/libcpp/macro.c +++ b/libcpp/macro.c @@ -357,13 +357,20 @@ _cpp_builtin_macro_text (cpp_reader *pfile, cpp_hashn= ode *node, time_t tt; struct tm *tb =3D NULL; =20 - /* (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 =3D 0; - tt =3D time(NULL); - if (tt !=3D (time_t)-1 || errno =3D=3D 0) - tb =3D localtime (&tt); + /* Set a reproducible timestamp for __DATE__ and __TIME__ macro + usage if SOURCE_DATE_EPOCH is defined. */ + if (pfile->source_date_epoch !=3D (time_t) -1) + tb =3D 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 =3D 0; + tt =3D time (NULL); + if (tt !=3D (time_t)-1 || errno =3D=3D 0) + tb =3D localtime (&tt); + } =20 if (tb) { --7iMSBzlTiPOCCT2k Content-Type: text/plain; charset=utf-8 Content-Disposition: attachment; filename=ChangeLog Content-Transfer-Encoding: quoted-printable Content-length: 1113 gcc/c-family/ChangeLog: 2016-04-26 Eduard Sanou Matthias Klose * c-common.c (get_source_date_epoch): New function, gets the environment variable SOURCE_DATE_EPOCH and parses it as long long with error=20 handling. * c-common.h (get_source_date_epoch): Prototype. * c-lex.c (c_lex_with_flags): set parse_in->source_date_epoch. gcc/ChangeLog: 2016-04-26 Eduard Sanou Matthias Klose * doc/cppenv.texi: Document SOURCE_DATE_EPOCH environment variable. libcpp/ChangeLog: 2016-04-26 Eduard Sanou Matthias Klose * include/cpplib.h (cpp_init_source_date_epoch): Prototype. * init.c (cpp_init_source_date_epoch): New function. * internal.h: Added source_date_epoch variable to struct cpp_reader to store a reproducible date. * macro.c (_cpp_builtin_macro_text): Set pfile->date timestamp from=20 pfile->source_date_epoch instead of localtime if source_date_epoch is=20 set, to be used for __DATE__ and __TIME__ macros to help reproducible=20 builds. --7iMSBzlTiPOCCT2k-- --TiqCXmo5T1hvSQQg Content-Type: application/pgp-signature; name="signature.asc" Content-length: 801 -----BEGIN PGP SIGNATURE----- iQIcBAABCgAGBQJXH91fAAoJEE+kV6GFFMxja/QQAIsE1bR8x1dr3BbfdP6NA42R 8+v2MGUDczyRXk+Fp08yYhP9pVtsVISP4iYlCQQQ3b4HKZ6czG29qC1M+L8s+vR6 VjKj7Z49mr1YyNX4a5dGm4aQ0zsfl5S0g/mU4XTMZHQiqCnfdoF8v2KJTEfNlIDQ H2VKZ0Y679yaSzERh+wISs0je6FFD/t2H9jOtW8T51cjZhkqBNIsJN9kzK6W7pnV 41GJGNiKmVQ4l3Nw3yUIaG3gcVJWCQbQcfpqftCz+2/iU/tZtl9PwELFBIyfLiHW 0r9Ncvjbc6o/cIj8JX9xAXe31TbXM/JmsxOJQ1KXx1M7YOHjDlghdIlEFa841w0T 6yxlc6P18zbOdO0vNDTDxfvcZk9WnKJpY5gFi6Qmucsvz6C9WuELXb8Fv0bvQjkV B6WdxdLRDQinIw7mF1c8UjLd29v0EKLL8H8Fwc4Yigfz5u/drD0WmK7DXpL+hP5S xzu+JKzT7RSu/DVNTZiP4kLkPaFKkZfRgpXpDzHwbOCuX7vzXG+zJefL+NBQcpcU nDXw2mKo8poBLjjIyaWeiDiVcN0Un0LbWF8tR5g/Nd/icJqXaTB7jYCrmeNe6U2G DYxyX3mkDfGpXXAE3Mcccazrr0J3oD9UHyMi0Qc4Ejn6ljAnv3f4A+kaE/9U2ELJ zY9uRyvRYgNtVde1j8Jb =dtmX -----END PGP SIGNATURE----- --TiqCXmo5T1hvSQQg--