カレントディレクトリに複数のXMLファイル (*.xml) があり、これをHTMLに変換したい。 このときMakeを使って、更新されたファイルだけ変換するようにしたいがどうすればいいか。
前提条件
もしXMLファイル数が変化しないならば、
Makefile に以下のように記述しておけばよい。
(変換対象となるファイルは foo1.xml foo2.xml foo3.xml)
.SUFFIXES:
.SUFFIXES: .xml .html
.xml.html :
cat $< | /bin/toHtml > $@
all: foo1.html foo2.html foo3.html
しかし、foo4.xml,foo5.xml,hoge1.xml といった具合にどんどん変換対象ファイルが増える場合、 ファイル名/ファイル数が変化するたびに、Makefile を書き換えるのは面倒な上、間違いが起きる。
ファイル数が変化しても、対応できるMakefileを書くにはどうしたらいいか?
これよりもっとよい方法は その2 を参照のこと。
ファイル名/ファイル数が変化しても対応できるように、 Makefile中に カレントディレクトリにある 全部のxmlファイルを列挙して make を実行する シェルスクリプトを書いてしまいます。
.SUFFIXES:
.SUFFIXES: .xml .html
.xml.html :
cat $< | /bin/toHtml > $@
.PHONY: all
all:
for xmlf in *.xml ; do htmlf=$${xmlf%.*}.html; $(MAKE) $$htmlf ; done
.PHONY: clean
clean:
$(RM) *.html
Makefile中にシェルスクリプトを書くのをさけたい場合は、 その2 の方法を使います。
Makefile中のシェルスクリプト記述の注意点
シェルスクリプトをMakefileに直接書く場合は、
- 一行で書く
- $はエスケープするため$$ のように重ねて書く必要がある
Makefile だけで解決する方法がありました。
.SUFFIXES:
.SUFFIXES: .xml .html
.xml.html :
cat $< | /bin/toHtml > $@
xmlfiles:=$(wildcard *.xml)
htmlfiles=$(xmlfiles:.xml=.html)
.PHONY: all
all: $(htmlfiles)
.PHONY: clean
clean:
$(RM) $(htmlfiles)
ポイントは以下の2つです。
ポイント1) カレントディレクトリのxmlの拡張子をもつファイルだけ集める
xmlfiles:=$(wildcard *.xml)
これでカレントディレクトリにあるxmlファイルを$(xmlfiles)に代入することができます。
ポイント2) xmlの拡張子をまとめてhtmlに変換する
makeでは最終的に生成したファイル名を指定しなければならないため、 xmlの拡張子を持つファイル名を得ただけでは、問題は半分しか解決していません。
たとえば、 foo-1.xml foo-2.xml がカレントディレクトリにあるならば、
ここで実際に得たい文字列は、 foo-1.html foo-2.html になります。
ポイント1)により既に、$(xmlfiles)= foo-1.xml foo-2.xml は得ているため、
あとはこのxmlの部分をhtmlに変えるために以下の記述をします。
htmlfiles=$(xmlfiles:.xml=.html)
以上です。