Makefile ifeq 逻辑或

发布于 2024-12-07 20:19:26 字数 436 浏览 0 评论 0 原文

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

例如,我有(简化的):

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

但想合并这些行。

(是的,是的,自动工具、配置等;对于当前情况来说过于严厉,希望将所有内容保留在 Makefile 中)

[与此问题逻辑相反:如何在“ifeq”语句中使用多个条件]

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 ]

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

浅浅 2024-12-14 20:19:26

在邮件列表存档中可以找到,

可以使用filter功能。

例如,

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

过滤器 X, A B 将返回 A、B 中等于 X 的值。
请注意,虽然这与上面的示例无关,但这是一个 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表达式仍然为真的。如果 VAR14 5,则过滤结果为 4 5,且 ifneq 表达式为 true。

一种简单的替代方法是将相同的操作放在 ifeq 和 else ifeq 分支中,例如:

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

As found on the mailing list archive,

one can use the filter function.

For example

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

filter X, A B will return those of A,B that are equal to X.
Note, while this is not relevant in the above example, this is a XOR operation. I.e. if you instead have something like:

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

And then do e.g. make VAR1=4 VAR2=4, the filter will return 4 4, which is not equal to 4.

A variation that performs an OR operation instead is:

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

where a negative comparison against an empty string is used instead (filter will return en empty string if GCC_MINOR doesn't match the arguments). Using the VAR1/VAR2 example it would look like this:

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

The downside to those methods is that you have to be sure that these arguments will always be single words. For example, if VAR1 is 4 foo, the filter result is still 4, and the ifneq expression is still true. If VAR1 is 4 5, the filter result is 4 5 and the ifneq expression is true.

One easy alternative is to just put the same operation in both the ifeq and else ifeq branch, e.g. like this:

ifeq ($(GCC_MINOR),4)
    @echo Supported version
else ifeq ($(GCC_MINOR),5)
    @echo Supported version
else
    @echo Unsupported version
endif
一念一轮回 2024-12-14 20:19:26

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

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

You can introduce another variable. It doesnt consolidate both checks, but it at least avoids having to put the body in twice:

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
好菇凉咱不稀罕他 2024-12-14 20:19:26

我认为没有一种简洁、明智的方法可以做到这一点,但是有冗长、明智的方法(例如 Foo Bah 的)和简洁、病态的方法,例如

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

(如果字符串 $(GCC_MINOR) 则执行命令出现在字符串 4-5) 内。

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

(which will execute the command provided that the string $(GCC_MINOR) appears inside the string 4-5).

拧巴小姐 2024-12-14 20:19:26

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

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

Here more flexible variant: it uses external shell, but allows to check for arbitrary conditions:

ifeq ($(shell test ".$(GCC_MINOR)" = .4  -o  \
                   ".$(GCC_MINOR)" = .5  -o  \
                   ".$(TODAY)"     = .Friday  &&  printf "true"), true)
    CFLAGS += -fno-strict-overflow
endif
情徒 2024-12-14 20:19:26

请注意,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

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

If you want to catch GCC_MINOR==4 or GCC_MINOR==5 this will do trick:

ifneq ($(filter $(GCC_MINOR),4 5),)
    echo "def"
endif
请别遗忘我 2024-12-14 20:19:26
ifeq ($(GCC_MINOR), 4)
    CFLAGS += -fno-strict-溢出
恩迪夫
ifeq ($(GCC_MINOR), 5)
    CFLAGS += -fno-strict-溢出
恩迪夫

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

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的问题。

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

Another you can consider using in this case is:

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

I actually use the same in my code because I don't want to maintain a separate config or Configure.

But you have to use a portable, non-anemic make, like GNU make (gmake), and not Posix's make.

And it does not address the issue of logical AND and OR.

九八野马 2024-12-14 20:19:26

如果您希望在逻辑上将多个布尔标志“或”在一起,一种实用的技巧就是简单地让字符串连接起来:if最终结果是一个空字符串,then没有一个选项为真,else非空then至少其中一个已启用:

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

In the case that you are looking to logically "or" several boolean flags together, one practical hack can be to simply let strings concatenate: if the end result is an empty string, then none of the options were true, else non-empty then at least one of them was enabled:

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文