条件付き展開を行う関数

前回はファイルの操作に関する関数を紹介した。今回は、関数としてはちょっと風変わりな「条件付き展開」を行う関数を取り上げる。制御構文としてのキーワードと似たワードが使われているので混乱しやすい部分だ。ここを整理しておこう。

GNU makeでは、次の3つの関数が条件付きの展開を行う関数となっている。

関数 シンタックス
if $(if 条件,条件が真の場合の式,条件が偽の場合の式)
or $(or 条件1,条件2,条件3...)
and $(and 条件1,条件2,条件3...)

それぞれ意味は次の通りだ。

関数 内容
if 条件を評価し、その結果が空ではない文字列だった場合には真、空の文字列だった場合には偽とする。真だった場合には真の式を評価し、その結果をif関数の評価とする。偽だった場合には偽の式を評価し、その結果をif関数の評価とする。偽だった場合でも、偽の式がなければ何も評価されない。真の式と偽の式はどちらか一方しか評価されない点に注意
or 条件を順番に評価し、空ではない文字列が展開されたら、それをor関数の評価とする。条件を最後まで評価して全てが空文字列あった場合、or関数の評価結果も空の文字列となる
and 条件を順番に評価し、空の文字列が展開されたら、その時点でand関数を評価を空文字列とする。全てが空ではない文字列に展開された場合、最後の条件の評価結果がand関数の評価となる

「if」という関数はMakefileにおいてフローを制御するif系の条件式に似ているが、まったくの別物だ。if関数はフローそのものを変えることはできない。「展開する対象を切り替えられる」というのがif関数の機能だ。

if関数、or関数、and関数については、説明を読んだだけではよくわからないのではないかと思う。これらの関数については、実際にMakefileを作成して動作を追っていく方が理解が早い。

if関数

if関数の動作を調べるために次のようなMakefileを用意した。

v1="value1"
v2="value2"
v3="value3"
e=

all:    list-values test1 test2 test3 test4 test5

list-values:
    @echo v1='"'$(v1)'"'
    @echo v2='"'$(v2)'"'
    @echo v3='"'$(v3)'"'
    @echo e=
    @echo 

test1:
    @echo '$$(if $$(v1),"真","偽")'
    @echo ' -> '$(if $(v1),"真","偽")
    @echo 

test2:
    @echo '$$(if $$(e),"真","偽")'
    @echo ' -> '$(if $(e),"真","偽")
    @echo 

test3:
    @echo '$$(if $$(e),"真")'
    @echo ' -> '$(if $(e),"真")
    @echo 

test4:
    @echo '$$(if $$(v1),$$(v2),$$(v3))'
    @echo ' -> '$(if $(v1),$(v2),$(v3))
    @echo 

test5:
    @echo '$$(if $$(e),$$(v2),$$(v3))'
    @echo ' -> '$(if $(e),$(v2),$(v3))
    @echo 

実行すると次のようになる。

% make
v1="value1"
v2="value2"
v3="value3"
e=

$(if $(v1),"真","偽")
        -> 真

$(if $(e),"真","偽")
        -> 偽

$(if $(e),"真")
        ->

$(if $(v1),$(v2),$(v3))
        -> value2

$(if $(e),$(v2),$(v3))
        -> value3

% 
  • 実行結果

    実行結果

それぞれ動きを追っていこう。まず、以下がif関数の基本的な使い方となる。

$(if $(v1),"真","偽")

if関数は、第1引数が空文字列であるかどうかで挙動を変える。第1引数が空文字列でなければ第2引数を評価し、その結果をif関数の結果とする。第1引数が空文字列であれば第3引数を評価し、その結果をif関数の結果とする。つまり、第1引数が空文字列であるかどうかによって評価する対象を変える(展開する変数を変える)のだ。この挙動は、if制御構文に似ており、if関数という名前になるのも納得である。

先ほどの例だと、$(v1)には文字列が代入されているので真となり、第2引数がif関数に置き換わる。

次は第1引数を空文字列にした場合だ。

$(if $(e),"真","偽")

つまり、こちらは第1引数が空文字列なので第3引数が評価されif関数と置き換わる。if的に表現するなら、変数が空文字列ではないならば「真」、空文字列であれば「偽」ということになる。

第2引数までしか書いてない場合、第1引数が空文字列だった場合(偽だった場合)、if関数は何も行わない。

$(if $(e),"真")

ここまでは第2引数と第3引数に文字列を書いてあるが、次のように変数を書いておくこともできる。

$(if $(v1),$(v2),$(v3))

第2引数や第3引数が変数であれば、変数が展開された結果がif関数に置き換わる。これがif関数の動きだ。変数が設定されているかどうかで展開する対象を変えることができる。デフォルト値の設定などに利用することができるわけだ。