2012年2月12日日曜日

LinuxカーネルのMakefileを解析する その4

今回は、LinuxカーネルのMakefileで多用されている書き方について、いくつかピックアップ。



まず、FORCEから。

hoge: piyo FORCE
    ...

みたいな感じでよく使われています。


FORCE はトップのMakefileの最後の方で

PHONY += FORCE
FORCE:

# Declare the contents of the .PHONY variable as phony.  We keep that
# information in a variable so we can use it in if_changed and friends.
.PHONY: $(PHONY)


のように書いてあります。(他にも scripts/Makefile.build とかにも書いてあります。)

つまり、FORCEはPHONYターゲットです。
だから、

hoge: piyo FORCE
    ...

のようにFORCEを依存関係に連れている hogeは新しかろうが古かろうが、かならず ... の部分が実行されます。

だったら、上のは
.PHONY:  hoge
hoge: piyo
    ...

と書いても同じことじゃないの?ということになりますが、この場合はたぶん同じですね。。

おそらくなんですが、PHONYターゲットには、 
.PHONY: this_is_phony
のように使って、実在のオブジェクトなんだけれど、毎回ルールを実行してほしいときには
this_is_object: FORCE
を使っているんじゃないかと想像するんですが、

PHONY += firmware_install
firmware_install: FORCE
    @mkdir -p $(objtree)/firmware
    $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.fwinst obj=firmware __fw_install

のように、PHONYターゲットでありながら、 FORCEを依存関係に連れている部分もあるようです。

ただ、パターンルールと併用するときには .PHONY: は使えないです。

例えば、

%.o : %.c FORCE
    $(CC) -c -o $@ $<

.PHONY: FORCE
FORCE:


という書き方はできます(%.o は必ず再構築されます)が、


.PHONY: %.o
%.o : %.c
    $(CC) -c -o $@ $<


という書き方はできませんね。これが .PHONY::FORCE の違いといえば違いのような。




2つ目の話題は「何もしない構築ルール」について。

(例1)
$(CURDIR)/Makefile Makefile: ;

のような書き方。

同様に

(例2)
__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) \
     $(if $(KBUILD_MODULES),$(obj-m) $(modorder-target)) \
     $(subdir-ym) $(always)
    @:

みたいな書き方です。

たぶん、

hoge: piyo ;



hoge: piyo
    @:


はほとんど同じことです。構築ルールの部分は何もしない。
ただし、前者の場合l何もしなかった場合に、
「`hoge'に対して行うことはありません」といちいちmakeがメッセージを出して来るので、それが嫌な場合は後者の @:の方を使います。
ちなみに、「:」はシェルのビルトインコマンドで、「何もしないコマンド」です。
ただし、make がエコーを返すので、 @ をつけてエコーを抑制しています。

あえて、こういった書き方をする理由は2通りあって、一つはmakeのビルトインルールを上書きするため。(例1の場合)

もうひとつは、他の場所にはもう構築ルールはなくて、ほんとに何もしなくていいんだよ、とはっきりさせること(例2の場合)

例えば、単に

hoge: piyo

のように依存関係だけを書いてしまうと、ずっと離れた場所に


hoge: fuga
    ...

のようなhogeを構築するルールが記述されているかもしれない。
上記の2つはまとめられて、

hoge: piyo fuga
    ...

と同じことなのだが、1つのターゲットに対し依存関係は何行でも書くことができてしまう。
一方、ターゲット1つに対し、構築ルールは1つしか存在できない。

だから、
hoge: piyo
    @:

と明示的に「何もしない」というルールを書いておけば、他にもうルールはないことがはっきりする。
もしも遠く離れたところに、

hoge: fuga
    ...

みたいな記述が現れたしても、hogeを構築するルールが「@:」と「...」の2つもあるのはおかしいよ、ってmakeがwarningで教えてくれるからだ。

ちなみに、makeには1つのターゲットに対し、複数の構築ルールを持たせることのできる、「二重コロンルール」というのも存在するのだが、マニアックなので脱線するのはやめておこう。

0 件のコメント:

コメントを投稿