ある程度大きな規模のビルドシステムを作ろうとしたときに、設計思想としては、再帰的makeを採用するか、非再帰的makeを採用するかに分かれると思います。
(1)再帰的make
では、上位階層のMakefile は下位階層のMakefileを再帰的に呼び出し、さらにその下にディレクトリがあればさらに呼び出し、といった具合に、1つ下のMakefileを呼び出して行きます。
top
├── Makefile
├── hoge
│ └── Makefile
└── piyo
└── Makefile
といった感じの階層があったとします。
(余談ですが、上のようなディレクトリ構造の絵を書くには、"tree"コマンドが重宝します。)
再帰的makeでは、top/Makefile の書き方は例えば次のような感じになっているでしょう。
.PHONY: all hoge piyo
all : hoge piyo
...
hoge piyo:
$(MAKE) -C $@
hoge をmakeするには、 make -C hoge のようにhogeディレクトリへ移動して、makeを実行します。
$(MAKE) -C $@ は (cd $@; $(MAKE))と書いても同じことです。
(2)非再帰的make
では、
top/Makefile は
include hoge/Makefile piyo/Makefile
all:
...
みたいに、下位ディレクトリのMakefileをincludeするだけで、再帰的にmakeを呼び出すことはないです。
(hoge, piyo)/Makefile には各ディレクトリの構築すべきオブジェクトファイルのリストなどが書かれているだけです。
さて、LinuxカーネルのMakefileですが、分類としては(1)再帰的makeになります。
ただ、大きく違うのは再帰的にmakeを実行するときに、 -C オプションを使いません。
(前2回の解説で、-O オプションを処理する時とかに make -C を使ってたりしますが、ここは例外です。)
LinuxカーネルのMakefileは -f オプションを使って、再帰的にmakeを呼び出します。
上の例と比較しますと
hoge piyo:
$(MAKE) -f $@/Makefile
といった感じの呼び出しになります。
-C を使うのと、-f を使うのでは何が違うのかといいますと、、
-C hoge はcurrent directory の移動が起きます。
なので、hoge/Makefileを実行しているときは、top/hoge にいます。
一方、-f hoge/Makefile で呼び出した時は、最初から最後までtopディレクトリにいます。
include文や、オブジェクトの構築は、相対パスで記述する限りは、current working directory が起点になるので、今どこのディレクトリにいるのかを理解しておくことは大事です。
Linuxは(-Oを処理するなどの一部例外を除き)、makeを最初に実行したディレクトリから移動しません。
なお、Linuxカーネルのmakeでは再帰的makeでよく見る「〜に入ります、〜から出ます」というメッセージが出ません。
これはMakefileの最初に
MAKEFLAGS += --no-print-directory
が書いてあるからです。
が書いてあるからです。
解析のときはこの部分を外してやると、なんども再帰的にmakeを呼び出していることがわかります。
0 件のコメント:
コメントを投稿