【问题标题】:GNU make conditional function $(if ...) inside a user-defined function always evaluates to trueGNU make 条件函数 $(if ...) 在用户定义的函数中总是计算为真
【发布时间】:2012-01-25 19:07:08
【问题描述】:

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

我的 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(即,没有$(if...)ifeq)给出/bin/sh: ifeq: command not found

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

警告:我知道如果文件不存在,仍有一些错误需要解决,但与这个障碍相比,这应该是微不足道的。

【问题讨论】:

  • GNU 网站虽然看起来不错,但简洁得几乎毫无意义,不是吗。他们会告诉你有一个函数存在,然后不给你任何如何使用它的例子,以便用它来骚扰你。

标签: makefile gnu-make


【解决方案1】:

$(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)

【讨论】:

    【解决方案2】:

    我遇到了这个问题,我发现你可以在“if”函数的“condition”部分使用“filter”函数的结果。这是一个示例,可用于在 Linux(使用“evince”)或在 OSX 中使用“open”打开 pdf)

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

    【讨论】:

      【解决方案3】:

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

      $(如果条件,THEN-PART[,ELSE-PART])' `if' 函数提供对条件扩展的支持 功能上下文

      第一个参数 CONDITION 首先包含所有前面的和 去除尾随空格,然后展开。如果扩展为 任何非空字符串,则认为条件为真。 如果它扩展为空字符串,则条件被认为是 是假的。

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

      【讨论】:

        【解决方案4】:

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

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

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

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-09-28
          • 2016-12-04
          • 2019-03-03
          • 2020-05-20
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多