Commit | Line | Data |
---|---|---|
d71d6fe8 MB |
1 | Make GCC respect SOURCE_DATE_EPOCH in __DATE__ and __TIME__ macros. |
2 | ||
3 | Patch adapted from upstream source repository: | |
4 | ||
5 | https://gcc.gnu.org/git/?p=gcc.git;a=commitdiff;h=e3e8c48c4a494d9da741c1c8ea6c4c0b7c4ff934 | |
6 | ||
7 | From e3e8c48c4a494d9da741c1c8ea6c4c0b7c4ff934 Mon Sep 17 00:00:00 2001 | |
8 | From: doko <doko@138bc75d-0d04-0410-961f-82ee72b054a4> | |
9 | Date: Thu, 28 Apr 2016 09:12:05 +0000 | |
10 | Subject: [PATCH] gcc/c-family/ChangeLog: | |
11 | ||
12 | diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c | |
13 | index 1bf5d080034..6f0898a38d7 100644 | |
14 | --- a/gcc/c-family/c-common.c | |
15 | +++ b/gcc/c-family/c-common.c | |
16 | @@ -12318,4 +12318,37 @@ pointer_to_zero_sized_aggr_p (tree t) | |
17 | return (TYPE_SIZE (t) && integer_zerop (TYPE_SIZE (t))); | |
18 | } | |
19 | ||
20 | +/* Read SOURCE_DATE_EPOCH from environment to have a deterministic | |
21 | + timestamp to replace embedded current dates to get reproducible | |
22 | + results. Returns -1 if SOURCE_DATE_EPOCH is not defined. */ | |
23 | +time_t | |
24 | +get_source_date_epoch () | |
25 | +{ | |
26 | + char *source_date_epoch; | |
27 | + long long epoch; | |
28 | + char *endptr; | |
29 | + | |
30 | + source_date_epoch = getenv ("SOURCE_DATE_EPOCH"); | |
31 | + if (!source_date_epoch) | |
32 | + return (time_t) -1; | |
33 | + | |
34 | + errno = 0; | |
35 | + epoch = strtoll (source_date_epoch, &endptr, 10); | |
36 | + if ((errno == ERANGE && (epoch == LLONG_MAX || epoch == LLONG_MIN)) | |
37 | + || (errno != 0 && epoch == 0)) | |
38 | + fatal_error (UNKNOWN_LOCATION, "environment variable $SOURCE_DATE_EPOCH: " | |
39 | + "strtoll: %s\n", xstrerror(errno)); | |
40 | + if (endptr == source_date_epoch) | |
41 | + fatal_error (UNKNOWN_LOCATION, "environment variable $SOURCE_DATE_EPOCH: " | |
42 | + "no digits were found: %s\n", endptr); | |
43 | + if (*endptr != '\0') | |
44 | + fatal_error (UNKNOWN_LOCATION, "environment variable $SOURCE_DATE_EPOCH: " | |
45 | + "trailing garbage: %s\n", endptr); | |
46 | + if (epoch < 0) | |
47 | + fatal_error (UNKNOWN_LOCATION, "environment variable $SOURCE_DATE_EPOCH: " | |
48 | + "value must be nonnegative: %lld \n", epoch); | |
49 | + | |
50 | + return (time_t) epoch; | |
51 | +} | |
52 | + | |
53 | #include "gt-c-family-c-common.h" | |
54 | diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h | |
55 | index fdb227f85c3..ba0a5d7df50 100644 | |
56 | --- a/gcc/c-family/c-common.h | |
57 | +++ b/gcc/c-family/c-common.h | |
58 | @@ -1437,4 +1437,10 @@ extern bool contains_cilk_spawn_stmt (tree); | |
59 | extern tree cilk_for_number_of_iterations (tree); | |
60 | extern bool check_no_cilk (tree, const char *, const char *, | |
61 | location_t loc = UNKNOWN_LOCATION); | |
62 | + | |
63 | +/* Read SOURCE_DATE_EPOCH from environment to have a deterministic | |
64 | + timestamp to replace embedded current dates to get reproducible | |
65 | + results. Returns -1 if SOURCE_DATE_EPOCH is not defined. */ | |
66 | +extern time_t get_source_date_epoch (void); | |
67 | + | |
68 | #endif /* ! GCC_C_COMMON_H */ | |
69 | diff --git a/gcc/c-family/c-lex.c b/gcc/c-family/c-lex.c | |
70 | index bb55be8063e..e68471b9d2b 100644 | |
71 | --- a/gcc/c-family/c-lex.c | |
72 | +++ b/gcc/c-family/c-lex.c | |
73 | @@ -402,6 +402,9 @@ c_lex_with_flags (tree *value, location_t *loc, unsigned char *cpp_flags, | |
74 | enum cpp_ttype type; | |
75 | unsigned char add_flags = 0; | |
76 | enum overflow_type overflow = OT_NONE; | |
77 | + time_t source_date_epoch = get_source_date_epoch (); | |
78 | + | |
79 | + cpp_init_source_date_epoch (parse_in, source_date_epoch); | |
80 | ||
81 | timevar_push (TV_CPP); | |
82 | retry: | |
83 | diff --git a/gcc/doc/cppenv.texi b/gcc/doc/cppenv.texi | |
84 | index 100811dc637..3b5317beb53 100644 | |
85 | --- a/gcc/doc/cppenv.texi | |
86 | +++ b/gcc/doc/cppenv.texi | |
87 | @@ -79,4 +79,21 @@ main input file is omitted. | |
88 | @ifclear cppmanual | |
89 | @xref{Preprocessor Options}. | |
90 | @end ifclear | |
91 | + | |
92 | +@item SOURCE_DATE_EPOCH | |
93 | + | |
94 | +If this variable is set, its value specifies a UNIX timestamp to be | |
95 | +used in replacement of the current date and time in the @code{__DATE__} | |
96 | +and @code{__TIME__} macros, so that the embedded timestamps become | |
97 | +reproducible. | |
98 | + | |
99 | +The value of @env{SOURCE_DATE_EPOCH} must be a UNIX timestamp, | |
100 | +defined as the number of seconds (excluding leap seconds) since | |
101 | +01 Jan 1970 00:00:00 represented in ASCII, identical to the output of | |
102 | +@samp{@command{date +%s}}. | |
103 | + | |
104 | +The value should be a known timestamp such as the last modification | |
105 | +time of the source or package and it should be set by the build | |
106 | +process. | |
107 | + | |
108 | @end vtable | |
109 | diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h | |
110 | index 1b731d1a3ad..7a5481219be 100644 | |
111 | --- a/libcpp/include/cpplib.h | |
112 | +++ b/libcpp/include/cpplib.h | |
113 | @@ -775,6 +775,9 @@ extern void cpp_init_special_builtins (cpp_reader *); | |
114 | /* Set up built-ins like __FILE__. */ | |
115 | extern void cpp_init_builtins (cpp_reader *, int); | |
116 | ||
117 | +/* Initialize the source_date_epoch value. */ | |
118 | +extern void cpp_init_source_date_epoch (cpp_reader *, time_t); | |
119 | + | |
120 | /* This is called after options have been parsed, and partially | |
121 | processed. */ | |
122 | extern void cpp_post_options (cpp_reader *); | |
123 | diff --git a/libcpp/init.c b/libcpp/init.c | |
124 | index 45a4d13ffa3..a8d00f4628b 100644 | |
125 | --- a/libcpp/init.c | |
126 | +++ b/libcpp/init.c | |
127 | @@ -530,6 +530,13 @@ cpp_init_builtins (cpp_reader *pfile, int hosted) | |
128 | _cpp_define_builtin (pfile, "__OBJC__ 1"); | |
129 | } | |
130 | ||
131 | +/* Initialize the source_date_epoch value. */ | |
132 | +void | |
133 | +cpp_init_source_date_epoch (cpp_reader *pfile, time_t source_date_epoch) | |
134 | +{ | |
135 | + pfile->source_date_epoch = source_date_epoch; | |
136 | +} | |
137 | + | |
138 | /* Sanity-checks are dependent on command-line options, so it is | |
139 | called as a subroutine of cpp_read_main_file (). */ | |
140 | #if ENABLE_CHECKING | |
141 | diff --git a/libcpp/internal.h b/libcpp/internal.h | |
142 | index c2d08168945..8507eba1747 100644 | |
143 | --- a/libcpp/internal.h | |
144 | +++ b/libcpp/internal.h | |
145 | @@ -502,6 +502,10 @@ struct cpp_reader | |
146 | const unsigned char *date; | |
147 | const unsigned char *time; | |
148 | ||
149 | + /* Externally set timestamp to replace current date and time useful for | |
150 | + reproducibility. */ | |
151 | + time_t source_date_epoch; | |
152 | + | |
153 | /* EOF token, and a token forcing paste avoidance. */ | |
154 | cpp_token avoid_paste; | |
155 | cpp_token eof; | |
156 | diff --git a/libcpp/macro.c b/libcpp/macro.c | |
157 | index eb32a6f8c98..3f3b278e97d 100644 | |
158 | --- a/libcpp/macro.c | |
159 | +++ b/libcpp/macro.c | |
160 | @@ -350,13 +350,20 @@ _cpp_builtin_macro_text (cpp_reader *pfile, cpp_hashnode *node) | |
161 | time_t tt; | |
162 | struct tm *tb = NULL; | |
163 | ||
164 | - /* (time_t) -1 is a legitimate value for "number of seconds | |
165 | - since the Epoch", so we have to do a little dance to | |
166 | - distinguish that from a genuine error. */ | |
167 | - errno = 0; | |
168 | - tt = time(NULL); | |
169 | - if (tt != (time_t)-1 || errno == 0) | |
170 | - tb = localtime (&tt); | |
171 | + /* Set a reproducible timestamp for __DATE__ and __TIME__ macro | |
172 | + usage if SOURCE_DATE_EPOCH is defined. */ | |
173 | + if (pfile->source_date_epoch != (time_t) -1) | |
174 | + tb = gmtime (&pfile->source_date_epoch); | |
175 | + else | |
176 | + { | |
177 | + /* (time_t) -1 is a legitimate value for "number of seconds | |
178 | + since the Epoch", so we have to do a little dance to | |
179 | + distinguish that from a genuine error. */ | |
180 | + errno = 0; | |
181 | + tt = time (NULL); | |
182 | + if (tt != (time_t)-1 || errno == 0) | |
183 | + tb = localtime (&tt); | |
184 | + } | |
185 | ||
186 | if (tb) | |
187 | { | |
188 | -- | |
189 | 2.11.0 | |
190 |