Makefile 如何使$(error…)在GNU Make中有条件地工作?
如果不满足某些先决条件,我想使用Makefile 如何使$(error…)在GNU Make中有条件地工作?,makefile,gnu-make,Makefile,Gnu Make,如果不满足某些先决条件,我想使用$(error…中止make过程。当测试失败-d/foobar时,工作失败目标应中止 BAD.mk all: this_works fails_to_work this_works: @echo echo works... @test -d ~ || echo ~ is not a directory @test -d /foobar || echo /foobar is not a directory fail
$(error…
中止make过程。当测试失败-d/foobar
时,工作失败
目标应中止
BAD.mk
all: this_works fails_to_work
this_works:
@echo echo works...
@test -d ~ || echo ~ is not a directory
@test -d /foobar || echo /foobar is not a directory
fails_to_work:
@echo error does not work...
@test -d ~ || $(error ~ is not a directory)
@test -d /foobar || $(error /foobar is not a directory)
$make-f BAD.mk
echo works...
/foobar is not a directory
BAD.mk:9: *** ~ is not a directory. Stop.
正如您所看到的,甚至“错误不起作用…”都不会在屏幕上出现。的配方无法工作
在开始之前就失败了。我如何解决这个问题?我的一个用例是@test-d$(my_ENV_VAR)
,但我认为这与示例中给出的硬编码路径没有什么不同
更新(版本信息)
$make--版本
您试图在配方中获取shell内容,以有条件地调用makefile内容,但正如您所发现的那样,这是行不通的 我可以想出两个选择:
$(错误)
内容。如果test
失败,则它将返回非零退出状态,并且Make进程将在该点终止为什么不直接使用
exit 1
shell命令而不是$(错误…
?有什么理由使用后者吗
try_this:
@test -d /foobar || { echo /foobar is not a directory; exit 1; }
or_this:
@if [ ! -d /foobar ]; then echo /foobar is not a directory; exit 1; fi
除非另有规定,否则这两个选项都将中止生成过程
-k
——继续前进
出错后尽可能多地继续。虽然无法重新生成失败的目标以及依赖它的目标,但仍然可以处理这些目标的其他先决条件
make配方的Shell命令有效地存储为单个递归扩展变量。在make决定运行recipe时,它展开变量,然后在自己的shell调用中运行每一行。任何扩展的
$(错误…
)都将导致make在调用第一个命令之前中止
但是请注意,$(if…
或$(or…
&c)的未调用分支。不会扩大。因此,你可以这样做
.PHONY: rule-with-assert
rule-with-assert:
$(if $(realpath ${should-be-file}/),$(error Assertion failure: ${should-be-file} is a folder!))
⋮
请注意,realpath
中的尾部/
当然,宏有助于整理这一切
assert-is-file = $(if $(realpath $1/),$(error Assertion failure: [$1] is a folder!))
.PHONY: rule-with-assert
rule-with-assert:
$(call assert-is-file,${should-be-file})
⋮
再次值得注意的是,将$(callassert是file,…)
放在配方的何处并不重要。
任何$(错误)
都将在配方展开时生成,
在运行任何shell命令之前。谢谢。您的第一个建议有效(我采用的是这样的:
if!test-d/foobar;then echo”/foobar不是目录);退出1;fi
),但您的第二个建议无效。如果有一个有效的目录,这个错误仍然存在。我在错误地认为test-d
在这两个目录中都可用的情况下,为windows cmd shell/sh的可移植性而努力。但是,我仍然对有条件地调用$(error…)的正确方法感兴趣。
.PHONY: rule-with-assert
rule-with-assert:
$(if $(realpath ${should-be-file}/),$(error Assertion failure: ${should-be-file} is a folder!))
⋮
assert-is-file = $(if $(realpath $1/),$(error Assertion failure: [$1] is a folder!))
.PHONY: rule-with-assert
rule-with-assert:
$(call assert-is-file,${should-be-file})
⋮