GNU make条件函数$(if ...)在用户定义的函数内总是求值为true

时间:2012-01-25 19:07:09

标签: makefile gnu-make

我正在尝试编写一个make函数来触摸/创建一个空文件和/或在可能的情况下设置权限,用户和组,或者如果没有则发出警告。但是,我的函数中的每个条件检查似乎都评估为真。

我的Makefile的基本要素是

INSTALL_USER  := fileUser
INSTALL_GROUP := fileGroup

.PHONY: test
test:
    $(call touchFile,~/test.ini)

define touchFile
$(eval fileName := $(strip $(1)))
-touch $(fileName)
-chmod -c 664 $(fileName)

$(info filename info $(fileName))
$(info $(shell stat -c "%a %U:%G" $(fileName)))

$(if ifeq  "foo" "bar", @echo match is broken, @echo match works)
$(if ifneq "foo" "bar", @echo match works, @echo match is broken)

$(if ifneq ($(shell stat -c %a $(fileName)),664), $(warning Error - $(fileName) does not have expected permissions of 664))
-chgrp -c $(INSTALL_GROUP) $(fileName)
$(if ifneq ($(shell stat -c %G $(fileName)),$(INSTALL_GROUP)), $(warning Error - $(fileName) does not belong to $(INSTALL_GROUP) group))
-chown -c $(INSTALL_USER) $(fileName)
$(if ifneq ($(shell stat -c %U $(fileName)),$(INSTALL_USER)), $(warning Error - $(fileName) does not belong to $(INSTALL_USER) user))
endef

运行make test输出

filename info ~/test.ini
664 myUserName:myGroup
Makefile:7: Error - ~/test.ini does not have expected permissions of 664
Makefile:7: Error - ~/test.ini does not belong to common group
Makefile:7: Error - ~/test.ini does not belong to netserve user
touch ~/test.ini
chmod -c 664 ~/test.ini
match is broken
match works
chgrp -c fileGroup ~/test.ini
changed group of `/home/myUserName/test.ini' to fileGroup
chown -c fileUser ~/test.ini
chown: changing ownership of `/home/myUserName/test.ini': Operation not permitted
make: [test] Error 1 (ignored)

我考虑过/尝试了以下内容:

    在使用参数调用函数之前,
  • $(if ...)在“编译时”进行评估。但是,硬编码的ifeq "foo" "bar"也会产生无效结果。此外,$(info ...)在“编译时”正确评估$(fileName)
  • documentation实际上没有提供示例,因此除了$(if ifeq...)之外,我还尝试了$(ifeq ...),这似乎被忽略了。
  • “非功能性”if(即ifeq没有$(if...))在函数内部提供/bin/sh: ifeq: command not found

有人可以帮助确定为什么我的条件不符合我的预期(或者为什么我会期待错误的事情)?

警告:我知道如果文件不存在仍然存在缺陷,但与此障碍相比,这应该是微不足道的。

4 个答案:

答案 0 :(得分:41)

当传递给它的第一个参数非空时,

$(if ...) conditional function求值为true。在你的情况下,条件是文字文本:ifeq "foo" "bar",显然是非空的。

ifeq/ifneq conditionals实际上是指令,而不是函数。它们不能在变量定义和函数内使用。

回到你的例子,在条件中测试字符串是否相等,使用像filter and findstring这样的函数:

$(if $(filter foo,bar),@echo match is broken,@echo match works)
$(if $(filter-out foo,bar),@echo match works,@echo match is broken)

顺便说一下,这也可以变成一个内联形式,以提高可读性:

@echo match $(if $(filter foo,bar),is broken,works)
@echo match $(if $(filter-out foo,bar),works,is broken)

答案 1 :(得分:7)

我遇到了这个问题,我发现你可以在“if”功能的“条件”部分使用“过滤”功能的结果。这是一个用于在Linux中打开pdf(带有“evince”)或在带有“打开”的OSX中打开pdf的示例。

uname     :=$(shell uname -s)
is_darwin :=$(filter Darwin,$(uname))
viewpdf   :=$(if $(is_darwin), open, evince)

答案 2 :(得分:2)

您似乎误解了$(if的工作方式。来自make info docs:

  

$(如果条件,那么[,部分])        `if'函数为a中的条件扩展提供支持        功能背景

     

第一个参数CONDITION首先包含所有前面的和        尾部空白被剥离,然后被扩展。如果它扩大到        任何非空字符串,则该条件被认为是真的。        如果它扩展为空字符串,则考虑条件        是假的。

在所有示例中,您的条件类似于ifeq SOMETHING OTHERTHING - 这是一个非空字符串(来自ifeq而不管其他内容是什么),因此被视为真

答案 3 :(得分:1)

如果您想检查您的操作系统版本是Linux还是其他版本,如果它是Linux,那么您想要打印一些消息,那么您可以按照以下步骤操作:

ifneq ($(TARGETOS), Linux)
    target: server
    @echo
    @echo $(MSG) $(TARGETOS)
else
target: server
    @echo $(MSG) $(TARGET)
endif

之前我尝试使用ifeq,但它只打印了else部分。 我的操作系统是Linux,ubuntu。

如果有人发现这个答案应该被修改,那么他们也可以给出更好的答案。