man make を読むと、
-C dir
makefile を読み込むなどの動作の前に、ディレクトリ dir に移動する。(中略) このオプションは通常、make を再帰的に呼び出すときに使われる。
と書いてあります。
ほとんどの場面で 「make -C dir」は「cd dir; make」と同じと考えていいと思うが、
わずかに挙動が違う部分があることに最近気づいた。
実験のため、次のような /home/foo/Makefile, /home/foo/bar/Makefile
という2つの Makefile を用意。
/home/foo/Makefileの内容:
all:
@ echo CURDIR = $(CURDIR)
@ echo PWD = $(PWD)
@ cd bar; $(MAKE)
/home/foo/bar/Makefileの内容:
all:
@ echo CURDIR = $(CURDIR)
@ echo PWD = $(PWD)
/home/foo にて make を実行してみると以下のように表示された。
CURDIR = /home/foo
PWD = /home/foo
make[1]: ディレクトリ `/home/foo/bar' に入ります
CURDIR = /home/foo/bar
PWD = /home/foo/bar
make[1]: ディレクトリ `/home/foo/bar' から出ます
さて、 cd bar; $(MAKE) の部分を $(MAKE) -C bar と書き変えるとどうだろう?
/home/foo/Makefileの内容:
all:
@ echo CURDIR = $(CURDIR)
@ echo PWD = $(PWD)
@ $(MAKE) -c bar ← 変更する
/home/foo/bar/Makefileの内容:
all:
@ echo CURDIR = $(CURDIR)
@ echo PWD = $(PWD)
実行結果は以下のようになった。
CURDIR = /home/foo
PWD = /home/foo
make[1]: ディレクトリ `/home/foo/bar' に入ります
CURDIR = /home/foo/bar
PWD = /home/foo ← 注目!!!
make[1]: ディレクトリ `/home/foo/bar' から出ます
/home/foo/bar/Makefile における $(PWD) の値が変わった。
からくりはこうだ。
CURDIR は make が提供する変数で、現在実行している make プロセスのカレントディレクトリを返す。
一方、PWD は環境変数であって、make 変数ではない。
「cd bar; make」で再帰的に make を呼び出した場合、
cd bar; の時点で PWD は /home/foo/bar に更新される。
一方、「make -C bar」で再帰的に make を呼び出した場合、
環境変数 PWD は /home/foo を指したまま、 /home/foo/bar/Makefile に引き継がれる。
このことから、make を実行しているカレントディレクトリを指す用途には、常に $(CURDIR) もしくは $(shell pwd) を使うべきだとわかる。
$(PWD) は使うべきでない。
上の例で明らかなように、上位階層の Makefile がどのように再帰的に呼び出しているかによって $(PWD) が返す値が変わってくるので、必ずしも期待通りに動かないからだ。
ちなみに、変数がどこからやってきているかは
$ make --print-data-base
と打ってみればわかる。
やってみると以下のように表示された。
# makefile 変数
CURDIR := /home/masahiro
(中略)
# 環境変数
PWD = /home/masahiro
PWD = /home/masahiro
さらにちなみにだが、上の例で /home/foo/bar/Makefile の $(PWD) の部分を $$PWD に書き変えるとまた違う結果になる。
make の構築ルールはサブシェル上で実行されることを知っている人は多いだろう。
echo PWD = $(PWD)
については、$(PWD) を make が展開した後にサブシェルに渡しているので、サブシェルは
echo PWD = /home/foo
を実行している。一方、
echo PWD = $$PWD
については、make が $$ を $ に変換してサブシェルに渡すので、サブシェルは
echo PWD = $PWD
を実行することになる。$PWD はサブシェルによって /home/foo/bar へと展開される。
0 件のコメント:
コメントを投稿