35

I am interested in using LaTeX in a way such that when I compile twice, I get the very same resulting file.

My test.tex:

\documentclass{article}
\begin{document}
Hello, World!
\end{document}

Compiling yields different hashes:

8493b40b225993d01d46ed7479725d8b4e9f6efbfddcc8d6d657f00084d41cdb  test.pdf
05f2a3cd3780df33470a4363da18b008595e42acd9a085d76c83b6c83dc71c41  test.pdf

and so on. (This also applies when compiling to DVI at least a minute apart.)

My guess is that this is, at least, due to the Created and Modified metadata of the PDF. I followed this answer for fixing those, but I still get different hashes.

I found out that when compiling with faketime '2008-12-24 08:15:42' pdflatex test the file will be reproducible. I conclude that there is no random data involved, but it's only dependent on the time.

My question is thus, can I influence that time for pdflatex from within my TeX document?

  • 2
    It's impossible. Even the DVI file cannot have the same checksum, because the date and time the job was started are written as soon as the first page is shipped out. – egreg Feb 22 '15 at 23:19
  • 1
    Ah, interesting! I guess I've recompiled the DVI file too quickly. The DVI files do indeed hash to different values when they compiled a minute apart. – Frederick Nord Feb 22 '15 at 23:23
  • I don't think you can influence the date information from within TeX. I tried setting the internal TeX variables carrying the information to Jan. 1, 2015, but the PDF file still reported /CreationDate (D:20150223002954+01'00'). – egreg Feb 22 '15 at 23:34
  • That will not work. But why do you want this? What's your Y? – Martin Schröder Feb 23 '15 at 12:27
  • 4
    Well. Reproducible builds become fashionable. Mainly for security reasons. Cf. Debian or Tor or Mozilla – Frederick Nord Feb 23 '15 at 22:14
25

Since TeX Live 2016, there are a couple of options to achieve reproducible builds:

pdfTeX

For pdfTeX (version ≥1.40.17), there are three new primitives:

  • \pdfinfoomitdate, which removes the /CreationDate and /ModDate entries in the document info dictionary. By default, these entries would be set to the date when the document was compiled. They could already be modified in older versions of pdfTeX using \pdfinfo{/CreationDate (...)} /ModDate (...)}, but with \pdfinfoomitdate=1, they can be removed completely from the resulting PDF file.
  • \pdftrailerid, which sets the file identifier of the PDF document in the /ID document info entry as described in the PDF specification, section 10.3. By default, it is computed by hashing the current date and time (even if \pdfinfoomitdate=1 is used) and the full path of the output file. By including \pdftrailerid{string} with a fixed string in your document, the hash of this string is used as the identifier instead. Leaving it blank like \pdftrailerid{} completely removes the /ID entry.
  • \pdfsuppressptexinfo controls some additional metadata written to the document: firstly, pdfTeX usually creates an entry PTEX.Fullbanner containing the full version string as seen in the output of pdftex --version. Furthermore, for every PDF image included in your document, some additional metadata is written. Suppressing these entries is not strictly necessary for reproducible builds, but might help if you want to compile the same document on different systems. It can be done by issuing \pdfsuppressptexinfo=-1.

TL; DR: So the easiest way to get reproducible PDF output is to use

\documentclass{article}
\pdfinfoomitdate=1
\pdftrailerid{}
\begin{document}
Hello, World!
\end{document}

 

LuaTeX

Since TeX Live 2017, LuaTeX (version ≥1.0.4) also supports these features, albeit with a little different syntax:

  • \pdfvariable suppressoptionalinfo prevents certain metadata do be included in the resulting PDF file, similar to \pdfsuppressptexinfo in pdfTeX, but with more options:

    \pdfvariable suppressoptionalinfo \numexpr
            0
        +   1   % PTEX.FullBanner
        +   2   % PTEX.FileName
        +   4   % PTEX.PageNumber
        +   8   % PTEX.InfoDict
        +  16   % Creator
        +  32   % CreationDate
        +  64   % ModDate
        + 128   % Producer
        + 256   % Trapped
        + 512   % ID
    \relax
    
  • \pdfvariable trailerid lets you specify your own file identifier like \pdftrailerid does, but you have to get the syntax right yourself, so I recommend simply suppressing the ID using the above command instead.

TL; DR: For reproducible builds in LuaLaTeX, use

\documentclass{article}
\pdfvariable suppressoptionalinfo \numexpr32+64+512\relax
\begin{document}
Hello, World!
\end{document}

 

All major engines (pdfTeX, LuaTeX, XeTeX)

As an alternative, pdfTeX, LuaTeX and XeTeX support SOURCE_DATE_EPOCH:

If you set the SOURCE_DATE_EPOCH environment variable to a certain date (in the form of a Unix timestamp, as produced e.g. by the output of date +%s), this date is used instead of the current date. Setting it to a fixed date therefore lets you create reproducible PDF files without any changes to the LaTeX source code. Keep in mind however that the output file name (for pdfTeX and LuaTeX including the full path, for XeTeX only the name itself) is still used to compute the file identifier described above: so if you move or rename your LaTeX document and compile, the resulting PDF document will change.

  • Excellent. I'm using the GNU Texinfo + MacTeX toolchain on macOS, and the SOURCE_DATE_EPOCH approach worked for me. Thanks! – Andrew Janke Jan 19 at 12:43
21

update there is now (texlive 2016) SOURCE_DATE_EPOCH support in pdftex to address this (see the other answer).

If you modify the source to

\pdfcompresslevel=0
\pdfobjcompresslevel=0
\documentclass{article}
\begin{document}
Hello, World!
\end{document}

And run it twice, you find exactly three lines change

/CreationDate (D:20150222233514Z)
/ModDate (D:20150222233514Z)

/ID [<84943B8BBB033F5EF8FAE4B3E350E35C> <84943B8BBB033F5EF8FAE4B3E350E35C>] >>

So one possibility would be to use a wrapper script that ran pdflatex then blanked out these fields, keeping the byte count the same.

  • 5
    +1 /CreationDate and /ModDate can be modified (set to a fixed value) from within TeX using \pdfinfo. The file identifier /ID however is calculated by pdfTeX by hashing the system date and time and the full path of the generated PDF file (cf. utils.c, function printID in the pdfTeX sources). There does not seem to be a way of changing the identifier from within, so ignoring it for the comparison or faking the system time seem to be the only options. – diabonas Feb 23 '15 at 8:06
  • Hm. By looking at the spec it seems as if the two document ID values should be provided by the author of the document, i.e. me. How eager are pdflatex people to enable me to provide those values? – Frederick Nord Feb 26 '15 at 22:28
  • @FrederickNord you'd need to ask on the pdftex list I don't think the pdftex developers are here normally. – David Carlisle Feb 26 '15 at 22:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.