TL; DR:error
関数を使用:
ifndef MY_FLAG
$(error MY_FLAG is not set)
endif
行はインデントしないでください。より正確には、これらの行の前にタブがあってはなりません。
一般的なソリューション
多くの変数をテストする場合は、そのための補助関数を定義する価値があります。
# Check that given variables are set and all have non-empty values,
# die with an error otherwise.
#
# Params:
# 1. Variable name(s) to test.
# 2. (optional) Error message to print.
check_defined = \
$(strip $(foreach 1,$1, \
$(call __check_defined,$1,$(strip $(value 2)))))
__check_defined = \
$(if $(value $1),, \
$(error Undefined $1$(if $2, ($2))))
そしてここにそれを使用する方法があります:
$(call check_defined, MY_FLAG)
$(call check_defined, OUT_DIR, build directory)
$(call check_defined, BIN_DIR, where to put binary artifacts)
$(call check_defined, \
LIB_INCLUDE_DIR \
LIB_SOURCE_DIR, \
library path)
これは次のようなエラーを出力します:
Makefile:17: *** Undefined OUT_DIR (build directory). Stop.
ノート:
実際のチェックはここで行われます:
$(if $(value $1),,$(error ...))
これはifndef
条件の動作を反映しているため、空の値に定義された変数も「未定義」と見なされます。ただし、これは単純な変数と明示的に空の再帰変数にのみ当てはまります。
# ifndef and check_defined consider these UNDEFINED:
explicitly_empty =
simple_empty := $(explicitly_empty)
# ifndef and check_defined consider it OK (defined):
recursive_empty = $(explicitly_empty)
コメントで@VictorSergienkoが示唆しているように、少し異なる動作が必要になる場合があります。
$(if $(value $1)
値が空でないかどうかをテストします。変数が空の値で定義されていても問題ない場合があります。私は使う$(if $(filter undefined,$(origin $1)) ...
そして:
さらに、それがディレクトリであり、チェックの実行時に存在している必要がある場合は、を使用します$(if $(wildcard $1))
。しかし、別の機能になります。
ターゲット固有のチェック
ソリューションを拡張して、特定のターゲットが呼び出された場合にのみ変数を要求できるようにすることもできます。
$(call check_defined, ...)
レシピの中から
チェックをレシピに移動するだけです。
foo :
@:$(call check_defined, BAR, baz value)
先頭の@
記号はコマンドのエコーをオフにします。これ:
は実際のコマンドであり、シェルのno-op stubです。
ターゲット名を表示しています
check_defined
この関数は、出力(を通じて提供ターゲット名に向上させることができる$@
変数)。
check_defined = \
$(strip $(foreach 1,$1, \
$(call __check_defined,$1,$(strip $(value 2)))))
__check_defined = \
$(if $(value $1),, \
$(error Undefined $1$(if $2, ($2))$(if $(value @), \
required by target `$@')))
つまり、チェックに失敗すると、適切にフォーマットされた出力が生成されます。
Makefile:7: *** Undefined BAR (baz value) required by target `foo'. Stop.
check-defined-MY_FLAG
特別なターゲット
個人的には、上記のシンプルで簡単なソリューションを使用します。ただし、たとえば、この回答は、実際のチェックを実行するために特別なターゲットを使用することを提案しています。これを一般化して、ターゲットを暗黙のパターンルールとして定義することができます。
# Check that a variable specified through the stem is defined and has
# a non-empty value, die with an error otherwise.
#
# %: The name of the variable to test.
#
check-defined-% : __check_defined_FORCE
@:$(call check_defined, $*, target-specific)
# Since pattern rules can't be listed as prerequisites of .PHONY,
# we use the old-school and hackish FORCE workaround.
# You could go without this, but otherwise a check can be missed
# in case a file named like `check-defined-...` exists in the root
# directory, e.g. left by an accidental `make -t` invocation.
.PHONY : __check_defined_FORCE
__check_defined_FORCE :
使用法:
foo :|check-defined-BAR
check-defined-BAR
が注文のみ(|...
)の前提条件としてリストされて
いることに注意してください。
長所:
短所:
- カスタムエラーメッセージを指定することはできません
- 実行すると
make -t
(「レシピを実行する代わりに」を参照)、多数のcheck-defined-...
ファイルでルートディレクトリが汚染されます。これは、パターンルールを宣言できない.PHONY
という悲しい欠点です。
これらの制限は、いくつかのeval
魔法の拡張ハックを使用して克服できると思いますが、それだけの価値があるかどうかはわかりません。