There is the original file(in English) here.
最初,,,最後のページ,目次 に移動.

Makefileの条件分岐部分

 条件分岐(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"
 arg1arg2のすべての変数参照を展開して比較します。もし二つが等しければ真の場合の内容が有効になり、そうでなければ偽の場合の内容があればこれが有効になります。 変数の値が空っぽではないかを調べたい場合がしばしばあります。変数や関数が複雑に拡張された結果の値では空っぽと思っていた拡張結果が実は空白文字を含んでいるために空白と扱われなかったりします。この場合はstrip関数(文字列を代入・分析する関数の項を参照)を使えば空白を空っぽではない値と解釈させないようにできます。例えば、

ifeq ($(strip $(foo)),)
text-if-empty
endif

…とすると、$(foo)が空白文字を含んでいても真の場合の内容は評価されます。
ifneq (arg1, arg2)
ifneq 'arg1' 'arg2'
ifneq "arg1" "arg2"
ifneq "arg1" 'arg2'
ifneq 'arg1' "arg2"
 arg1arg2のすべての変数参照を展開して比較します。二つが等しくなければ真の場合の内容が有効になり、そうでない場合は偽の場合の内容があればそれが有効になります。
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 変数名
 変数名という変数が空っぽの値であれば、真の場合の内容が有効になり、そうでない場合は偽の場合の内容があればそれば有効になります。

 条件分岐ディレクティヴ行の最初に余分な空白を加えてもよく、その空白は無視されますが、タブは付加してはいけません。(タブで始まる行はルールのコマンドとして扱われます。)この禁止事項を除けば、ディレクティヴ名の中と引数の中以外ならどこでも、いくら空白やタブをつけても動作に影響することはありません。`#'で始まるコメントが行末についても構いません。

 elseendifという条件分岐の残り二つのディレクティヴはどちらも引数を持たず、一つの単語だけで記述されます。前後の余分な空白と行末のタブは無視されるのでつけても構いません。`#'で始まるコメントが行末についても構いません。

 条件分岐は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の再帰利用の項を見てください。


最初,,,最後のページ,目次 に移動.