17 July 2013

GNU make での話。

makefile のコマンド行は単純に、上から1行ずつ順番に実行されるものと思っていた。

例えば、次のような makefile を作成。

all:
    echo foo > a
    cat a

echo コマンドをファイルにリダイレクトし、すぐさま cat で読み出すという単純なものです。試しに実行してみます。

$ make
echo foo > a
cat a
foo

予想通りの結果。

では、 makefile をちょっとだけ変えて、

all:
    echo foo > a
    echo $(shell cat a)

としてみる。同じ結果になると思いきや、、

$ rm -f a
$ make
cat: a: そのようなファイルやディレクトリはありません
echo foo > a
echo 

なんと、動かないではないか!

echo foo > a よりも cat a が先に実行されてしまっているようです。

この実験結果を見ると、上から1行ずつ関数を展開しつつ実行するのではなく、 すべての関数を展開してしまってからコマンド行を上から順に実行するように見えます。

しかも、関数を展開する順番は、出現順でもないらしい。

例えば、

all:
    : $(shell touch a1)
    touch a2
    echo $(shell ls a*)

という makefile を実行すると

$ rm a*
$ make 
: 
touch a2
echo a1
a1

となった。

$(shell touch a1)$(shell ls a*) の順に行われているようです。

一方、

all:
    : $(shell touch a1)
    touch a2
    echo $(wildcard a*)

という makefile を実行すると

$ rm a*
$ make 
: 
touch a2
echo 

となった。

今度は $(wildcard a*)$(shell touch a1) の順に行われたようです。



blog comments powered by Disqus