42

I am writing a long document with many chapters. They are all included from a root document using \input{chapterX.tex} etc. Compiling everything takes pretty long.

As a workaround to make compilation faster, I typically comment out most \input commands and include only the chapter I'm currently working on. But that's a bad method because then the references to chapters that are not currently included won't work, and the table of contents is almost empty.

I'm wondering if there is a method that does precompilation? Ideally, it would detect that, while I am working on chapter1.tex, nothing in chapter2.tex etc. has changed, and reuse the results from previous compilation runs.

Is that possible? It would be like separate compilation units in languages like C.

Stefan Kottwitz
  • 231,401
Frank
  • 7,175
  • 2
    For others finding this in the future, consider using the package newclude if you want to use \include and \includeonly, as two answers suggested. Standard \include is very finicky about component source file locations; newclude redefines it to avoid path problems, and provides other potentially useful benefits. – Mars May 21 '19 at 18:00

3 Answers3

37

You can't precompile chapters, but you can use the \includeonly mechanism to ensure that your cross-references and page numbers stay correct while choosing to only include parts of your source.

Joseph Wright
  • 259,911
  • 34
  • 706
  • 1,036
18

Extending Joseph's answer a bit: This mean that you use \include and not \input for including the desired chapters. See here for example usage.

tjanson
  • 135
1

The above answers helped me a lot and I used the \includeonly method for a while, but was too bothered by having to manually edit the \includeonly line with the correct files. I then realized that this work could easily be automated and I wrote a small script that does it for me and that I share with you here:

My idea was to include only files that were modified since the last creation of the pdf (which in practice is what I want). To do this, I input in the preamble a file only.tex. This file which will contain the line with the \includeonly will be generated automatically by my script.

Hence, my main tex file looks like:

main.tex

\documentclass{article}
\input{only.tex}
\begin{document}
\include{fileA.tex}
\include{fileB.tex}
\end{document}

To generate the only.tex file, my script retrieves the last modification date of the pdf, and writes in only.tex the name of all the .tex files that are newer than this date (this is done using the find -newer command)

diff.sh

TARGET=only.tex
LAST=$(stat --format='%Y' build/$1.pdf) # last modification of the pdf file
elapsed=$(echo "$(date +%s) - $LAST" | bc) # number of seconds elapsed since
echo "last modification was $elapsed seconds ago"

printf "\includeonly{" > $TARGET for i in $(find . -name "*.tex" -newermt "$elapsed seconds ago"); do file="$(basename $i)" # we skip the generated file, and the main .tex file which is an # argument of this script if [ "$file" != "$1.tex" ] && [ "$file" != $TARGET ]; then printf "$file," >> $TARGET fi done printf "}" >> $TARGET

This script can very probably be improved, made more robust or more concise, but I never felt the need for it personally.

Finally, all that remains to do is to wrap the whole thing within a Makefile that allows me to switch between partial (make) and full compilation (make full).

Makefile

partial:
    ./diff.sh main
    pdflatex main.tex

full : echo "" > only.tex pdflatex main.tex

When compiling partially, we first call the diff.sh script, and then compile normally while the full compilation consists of simply overwriting the only.tex file with an empty string, then compiling normally.

ghilesZ
  • 119