TL; DR : Gunakan error
fungsinya :
ifndef MY_FLAG
$(error MY_FLAG is not set)
endif
Perhatikan bahwa garis tidak boleh diindentasi. Lebih tepatnya, tidak ada tab yang harus mendahului garis-garis ini.
Solusi umum
Jika Anda akan menguji banyak variabel, ada baiknya mendefinisikan fungsi bantu untuk itu:
# 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))))
Dan inilah cara menggunakannya:
$(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)
Ini akan menghasilkan kesalahan seperti ini:
Makefile:17: *** Undefined OUT_DIR (build directory). Stop.
Catatan:
Pemeriksaan sebenarnya dilakukan di sini:
$(if $(value $1),,$(error ...))
Ini mencerminkan perilaku ifndef
kondisional, sehingga variabel yang didefinisikan sebagai nilai kosong juga dianggap "tidak terdefinisi". Tapi ini hanya berlaku untuk variabel sederhana dan variabel rekursif kosong secara eksplisit:
# 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)
Seperti yang disarankan oleh @VictorSergienko dalam komentar, perilaku yang sedikit berbeda mungkin diinginkan:
$(if $(value $1)
menguji apakah nilainya tidak kosong. Terkadang OK jika variabel didefinisikan dengan nilai kosong . Saya akan menggunakan$(if $(filter undefined,$(origin $1)) ...
Dan:
Selain itu, jika itu adalah direktori dan harus ada saat pemeriksaan dijalankan, saya akan menggunakan $(if $(wildcard $1))
. Tetapi akan menjadi fungsi lain.
Pemeriksaan spesifik target
Dimungkinkan juga untuk memperluas solusi sehingga seseorang dapat memerlukan variabel hanya jika target tertentu dipanggil.
$(call check_defined, ...)
dari dalam resep
Cukup pindahkan cek ke dalam resep:
foo :
@:$(call check_defined, BAR, baz value)
Tanda terkemuka @
mematikan perintah yang bergema dan :
merupakan perintah aktual, sebuah shell no-op stub .
Menampilkan nama target
Itu check_defined
fungsi dapat ditingkatkan untuk juga output nama sasaran (disediakan melalui $@
variabel):
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 `$@')))
Jadi, sekarang cek yang gagal menghasilkan output yang diformat dengan baik:
Makefile:7: *** Undefined BAR (baz value) required by target `foo'. Stop.
check-defined-MY_FLAG
target khusus
Secara pribadi saya akan menggunakan solusi sederhana dan mudah di atas. Namun, misalnya, jawaban ini menyarankan menggunakan target khusus untuk melakukan pemeriksaan yang sebenarnya. Orang bisa mencoba menggeneralisasi itu dan mendefinisikan target sebagai aturan pola implisit:
# 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 :
Pemakaian:
foo :|check-defined-BAR
Perhatikan bahwa check-defined-BAR
terdaftar sebagai pesanan saja|...
prasyarat ( ).
Pro:
- (bisa dibilang) sintaks yang lebih bersih
Cons:
- Seseorang tidak dapat menentukan pesan kesalahan khusus
- Menjalankan
make -t
(lihat Alih-alih Melaksanakan Resep ) akan mencemari direktori root Anda dengan banyak check-defined-...
file. Ini adalah kelemahan menyedihkan dari kenyataan bahwa aturan pola tidak dapat dinyatakan.PHONY
.
Saya percaya, keterbatasan ini dapat diatasi dengan menggunakan beberapa eval
sulap ekspansi sihir dan sekunder , meskipun saya tidak yakin itu layak.