Makefile 内で sed を使って文字列を加工してみる

Makefile プログラミング

Makefile 内で変数に渡されてきた文字列を自由に加工したくて、Makefile 内で sed コマンドを使ってみることにしました。


Makefile で、変数に渡されてきた文字列を加工したくなったのですけど、組み込みの findstring 関数とかを使うのは辛そうだったので、シェルコマンドの sed を使って文字列を加工してみることにしました。

試行錯誤でやってみたので、力技なところが多いかもしれません。似たようなことをしたくてどうにも困ったときなどの参考程度にしてみてください。

Makefile で sed を使ってみる

Linux シェル上で sed を使ってみて感じた癖などについては、以前に 文字列から特定の文字を抽出する で記していたのですけど、Makefile ではそれとは勝手が違う様子でした。

終わってみれば、単純に $ 記号を $$ と重ねないといけないくらいだった様子ですけど、それになかなか気づけなくて時間がかかってしまいました。

sed を実行する方法

Makefile でシェルコマンドを実行するには shell 関数を使います。

VALUE = $(shell echo $@ | sed -e 's/^[^.]*//')

たとえばこのようにすることで、変数 $@ に入っていた値を sed にかけて、その結果を変数 VALUE に入れるみたいなことができるようになっていました。

大域に使うものを用意してみる

最初に思い描いたのは『各ルールの中で、ローカル変数に sed で文字列を加工したものを入れて使う』というやり方だったのですけど、ローカル変数を使う方法がわかりませんでした。

それならルール内の必要なところで shell コマンドを実行してもよかったのですけど、それだとその行が必要以上に長くなって読みづらそうだったので、ルールの外であらかじめ次のような準備をしておくことにしました。

SED_NAME = sed -e 's/^\([^.]*\)\.\(.*\)$$/\2/'
GETNAME = echo $< | $(SED_NAME)

上の例では、ここで定義した GETNAME 変数を shell 関数で実行する予定です。

この中では $< のような、ルール実行時に渡されてくる変数を使うように記載されていますけど、このようにあらかじめ書いておいても、実際にルールの中で実行したときに、そのときの変数の値が利用される様子です。

ルール内で実行する

ここまで準備をしたら、あとは必要なタイミングで使います。

%.lastpush : %.podspec
	pod repo push $(REPO) $(shell $(GETNAME))
	

たとえばこのようにすることで、あらかじめ GETNAME に用意しておいた命令を shell 関数で実行して、目的の値を受け取って使うことができるようになりました。

まとめ

このようにしてなんとかぎりぎり、ルール内を混沌とさせることなく sed を使って文字列を加工することができましたけど、これが良い感じの方法なのかはいまいちわかりませんでした。

できれば shell コマンドを使わずに柔軟性の高い処理が書ければ良かったなとか、大域に変に準備をしなくてもローカル変数に直接 sed で値を入れられたらよかったなとか思いましたけど、それが可能なのかというところから調べきれませんでした。


ここまで書いていて、もしかして、適切な情報を渡すと目的の処理をしてくれる外部コマンドを Makefile のカレント辺りにあらかじめ作っておいて、普通に Makefile 内でそれを実行すれば良んじゃないかとも思ってきました。

それの方が上手いやりかたなのかさえ分かりませんけど、次に必要になったときにはそんなことも思い出して工夫してみたいと思います。