summaryrefslogtreecommitdiff
path: root/debian/patches/gcc-SOURCE_DATE_EPOCH.diff
blob: 5f3f66cd63f426fa2c57a1328a1f74bbca44316e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
# DP: Allow embedded timestamps by C/C++ macros to be set externally

gcc/c-family/ChangeLog:

2016-04-27  Eduard Sanou  <dhole@openmailbox.org>
	    Matthias Klose  <doko@debian.org>

	* 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.

gcc/ChangeLog:

2016-04-27  Eduard Sanou  <dhole@openmailbox.org>
	    Matthias Klose  <doko@debian.org>

	* doc/cppenv.texi: Document SOURCE_DATE_EPOCH environment variable.

libcpp/ChangeLog:

2016-04-27  Eduard Sanou  <dhole@openmailbox.org>
	    Matthias Klose  <doko@debian.org>

	* 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 
	pfile->source_date_epoch instead of localtime if source_date_epoch is 
	set, to be used for __DATE__ and __TIME__ macros to help reproducible 
	builds.

Index: b/src/gcc/c-family/c-common.c
===================================================================
--- a/src/gcc/c-family/c-common.c
+++ b/src/gcc/c-family/c-common.c
@@ -12743,4 +12743,37 @@ valid_array_size_p (location_t loc, tree
   return true;
 }
 
+/* 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 = 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))
+    fatal_error (UNKNOWN_LOCATION, "environment variable $SOURCE_DATE_EPOCH: "
+		 "strtoll: %s\n", xstrerror(errno));
+  if (endptr == source_date_epoch)
+    fatal_error (UNKNOWN_LOCATION, "environment variable $SOURCE_DATE_EPOCH: "
+		 "no digits were found: %s\n", endptr);
+  if (*endptr != '\0')
+    fatal_error (UNKNOWN_LOCATION, "environment variable $SOURCE_DATE_EPOCH: "
+		 "trailing garbage: %s\n", endptr);
+  if (epoch < 0)
+    fatal_error (UNKNOWN_LOCATION, "environment variable $SOURCE_DATE_EPOCH: "
+		 "value must be nonnegative: %lld \n", epoch);
+
+  return (time_t) epoch;
+}
+
 #include "gt-c-family-c-common.h"
Index: b/src/gcc/c-family/c-common.h
===================================================================
--- a/src/gcc/c-family/c-common.h
+++ b/src/gcc/c-family/c-common.h
@@ -1467,4 +1467,9 @@ extern bool reject_gcc_builtin (const_tr
 extern void warn_duplicated_cond_add_or_warn (location_t, tree, vec<tree> **);
 extern bool valid_array_size_p (location_t, tree, tree);
 
+/* 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 */
Index: b/src/gcc/c-family/c-lex.c
===================================================================
--- a/src/gcc/c-family/c-lex.c
+++ b/src/gcc/c-family/c-lex.c
@@ -385,6 +385,9 @@ c_lex_with_flags (tree *value, location_
   enum cpp_ttype type;
   unsigned char add_flags = 0;
   enum overflow_type overflow = OT_NONE;
+  time_t source_date_epoch = get_source_date_epoch ();
+
+  cpp_init_source_date_epoch (parse_in, source_date_epoch);
 
   timevar_push (TV_CPP);
  retry:
Index: b/src/libcpp/include/cpplib.h
===================================================================
--- a/src/libcpp/include/cpplib.h
+++ b/src/libcpp/include/cpplib.h
@@ -784,6 +784,9 @@ extern void cpp_init_special_builtins (c
 /* Set up built-ins like __FILE__.  */
 extern void cpp_init_builtins (cpp_reader *, int);
 
+/* 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 *);
Index: b/src/libcpp/init.c
===================================================================
--- a/src/libcpp/init.c
+++ b/src/libcpp/init.c
@@ -533,8 +533,15 @@ cpp_init_builtins (cpp_reader *pfile, in
     _cpp_define_builtin (pfile, "__OBJC__ 1");
 }
 
+/* Initialize the source_date_epoch value.  */
+void
+cpp_init_source_date_epoch (cpp_reader *pfile, time_t source_date_epoch)
+{
+  pfile->source_date_epoch = source_date_epoch; 
+}
+
 /* 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)
Index: b/src/libcpp/internal.h
===================================================================
--- a/src/libcpp/internal.h
+++ b/src/libcpp/internal.h
@@ -502,6 +502,10 @@ struct cpp_reader
   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;
Index: b/src/libcpp/macro.c
===================================================================
--- a/src/libcpp/macro.c
+++ b/src/libcpp/macro.c
@@ -357,13 +357,20 @@ _cpp_builtin_macro_text (cpp_reader *pfi
 	  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)
 	    {