gnumakeで「このファイル」__FILE__を実装する

多くのプログラミング言語が「このファイル」を変数__FILE__で教えてくれる。__FILE__を参照したコードを含むソースファイルのパスが返ってくる。この便利な機能はgnumakeにない。しかし、MAKEFILE_LISTという変数から現ファイルを推測できる。

config.mkに

THIS_FILE=$(filter %config.mk,$(MAKEFILE_LIST))                                                                    

とするとTHIS_FILEがconfig.mkのパスを値として持つことになる。ただし、「config.mk」が唯一この名をもつMakefileであることを前提とする。

このハックを発見していい気になっていたら、JGCがすでに丁寧に解説しているのを発見:
http://blog.jgc.org/2007/01/what-makefile-am-i-in.html

どうやらMAKEFILE_LISTの最後の値が現makefileになるらしい。つまり上記のfilterが無用ってことになる。さらにコメントにgmake 3.81以降だとlastwordが使える、と改善案が。つまりこれが、__FILE__として使えることになる:

$(lastword $(MAKEFILE_LIST))                                                                                       


プロジェクトのルートディレクトリのconfig.mkやらinclude.mkにこれを入れておけばどこからincludeしても常にプロジェクトルートを参照できることになる。
PROJECT_ROOT=$(abspath $(dir $(lastword $(MAKEFILE_LIST))))


これにより次のようgnumakeによるプロジェクト構成が可能になる:

  • 各サブディレクトリはconfig.mkをincludeする
  • config.mkは上記の方法でPROJECT_ROOTをexportする
  • サブディレクトリのMakefileはPROJECT_ROOT下のリソースを参照することができる。
    • virtualenvとか: $(PROJECT_ROOT)/virtualenv/bin/python foo.py
    • binに入れてあるコマンドとか: $(PROJECT_ROOT)/bin/my-build-util.py