53

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?

9
  • 3
    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. 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? Feb 23 '15 at 12:27
  • 6
    Well. Reproducible builds become fashionable. Mainly for security reasons. Cf. Debian or Tor or Mozilla Feb 23 '15 at 22:14
42

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}

 

XeTeX

Since TeX Live 2019, XeTeX supports specifying the file identifier:

  • pdf:trailerid is a \special command recognized by dvipdfmx, which is used by XeTeX to produce PDF files. The value format is the same as for the \pdfvariable trailerid in LuaTeX: a raw PDF array of two PDF strings. Both strings must be 16 bytes. The dvipdfmx doc gives an example with literal strings (specified between parentheses). Another example is with a 16-byte hex string (specified between brackets <[…]>) that could be an MD5 hash identifying the document:

    \special{pdf:trailerid [
        <00112233445566778899aabbccddeeff>
        <00112233445566778899aabbccddeeff>
    ]}
    

 

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.

3
  • 2
    Excellent. I'm using the GNU Texinfo + MacTeX toolchain on macOS, and the SOURCE_DATE_EPOCH approach worked for me. Thanks! Jan 19 '19 at 12:43
  • 2
    For what it's worth, neither pdftrailerid nor pdfinfoomitdate changes anything in the output of exiftool output.pdf: it still includes timestamps precise to the second. My texlive version is from 2019 and when I make an intentional typo, it complains that the command sequence is unknown, so it reads the command, knows it, then ignores it.
    – Luc
    May 26 '20 at 17:11
  • You need to add \pdfinfo{ /Producer () } or pdfTeX version will be visible from exiftool. I also added /Creator () to save a few bytes and not make TeX visible to exiftool.
    – MCCCS
    Jun 12 '20 at 21:03
22

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.

3
  • 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? 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. Feb 26 '15 at 22:42
1

You can use the package pdfprivacy with the option nopdftrailerid:

pdfprivacy can also remove the document meta-data: Author, Title, Subject, and Keywords; and the pdftrailerid which allows you to create reproducible pdfs.

https://ctan.gutenberg.eu.org/macros/latex/contrib/pdfprivacy/pdfprivacy.pdf


\usepackage[nopdftrailerid=true]{pdfprivacy}

See also: Reproducible builds on different installations

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.