make-default - Makefile 内でデフォルトのターゲットを任意に変更する
目的
コマンドラインでターゲットを指定せずにmakeを実行したとき、ビルドされるのはMakefileの最初に定義されたターゲットになる。
この「デフォルトターゲット」を、Makefile内で任意のものに変更したい。
背景と動機
大きなソースツリーでは、システム全体で使うMakefileを個々のディレクトリのMakeilfeがincludeして使う、という構成になっている場合が多い。
たとえば以下のような感じで、個々のMakefileがmk/env.mkをincludeして、変数定義やビルド方法などを共通化している。
+ TOP + mk + env.mk <----+--+ + src | | 共通のファイルをinclude + subdir1 | | + Makefile ---+ | + subdir2 | + Makefile ------+
このとき、共通のMakefileが多数あってinclude関係が複雑になっていると、個々のMakefile内の記述の自由度が少なく、色々と困る場合がある。
今、includeの都合で最初に定義できないターゲットを、makeのデフォルトターゲットにしたくて困っているとしよう。
マニュアルで該当機能を発見
3.6 Other Special Variables
GNU make also supports other special variables....
.DEFAULT_GOAL
Sets the default goal to be used if no targets were specified on the command line....
とあり、.DEFAULT_GOALという変数を設定すれば、デフォルトターゲットを任意に変更できるようだ。
テスト用のファイル
以下のファイルで、.DEFAULT_GOAL の動作テストをする。
- default-target.mk
- https://sssvn.jp/svn/spikelet/make/default-target.mk
.DEFAULT_GOAL := 2nd 1st: @echo $@ 2nd: @echo $@
以下のようになれば、目的達成。
% make -f default-target.mk 2nd
makeのバージョンにより動作がことなる
手元の環境*1ではうまくいかない。
% make -f default-target.mk 1st % make -v | head -1 GNU Make 3.80
GNU makeのマニュアルは3.81を対象に書かれているので、3.81でためしてみると、今度は成功。
% make -f default-target.mk 2nd % make -v | head -1 GNU Make 3.81
ソースを解析する
GNU make 3.81 では、以下のような処理をしている。
- デフォルトゴールについて、2つの変数がある
- default_goal_name: .DEFAULT_GOAL_NAME の値
- default_goal_file: 最初に定義されたターゲット
- コマンドラインでターゲット指定無しの場合
- default_goal_name が定義済みなら、これをビルドする
- (そうでなければ)default_goal_file をビルドする
main.c: main() にて、 { struct variable *v = define_variable (".DEFAULT_GOAL", 13, "", o_file, 0); default_goal_name = &v->value; } // グローバル変数 "default_goal_name" の領域を確保 // その他にも、.DEFAULT_GOALが存在しない場合の処理がある read.c: eval() にて、 if (**default_goal_name == '\0' && set_default) { .... if (!reject) { define_variable_global (".DEFAULT_GOAL", 13, t->name, o_file, 0, NILF); break; } .... } // デフォルトターゲットが指定されていない場合は、依存リストで先頭にある(有効な)ものをターゲットを設定する
一方 GNU make 3.80 では、default_goal_name に関する処理が無い。ターゲット未指定時はdefault_goal_nameのみを処理する。
つまり、.DEFAULT_GOAL 変数での指定は、GNU make 3.81 で導入されたもの。
念のためChangeLogを確認
GNU make 3.81 の ChangeLog で以下を発見:
2005-05-03 Paul D. Smith <psmith@gnu.org> Rename .DEFAULT_TARGET to .DEFAULT_GOAL: in GNU make terminology the targets which are to ultimately be made are called "goals"; see the GNU make manual. Also, MAKECMDGOALS, etc. 2005-03-09 Boris Kolpackov <boris@kolpackov.net> * main.c (main): Use o_file instead of o_default when defining the .DEFAULT_TARGET special variable. * read.c (eval): Use define_variable_global() instead of define_variable() when setting new value for the .DEFAULT_TARGET special variable. Fixes Savannah bug #12266. 2005-02-28 Boris Kolpackov <boris@kolpackov.net> Implementation of the .DEFAULT_TARGET special variable.
3.80が2002-10-03、3.81が2006-04-01リリースなので、たしかに.DEFAULT_GOAL機能は3.81以降でしか使えないことを確認した。
*1:Red Hat Enterprise Linux WS release 4