Makefile ifeq logical or

How do you perform a logical OR using make's ifeq operator?

e.g., I have (simplified):

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

but would like to consolidate these lines.

(yes, yes, autotools, configure, etc etc; too heavy-handed for the current situation, would like to keep everything within the Makefile here)

[logical opposite of this question: How to Use of Multiple condition in 'ifeq' statement ]

177108 次浏览

可以引入另一个变量。它不会合并两个检查,但至少可以避免将尸体放入两次:

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

I don't think there's a concise, sensible way to do that, but there are verbose, sensible ways (such as Foo Bah's) and concise, pathological ways, such as

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

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

正如在邮件列表存档中发现的那样,

可以使用 filter函数。

比如说

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

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

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,则过滤器结果仍然是 4,并且 ifneq表达式仍然为 true。如果 VAR14 5,则过滤器结果为 4 5,且 ifneq表达式为 true。

一个简单的替代方法是在 ifeqelse ifeq分支中使用相同的操作,例如:

ifeq ($(GCC_MINOR),4)
@echo Supported version
else ifeq ($(GCC_MINOR),5)
@echo Supported version
else
@echo Unsupported version
endif
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的问题。

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

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

在你寻找逻辑“或”几个布尔标志在一起的情况下,一个实际的黑客可以简单地让字符串串联: 如果的最终结果是一个空字符串,那么没有一个选项是真的,别的非空 那么 at least其中之一是启用:

# 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)


Note that ifeq ($(GCC_MINOR),$(filter $(GCC_MINOR),4 5)) will catch the case where GCC_MINOR is not defined at all.

如果您想捕获 GCC _ MINOR = = 4或 GCC _ MINOR = = 5,这将会有所帮助:

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