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

时间:2009-12-18 03:17:47

标签: makefile

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

JPI=4
JPJ=2

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

8 个答案:

答案 0 :(得分:27)

使用Bash arithmetic expansion

SHELL=/bin/bash
JPI=4
JPJ=2
all:
    echo $$(( $(JPI) * $(JPJ) ))

第一行是choose the Bash shell instead of the default (sh)。通常,sh不支持算术扩展。但是在Ubuntu中,/ bin / sh由Dash, which supports this feature提供。所以可以跳过该行。

双美元符号是因为我们需要the expansion to be done by the shell。注意:首先通过make扩展JPI和JPJ变量,然后将表达式传递给bash,如下所示:

$(( 4 * 2 ))

答案 1 :(得分:13)

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

JPI=4
JPJ=2
FOO=$(shell echo $(JPI)\*$(JPJ) | bc)
all:
  echo $(FOO)

答案 2 :(得分:10)

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

答案 3 :(得分: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))

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

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

答案 4 :(得分:4)

GNU Make Standard Library提供整数运算函数。

include gmsl

JPI = 4
JPJ = 2

JPIJ = $(call plus,$(JPI),$(JPJ))

答案 5 :(得分:2)

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

一个例子

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

$(info JP-IJ = $(JP-IJ) )
# prints: JP-IJ = 8

另见Guile手册Arithmetic Functions

可能检查Guile:

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

答案 6 :(得分:0)

使用makepp会更容易。您可以直接访问底层的Perl解释器。在这种情况下,makeperl函数在作为Perl进行求值之前进行变量扩展,OTO只会评估perl函数:

JPI=4
JPJ=2
JPIJ = $(makeperl $(JPI)*$(JPJ))
&echo result: $(JPIJ)

您可以将规则之外的builtin& echo命令用作语句。

答案 7 :(得分:0)

要向池中添加最新答案:The GNUmake table toolkit具有许多算术函数。您可以加,减,乘,除,取底数为8,10和16的模数。还有常用的二进制运算andorxor和{{1} }。数字可以在60位数左右,但是如果您需要更多的数字,可以进行调整。该代码是纯GNUmake语法,因此可在Windows和Unix之间移植,与shell脚本相反-如果您想对数字进行紧缩处理,当然可能会有更好的解决方案;)

这里是一个例子:

not

输出:

include gmtt/gmtt.mk

NUMBER_A := -12392834798732429827442389
NUMBER_B := 984398723982791273498234
$(info $(call add,$(NUMBER_A),$(NUMBER_B)))
$(info $(call sub,$(NUMBER_A),$(NUMBER_B)))
$(info $(call mul,$(NUMBER_A),$(NUMBER_B)))
$(info $(call div,$(NUMBER_A),$(NUMBER_B)))
$(info $(call mod,$(NUMBER_A),$(NUMBER_B)))