Makefileには条件分岐を行うためのディレクティブが用意されている。前回までに、その機能として「ifeq」と「ifneq」を取り上げた。こうした機能はレシピ以外の場所で使われることが多い。今回は、残りの条件分岐ディレクティブである「ifdef」と「ifndef」を取り上げる。条件分岐のディレクティブに関する説明は今回で完了だ。
条件分岐ディレクティブ「ifdef」と「ifndef」
GNU makeのMakefileで使える条件分岐ディレクティブは、これまでに紹介した「ifeq」と「ifneq」のほかに「ifdef」と「ifndef」がある。
ifdefとifndefも、よく使う条件分岐ディレクティブだ。この2つはそれぞれ真偽値が逆になるだけなので、まとめて覚えてしまうと良い。それぞれ次のような使い方をする。
◆条件分岐ifdefの使い方サンプル その1
ifdef 変数名
変数が存在する場合の処理
endif
◆条件分岐ifdefの使い方サンプル その2
ifdef 変数名
変数が存在する場合の処理
else
変数が存在しない場合の処理
endif
◆条件分岐ifdefの使い方サンプル その3
ifdef 変数名1
変数1が存在する場合の処理
else ifdef 変数名2
変数2が存在する場合の処理
else
それ以外のときの処理
endif
◆条件分岐ifndefの使い方サンプル その1
ifndef 変数名
変数が存在しない場合の処理
endif
◆条件分岐ifndefの使い方サンプル その2
ifndef 変数名
変数が存在しない場合の処理
else
変数が存在する場合の処理
endif
◆条件分岐ifndefの使い方サンプル その3
ifndef 変数名1
変数1が存在しない場合の処理
else ifndef 変数名2
変数2が存在しない場合の処理
else
それ以外のときの処理
endif
ifdefはその後に指定した変数が空以外の値を持っている場合に「真」となり、その後に書いてある式が評価される。変数が空だったり定義されていなかったりする場合には「偽」となり、その後に書いてある式は評価されない。「else」でつなげてある場合には、elseの後に記載されている式が評価される。
ifndefの動作は、ifdefの動作の逆だ。ifndefの後に指定した変数が空以外の値を持っている場合には「偽」となり、それ以外の場合に「真」となる。ifdefと真逆の動きをする。ifdefだけでも記述できるのだが、ifndefで書いた方が意図がよく伝わるシーンも多い。この2つはそれぞれに適切に使い分けていこう。
条件分岐ディレクティブ ifdefの実行サンプル
まず、条件分岐ディレクティブifdefを使ってみよう。ここでは次のようなMakefileを用意した。
ifdef DEFAULT_EMAIL_TO
email= $(DEFAULT_EMAIL_TO)
else ifdef DEFAULT_EMAIL_CC
email= $(DEFAULT_EMAIL_CC)
else
email= user@example.com
endif
test:
@echo -n "Email to $(email) ? [Y/n] = "; \
read ans; \
case "$$ans" in \
[Yy]) \
echo "I will send email to $(email)."; \
;; \
*) \
echo "done."; \
;; \
esac
Makefileに記載されているDEFAULT_EMAIL_TOやDEFAULT_EMAIL_CCは環境変数を想定している。環境変数でデフォルトのメールアドレスが設定されていればそれを使い、設定されていなければMakefileに直接記載されている「user@example.com」というメールアドレスを使うといった内容になっている。
実行すると次のようになる。
% make
Email to user@example.com ? [Y/n] = y
I will send email to user@example.com.
% env DEFAULT_EMAIL_TO=a@example.com make
Email to a@example.com ? [Y/n] = n
done.
% env DEFAULT_EMAIL_CC=b@example.com make
Email to b@example.com ? [Y/n] = y
I will send email to b@example.com.
%
環境変数はenvで指定すればそのときの実行に限り変更することができるので、実際に変更しながら動作の確認を行っている。想定した通りに動作していることがわかる。これが機能としてのifdefの使い方だ。
条件分岐ディレクティブ - ifndefの実行サンプル
今度は条件分岐ディレクティブifndefを使ってみよう。使い方としてはこちらの方がわかりやすいかもしれない。ここでは次のようなMakefileを用意した。
ifndef DEFAULT_EMAIL_TO
DEFAULT_EMAIL_TO=user@example.com
endif
ifndef email
email= $(DEFAULT_EMAIL_TO)
endif
test:
@echo -n "Email to $(email) ? [Y/n] = "; \
read ans; \
case "$$ans" in \
[Yy]) \
echo "I will send email to $(email)."; \
;; \
*) \
echo "done."; \
;; \
esac
このMakefileでは、emailが指定されていなければ「DEFAULT_EMAIL_TO」を使うこと、さらにDEFAULT_EMAIL_TOが設定されていなければuser@example.comを使用する、といった内容になっている。ifndefで変数が定義されていない場合の動作になるので、こういった書き方をしておくと何をしたいのかがクリアになってわかりやすい。
実行すると次のようになる。
% make
Email to user@example.com ? [Y/n] = y
I will send email to user@example.com.
% make email=a@example.com
Email to a@example.com ? [Y/n] = n
done.
% make email=b@example.com
Email to b@example.com ? [Y/n] = y
I will send email to b@example.com.
%
「make email=foo@bar」のように引数でemailを指定すればそれが使われるし、指定されていなければDEFAULT_EMAIL_TOが使われている。これも想定した通りに動作していることがわかる。
条件分岐ディレクティブifdefとifndefはどこで使うべきか
条件分岐ディレクティブは、レシピでもそれ以外の場所でも使うことができる。なかなか強力な機能なのだが、利用は必要最小限に抑えた方がよいと思う。条件分岐ディレクティブは、多用するとMakefileが読みにくくなるし、内容を理解しにくくなるからだ。
また、レシピ部分はシェルの機能を使うことで変数の有無に対する動作を起こすことができる。レシピ部分はシェルの機能を使い、それ以外のところでMakefileの条件分岐ディレクティブを使う、といったように分けて使うのがわかりやすい。この辺りはifeqおよびifneqとも同じだ。
これまでに、GNU makeのMakefileで使用できる主だった機能は大体取り上げてきた。もちろん、もっと細かい機能や、高度な機能、高速に処理するためのテクニックなど、取り上げようと思えばいくらでもあるのだが、まずはここまでに紹介した機能を抑えておけば十分だろう。次回以降、まだいくつか紹介するが、それでMakefileで使う機能に関してはいったん切り上げようと思う。
本連載の読者は、すでにかなり深いところまでGNU makeのMakefileを理解し、書けるようになっているはずだ。Makefileは、作業をシンプルにする上で役立つ。今後は、この機能を使って楽に仕事する方法を探っていこう。