【问题标题】:Makefile ifeq logical orMakefile ifeq 逻辑或
【发布时间】:2011-12-01 04:02:55
【问题描述】:

如何使用 make 的 ifeq 运算符执行逻辑 OR?

例如,我有(简化):

ifeq ($(GCC_MINOR), 4)
    CFLAGS += -fno-strict-overflow
endif
ifeq ($(GCC_MINOR), 5)
    CFLAGS += -fno-strict-overflow
endif

但想合并这些线路。

(是的,是的,autotools、configure 等;对于目前的情况来说过于严厉,希望将所有内容都保留在 Makefile 中)

[这个问题的逻辑反面:How to Use of Multiple condition in 'ifeq' statement]

【问题讨论】:

标签: makefile


【解决方案1】:

你可以引入另一个变量。它并没有合并两个检查,但它至少避免了必须将 body 放入两次:

do_it = 
ifeq ($(GCC_MINOR), 4)
    do_it = yes
endif
ifeq ($(GCC_MINOR), 5)
    do_it = yes
endif
ifdef do_it
    CFLAGS += -fno-strict-overflow
endif

【讨论】:

  • 大规模的可维护性对我来说似乎不是很好:/ 再说一次,一旦我们开始谈论规模,我想我们正在谈论自动工具
  • @Pat:我更喜欢这种方法,我可以在 Makefile 中的一个位置分隔分配,可能使用 ifeq/else ifeq/else 与更多值进行比较,而不是使用过滤器功能只是让非常长的难以阅读的行。
【解决方案2】:

我不认为有一种简洁、明智的方式来做到这一点,但有冗长、明智的方式(例如 Foo Bah's)和简洁、病态的方式,例如

ifneq (,$(findstring $(GCC_MINOR),4-5))
    CFLAGS += -fno-strict-overflow
endif

(如果字符串 $(GCC_MINOR) 出现在字符串 4-5 中,它将执行命令)。

【讨论】:

  • 无论好坏(可能更糟),正是我正在寻找的那种肮脏的黑客;谢谢
  • 我认为这根本不是病态的,除了 Makefile 中的 everything 都是病态的事实。它真的很优雅。我已经阅读了四五种不同的方法来实现这一点,而你的方法是迄今为止最容易理解的。
【解决方案3】:

在邮件列表存档中找到,

可以使用filter函数。

例如

ifeq ($(GCC_MINOR),$(filter $(GCC_MINOR),4 5))

filter X, A B 将返回 A,B 中等于 X 的值。 请注意,虽然这在上面的示例中不相关,但这是一个 XOR 操作。 IE。如果你有类似的东西:

ifeq (4, $(filter 4, $(VAR1) $(VAR2)))

然后做例如make VAR1=4 VAR2=4,过滤器会返回4 4,不等于4

执行 OR 操作的变体是:

ifneq (,$(filter $(GCC_MINOR),4 5))

改为使用与空字符串的否定比较(如果GCC_MINOR 与参数不匹配,filter 将返回空字符串)。使用VAR1/VAR2 示例,它看起来像这样:

ifneq (, $(filter 4, $(VAR1) $(VAR2)))

这些方法的缺点是您必须确保这些参数始终是单个单词。例如VAR14 foo,则过滤结果仍为4ifneq表达式仍为真。如果VAR14 5,则过滤结果为4 5ifneq 表达式为真。

一个简单的替代方法是在 ifeqelse ifeq 分支中放置相同的操作,例如像这样:

ifeq ($(GCC_MINOR),4)
    @echo Supported version
else ifeq ($(GCC_MINOR),5)
    @echo Supported version
else
    @echo Unsupported version
endif

【讨论】:

  • 迟到的注意事项:在上面的两个变体中,如果 $(GCC_MINOR) 为空,第一个将解析为 true,而第二个不会(因此一般来说第二个是更好的解决方案) .
  • 其实应该是ifneq (,$(filter 4 5,$(GCC_MINOR))) :)
  • 为简单起见,最好保持原样?
  • 另一个注意事项:这不能用作一般 OR 语句。我们有一些东西要检查if(flagA == TRUE || flagB == true),但如果你检查$(filter true, $(flagA) $(flagB) 并且两者都是真的,你会得到ifeq(true, true true)
【解决方案4】:
ifeq ($(GCC_MINOR), 4)
    CFLAGS += -fno-strict-overflow
endif
ifeq ($(GCC_MINOR), 5)
    CFLAGS += -fno-strict-overflow
endif

在这种情况下您可以考虑使用的另一个是:

GCC42_OR_LATER = $(shell $(CXX) -v 2>&1 | $(EGREP) -c "^gcc version (4.[2-9]|[5-9])")

# -Wstrict-overflow: http://www.airs.com/blog/archives/120
ifeq ($(GCC42_OR_LATER),1)
  CFLAGS += -Wstrict-overflow
endif

我实际上在我的代码中使用相同的,因为我不想维护单独的 configConfigure

但您必须使用可移植的、非贫血的 make,例如 GNU make (gmake),而不是 Posix 的 make

并且它没有解决逻辑ANDOR的问题。

【讨论】:

    【解决方案5】:

    这里更灵活的变体:它使用外部外壳,但允许检查任意条件:

    ifeq ($(shell test ".$(GCC_MINOR)" = .4  -o  \
                       ".$(GCC_MINOR)" = .5  -o  \
                       ".$(TODAY)"     = .Friday  &&  printf "true"), true)
        CFLAGS += -fno-strict-overflow
    endif
    

    【讨论】:

      【解决方案6】:

      如果您希望在逻辑上“或”几个布尔标志一起使用,一个实用的技巧可以是简单地让字符串连接:如果最终结果是一个空字符串,那么没有一个选项是真的,else非空然后 至少其中一个被启用:

      # Use `docker build --pull` in case either `PULL=whatever` is set OR if the `CI` environment variable is present.
      ifneq ($(PULL)$(CI),)
      PULL_OR_NOT := --pull
      endif
      
      build:
          docker build $(PULL_OR_NOT)
      
      

      【讨论】:

        【解决方案7】:

        请注意,ifeq ($(GCC_MINOR),$(filter $(GCC_MINOR),4 5)) 将捕获根本未定义 GCC_MINOR 的情况。

        如果您想捕捉 GCC_MINOR==4 或 GCC_MINOR==5,这会奏效:

        ifneq ($(filter $(GCC_MINOR),4 5),)
            echo "def"
        endif
        

        【讨论】:

          猜你喜欢
          • 2011-09-21
          • 1970-01-01
          • 2021-03-03
          • 2012-04-13
          • 1970-01-01
          • 1970-01-01
          • 2012-08-13
          • 2023-03-07
          • 1970-01-01
          相关资源
          最近更新 更多