Hi.

Looking at debian package canl-c, I saw it uses \today in the
documentation LaTeX files, so that it can't build reproducibly.
I also heard about gle-graphics [1], which has to be patched to give a
fixed value to \today.

Can we consider turning LaTeX into using SOURCE_DATE_EPOCH (when
available) as \today's epoch? Maybe a way to do this is telling
get_date_and_time to honour SOURCE_DATE_EPOCH. As this function is used
to give a value to the \day, \month and \year LaTeX primitives, this
should be ok. See attached patch for an example.

However, some little more work has to be done if we need the same result
for lualatex and xelatex, as shown in the attached test.

Regards,
Alexis Bienvenüe.

[1]
https://lists.alioth.debian.org/pipermail/reproducible-builds/Week-of-Mon-20160328/005135.html
diff -Nru texlive-bin-2015.20160222.37495/debian/patches/honour-source-date-epoch-today texlive-bin-2015.20160222.37495/debian/patches/honour-source-date-epoch-today
--- texlive-bin-2015.20160222.37495/debian/patches/honour-source-date-epoch-today	1970-01-01 01:00:00.000000000 +0100
+++ texlive-bin-2015.20160222.37495/debian/patches/honour-source-date-epoch-today	2016-04-04 17:14:46.000000000 +0200
@@ -0,0 +1,142 @@
+Description: Make \today honour SOURCE_DATE_EPOCH
+ See https://reproducible-builds.org/ and https://reproducible-builds.org/specs/source-date-epoch/
+Author: Alexis Bienvenüe <p...@passoire.fr>
+
+Index: texlive-bin-2015.20160222.37495/texk/web2c/lib/texmfmp.c
+===================================================================
+--- texlive-bin-2015.20160222.37495.orig/texk/web2c/lib/texmfmp.c
++++ texlive-bin-2015.20160222.37495/texk/web2c/lib/texmfmp.c
+@@ -2143,6 +2143,49 @@ catch_interrupt (int arg)
+ }
+ #endif /* not WIN32 */
+ 
++static boolean start_time_set = false;
++static time_t start_time = 0;
++
++void init_start_time() {
++  char *source_date_epoch;
++  unsigned long long epoch;
++  char *endptr;
++  if (!start_time_set) {
++    start_time_set = true;
++    source_date_epoch = getenv("SOURCE_DATE_EPOCH");
++    if (source_date_epoch)
++      {
++        errno = 0;
++        epoch = strtoull(source_date_epoch, &endptr, 10);
++        if ((errno == ERANGE && (epoch == ULLONG_MAX || epoch == 0))
++            || (errno != 0 && epoch == 0))
++          {
++            fprintf(stderr, "Environment variable $SOURCE_DATE_EPOCH: strtoull: %s\n", strerror(errno));
++            uexit(EXIT_FAILURE);
++          }
++        if (endptr == source_date_epoch)
++          {
++            fprintf(stderr, "Environment variable $SOURCE_DATE_EPOCH: No digits were found: %s\n", endptr);
++            uexit(EXIT_FAILURE);
++          }
++        if (*endptr != '\0')
++          {
++            fprintf(stderr, "Environment variable $SOURCE_DATE_EPOCH: Trailing garbage: %s\n", endptr);
++            uexit(EXIT_FAILURE);
++          }
++        if (epoch > ULONG_MAX)
++          {
++            fprintf(stderr, "Environment variable $SOURCE_DATE_EPOCH: value must be smaller than or equal to: %lu but was found to be: %llu \n", ULONG_MAX  ,epoch);
++            uexit(EXIT_FAILURE);
++          }
++        start_time = epoch;
++      }
++    else {
++      start_time = time((time_t *) NULL);
++    }
++  }
++}
++
+ /* Besides getting the date and time here, we also set up the interrupt
+    handler, for no particularly good reason.  It's just that since the
+    `fix_date_and_time' routine is called early on (section 1337 in TeX,
+@@ -2153,8 +2196,14 @@ void
+ get_date_and_time (integer *minutes,  integer *day,
+                    integer *month,  integer *year)
+ {
+-  time_t myclock = time ((time_t *) 0);
+-  struct tm *tmptr = localtime (&myclock);
++  struct tm *tmptr;
++  if(getenv("SOURCE_DATE_EPOCH")) {
++    init_start_time();
++    tmptr = gmtime (&start_time);
++  } else {
++    time_t myclock = time ((time_t *) 0);
++    tmptr = localtime (&myclock);
++  }
+ 
+   *minutes = tmptr->tm_hour * 60 + tmptr->tm_min;
+   *day = tmptr->tm_mday;
+@@ -2869,11 +2918,10 @@ void pdftex_fail(const char *fmt, ...)
+ }
+ #endif /* not pdfTeX */
+ 
+-static boolean start_time_set = false;
+-static time_t start_time = 0;
+ #define TIME_STR_SIZE 30
+ char start_time_str[TIME_STR_SIZE];
+-static char time_str[TIME_STR_SIZE];
++
++ static char time_str[TIME_STR_SIZE];
+     /* minimum size for time_str is 24: "D:YYYYmmddHHMMSS+HH'MM'" */
+ 
+ static void makepdftime(time_t t, char *time_str, int utc)
+@@ -2931,45 +2979,14 @@ static void makepdftime(time_t t, char *
+ 
+ void initstarttime(void)
+ {
+-	char *source_date_epoch;
+-	unsigned long long epoch;
+-	char *endptr;
+-    if (!start_time_set) {
+-        start_time_set = true;
+-	source_date_epoch = getenv("SOURCE_DATE_EPOCH");
+-	if (source_date_epoch)
+-	{
+-		errno = 0;
+-		epoch = strtoull(source_date_epoch, &endptr, 10);
+-		if ((errno == ERANGE && (epoch == ULLONG_MAX || epoch == 0))
+-				|| (errno != 0 && epoch == 0))
+-		{
+-			fprintf(stderr, "Environment variable $SOURCE_DATE_EPOCH: strtoull: %s\n", strerror(errno));
+-			uexit(EXIT_FAILURE);
+-		}
+-		if (endptr == source_date_epoch)
+-		{
+-			fprintf(stderr, "Environment variable $SOURCE_DATE_EPOCH: No digits were found: %s\n", endptr);
+-			uexit(EXIT_FAILURE);
+-		}
+-		if (*endptr != '\0')
+-		{
+-			fprintf(stderr, "Environment variable $SOURCE_DATE_EPOCH: Trailing garbage: %s\n", endptr);
+-			uexit(EXIT_FAILURE);
+-		}
+-		if (epoch > ULONG_MAX)
+-		{
+-			fprintf(stderr, "Environment variable $SOURCE_DATE_EPOCH: value must be smaller than or equal to: %lu but was found to be: %llu \n", ULONG_MAX  ,epoch);
+-			uexit(EXIT_FAILURE);
+-		}
+-		start_time = epoch;
+-		makepdftime(start_time, start_time_str, 1);
+-	}
+-	else {
+-		start_time = time((time_t *) NULL);
+-		makepdftime(start_time, start_time_str, 0);
+-	}
++  if (!start_time_set) {
++    init_start_time();
++    if(getenv("SOURCE_DATE_EPOCH")) {
++      makepdftime(start_time, start_time_str, 1);
++    } else {
++      makepdftime(start_time, start_time_str, 0);
+     }
++  }
+ }
+ 
+ char *makecstring(integer s)
diff -Nru texlive-bin-2015.20160222.37495/debian/patches/series texlive-bin-2015.20160222.37495/debian/patches/series
--- texlive-bin-2015.20160222.37495/debian/patches/series	2016-03-03 23:21:40.000000000 +0100
+++ texlive-bin-2015.20160222.37495/debian/patches/series	2016-04-04 17:11:34.000000000 +0200
@@ -23,3 +23,4 @@
 fix-mktexlsr-bashims
 suppress-dvips-creationdate
 remove-timestamp-tex-preamble
+honour-source-date-epoch-today
******************************** TODAY

* LATEX

TODAY=April 4, 2016
 TeX output 

* pdfLATEX

TODAY=April 4, 2016
/ModDate (D:20160404181456+02'00')
/CreationDate (D:20160404181456+02'00')

* luaLATEX

TODAY=April 4, 2016
/ModDate (D:20160404181456+02'00')
/CreationDate (D:20160404181456+02'00')

* xeLATEX

TODAY=April 4, 2016
/CreationDate (D:20160404181457+02'00')


******************************** 1970

* LATEX

TODAY=January 1, 1970
 TeX output 

* pdfLATEX

TODAY=January 1, 1970
/ModDate (D:19700101000000Z)
/CreationDate (D:19700101000000Z)

* luaLATEX

TODAY=April 4, 2016
/ModDate (D:20160404181457+02'00')
/CreationDate (D:20160404181457+02'00')

* xeLATEX

TODAY=January 1, 1970
/CreationDate (D:20160404181458+02'00')

Attachment: test.sh
Description: application/shellscript

_______________________________________________
Reproducible-builds mailing list
Reproducible-builds@lists.alioth.debian.org
http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/reproducible-builds

Reply via email to