web-dev-qa-db-ja.com

makefileで演算を実行するにはどうすればよいですか?

Makefile内の変数に対していくつかの操作を実行することは可能ですか?たとえば、定義

JPI=4
JPJ=2

$(JPI)* $(JPJ)の拡張値に等しい変数JPIJを同じメイクファイルで定義することは可能ですか?

37
malaboca

Bash算術展開を使用

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

最初の行は、 デフォルト(sh)の代わりにBashシェルを選択することです 。通常、shは算術展開をサポートしていません。ただし、Ubuntuでは、/ bin/shは Dashによって提供され、この機能をサポートしています 。そのため、その行はスキップできます。

ダブルドル記号は、 拡張がシェルによって実行されることを望んでいるためです 。注:JPIおよびJPJ変数は、最初にmakeによって展開され、次に式が次のようにbashに渡されます。

$(( 4 * 2 ))
27
Dominic

GNU makeを使用していて、bcがシステムにインストールされている場合は、次のように使用できます。

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

不器用です(または見方によっては見事です)が、GNU makeで直接算術演算を実行できます。 Learning GNU Make Functions with算数 。ただし、この方法は適切にスケーリングされないことに注意してください。質問で示したように、この方法は小さな数値に対してはうまく機能しますが、大きなマグニチュードを持つ数値を処理するときはうまく機能しません。 (10,000,000以上)。

10
Eric Melski

@mrkjからの回答は素晴らしいですが、@ Danielが言及しているように、すべてのシステムにbcがあるわけではありません(たとえば、MSysにはありません)。

シェルを使用する次の2つの方法を見つけました:$$((...))および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を使用する場合、[shall+の前後にスペースを入れるか、4+2を返すことに注意してください。 $$を使用する場合、これは必要ありません。

bcが手元にあれば、間違いなくそれを使用できます。次のページは非常に興味深いものでした: http://www.humbug.in/2010/makefile-tricks-arithmetic-addition-subtraction-multiplication-division-modulo-comparison/

8

GNU Make Standard Library は整数演算関数を提供します。

include gmsl

JPI = 4
JPJ = 2

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

GNU Make with Guile のサポート(つまり、バージョン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

Guile 算術関数 のマニュアルも参照してください。

ガイルの可能なチェック:

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

遅い答えをプールに追加するには、次のようにします。 GNUmakeテーブルツールキット は、多くの算術関数を備えています。加算、減算、乗算、除算、8、10、16を基数とするモジュラスを使用できます。また、通常のバイナリ演算andorxornotもあります。数値は約60桁ですが、さらに必要な場合はこれを採用できます。コードは純粋なGNUmake構文であるため、シェルスクリプトとは異なり、WindowsとUnix間で移植可能です。

次に例を示します。

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

出力:

$ make
-11408436074749638553944155
-13377233522715221100940623
-12199490762401735834920873237276176262117128241026
-12
-580050110938934545463581
0
Vroomfondel

makepp を使用すると、はるかに簡単です。基盤となるPerlインタープリターに直接アクセスできます。この場合、makeperl関数はPerlとして評価する前に変数の展開を行い、Perl関数OTOHは次のもののみを評価します。

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

組み込みの&echoコマンドをルールの外でステートメントとして使用できます。

0
Daniel