2010-10-20

makeでちょっと便利なメタプログラミング

GNU Make 第3版を見てたら、マクロとevalを使ってちょっと便利でおもしろいことができることに気づいた。

とりあえず例を書くとこんな感じ。
rules = foo bar baz

define def-rule
$1:
 @echo $1
endef

$(foreach i, $(rules), $(eval $(call def-rule, $i)))

マクロとevalを使えば動的にルールを生成できるのだ。
これだけでfoo bar bazの三つのルールがつかえるようになる。
便利!

これを使えばサブコマンドを受け付けるコマンドを使うルールを定義したい時とか、複数のディレクトリに対して処理を行いたい時に妥協したシェルスクリプトを書く割合が減る気がする。

ただし、マクロの中は二重に評価されてしまうので、makeの自動変数やfor文、シェル変数を使いたい時は$の個数に注意が必要
rules = foo bar baz

define def-rule
$1:
 @for i in foo*; \
 do \
 echo $$$$$$$$; \
 echo $$$$i; \
 echo $$@; \
 echo $1; \
 done
endef

$(foreach i, $(rules), $(eval $(call def-rule, $i)))
これはきもい

(※ $$はそのコマンドのpidを返すシェル変数。$@はそのルールのターゲット名を表すmakeの自動変数)


ZenBackWidget