如何在makefile中执行算术运算?

mal*_*oca 37 makefile

是否可以对makefile中的变量执行某些操作?例如,定义

JPI=4
JPJ=2
Run Code Online (Sandbox Code Playgroud)

是否有可能在同一个makefile中定义一个等于$(JPI)*$(JPJ)扩展值的变量JPIJ?

小智 27

使用Bash算术扩展:

SHELL=/bin/bash
JPI=4
JPJ=2
all:
    echo $$(( $(JPI) * $(JPJ) ))
Run Code Online (Sandbox Code Playgroud)

第一行是选择Bash shell而不是默认值(sh).通常,sh不支持算术扩展.但是在Ubuntu中,/ bin/sh由Dash提供,它支持此功能.这样就可以跳过这条线.

双美元符号是因为我们希望通过壳来进行扩张.注意:首先通过make扩展JPI和JPJ变量,然后将表达式传递给bash,如下所示:

$(( 4 * 2 ))
Run Code Online (Sandbox Code Playgroud)

  • POSIX`sh`确实支持[算术扩展](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_04). (4认同)
  • +1 因为这是最好的解决方案,因为它只依赖于 POSIX 兼容的 shell。感谢您指出在 make 中进行 shell 算术时我们需要一个双美元符号。 (2认同)

mrk*_*rkj 13

如果您正在使用GNU make并已bc在系统上安装,则可以使用以下内容:

JPI=4
JPJ=2
FOO=$(shell echo $(JPI)\*$(JPJ) | bc)
all:
  echo $(FOO)
Run Code Online (Sandbox Code Playgroud)

  • expr比bc更常见:`$(shell expr $(JPI)\*$(JPJ))` (3认同)

Eri*_*ski 10

它是笨拙的(或者很棒,取决于你的观点),但你可以直接在GNU make中进行算术运算.请参阅学习GNU使用算术生成函数.请注意,此方法不能很好地扩展.正如你在问题中所展示的那样,它会很好地用于小数字,但是当你处理大数量(大于10,000,000)的数字时它不会很好.


Jea*_* T. 7

来自@mrkj的答案很棒,但正如@Daniel所提到的,并非所有系统都有bc(例如,我没有在MSys上使用它).

我找到了以下两种方法,都使用shell:$$((...))expr ...

JPI=4
JPJ=2

#With Double-dollar
JPIJ_1 = $(shell echo $$(( $(JPI) + $(JPJ) )))

#With 'expr'
JPIJ_2 = $(shell expr $(JPI) + $(JPJ) )

$(info Sum with Double-$$: $(JPIJ_1))
$(info Sum with 'expr': $(JPIJ_2))
Run Code Online (Sandbox Code Playgroud)

请注意,使用时expr,您在其周围放置空格,+否则它将返回4+2.使用时不需要这样做$$.

.

当你bc有空的时候,你肯定可以使用它.我发现以下页面非常有趣:http://www.humbug.in/2010/makefile-tricks-arithmetic-addition-subtraction-multiplication-division-modulo-comparison/


ruv*_*vim 5

在支持Guile 的GNU Make (即从 4.0 版开始)中,很容易调用 Scheme 语言进行算术或其他计算。它是在不创建任何子外壳或子进程的情况下完成的。

一个例子

JP-I := 4
JP-J := 2
JP-IJ := $(guile (* $(JP-I) $(JP-J) ))

$(info JP-IJ = $(JP-IJ) )
# prints: JP-IJ = 8
Run Code Online (Sandbox Code Playgroud)

另请参阅 Guile算术函数手册。

Guile 的可能检查:

ifeq (,$(filter guile,$(.FEATURES)))
  $(error Your Make version $(MAKE_VERSION) is not built with support for Guile)
endif
Run Code Online (Sandbox Code Playgroud)