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の使い方だ。