2 # Example makefile using mjotex and a BibTeX references database.
6 LATEX = pdflatex -file-line-error -halt-on-error
8 # The name of this document.
10 # For example, to use the name of our parent directory:
12 # PN = $(notdir $(realpath .))
16 # A space-separated list of bib files. These must all belong to paths
17 # contained in your $BIBINPUTS environment variable.
19 # Leave commented if you don't use a bibliography database.
21 #BIBS = references.bib
23 # A space-separated list of the mjotex files that you use. The path to
24 # mjotex must be contain in your $TEXINPUTS environment variable.
28 MJOTEX = mjo-algebra.tex mjo-algorithm.tex mjo-arrow.tex mjo-calculus.tex
29 MJOTEX += mjo-common.tex mjo-complex.tex mjo-cone.tex mjo-convex.tex
30 MJOTEX += mjo-eja.tex mjo-font.tex mjo-linear_algebra.tex mjo-listing.tex
31 MJOTEX += mjo-misc.tex mjo-proof_by_cases.tex mjo-theorem.tex
32 MJOTEX += mjo-theorem-star.tex mjo-topology.tex mjo.bst
34 # Compile a list of raw source code listings (*.listing) and their
35 # associated output files (*.py) that will be tested by check-sage.
36 SAGE_LISTING_SRCS = $(wildcard sage_listings/*.listing)
37 SAGE_LISTING_DSTS = $(patsubst %.listing,%.py,$(SAGE_LISTING_SRCS))
39 # Use kpsewhich (from the kpathsea suite) to find the absolute paths
40 # of the bibtex/mjotex files listed in in $(BIBS)/$(MJOTEX). The SRCS
41 # variable should contain all (Bib)TeX source files for the document.
44 BIBPATHS = $(shell kpsewhich $(BIBS))
48 MJOTEXPATHS = $(shell kpsewhich $(MJOTEX))
49 SRCS += $(MJOTEXPATHS)
51 ifdef SAGE_LISTING_SRCS
52 SRCS += $(SAGE_LISTING_SRCS)
55 # The first target is the default, so put the PDF document first.
57 # This voodoo is all designed to find a "fixed point" of calling
58 # $(LATEX). When you build a LaTeX document, it requires an unknown
59 # number of compilation passes. How do you know when to stop? Easy,
60 # stop when the output file stops changing! But how to encode that
63 # At the start of this target, we call $(LATEX) to compile $(PN).tex.
64 # If you ignore the "sed" for now, then the next step is to check for
65 # the existence of a "previous" file. If there isn't one, this is the
66 # first time that we've tried to build the PDF. In that case, take the
67 # PDF that we've just built and make *that* the previous file. Then
68 # start all over. If there is a previous file, then this is the second
69 # (or more) time that we've tried to build the PDF. We diff the PDF
70 # file that we've just built against the previous file; if they're the
71 # same, then we've succeeded and stop. Otherwise, we make the new PDF
72 # the previous file, and start all over. The end result is that we
73 # will loop until the newly-created PDF and the previous file are
76 # But what about the "sed" call? By default, pdflatex will compile the
77 # creation date, modification date, and a unique ID into the output
78 # PDF. That means that two otherwise-identical documents, created
79 # seconds apart, will look different. We only need to know when the
80 # *contents* of the document are the same -- we don't care about the
81 # metadata -- so sed is used to remove those three nondeterministic
82 # pieces of information.
84 # The creation and modification dates should become optional in pdftex
85 # v1.40.17 thanks to Debian's SOURCE_DATE_EPOCH initiative. When that
86 # version of pdflatex makes it into TeX Live 2016, we can replace
87 # those two sed scripts with something smarter.
89 $(PN).pdf: $(SRCS) $(PN).bbl
93 -e '/^\/ID \[<.*>\]/d' \
94 -e "s/^\/\(ModDate\) (.*)/\/\1 (D:19700101000000Z00'00')/" \
95 -e "s/^\/\(CreationDate\) (.*)/\/\\1 (D:19700101000000Z00'00')/" \
98 if [ ! -f $@.previous ]; then \
103 if cmp -s $@ $@.previous; then \
115 # The pipe below indicates an "order-only dependency" on the aux file.
116 # Without it, every compilation of $(PN).tex would produce a new
117 # $(PN).aux, and thus $(PN).bbl would be rebuilt. This in turn causes
118 # $(PN).pdf to appear out-of-date, which leads to a recompilation of
119 # $(PN).tex... and so on. The order-only dependency means we won't
120 # rebuild $(PN).bbl if $(PN).aux changes.
122 # As a side effect, we now need to depend on $(SRCS) here, since we
123 # won't pick it up transitively from $(PN).aux.
125 # If the $BIBS variable is undefined, we presume that there are no
126 # references and create an empty bbl file. Otherwise, we risk trying
127 # to run biblatex on an aux file containing no citations. If you do
128 # define $BIBS but don't cite anything, you'll run into a similar
129 # problem. Don't do that.
131 $(PN).bbl: $(SRCS) | $(PN).aux
138 # If the output PDF exists but the log file does not, then an attempt
139 # to "build the log file" (i.e. build the PDF) would do nothing. Thus
140 # whenever the log file does not exist, we do a fresh build.
145 # How do we convert a raw listing into something testable by sage? We
146 # append/prepend triple quotes to make the whole thing into a doctest.
147 sage_listings/%.py: sage_listings/%.listing
148 echo '"""' > $@ && cat $< >> $@ && echo '"""' >> $@
150 # Ensure that there are no overfull or underfull boxes in the output
151 # document by parsing the log for said warnings.
153 check-boxes: $(PN).log
154 @! grep -i 'overfull\|underfull' $<
156 # Run chktex to find silly mistakes. There is some exit code weirdness
157 # (Savannah bug 45979), so we just look for empty output.
159 CHKTEX = chktex --localrc .chktexrc --quiet --inputfiles=0
161 @[ -z "$(shell $(CHKTEX) mjotex.sty)" ]
163 # Ensure that there are no undefined references in the document by
164 # parsing the log file for said warnings.
165 .PHONY: check-undefined
166 check-undefined: $(PN).log
167 @! grep -i 'undefined' $<
169 # Use sage to doctest any \sagelisting{}s in SAGE_LISTING_DSTS.
170 # The actuall command is ifdef'd so that we can comment out
171 # the definition of SAGE_LISTING_DSTS without breaking the
172 # default definition of the "check" target.
174 check-sage: $(SAGE_LISTING_DSTS)
175 ifdef SAGE_LISTING_DSTS
176 PYTHONPATH="$(HOME)/src/sage.d" \
177 sage -t --timeout=0 --memlimit=0 \
181 # Run a suite of checks.
183 check: check-boxes check-chktex check-undefined check-sage
185 # Clean up leftover junk. This only looks overcomplicated because
186 # the *.{foo,bar} syntax supported by Bash is not POSIX, and Make
187 # will execute these commands using /bin/sh (which should be POSIX).
188 JUNK_EXTENSIONS = aux bbl bcf bib blg listing lof log nav out pdf
189 JUNK_EXTENSIONS += snm spl toc xml
192 for ext in $(JUNK_EXTENSIONS); do rm -f *.$$ext; done;
194 rm -f $(SAGE_LISTING_DSTS)
196 # If this document will be published, the publisher isn't going to
197 # have your BibTeX database or your mjotex files. So, you need to
198 # package them up along with the code for your document. This target
199 # will create a "dist" directory and copy the necessary stuff there.
204 cp $(SRCS) $(PN).bbl $(BIBPATHS) $(MJOTEXPATHS) dist/