在生成文件中,我正在尝试
- 运行shell命令并在make变量中捕获输出
- 如果变量不为空,请执行操作
我创建了这个简化的makefile来演示我的问题。make a
和make b
都不执行if的主体,我不明白为什么不执行。
.PHONY: a b
a:
$(eval MY_VAR = $(shell echo whatever))
@echo MY_VAR is $(MY_VAR)
$(info $(MY_VAR))
ifneq ($(strip $(MY_VAR)),)
@echo "should be executed"
endif
@echo done
b:
$(eval MY_VAR = $(shell echo ''))
@echo MY_VAR is $(MY_VAR)
$(info $(MY_VAR))
ifneq ($(strip $(MY_VAR)),)
@echo "should not be executed"
endif
@echo done
我正在使用
$ make --version
GNU Make 3.81
编辑:正如所指出的,vars不需要使vars
如果您想动态测试MY_VAR
的内容,您可能需要:
a:
$(eval MY_VAR = $(shell echo ''))
$(if $(strip $(MY_VAR)),echo ok,echo no)
如果MY_VAR
不为空,则if
评估将变为echo ok
,否则将变为echo no
请注意,由于评估时间的原因,make条件语句(ifeq
、ifneq
…(不能以您尝试的方式在配方中使用。请改用shell条件语句,如下所示。
由于您的MY_VAR
变量仅在配方中使用,与目标相关,并且您希望仅在需要时计算它,为什么不使用shell变量而不是make变量呢?
$ cat Makefile
.PHONY: a b
a:
MY_VAR=$$(echo 'whatever') &&
echo '$@: MY_VAR is $$MY_VAR' &&
if [ -n "$$MY_VAR" ]; then
echo '$@: should be executed';
fi &&
echo '$@: done'
b:
MY_VAR=$$(echo '') &&
echo '$@: MY_VAR is $$MY_VAR' &&
if [ -n "$$MY_VAR" ]; then
echo '$@: should not be executed';
fi &&
echo '$@: done'
$ make a
a: MY_VAR is whatever
a: should be executed
a: done
$ make b
b: MY_VAR is
b: done
如果你绝对需要MY_VAR
作为目标特定的make变量,但只想(每个目标(执行一次产生其值的shell命令,MadScientist有一个绝妙的技巧,你可能应该看看
$ make --version
GNU Make 4.1
...
$ cat Makefile
a: MY_VAR = $(eval a: MY_VAR := $$(shell echo 'whatever'))$(MY_VAR)
b: MY_VAR = $(eval b: MY_VAR := $$(shell echo ''))$(MY_VAR)
a:
@echo '$@: MY_VAR is $(MY_VAR)' &&
if [ -n "$(MY_VAR)" ]; then
echo '$@: should be executed';
fi &&
echo '$@: done'
b:
@echo '$@: MY_VAR is $(MY_VAR)' &&
if [ -n "$(MY_VAR)" ]; then
echo '$@: should not be executed';
fi &&
echo '$@: done'
$ make a
a: MY_VAR is whatever
a: should be executed
a: done
$ make b
b: MY_VAR is
b: done
$ make b a
b: MY_VAR is
b: done
a: MY_VAR is whatever
a: should be executed
a: done
它看起来可能非常奇怪,但它保证了当且仅当调用目标a
或b
时才计算MY_VAR
,并且每个目标最多只能调用一次。看看《疯狂科学家》的帖子,了解详细的解释。加油,太棒了。
在解析Makefile时会评估ifeq
和条件语句族。如果在扩展规则时需要Make变量的条件,则需要使用$(if )
函数:
.PHONY: a b
a b:
@$(if $(strip $(MY_VAR)),echo "MY_VAR isn't empty",)
@echo done
a: MY_VAR =
b: MY_VAR = something
一个稍左的字段,但在我的情况下很有用,所以我想它值得分享:使用--no-run-if-empty
选项将值管道传输到xargs
:
echo $(POSSIBLY_EMPTY) | xargs --no-run-if-empty echo
请注意,这将在OSX上不起作用。请参阅如果stdin输入为空,如何忽略xargs命令?有关xargs --no-run-if-empty
的更多详细信息