]> gitweb.michael.orlitzky.com - mjotex.git/commitdiff
GNUmakefile: use a separate build directory
authorMichael Orlitzky <michael@orlitzky.com>
Thu, 25 Jul 2024 16:16:37 +0000 (12:16 -0400)
committerMichael Orlitzky <michael@orlitzky.com>
Thu, 25 Jul 2024 16:17:47 +0000 (12:17 -0400)
This is mainly to support a preview workflow with zathura, which likes
to crash or go blank or lose your position in the document during
renames. But it's also just nicer, and will probably keep e.g. atril
from flickering as well.

GNUmakefile

index 3669ac21f657341c85f88ff72335d90425fecaaa..89bb5d599304cb7f3c417d9da39e8da30f34d796 100644 (file)
@@ -1,13 +1,26 @@
 #
 # 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.
 #
@@ -75,8 +88,8 @@ SRCS += $(SAGE_LISTING_DSTS)
 endif
 
 ifdef INDICES
-INDEX_SRCS = $(addsuffix .idx,$(INDICES))
-INDEX_DSTS = $(addsuffix .ind,$(INDICES))
+INDEX_SRCS = $(addprefix $(BUILDDIR)/,$(addsuffix .idx,$(INDICES)))
+INDEX_DSTS = $(addprefix $(BUILDDIR)/,$(addsuffix .ind,$(INDICES)))
 endif
 
 # The first target is the default, so put the PDF document first.
@@ -87,31 +100,32 @@ endif
 # 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 $(INDEX_DSTS)
+# 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 $(INDEX_DSTS)
        $(LATEX) $(PN).tex
 
-       if [ -f $@.previous ] && cmp -s $@ $@.previous; then \
-               rm $@.previous; \
-       else \
-               mv $@ $@.previous; \
-               $(REMAKE_INDICES); \
-               $(MAKE) $@; \
+       if [ -f $@ ]; then \
+         while ! cmp -s $@ $(BUILDDIR)/$(PN).pdf; do \
+           mv $(BUILDDIR)/$(PN).pdf $@; \
+           $(REMAKE_INDICES); \
+           $(LATEX) $(PN).tex; \
+         done; \
        fi;
 
+       mv $(BUILDDIR)/$(PN).pdf $@
 
-$(PN).aux: $(SRCS)
+$(BUILDDIR):
+       mkdir $@
+
+$(BUILDDIR)/$(PN).aux: $(SRCS) | $(BUILDDIR)
        $(LATEX) $(PN).tex
 
 
@@ -120,7 +134,7 @@ ifdef INDICES
 # the main $(PN).pdf rule, in order to avoid a chicken-and-egg problem.
 # This is similar to the $(PN).aux rule above, except that an index is
 # optional and there might be more than one of them.
-$(INDEX_SRCS): $(PN).tex
+$(INDEX_SRCS): $(PN).tex | $(BUILDDIR)
        $(LATEX) $(PN).tex
 endif
 
@@ -150,9 +164,9 @@ endif
 # 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
@@ -212,7 +226,7 @@ JUNK_EXTENSIONS += snm spl toc xml
 .PHONY: clean
 clean:
        for ext in $(JUNK_EXTENSIONS); do rm -f *.$$ext; done;
-       rm -rf dist/
+       rm -rf dist/ $(BUILDDIR)/
        rm -f $(SAGE_LISTING_DSTS) $(INDEX_SRCS) $(INDEX_DSTS)
 
 # If this document will be published, the publisher isn't going to
@@ -221,6 +235,7 @@ clean:
 # will create a "dist" directory and copy the necessary stuff there.
 #
 .PHONY: dist
-dist: $(PN).bbl
+dist: $(BUILDDIR)/$(PN).bbl
        mkdir -p dist
-       cp $(SRCS) $(PN).bbl dist/
+       cp $(SRCS) $(BUILDDIR)/$(PN).bbl dist/
+