[ < ] [ > ]   [ << ] [] [ >> ]         [冒頭] [目次] [見出し] [ ? ]

7. Makefileの条件文

makefileの条件文は、変数の値に依存し、値によってそれに従うか無視されます。 また条件文はある変数とほかの変数の値、あるいは定数の文字列との比較を 行ないます。さらに、条件文はmakeがmakefileのなかで何を監視しているかを コントロールするため、実行時のシェルコマンドでコントロールされることは ありません


[ < ] [ > ]   [ << ] [] [ >> ]         [冒頭] [目次] [見出し] [ ? ]

7.1 条件文の例

以下の例では、条件文がmakeに対して、CC変数が‘gcc’ の場合に、あるライブラリのセットを使用し、そうでない場合には 異なるライブラリを使用するように指示しています。2つのコマンド行のうち どちらかがルールのためのコマンドとして使われるかがコントロール されています。結果的に、‘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

条件文は3つのディレクティブを使います。それらは、ifeqelse、とendifです。

条件文はifreqディレクティブで始まり、条件を指定します。2つの引数が あり、それらはカンマで区切られ、括弧で括られています。変数の代用は両者の 引数で行なわれ、比較されます。2つの引数がマッチしている場合にはifreqに 続くmakefileの行はそれに従い、そうでない場合は無視されます。

まえの条件が失敗した場合、elseディレクティブはそのあとに続く行を 無視させます。上記の例では、1番目の条件が合わない場合にはつねに2番目の リンクコマンドが実行されることを示しています。条件文で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)

変数割り当てのもう1つの条件文と変数の無条件使用によって同等の結果が 得られます。

 
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)

[ < ] [ > ]   [ << ] [] [ >> ]         [冒頭] [目次] [見出し] [ ? ]

7.2 条件文のシンタックス

elseのない簡単な条件文のシンタックスは以下のようになります。

 
conditional-directive
text-if-true
endif

text-if-trueはどこにあってもよいのですが、条件が真の場合にmakefileの 一部とみなされます。条件が偽である場合はテキストがかわりに用いられることは ありません。

複雑な条件文のシンタックスは以下のようになります。

 
conditional-directive
text-if-true
else
text-if-false
endif

条件が真の場合、text-if-trueが使用され、そうでない場合は text-if-falseがかわりに使用されます。text-if-falseはテキストの どの行に置いてもかまいません。

conditional-directiveのシンタックスは、条件文が単純だろうが 複雑だろうが同じです。異なる条件をテストするための4つの異なる ディレクティブがあり、これを一覧にすると以下のようになります。

ifeq (arg1, arg2)
ifeq 'arg1' 'arg2'
ifeq "arg1" "arg2"
ifeq "arg1" 'arg2'
ifeq 'arg1' "arg2"

arg1arg2におけるすべての変数参照を展開し、比較します。それらが 同一である場合には、text-if-trueが有効となり、そうでない場合には text-if-falseが有効となります。

変数が空でない値を持つかどうかをテストしたい場合があります。その値が変数や ファンクションの複雑な展開によりもたらされ、空とみなした展開が実際には スペース文字を含み空でないように見える場合があります。しかしながら その場合は、stripファンクション (see section 文字列の代用と分析のファンクション.)を 使用して空白を空でない値と解釈するのを回避することができます。たとえば、 以下のようになります。

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

$(foo)の展開が空白文字を含む場合でさえ、text-if-emptyを 評価します。

ifneq (arg1, arg2)
ifneq 'arg1' 'arg2'
ifneq "arg1" "arg2"
ifneq "arg1" 'arg2'
ifneq 'arg1' "arg2"

arg1arg2におけるすべての変数参照を展開し、比較します。それらが 異なる場合には、text-if-trueが有効となり、そうでない場合には text-if-falseが有効となります。

ifdef variable-name

変数variable-nameが空でない値を持つ場合、text-if-trueが 有効となり、そうでない場合は、text-if-falseが有効となります。以前に 定義されていない変数は空の値を持つことになります。

注意しなければならないのは、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 variable-name

変数variable-nameが空の値を持つ場合、text-if-trueが有効となり、 そうでない場合は、text-if-falseが有効となります。

複数のスペースは条件文のディレクティブの行の始めに置かれても無視されるだけ ですが、タブは許されません。(もしタブで行が始まる場合には、ルールに対する コマンドとみなされます。)これとは別ですが、ディレクティブ名あるいは引数を 除けば、複数のスペースやタブはどこに置かれても何の効果もありません。 ‘#’で始まるコメントは行の終わりに置くことができます。

条件文のなかで役割を持つほかの2つのディレクティブは、elseendifです。それぞれのディレクティブは引数を持たず、1語で書かれます。 複数のスペースを行の先頭に置くことができますが、それらは無視されます。 終わりはスペースかタブです。‘#’で始まるコメントは行の終わりに 置くことができます。

条件文はmakeが使用するmakefileの行に影響を与えます。条件が真で あるときmaketext-if-trueの行をmakefileの一部として読みます。 条件が偽であるときはmakeはその行を完全に無視します。したがって、 ルールのようなmakefileの文法的な単位は条件文の最初から最後まで 安全に分離されるのです。

makefileを読み込むときにmakeは条件文を評価します。したがって、 自動変数を条件文のなかに使用することはできません。なぜならば、コマンドが 実行されるまでそれらは定義されないからです (see section 自動変数.)。

混乱を避ける意味で、1つのmakefileで条件文を開始し、別のmakefileで 終了するといった使い方は許可されません。しかし、条件文にinclude ディレクティブを記述することができ、インクルードファイルのなかでその条件文を 終了させることをしないようにさせています。


[ < ] [ > ]   [ << ] [] [ >> ]         [冒頭] [目次] [見出し] [ ? ]

7.3 フラグテストの条件文

findstringファンクション (see section 文字列の代用と分析のファンクション.) とともに変数MAKEFLAGSを使用して‘-t’のようなmakeコマンドの フラグをテストする条件文を記述することができます。この方法は、ファイルを 最新であるようにするのに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’フラグの使用にもかかわらず実行されるようにします。 See section makeの再帰的用法.。


[ << ] [ >> ]           [冒頭] [目次] [見出し] [ ? ]

この文書は新堂 安孝によって2009年9月22日texi2html 1.82を用いて生成されました。