条件分岐(conditional)を使えば変数の値によってmakefileの一部を従うか無視するか分岐させることができます。条件分岐ではある変数を別の変数と比較するか、変数を定数文字列と比較させかします。条件分岐ではmake
がmakefile中に実際に「見る部分」を制御するため、実行時のシェルコマンドを制御するのに条件分岐は使えません。
次の条件分岐例では、CC
変数が`gcc'の時はmake
にあるライブラリのセットを使い、そうでない場合は別のライブラリセットを使います。この動作はルールに変更を与えるものと変更を与えないものの二つのうちどちらのコマンドを使うかで制御します。つまり、`CC=gcc'をmake
の引数に渡す事がどのコンパイラを使うかという事だけでなくどのライブラリをリンクするかという事をも変更することになります。
libs_for_gcc = -lgnu normal_libs = foo: $(objects) ifeq ($(CC),gcc) $(CC) -o foo $(objects) $(libs_for_gcc) else $(CC) -o foo $(objects) $(normal_libs) endif
この条件分岐では三つのディレクティヴを使っています。一つ目がifeq
、二つ目がelse
、三つ目がendif
です。
ifeq
ディレクティヴは条件分岐を開始し、条件を指定します。このディレクティヴは二つの引数を持ち、括弧で括った中でコンマで分けて記述します。変数代入はどちらの引数でも有効であり比較対象にできます。makefileのifeq
以降の行は二つの引数が一致した場合に従いますが、そうでなければ無視されます。
else
ディレクティヴ以降の行は条件が一致しなかった場合に従わせるものです。上の例では第一のリンクコマンドが選択されなければ二つ目のものを選択するという意味になります。else
を条件分岐に使うかどうかは自由です。
endif
ディレクティヴは条件分岐を終了します。あらゆる条件分岐がendif
で終わらなければなりません。それ以降は条件分岐でないmakefileの本文が続きます。
この例で示したように条件分岐は文章レベルで動作します。つまり条件分岐の各行はmakefileの一部として扱うか、無視するかを条件によって分岐させます。このため、ルールのような大きな文法上の構成単位を条件分岐の開始や終了に交差させることもできます。
CC
という変数が`gcc'という値を持っていた時、上の例はこういう効果になります。
foo: $(objects) $(CC) -o foo $(objects) $(libs_for_gcc)
CC
という変数が別の値を持っていた場合は常に次のような効果になります。
foo: $(objects) $(CC) -o foo $(objects) $(normal_libs)
変数式を条件分岐にしたもう一つの方法でも同じ結果が得られ、この場合はある変数を無条件に使います。
libs_for_gcc = -lgnu normal_libs = ifeq ($(CC),gcc) libs=$(libs_for_gcc) else libs=$(normal_libs) endif foo: $(objects) $(CC) -o foo $(objects) $(libs)
次のような単純な条件分岐ではelse
を使いません。
条件分岐ディレクティヴ 真の場合の内容 endif
真の場合の内容はどんな内容であってもよく、条件が真(true)であればその部分はmakefileの一部として読み込みます。条件が偽(false)であれば、代わりに読み込む内容がない事になります。
複雑な条件分岐構文は次のようなものになります。
条件分岐ディレクティヴ 真の場合の内容 else 偽の場合の内容 endif
条件が真の場合、真の場合の内容を使い、そうでなければ、偽の場合の内容を代わりに使います。偽の場合の内容は何行になっても構いません。
条件分岐ディレクティヴの構文は単純なほうでも複雑なほうでも同じです。それぞれ違う条件を調べるため4つのディレクティヴが存在します。これがその表です。
ifeq (arg1, arg2)
ifeq 'arg1' 'arg2'
ifeq "arg1" "arg2"
ifeq "arg1" 'arg2'
ifeq 'arg1' "arg2"
strip
関数(文字列を代入・分析する関数の項を参照)を使えば空白を空っぽではない値と解釈させないようにできます。例えば、
ifeq ($(strip $(foo)),) text-if-empty endif…とすると、
$(foo)
が空白文字を含んでいても真の場合の内容は評価されます。
ifneq (arg1, arg2)
ifneq 'arg1' 'arg2'
ifneq "arg1" "arg2"
ifneq "arg1" 'arg2'
ifneq 'arg1' "arg2"
ifdef 変数名
ifdef
は変数に値があるかを調べるだけである、という事です。値が非空かどうかを調べるのに変数を展開しません。ifdef
を使った判断ではfoo =
のような定義以外のすべての定義で真を返します。空っぽの値を調べるのにはifeq ($(foo),)
を使って下さい。例えば、
bar = foo = $(bar) ifdef foo frobozz = yes else frobozz = no endif…とすると、`frobozz'に`yes'をセットします。一方、
foo = ifdef foo frobozz = yes else frobozz = no endif…とすると、`frobozz'に`no'をセットします。
ifndef 変数名
条件分岐ディレクティヴ行の最初に余分な空白を加えてもよく、その空白は無視されますが、タブは付加してはいけません。(タブで始まる行はルールのコマンドとして扱われます。)この禁止事項を除けば、ディレクティヴ名の中と引数の中以外ならどこでも、いくら空白やタブをつけても動作に影響することはありません。`#'で始まるコメントが行末についても構いません。
else
とendif
という条件分岐の残り二つのディレクティヴはどちらも引数を持たず、一つの単語だけで記述されます。前後の余分な空白と行末のタブは無視されるのでつけても構いません。`#'で始まるコメントが行末についても構いません。
条件分岐はmake
がどちらの本文を使うかを左右します。条件が真ならmake
は真の場合の内容をmakefileの一部として読み込み、偽ならmake
はその部分を完全に無視します。そのため、ルールのような構文上の構成単位が条件分岐の開始や終了にかかって分けられていても問題なく動作します。
make
はmakefile読み込み時に条件分岐を評価します。自動変数はコマンド実行まで定義されないので、結果として条件分岐では自動変数を調べることができません(自動変数の項を参照)。
耐え難い混乱を防ぐため、条件分岐の開始と終了を別々のmakefileで行うことはできないようにしていますが、インクルードファイル中で条件分岐を終わらせようとしないのなら条件分岐中にinclude
を使うことが可能です。
`-t'のようなmake
コマンドのフラグを条件分岐で調べさせるには、MAKEFLAGS
という変数と一緒にfindstring
関数を使って下さい(文字列を代入・分析する関数の項を参照)。これはtouch
ではファイルを更新させるのに不十分な時に役立ちます。
findstring
関数はある文字列が別の文字列に含まれるかを判断します。`-t'フラグを調べたいなら`t'を最初の文字列、MAKEFLAGS
の値をもう一つの文字列として使います。
例えば、ここにあるのは`ranlib -t'を使ってちゃんとアーカイブファイルを更新したというしるしをつけさせる方法です。
archive.a: ... ifneq (,$(findstring t,$(MAKEFLAGS))) +touch archive.a +ranlib -t archive.a else ranlib archive.a endif
先頭についている`+'は`-t'フラグが指定されていてもコマンド行が実行されるための「再帰」のしるしです。
これについてはmake
の再帰利用の項を見てください。