변수가 설정되지 않은 경우 makefile 중단
makefile의 변수가 설정 / 값 지정되지 않은 상태에서 make / makefile 실행을 중단하려면 어떻게해야합니까?
나는 이것을 생각해 냈지만 호출자가 대상을 명시 적으로 실행하지 않으면 (즉, 실행 make
만) 작동 합니다.
ifeq ($(MY_FLAG),)
abort: ## This MUST be the first target :( ugly
@echo Variable MY_FLAG not set && false
endif
all:
@echo MY_FLAG=$(MY_FLAG)
나는 이것과 같은 것이 좋은 생각이라고 생각하지만 make 매뉴얼에서 아무것도 찾지 못했습니다.
ifndef MY_FLAG
.ABORT
endif
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)
The leading @
sign turns off command echoing and :
is the actual command, a shell no-op stub.
Showing target name
The check_defined
function can be improved to also output the target name (provided through the $@
variable):
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 `$@')))
So that, now a failed check produces a nicely formatted output:
Makefile:7: *** Undefined BAR (baz value) required by target `foo'. Stop.
check-defined-MY_FLAG
special target
Personally I would use the simple and straightforward solution above. However, for example, this answer suggests using a special target to perform the actual check. One could try to generalize that and define the target as an implicit pattern rule:
# 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 :
Usage:
foo :|check-defined-BAR
Notice that the check-defined-BAR
is listed as the order-only (|...
) prerequisite.
Pros:
- (arguably) a more clean syntax
Cons:
- One can't specify a custom error message
- Running
make -t
(see Instead of Executing Recipes) will pollute your root directory with lots ofcheck-defined-...
files. This is a sad drawback of the fact that pattern rules can't be declared.PHONY
.
I believe, these limitations can be overcome using some eval
magic and secondary expansion hacks, although I'm not sure it's worth it.
Use the shell function test
:
foo:
test $(something)
Usage:
$ make foo
test
Makefile:2: recipe for target 'foo' failed
make: *** [foo] Error 1
$ make foo something=x
test x
You can use an IF to test:
check:
@[ "${var}" ] || ( echo ">> var is not set"; exit 1 )
Result:
$ make check
>> var is not set
Makefile:2: recipe for target 'check' failed
make: *** [check] Error 1
Use the shell error handling for unset variables (note the double $
):
$ cat Makefile
foo:
echo "something is set to $${something:?}"
$ make foo
echo "something is set to ${something:?}"
/bin/sh: something: parameter null or not set
make: *** [foo] Error 127
$ make foo something=x
echo "something is set to ${something:?}"
something is set to x
If you need a custom error message, add it after the ?
:
$ cat Makefile
hello:
echo "hello $${name:?please tell me who you are via \$$name}"
$ make hello
echo "hello ${name:?please tell me who you are via \$name}"
/bin/sh: name: please tell me who you are via $name
make: *** [hello] Error 127
$ make hello name=jesus
echo "hello ${name:?please tell me who you are via \$name}"
hello jesus
참고URL : https://stackoverflow.com/questions/10858261/abort-makefile-if-variable-not-set
'development' 카테고리의 다른 글
SDF 파일을 어떻게 열 수 있습니까 (SQL Server Compact Edition)? (0) | 2020.06.30 |
---|---|
일련의 jQuery 연기로 어떻게 작업합니까? (0) | 2020.06.30 |
Safari의 html5 localStorage 오류 :“QUOTA_EXCEEDED_ERR : DOM 예외 22 : 할당량을 초과 한 스토리지에 무언가를 추가하려고했습니다.” (0) | 2020.06.30 |
PHP에서 "풀에 메모리를 할당 할 수 없습니다"는 무엇입니까? (0) | 2020.06.30 |
Java에서 HTML 문자 엔티티를 이스케이프 해제하는 방법은 무엇입니까? (0) | 2020.06.30 |