Makefile GNU make 4.1:定义函数中的$(if…)为true时缺少分隔符
当在shell命令的输出中找不到字符串时,我试图在Makefile中生成一个错误。shell命令依赖于一个参数,因此整个过程都在一个已定义的函数中。以下是一个极简主义的例子:Makefile GNU make 4.1:定义函数中的$(if…)为true时缺少分隔符,makefile,gnu-make,Makefile,Gnu Make,当在shell命令的输出中找不到字符串时,我试图在Makefile中生成一个错误。shell命令依赖于一个参数,因此整个过程都在一个已定义的函数中。以下是一个极简主义的例子: define check_in_abcdefg $(eval TMP := $(shell echo abcdefg)) $(if $(findstring $(1),$(TMP)),,$(error $(1) not in $(TMP))) endef $(call check_in_abcdefg,def) all
define check_in_abcdefg
$(eval TMP := $(shell echo abcdefg))
$(if $(findstring $(1),$(TMP)),,$(error $(1) not in $(TMP)))
endef
$(call check_in_abcdefg,def)
all:
@echo Hello, world!
我想让这个Makefile输出Hello,world
在这种情况下,但是如果我用这个替换呼叫线路,我希望它在abcdefg中输出xyz而不是:
$(call check_in_abcdefg,xyz)
问题是,通过def
检查,我有以下输出:
Makefile:6:**缺少分隔符。停下来
其中第6行是$(调用check\u in\u abcdefg,def)
当$(if…
条件为true时,语法检查为什么会失败,因为它实际上是空的?
请注意,虚拟目标
all
中的echo命令前面正确地有一个制表符,而不是四个空格。我正在运行为Windows32构建的GNU make 4.1.90,对于较新版本的GNU make
,这似乎不会发生。我正在寻找任何可以帮助我使用GNU make 4.1.90
的答案,我不知道为什么较旧的make
版本会在这里阻塞,但你可以使用一个大的$(eval)
使其工作,如下所示:
define check_in_abcdefg
$(eval
TMP := $$(shell echo abcdefg)
ifeq ($$(findstring $$(1),$$(TMP)),)
$$(error $$(1) not in $$(TMP))
endif
)
endef
$(call check_in_abcdefg,def)
all:
@echo Hello, world!
为了回答为什么GNUMake4.1抛出这个错误的问题:GNUMake的那个版本错误地处理了新行。在您的示例中:
define check_in_abcdefg
$(eval TMP := $(shell echo abcdefg))
$(if $(findstring $(1),$(TMP)),,$(error $(1) not in $(TMP)))
endef
$(call check_in_abcdefg,def)
定义的宏的第一行(eval
)扩展为空字符串,第二行(if)也扩展为空字符串。因此,调用
扩展为单个换行符
该版本的GNU make没有正确地忽略这个换行符,而是抛出了一个错误。通过删除换行符,可以将makefile更改为在这些旧版本中工作:
define check_in_abcdefg
$(eval TMP := $(shell echo abcdefg))$(if $(findstring $(1),$(TMP)),,$(error $(1) not in $(TMP)))
endef
$(call check_in_abcdefg,def)
我无法重现您的问题(x86_64-pc-msys上的GNU Make 4.2.1)。@FelixPalmen感谢您的尝试,实际上我刚刚尝试了
GNU Make 4.2
,它似乎可以工作。我不知道为什么4.1.90版会失败,不幸的是,这是在我的上下文中全局部署的版本。我使用GNU Make 4.1 x86_64-pc-linux-GNU,当第3行的计算结果为true
时,我有相同的错误。如果指定了某些内容,该问题似乎得到了解决,例如:$(如果$(findstring$(1),$(TMP),$(error$(1)在$(TMP)中,$(error$(1)不在$(TMP)中)
有效。希望这可以help@Hollyol感谢您的尝试,但是这对我来说并不起作用,因为问题发生在之后。在您的情况下,它不会发生,因为make
会在错误处停止,但是如果您在失败时放置一个信息:$(if$(findstring$(1),$(TMP)),$(info OK),$(error$(1)不在$(TMP)中)
。显示OK
,后跟***缺少分隔符。停止。
4.1.90是内部版本(这就是“90”的意思;所有“9x”版本都是内部版本)。任何人将其用于生产用途都是非常糟糕的。无法知道您为什么会看到这种行为,因为无法知道您正在使用的实际代码。可能会引入各种错误,然后在下一版本之前在同一版本中修复,所有这些都是版本“4.1.90”,而且大多数都没有在新闻中明确指出,等等。非常感谢,这非常好用。我仍然很有兴趣看到大家对这个问题的看法。我还没有在GNU make 4.2的更改日志中看到任何与完整性相关的内容:注意缩进是空格而不是制表符,因为这不是一个规则。将制表符放在这里将使案例xyz
失败。感谢您的有趣解释(以及您在gnumake
上的工作)。如果我们不更新到4.2
或更新版本,我会尽量记住这一点。