#
# Example makefile using mjotex and a BibTeX references database.
#
+# After defining $(PN) to be the name of your document, this will
+# compile the source file $(PN).tex to $(PN).pdf.
+#
+# To support workflows where the document is kept open in a PDF reader
+# during recompilation, the build process takes place in a separate
+# $(BUILDDIR) directory that defaults to "build". Only when the build
+# has completed do we move the resulting $(PN).pdf to the current
+# directory. This avoids renaming or modifying the open document in
+# place, which in turn helps prevent flickering, loss of bookmarks, et
+# cetera, in several PDF readers.
+
+# The build directory. Not broken? Don't fix.
+BUILDDIR=build
# The latex compiler. The SOURCE_DATE_EPOCH=0 prevents the creation
# and modification dates from being embedded as metadata into the
# output file; that in turn is important because it allows us to tell
# when the output stops changing (that is, when we are done). The
# variable is supported in pdftex v1.40.17 and later.
-LATEX = SOURCE_DATE_EPOCH=0 pdflatex -file-line-error -halt-on-error
+LATEX = SOURCE_DATE_EPOCH=0 pdflatex -file-line-error -halt-on-error --output-directory $(BUILDDIR)
# The name of this document.
#
# stop when the output file stops changing! But how to encode that
# in a makefile?
#
-# At the start of this target, we call $(LATEX) to compile $(PN).tex.
-# Afterwards, we check for the existence of a "previous" file. If
-# there isn't one, then this is the first time that we've built the
-# PDF. In that case, we take the PDF that we've just built and make it
-# the "previous" file before starting all over. If, on the other hand,
-# there already *was* a "previous" file, then this is the second (or
-# third...) time that we've built the PDF. We diff the newly-built PDF
-# against the "previous" file; if they're the same, then we've
-# succeeded and stop. Otherwise, we make the new PDF the "previous"
-# one, and start all over. The end result is that we will loop until
-# the newly-created PDF and the "previous" one are identical.
-#
-$(PN).pdf: $(SRCS) $(PN).bbl
+# At the start of this rule, we call $(LATEX) to compile $(PN).tex.
+# It stores the resulting PDF in a separate "build" directory, so this
+# will not actually create or overwrite the target $(PN).pdf. If there
+# is no $(PN).pdf already, then we rename the new one to $(PN).pdf and
+# we are done. But if there was a previous version, then we compare
+# the two (new & old) versions. In either case, we rename the new one
+# over the old one. But if the two differ, then we repeat this process
+# in a loop until the just-built PDF is identical to the one from the
+# previous iteration.
+$(PN).pdf: $(SRCS) $(BUILDDIR)/$(PN).bbl
$(LATEX) $(PN).tex
- if [ -f $@.previous ] && cmp -s $@ $@.previous; then \
- rm $@.previous; \
- else \
- mv $@ $@.previous; \
- $(MAKE) $@; \
+ if [ -f $@ ]; then \
+ while ! cmp -s $@ $(BUILDDIR)/$(PN).pdf; do \
+ mv $(BUILDDIR)/$(PN).pdf $@; \
+ $(LATEX) $(PN).tex; \
+ done; \
fi;
+ if grep -q 'Rerun to get' $(BUILDDIR)/$(PN).log; then \
+ $(LATEX) $(PN).tex; \
+ fi;
+
+ mv $(BUILDDIR)/$(PN).pdf $@
+
+$(BUILDDIR):
+ mkdir $@
-$(PN).aux: $(SRCS)
+$(BUILDDIR)/$(PN).aux: $(SRCS) | $(BUILDDIR)
$(LATEX) $(PN).tex
# define $BIBS but don't cite anything, you'll run into a similar
# problem. Don't do that.
#
-$(PN).bbl: $(SRCS) | $(PN).aux
+$(BUILDDIR)/$(PN).bbl: $(SRCS) | $(BUILDDIR)/$(PN).aux
ifdef BIBS
- bibtex $(PN).aux
+ bibtex $(BUILDDIR)/$(PN).aux
else
printf '' > $@
endif
# If the output PDF exists but the log file does not, then an attempt
# to "build the log file" (i.e. build the PDF) would do nothing. Thus
# whenever the log file does not exist, we do a fresh build.
-$(PN).log: $(SRCS)
+$(BUILDDIR)/$(PN).log: $(SRCS)
$(MAKE) clean
$(MAKE)
# Ensure that there are no overfull or underfull boxes in the output
# document by parsing the log for said warnings.
.PHONY: check-boxes
-check-boxes: $(PN).log
+check-boxes: $(BUILDDIR)/$(PN).log
@! grep -i 'overfull\|underfull' $<
# Run chktex to find silly mistakes. There is some exit code weirdness
# Ensure that there are no undefined references in the document by
# parsing the log file for said warnings.
.PHONY: check-undefined
-check-undefined: $(PN).log
+check-undefined: $(BUILDDIR)/$(PN).log
@! grep -i 'undefined' $<
# Run a suite of checks.
.PHONY: clean
clean:
for ext in $(JUNK_EXTENSIONS); do rm -f *.$$ext; done;
+ rm -rf $(BUILDDIR)/