Index > Makefileの中でワイルドカードを使ってファイルを指定する方法
Fri, May 2, 2008

Makefileの中でワイルドカードを使ってファイルを指定する方法

カレントディレクトリに複数のXMLファイル(*.xml)があり、 これをHTMLに変換したい。 このときMakeを使って、更新されたファイルだけ変換するようにしたいがどうすればいいか。

前提条件

結論だけを知りたい方はここをクリック。

もしXMLファイル数が変化しないならば...

もし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を書くにはどうしたらいいか?

ファイル数が変化しても対応できるMakefile その1(もっとよい方法はその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に直接書く場合は、

1) 一行で書く
2) $はエスケープするため$$ のように重ねて書く必要がある

ファイル数が変化しても対応できるMakefile その2(もっとよい方法)

※この方法は、MASA.H氏に教えていただきました。感謝します。

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)
 Twitter
follow me on Twitter
 Categories