子make というか、サブmake というか、入れ子で複数の target を make するのに、Makfile 中で for で ループを回したいなぁと思ったら、色々はまりながらも試行錯誤したらうまく行ったので、その時のメモ。
; と && の違い
Makefile 中の for ループの各ステートメントを ; で結ぶと、失敗しても(戻り値が0でなくても)先へ進んでしまうようです:
***/make $ cat Makefile TARGETS := a b c hoge: @for target in $(TARGETS); do\ make aaa; \ make bbb; \ done make ccc bbb: echo "bbb" ccc: echo "ccc" ***/make $ make make[1]: ディレクトリ `/***/make' に入ります make[1]: *** ターゲット `aaa' を make するルールがありません. 中止. make[1]: ディレクトリ `/***/make' から出ます make[1]: ディレクトリ `/***/make' に入ります echo "bbb" bbb make[1]: ディレクトリ `/***/make' から出ます make[1]: ディレクトリ `/***/make' に入ります make[1]: *** ターゲット `aaa' を make するルールがありません. 中止. make[1]: ディレクトリ `/***/make' から出ます make[1]: ディレクトリ `/***/make' に入ります echo "bbb" bbb make[1]: ディレクトリ `/***/make' から出ます make[1]: ディレクトリ `/***/make' に入ります make[1]: *** ターゲット `aaa' を make するルールがありません. 中止. make[1]: ディレクトリ `/***/make' から出ます make[1]: ディレクトリ `/***/make' に入ります echo "bbb" bbb make[1]: ディレクトリ `/***/make' から出ます make ccc make[1]: ディレクトリ `/***/make' に入ります echo "ccc" ccc make[1]: ディレクトリ `/***/make' から出ます ***/make $
; の代わりに && を使うと、ステートメントが失敗(戻り値が 0 以外)したら、ループの先頭に戻ります。continue 相当って感じですかね:
***/make $ cat Makefile TARGETS := a b c hoge: @for target in $(TARGETS); do\ make aaa && \ make bbb; \ done make ccc bbb: echo "bbb" ccc: echo "ccc" ***/make $ make hoge make[1]: ディレクトリ `/***/make' に入ります make[1]: *** ターゲット `aaa' を make するルールがありません. 中止. make[1]: ディレクトリ `/***/ make' から出ます make[1]: ディレクトリ `/***/ make' に入ります make[1]: *** ターゲット `aaa' を make するルールがありません. 中止. make[1]: ディレクトリ `/***/ make' から出ます make[1]: ディレクトリ `/***/ make' に入ります make[1]: *** ターゲット `aaa' を make するルールがありません. 中止. make[1]: ディレクトリ `/***/ make' から出ます make: *** [hoge] エラー 2 ***/make $
***/make/for2 $ cat Makefile TARGETS := a b c hoge: @for target in $(TARGETS); do\ make aaa || exit 50; \ make bbb; \ done make ccc bbb: echo "bbb" ccc: echo "ccc" $ make make[1]: ディレクトリ `/***/make/for2' に入ります make[1]: *** ターゲット `aaa' を make するルールがありません. 中止. make[1]: ディレクトリ `/***/make/for2' から出ます make: *** [hoge] エラー 50 ***/make/for2 $
|| を使うと、直前の make が失敗したら || 以降を実行してくれます。そこで exit 50; としてるわけです。なお、50 にしたのは見た目がわかりやすいかなー位で、数値自体に意味はないス。
for ループの中でかっこ () も使いたい
make の中でかっこ()を使うと、cd とかの影響範囲を限定できます。
例えば、サブディレクトリ名を for ループで回して、各サブディレクトリに入って make とかしたいなーという場合には、こんな感じで書けます(このサンプルでは、サブディレクトリの Makefile は echo してるだけです):
***/make/for$ tree . ├── a │ └── Makefile ├── b │ └── Makefile ├── c │ └── Makefile └── Makefile 3 directories, 4 files ***/make/for$ cat Makefile TARGETS := a b c all: @for target in $(TARGETS); do \ ( \ cd $$target; \ make; \ ) \ done ***/make/for$ make make[1]: Entering directory `/***/make/for/a' echo "aaa" aaa make[1]: Leaving directory `/***/make/for/a' make[1]: Entering directory `/***/make/for/b' echo "bbb" bbb make[1]: Leaving directory `/***/make/for/b' make[1]: Entering directory `/***/make/for/c' echo "ccc" ccc make[1]: Leaving directory `/***/make/for/c' ***/make/for$
かっこ()内で cd すると、かっこを抜けた時にカレントディレクトリが元に戻ります。
そんな for ループも、失敗したらその時点で make 全体止まってほしいなぁと思って、上と同じように、こんな感じで書いてみました:
***/make/for3$ cat Makefile TARGETS := a b c hoge: @for target in $(TARGETS); do\ ( \ make aaa || exit 50; \ make bbb; \ ) \ done make ccc bbb: echo "bbb" ccc: echo "ccc" ***/make/for3$ make make[1]: ディレクトリ `/***/make/for3' に入ります make[1]: *** ターゲット `aaa' を make するルールがありません. 中止. make[1]: ディレクトリ `/***/make/for3' から出ます make[1]: ディレクトリ `/***/make/for3' に入ります make[1]: *** ターゲット `aaa' を make するルールがありません. 中止. make[1]: ディレクトリ `/***/make/for3' から出ます make[1]: ディレクトリ `/***/make/for3' に入ります make[1]: *** ターゲット `aaa' を make するルールがありません. 中止. make[1]: ディレクトリ `/***/make/for3' から出ます make: *** [hoge] エラー 50 ***/make/for3$
うーん、かっこ()をつけたら、また for ループが止まらなくなってしまいました。というわけで、かっこ()に対してもさらに || exit をつけたら、期待した通りの動きになりました:
***/make/for3$ cat Makefile TARGETS := a b c hoge: @for target in $(TARGETS); do\ ( \ make aaa || exit 50; \ make bbb; \ ) || exit 70; \ done make ccc bbb: echo "bbb" ccc: echo "ccc" ***/make/for3$ make make[1]: ディレクトリ `/***/make/for3' に入ります make[1]: *** ターゲット `aaa' を make するルールがありません. 中止. make[1]: ディレクトリ `/***/make/for3' から出ます make: *** [hoge] エラー 70 ***/make/for3$
例によって、exit の 50 とか 70 とかは深い意味なしです。