|
| 1 | +### |
| 2 | +### generic GNU make Makefile for .tex -> .pdf. |
| 3 | +### ransford at cs.washington.edu |
| 4 | +### http://github.com/ransford/pdflatex-makefile |
| 5 | +### |
| 6 | +### Recommended usage: |
| 7 | +### 1. echo 'include Makefile.include' > Makefile |
| 8 | +### 2. Optional: Edit the Makefile to override $(TARGET) |
| 9 | +### and anything else (e.g., PDFVIEWER, AFTERALL) |
| 10 | +### |
| 11 | +### Final result: |
| 12 | +### % cat Makefile |
| 13 | +### TARGET=mypaper |
| 14 | +### PDFVIEWER=open -a 'Adobe Acrobat Professional' |
| 15 | +### AFTERALL=mypostprocessingstep |
| 16 | +### include Makefile.include |
| 17 | +### |
| 18 | +### mypostprocessingstep: |
| 19 | +### # do something... |
| 20 | +### |
| 21 | + |
| 22 | +PDFLATEX ?= pdflatex -halt-on-error -file-line-error |
| 23 | +BIBTEX ?= bibtex |
| 24 | + |
| 25 | +ifneq ($(QUIET),) |
| 26 | +PDFLATEX += -interaction=batchmode |
| 27 | +ERRFILTER := > /dev/null || (egrep ':[[:digit:]]+:' *.log && false) |
| 28 | +BIBTEX += -terse |
| 29 | +else |
| 30 | +PDFLATEX += -interaction=nonstopmode |
| 31 | +ERRFILTER= |
| 32 | +endif |
| 33 | + |
| 34 | +## Action for 'make view' |
| 35 | +OS=$(shell uname -s) |
| 36 | +ifeq ($(OS),Darwin) |
| 37 | +PDFVIEWER ?= open |
| 38 | +else |
| 39 | +PDFVIEWER ?= xdg-open |
| 40 | +endif |
| 41 | + |
| 42 | +## Name of the target file, minus .pdf: e.g., TARGET=mypaper causes this |
| 43 | +## Makefile to turn mypaper.tex into mypaper.pdf. |
| 44 | +TARGETS += $(TARGET) |
| 45 | +TEXTARGETS = $(TARGETS:=.tex) |
| 46 | +PDFTARGETS = $(TARGETS:=.pdf) |
| 47 | +AUXFILES = $(TARGETS:=.aux) |
| 48 | +LOGFILES = $(TARGETS:=.log) |
| 49 | + |
| 50 | +## If $(TARGET).tex refers to .bib files like \bibliography{foo,bar}, then |
| 51 | +## $(BIBFILES) will contain foo.bib and bar.bib, and both files will be added as |
| 52 | +## dependencies to $(PDFTARGETS). |
| 53 | +## Effect: updating a .bib file will trigger re-typesetting. |
| 54 | +BIBFILES = $(patsubst %,%.bib,\ |
| 55 | + $(shell grep '^[^%]*\\bibliography{' $(TEXTARGETS) | \ |
| 56 | + grep -o '\\bibliography{[^}]\+}' | \ |
| 57 | + sed -e 's/^[^%]*\\bibliography{\([^}]*\)}.*/\1/' \ |
| 58 | + -e 's/, */ /g')) |
| 59 | + |
| 60 | +## Add \input'ed or \include'd files to $(PDFTARGETS) dependencies; ignore |
| 61 | +## .tex extensions. |
| 62 | +INCLUDEDTEX = $(patsubst %,%.tex,\ |
| 63 | + $(shell grep '^[^%]*\\\(input\|include\){' $(TEXTARGETS) | \ |
| 64 | + grep -o '\\\(input\|include\){[^}]\+}' | \ |
| 65 | + sed -e 's/^.*{\([^}]*\)}.*/\1/' \ |
| 66 | + -e 's/\.tex$$//')) |
| 67 | + |
| 68 | +AUXFILES += $(INCLUDEDTEX:.tex=.aux) |
| 69 | + |
| 70 | +## grab a version number from the repository (if any) that stores this. |
| 71 | +## * REVISION is the current revision number (short form, for inclusion in text) |
| 72 | +## * VCSTURD is a file that gets touched after a repo update |
| 73 | +SPACE = $(empty) $(empty) |
| 74 | +ifeq ($(shell git status >/dev/null 2>&1 && echo USING_GIT),USING_GIT) |
| 75 | + ifeq ($(shell git svn info >/dev/null 2>&1 && echo USING_GIT_SVN),USING_GIT_SVN) |
| 76 | + # git-svn |
| 77 | + REVISION := $(shell git svn find-rev git-svn) |
| 78 | + VCSTURD := $(subst $(SPACE),\ ,$(shell git rev-parse --git-dir)/refs/remotes/git-svn) |
| 79 | + else |
| 80 | + # plain git |
| 81 | + REVISION := $(shell git rev-parse --short HEAD) |
| 82 | + GIT_BRANCH := $(shell git symbolic-ref HEAD 2>/dev/null) |
| 83 | + VCSTURD := $(subst $(SPACE),\ ,$(shell git rev-parse --git-dir)/$(GIT_BRANCH)) |
| 84 | + endif |
| 85 | +else ifeq ($(shell hg root >/dev/null 2>&1 && echo USING_HG),USING_HG) |
| 86 | + # mercurial |
| 87 | + REVISION := $(shell hg id -i) |
| 88 | + VCSTURD := $(subst $(SPACE),\ ,$(shell hg root)/.hg/dirstate) |
| 89 | +else ifneq ($(wildcard .svn/entries),) |
| 90 | + # subversion |
| 91 | + REVISION := $(subst :,-,$(shell svnversion -n)) |
| 92 | + VCSTURD := .svn/entries |
| 93 | +endif |
| 94 | + |
| 95 | +# .PHONY names all targets that aren't filenames |
| 96 | +.PHONY: all clean pdf view snapshot distill distclean |
| 97 | + |
| 98 | +all: pdf $(AFTERALL) |
| 99 | + |
| 100 | +pdf: $(PDFTARGETS) |
| 101 | + |
| 102 | +view: $(PDFTARGETS) |
| 103 | + $(PDFVIEWER) $(PDFTARGETS) |
| 104 | + |
| 105 | +# define a \Revision{} command you can include in your document's preamble. |
| 106 | +# especially useful with e.g. draftfooter.sty or fancyhdr. |
| 107 | +# usage: \input{revision} |
| 108 | +# ... \Revision{} |
| 109 | +ifneq ($(REVISION),) |
| 110 | +REVDEPS += revision.tex |
| 111 | +revision.tex: $(VCSTURD) |
| 112 | + /bin/echo '\newcommand{\Revision}'"{$(REVISION)}" > $@ |
| 113 | +AUXFILES += revision.aux |
| 114 | +endif |
| 115 | + |
| 116 | +# to generate aux but not pdf from pdflatex, use -draftmode |
| 117 | +.INTERMEDIATE: $(AUXFILES) |
| 118 | +%.aux: %.tex $(REVDEPS) |
| 119 | + $(PDFLATEX) -draftmode $* $(ERRFILTER) |
| 120 | + |
| 121 | +# introduce BibTeX dependency if we found a \bibliography |
| 122 | +ifneq ($(strip $(BIBFILES)),) |
| 123 | +BIBDEPS = %.bbl |
| 124 | +%.bbl: %.aux $(BIBFILES) |
| 125 | + $(BIBTEX) $* |
| 126 | +endif |
| 127 | + |
| 128 | +$(PDFTARGETS): %.pdf: %.tex %.aux $(BIBDEPS) $(INCLUDEDTEX) $(REVDEPS) |
| 129 | + $(PDFLATEX) $* $(ERRFILTER) |
| 130 | +ifneq ($(strip $(BIBFILES)),) |
| 131 | + @if egrep -q "undefined (references|citations)" $*.log; then \ |
| 132 | + $(BIBTEX) $* && $(PDFLATEX) $* $(ERRFILTER); fi |
| 133 | +endif |
| 134 | + @while grep -q "Rerun to" $*.log; do \ |
| 135 | + $(PDFLATEX) $* $(ERRFILTER); done |
| 136 | + |
| 137 | +DRAFTS := $(PDFTARGETS:.pdf=-$(REVISION).pdf) |
| 138 | +$(DRAFTS): %-$(REVISION).pdf: %.pdf |
| 139 | + cp $< $@ |
| 140 | +snapshot: $(DRAFTS) |
| 141 | + |
| 142 | +%.distilled.pdf: %.pdf |
| 143 | + gs -q -dSAFER -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sOutputFile=$@ \ |
| 144 | + -dCompatibilityLevel=1.5 -dPDFSETTINGS=/prepress -c .setpdfwrite -f $< |
| 145 | + exiftool -overwrite_original -Title="" -Creator="" -CreatorTool="" $@ |
| 146 | + |
| 147 | +distill: $(PDFTARGETS:.pdf=.distilled.pdf) |
| 148 | + |
| 149 | +distclean: clean |
| 150 | + $(RM) $(PDFTARGETS) $(PDFTARGETS:.pdf=.distilled.pdf) $(EXTRADISTCLEAN) |
| 151 | + |
| 152 | +clean: |
| 153 | + $(RM) $(foreach T,$(TARGETS), \ |
| 154 | + $(T).bbl $(T).bcf $(T).bit $(T).blg \ |
| 155 | + $(T)-blx.bib $(T).brf $(T).glo $(T).glx \ |
| 156 | + $(T).gxg $(T).gxs $(T).idx $(T).ilg \ |
| 157 | + $(T).ind $(T).loa $(T).lof $(T).lol \ |
| 158 | + $(T).lot $(T).maf $(T).mtc $(T).nav \ |
| 159 | + $(T).out $(T).pag $(T).run.xml $(T).snm \ |
| 160 | + $(T).svn $(T).tdo $(T).tns $(T).toc \ |
| 161 | + $(T).vtc $(T).url) \ |
| 162 | + $(REVDEPS) $(AUXFILES) $(LOGFILES) \ |
| 163 | + $(EXTRACLEAN) |
| 164 | + |
0 commit comments