最終更新:2017-09-12 (火) 17:56:36 (427d)

FrontPage

TeX 用 Makefile の作成

(GNU) Make は再コンパイル支援ツールです。複数のファイルの依存関係を調べて、ソースファイルのコンパイルを楽にします。このツールを LaTeX のタイプセットにも使用することが出来ます。

まずは簡単な例を一つ。

F=input
all: $F.dvi
$F.dvi: $F.tex
	 uplatex $F && uplatex $F

変数 $F に入力ファイル input.tex の .tex という拡張子を取り除いたファイル名を書きます。 次に標準のターゲット (all) を $F.dvi (input.dvi) に指定します。 これにより input.dvi の作成を最終目標とします。次に $F.dvi の依存ファイルを指定します。 この場合は簡単に $F.tex とします。次に行は、行頭にタブ文字を書き、 続けて $F.tex から $F.dvi を生成するために必要な作業を記述します。 ここでは uplatex プログラムを 2 回ほど走らせることになります。

Makefile のサンプル

# Title: Makefile
# Date:  2014/04/30
# Name:  Thor Watanabe
# Mail:  hakodate12@hotmail.com
# 主となる原稿
FILE=sample
# 分割され、インクルードされているファイル
SRC=#chap1.tex chap2.tex,..., chap<n>.tex
#スタイルファイルやクラスファイルなど
OHTERS=#funthesis.cls mymacro.sty
# 画像などのバイナリファイル
IMG=#hoge.eps capture1.jpg
#文献データベース、あるならば.
REF=biblio.bib
#走らせるTeXプログラム
TEX=uplatex
# dvips
DVIPS=dvips -Ppdf
# dvipdfmx
DVIPDF  =dvipdfmx -p a4 -f dlbase14.map -o $(FILE).pdf 
# 相互参照の解消のため
REFGREP=grep "^LaTeX Warning: Label(s) may have changed."
# プリンタの設定
PRINTER=//server/printername
# 標準のターゲット
all:$(FILE).ps $(FILE).pdf 
printps:  $(FILE).ps
	lpr -P$(PRINTER) $(FILE).ps
printpdf:  $(PSFILE)
	lpr -P$(PRINTER) $(FILE).ps
$(FILE).pdf: $(FILE).dvi
	$(DVIPDF) $(FILE)
$(FILE).ps: $(FILE).dvi
	$(DVIPS) -o $(FILE).ps $(FILE)
$(FILE).dvi: $(FILE).aux $(FILE).bbl
	(while $(REFGREP) $(FILE).log; do $(TEX) $(FILE); done)
$(FILE).bbl: $(REFFILE)
	$(BIBTEX) $(FILE)
$(FILE).aux: $(FILE).tex
	$(TEX) $(FILE)
clean:
	rm -f $(FILE).aux $(FILE).log $(FILE).toc $(FILE).dvi 
	rm -f $(FILE).pdf $(FILE).tex~ $(FILE).lof $(FILE).lot
tar:
	mkdir -p $(FILE)
	cp $(SRC) $(OHTERS) $(REF) $(IMG) $(FILE).tex Makefile $(FILE)/
	tar czf $(FILE)src.tgz $(FILE)/
	rm -fr $(FILE)/

Makefile の実際の表記

Makefile 中では便利な省略表記が使われます。頻繁に使われるものは次の三つです。

$<
入力ファイル名
$*
入力ファイル名から拡張子を取り除いたもの
$@
出力ファイル名

標準的な Makefile は、次の三つの部分に分かれています。

  1. 各種変数の宣言
  2. 一般的な依存関係とファイル生成規則
  3. 実ファイルの依存関係

各種変数の宣言とは次のようにコマンドやコマンドラインオプションなどを保存します。

TEX=uplatex
PDFOPT=-p a4 -r 2400 -V 4 -o $@
F=test

TEX には主となる TeX エンジン、PDFOPT には dvipdfmx のコマンドライン オプション、F には原稿となる TeX ファイル名(拡張子なし)を記述します。 変数を使用するときは $(TEX) 等として、先頭にドルを追加し、全体をパーレンで くくります。

次に一般的な依存関係を記述します。普通、 file.tex から PDF を生成するには

uplatex file.tex
dvipdfmx file.dvi

とするので、依存関係に関わる処理は次のように記述します。

.tex.dvi:
	 $(TEX) $<
.dvi.pdf:
	 dvipdfmx $(PDFOPT) $<

次に実ファイルの依存関係を記述します。まずは標準のターゲット、 最終的に作成したい(とは限らないが)ファイルを次のように指定します。

all: $F.pdf

このようにして、実際の依存関係を明記します。

$F.pdf:	$F.dvi
$F.dvi:	$F.tex

しかし、実はこのままではうまく行きません。make に対して、新規に次の拡張子を 登録します。

.SUFFIXES: .tex .dvi .pdf

この .SUFFIXES は $* 等で必要になりますので、ファイルの先頭にでも記述すると良いでしょう。

このようにして、次のようなファイル Makefile が完成します。

.SUFFIXES: .tex .dvi .pdf
TEX=uplatex
PDFOPT=-p a4 -r 2400 -V 4 -o $@
F=test

.tex.dvi:
	$(TEX) $<
.dvi.pdf:
	 dvipdfmx $(PDFOPT) $<

all:	$F.pdf

$F.pdf:	$F.dvi
$F.dvi:	$F.tex

実際に test.tex を次のように作成し make コマンドを引数なしで実行してください。

\documentclass{ujarticle}
\begin{document}
test
\end{document}

これを

make 

とすると

uplatex test.tex
dvipdfmx -p a4 -r 2400 -V 4 -o test.pdf

を実行したのと等価になります。ためしにもう一度

make 

として、

make: Nothing to be done for `all'.

と表示されれば、きちんと依存関係が記述されていることになります。 さらに

touch test.tex 

と実行して、ファイルのタイムスタンプを変更し

make

と実行するともう一度 uplatex と dvipdfmx が実行され test.pdf が生成されます。

まぁ、普段は次のような Makefile を用意するだけで実は良かったりします。

.SUFFIXES: .tex .dvi .aux .log .toc .lof .lot .pdf .ps
F=gs20050501
TEX=uplatex

all: $F.dvi

pdf: $F.pdf
ps: $F.ps
dvi: $F.dvi

$F.dvi: $F.tex
$F.pdf: $F.dvi
$F.ps:  $F.dvi

.dvi.ps:
       dvips -Ppdf -o $@ $<
.dvi.pdf:
       dvipdfmx $<
clean:
       rm -f *~ $F.dvi $F.aux $F.lof $F.toc $F.lot $F.log $F.pdf $F.ps

いやはや、実は upBibTeX も使っているという人は以下の ように変更すれば良いでしょう。

.SUFFIXES: .tex .dvi .aux .log .toc .lof .lot .pdf .ps .bbl .bib .blg
F=gs20050501
TEX=uplatex

all: $F.dvi
pdf: $F.pdf
dvi: $F.dvi
bbl: $F.bbl
ps:  $F.ps

$F.dvi:        $F.tex $F.bbl
$F.pdf:        $F.dvi
$F.ps: $F.dvi
$F.bbl: $F.bib
$F.aux: $F.tex

.dvi.ps:
       dvips -Ppdf -o $@ $*
.dvi.pdf:
       dvipdfmx $*
.bib.bbl:
       uplatex $*; upbibtex $*; uplatex $*
.tex.aux:
       $(TEX) $*

clean:
       rm -f *~ $F.dvi $F.aux $F.lof $F.toc $F.lot $F.log \
               $F.pdf $F.ps $F.bbl $F.blg

さらに索引とか用語集とか、いろいろある人はまぁ、適当に。 折角なのでプレビューと印刷も簡単にできるようにしておきましょう。 依存関係とか適当に書いて終わりです。

もっと高度な例

.SUFFIXES: .tex .dvi .aux .log .toc .lof .lot .pdf .ps .bbl .bib .blg .lol .cls .sty .eps .eepic .plt .out .obj .title

F=     m1201234
SRC=   title.pl rmlgbm.map
CLS=   funthesis.cls
setting=gsset.sty
abst=  00abst.tex

TEX=   uplatex
#DVIPDF=       dvipdfmx -f rmlgbm.map -p a4 -V 4
DVIPDF=        dvipdfmx -p a4 -V 4
BIBTEX=        upbibtex
RM=    rm -f
AUTOMAKE=make
MKDIR= mkdir -p

#your favorite line printer name
#LPNAME=       atlantic
LPNAME=        192.168.11.3

# for macOS with MacTeX
XDVI=  open -a Skim.app
PDFVIEWER=open -a Skim.app
DVIPS= dvips -t a4

# for Unix/Linux/Solaris/BSD/...
#XDVI= xdvi
#PDFVIEWER=acroread

# for Windows
#XDVI= dviout 
#PDFVIEWER=iexplore

all: $F.pdf README 

pdf:   $F.pdf
ps:    $F.ps
dvi:   $F.dvi
bbl:   $F.bbl
2up:   $(F)up.ps
title: $F.title

view:  $F.dvi
       $(XDVI) $<
viewpdf: $F.pdf
       $(PDFVIEWER) $<
check: $F.pdf
       pdfinfo $<
       pdffonts $<
README:        $(setting)
       cat $< | grep -e "^%%" | sed -e "s/^%%//;" > README
today: $F.pdf
       cp $< $F-`date +%Y-%m-%d-%H-%M`.pdf
#img:
#      cd img && $(AUTOMAKE)

$F.dvi:        $F.tex
$F.pdf:        $F.dvi
$F.ps: $F.dvi
$(F)up.ps: $F.ps
$F.bbl: $F.bib
$F.aux: $F.tex
$F.title: $(abst)

.dvi.pdf:
       $(DVIPDF) $*
$(F)up.ps: $F.ps
       psnup -2 $< $@
.dvi.ps:
       $(DVIPS) -o $@ $*
.bib.bbl:
       $(TEX) $*; $(BIBTEX) $*; $(TEX) $*
.tex.dvi:
       $(TEX) $<
       (while egrep "may have changed" $*.log; \
           do $(TEX) $<; done)
.tex.aux:
       $(TEX) $*
.tex.title:
       echo "cat $(setting) $F.tex | ./title.pl > $F.title"

fast:
       $(TEX) $F; $(TEX) $F
faster:
       $(TEX) $F;

clean:
       $(RM) *~ $F.dvi $F.aux $F.lof $F.toc $F.lot $F.log \
               $F.ps $F.bbl $F.blg $F.lol $F.out
       $(RM) *.dvi *.aux *.log *.toc *.blg *.bbl *.lof *.lot

tar: $F.tex title README $(SRC) $(CLS) 
       $(MKDIR) $(F)src/img
       cp $F.tex $F.title Makefile README $(SRC) $(CLS) $(F)src/
       cp img/* $(F)src/img/
       tar czf $(F)src.tgz $(F)src/
       rm -fr $(F)src

# Gnuplot の場合
SRC := $(wildcard img/*.plt)
obj := $(patsubst %.plt,%.eps,$(SRC))
pdfobj := $(patsubst %.plt,%.pdf,$(SRC))
# Tgif の場合
TGIF := $(wildcard img/*.obj)
tgifobj := $(patsubst %.obj,%.eps,$(TGIF))
tgifpdfobj := $(patsubst %.obj,%.pdf,$(TGIF))

img: $(pdfobj) $(tgifpdfobj)

.plt.eps:
       gnuplot $<
       mv `basename $@` img/
.obj.eps:
       tgif -print -eps -color $<
.eps.pdf:
       epstopdf $<

$(obj): %.eps: %.plt
$(pdfobj): %.pdf: %.eps

$(tgifobj): %.eps: %.obj
$(tgifpdfobj): %.pdf: %.eps

cleanimg:
       echo "rm -f *.eps *.pdf"

もっともっと色々やる例

upbibtex にも対応.

.SUFFIXES: .tex .dvi .pdf .obj .eps .aux .tgz .tar .gz .out \
       .bz2 .tbz .zip .jpg .jpeg .bmp .png .log .toc .lof .lot \
       .idx .glo .ilg .glg .gls .ltx .dtx .bib .bbl .blg

VERSION:=$(shell date +%Y-%m-%d)
ID:=$(shell whoami)

# required sources
MAIN=f
SRC=000.tex 010.tex 020.tex 030.tex 040.tex 050.tex 060.tex 070.tex \
       080.tex 090.tex 100.tex 101.tex
ETC=funthesis.cls f.bib

# program setting
EDITOR=openemacs
TEX=uplatex -synctex=1
BIBTEX=upbibtex
DVIPDF=dvipdfmx
XDVI=open -a Skim.app
XPDF=open -a Skim.app
REFGREP=grep "^LaTeX Warning: Label(s) may have changed."

# sub-directory setting
IMGDIR=img
PDFDIR=pdf
DISTDIR=$(ID)-$(VERSION)

# default target
all:   dvi

# aliases
dvi:   $(MAIN).dvi
pdf:   $(MAIN).pdf
bib:   $(MAIN).bbl

# indipendency
$(MAIN).dvi:   $(MAIN).tex $(MAIN).bbl $(SRC)
$(MAIN).pdf:   $(MAIN).dvi
$(MAIN).aux:   $(MAIN).tex
$(MAIN).bbl:   $(MAIN).bib 
$(MAIN).bib:   $(MAIN).aux

# translation rules
.dvi.pdf:
       $(DVIPDF) $<
.tex.dvi:
       $(TEX) $<
       (while grep "^No file $*.lo" $*.log; do $(TEX) $<; done)
       (while $(REFGREP) $*.log; do $(TEX) $<; done)
.bib.bbl:
       $(BIBTEX) $*
.tex.aux:
       $(TEX) $<
# 
#  
fast:
       $(TEX) -interaction=batchmode $(MAIN) 
view:  $(MAIN).dvi
       $(XDVI) $< & 
viewpdf:       $(MAIN).pdf
       $(XPDF) $< & 

edit:
       $(EDITOR) $(MAIN).tex & 

dist:  clean
       mkdir $(DISTDIR)
       cp -r $(IMGDIR) $(PDFDIR) $(DISTDIR)
       cp $(SRC) $(MAIN).tex $(ETC) Makefile $(DISTDIR)
       tar cjf ../$(DISTDIR).tar.bz2 $(DISTDIR)
       rm -fr $(DISTDIR)

clean:
       rm -f *~
       rm -f *.aux *.log $(MAIN).{lof,lot,toc,dvi,pdf,bbl,out}

もっともっともっと色々やる例

.SUFFIXES: .tex .dvi .pdf .obj .eps .aux .tgz .tar .gz .out \
       .bz2 .tbz .zip .jpg .jpeg .bmp .png .log .toc .lof .lot \
       .idx .glo .ilg .glg .gls .ltx .dtx .bib .bbl .blg

VERSION        :=      $(shell date +%Y-%m-%d)
ID     :=      $(shell whoami)

# required sources
MAIN   =       main
SRC    =       000.tex  030.tex  051.tex  055-01.tex  057.tex  061.tex  \
               100.tex  001.tex  031.tex  052.tex  055-02.tex  058.tex  \
               070.tex  101.tex  010.tex  040.tex  053.tex  055.tex \
               059.tex  090.tex  102.tex  020.tex  050.tex  054.tex \
               056.tex  060.tex  099.tex  999.tex

ETC    =       funthesis.cls main.bib jdummy.def labelfig.tex \
               labelfig.sty eclclass.sty plistings.sty jsai.bst 

# program setting
EDITOR =       openemacs
TEX    =       uplatex -synctex=1
BIBTEX =       upbibtex
DVIPDF =       dvipdfmx
XDVI   =       open -a Skim.app
XPDF   =       open -a Skim.app
REFGREP        =       grep "^LaTeX Warning: Label(s) may have changed."

# sub-directory setting
# JPEG, PNG などのビットマップ画像の保存先
IMGDIR =       img
# PDF の保存先
PDFDIR =       pdf
# OmniGraffle 等で作成したオリジナルファイル(dvipdfmx で未対応)
PICTDIR        =       pict
# 表の原稿ファイル
TABLEDIR       =       table
# Gnuplot のプロットデータや CSV ファイルの格納場所
PLOTDIR        =       plt
#
ETCDIR =       tex
# バックアップファイルの名前
DISTDIR        =       $(ID)-$(VERSION)

# default target
all:   dvi

# aliases
dvi:   $(MAIN).dvi
pdf:   $(MAIN).pdf
bib:   $(MAIN).bbl

# indipendency
$(MAIN).dvi:   $(MAIN).tex $(MAIN).bbl $(SRC)
$(MAIN).pdf:   $(MAIN).dvi
$(MAIN).aux:   $(MAIN).tex
$(MAIN).bbl:   $(MAIN).bib 
$(MAIN).bib:   $(MAIN).aux

# translation rules
.dvi.pdf:
       $(DVIPDF) $<
.tex.dvi:
       $(TEX) $<
       (while grep "^No file $*.lo" $*.log; do $(TEX) $<; done)
       (while $(REFGREP) $*.log; do $(TEX) $<; done)
.bib.bbl:
       $(BIBTEX) $*
.tex.aux:
       $(TEX) $<
# 
#  
fast:
       $(TEX) -interaction=batchmode $(MAIN) 
view:  $(MAIN).dvi
       $(XDVI) $< & 
viewpdf:       $(MAIN).pdf
       $(XPDF) $< & 

edit:
       $(EDITOR) $(MAIN).tex & 

dist:  clean
       mkdir $(DISTDIR)
       cp -r $(IMGDIR) $(PDFDIR) $(PICTDIR) $(TABLEDIR) $(PLOTDIR) $(ETCDIR) \
               $(DISTDIR)
       cp $(SRC) $(MAIN).tex $(ETC) Makefile $(DISTDIR)
       tar cjf ../$(DISTDIR).tar.bz2 $(DISTDIR)
       rm -fr $(DISTDIR)

clean:
       rm -f *~
       rm -f *.{aux,bbl,blg} *.log $(MAIN).{lof,lot,toc,dvi,pdf,out}

help:
       @echo -e "\nusage: make [<target>]\n"
       @echo -e "all:\tDVI ファイル $(MAIN).dvi を作成する"
       @echo -e "bib:\t文献ファイル $(MAIN).bbl を作成する"
       @echo -e "clean:\t一時ファイルを全て削除する"
       @echo -e "dist:\tバックアップ $(DISTDIR).tar.bz2 を一つの上のフォルダに作成する"
       @echo -e "dvi:\tDVI ファイル $(MAIN).dvi を作成する"
       @echo -e "edit:\tテキストエディッタ $(EDITOR) で $(MAIN).tex を開く\t"
       @echo -e "fast:\t依存関係を無視して $(MAIN).tex をコンパイルする"
       @echo -e "help:\tこのメッセージを表示する"
       @echo -e "pdf:\tPDF ファイル $(MAIN).pdf を作成する"
       @echo -e "view:\tDVI を $(XDVI) で開く"
       @echo -e "viewpdf:\tPDF を $(XPDF) で開く\n"

その他 jhb

.SUFFIXES: .tex .dvi .pdf .obj .eps .aux .tgz .tar .gz .out \
       .bz2 .tbz .zip .jpg .jpeg .bmp .png .log .toc .lof .lot \
       .idx .glo .ilg .glg .gls .ltx .dtx .bib .bbl .blg

VERSION        :=      $(shell date +%Y-%m-%d)

# programs
# for macOS
EDITOR =       openemacs
XDVI   =       open -a Skim.app
XPDF   =       open -a Skim.app
# using utf8 (euc (E), jis (J), sjis (S) )
TEX    =       uplatex -synctex=1 
BIBTEX =       upbibtex
MAKEIDX        =       upmendex -d hb.dic
DVIPDF =       dvipdfmx
REFGREP        =       grep "^LaTeX Warning: Label(s) may have changed."

# directories
SRC_DIR        =       img
IMG_DIR        =       src
STY_DIR        =       mcr

# source files
MAIN   =       hb
SRC    =       Makefile jhb.sty
IST    =       $(STY_DIR)/sind.ist
GST    =       $(STY_DIR)/sgls.ist
BST    =       $(STY_DIR)/splain.bst
# for distributable archive file
DISTDIR        =       $(MAIN)src-$(VERSION)

# aliases
all:   fast
dvi:   $(MAIN).dvi
pdf:   $(MAIN).pdf
bib:   $(MAIN).bbl
fast:  $(MAIN).tex
       $(TEX) $(MAIN) && $(TEX) $(MAIN)

$(MAIN).dvi:   $(SRC) $(MAIN).bbl $(MAIN).aux $(MAIN).gls $(MAIN).ind
$(MAIN).pdf:   $(MAIN).dvi
$(MAIN).aux:   $(MAIN).tex
$(MAIN).bbl:   $(MAIN).bib 
$(MAIN).bib:   $(MAIN).aux
$(MAIN).ind:   $(MAIN).idx
$(MAIN).gls:   $(MAIN).glo
$(MAIN).idx:   $(MAIN).aux
$(MAIN).glo:   $(MAIN).aux

$(MAIN).ind:   $(MAIN).idx
       $(MAKEIDX) -s $(IST) -t $*.ilg -o $@ $<
$(MAIN).gls:   $(MAIN).glo
       $(MAKEIDX) -s $(GST) -t $*.glg -o $@ $<

# translation rules
.dvi.pdf:
       $(DVIPDF) $<
.tex.dvi:
       $(TEX) $<
       $(TEX) $<
       (while grep "^No file $*.lo" $*.log; do $(TEX) $<; done)
       (while $(REFGREP) $*.log; do $(TEX) $<; done)
.bib.bbl:
       $(BIBTEX) $*
.tex.aux:
       $(TEX) $<
       (while grep "^No file $*.lo" $*.log; do $(TEX) $<; done)
       (while $(REFGREP) $*.log; do $(TEX) $<; done)

# preview
view:  $(MAIN).dvi
       $(XDVI) $< & 
viewpdf:       $(MAIN).pdf
       $(XPDF) $< & 
# edit
edit:
       $(EDITOR) $(MAIN).tex & 

clean: 
       touch hb.{aux,log,toc,out,lof,lot,idx,ilg,ind,glo,glg,gls,bbl,blg}
       rm -f hb.{aux,log,toc,out,lof,lot,idx,ilg,ind,glo,glg,gls,bbl,blg}

cleanall:      clean
       touch hb.{dvi,pdf}
       rm -f hb.{dvi,pdf}
       rm -f *~
       rm -f $(SRC_DIR)/*~
       rm -f $(SRC_DIR)/*.aux
       rm -f $(IMG_DIR)/*~
       rm -f $(STY_DIR)/*~

dist:  cleanall
       mkdir -p $(DISTDIR)/{$(SRC_DIR),$(IMG_DIR),$(STY_DIR)}
       cp -r img mcr src $(DISTDIR)
       cp $(MAIN).tex $(MAIN).dic $(MAIN).bib  $(SRC) $(DISTDIR)
       tar cjf ../$(DISTDIR).tar.bz2 $(DISTDIR)
       rm -fr $(DISTDIR)

help:
       @echo -e "\nusage: make [<target>]\n"
       @echo -e "all:\tDVI ファイル $(MAIN).dvi を作成する"
       @echo -e "bib:\t文献ファイル $(MAIN).bbl を作成する"
       @echo -e "clean:\t一時ファイルを全て削除する"
       @echo -e "dist:\tバックアップ $(DISTDIR).tar.bz2 を一つの上のフォルダに##成する"
       @echo -e "dvi:\tDVI ファイル $(MAIN).dvi を作成する"
       @echo -e "edit:\tテキストエディッタ $(EDITOR) で $(MAIN).tex を開く\t"
       @echo -e "fast:\t依存関係を無視して $(MAIN).tex をコンパイルする"
       @echo -e "help:\tこのメッセージを表示する"
       @echo -e "pdf:\tPDF ファイル $(MAIN).pdf を作成する"
       @echo -e "view:\tDVI を $(XDVI) で開く"
       @echo -e "viewpdf: PDF を $(XPDF) で開く"
       @echo -e "viewcfg: 設定情報を閲覧する\n"

viewcfg:
       @echo -e "VERSION:\t$(VERSION)"
       @echo -e "EDITOR:\t$(EDITOR)"
       @echo -e "XDVI:\t$(XDVI)"
       @echo -e "XPDF:\t$(XPDF)"
       @echo -e "TEX:\t$(TEX)"
       @echo -e "BIBTEX:\t$(BIBTEX)"
       @echo -e "MAKEIDX:\t$(MAKEIDX)"
       @echo -e "DVIPDF:\t$(DVIPDF)"
       @echo -e "SRC_DIR:\t$(SRC_DIR)"
       @echo -e "IMG_DIR:\t$(IMG_DIR)"
       @echo -e "STY_DIR:\t$(STY_DIR)"
       @echo -e "MAIN:\t$(MAIN)"
       @echo -e "SRC:\t$(SRC)"