Как выполнить арифметику в make-файле? - PullRequest
35 голосов
/ 18 декабря 2009

Можно ли выполнить некоторые операции над переменными в make-файле? Например, определение

JPI=4
JPJ=2

Можно ли в том же make-файле определить переменную JPIJ, равную расширенному значению $ (JPI) * $ (JPJ)?

Ответы [ 8 ]

27 голосов
/ 12 апреля 2013

Использование Расширение арифметики Bash :

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

Первая строка должна выбрать оболочку Bash вместо значения по умолчанию (sh) . Как правило, sh не поддерживает арифметическое расширение. Однако в Ubuntu / bin / sh предоставляется Dash, который поддерживает эту функцию . Так что эту строку можно пропустить.

Двойной знак доллара - потому что мы хотим, чтобы расширение было выполнено оболочкой Примечание: переменные JPI и JPJ сначала расширяются с помощью make, затем выражение передается в bash следующим образом:

$(( 4 * 2 ))
13 голосов
/ 18 декабря 2009

Если вы используете GNU make и в вашей системе установлено bc, вы можете использовать что-то вроде этого:

JPI=4
JPJ=2
FOO=$(shell echo $(JPI)\*$(JPJ) | bc)
all:
  echo $(FOO)
10 голосов
/ 18 декабря 2009

Это неуклюже (или блестяще, в зависимости от вашей перспективы), но вы можете делать арифметику прямо в GNU make. См. Изучение функций GNU Make с помощью арифметики . Имейте в виду, что этот метод плохо масштабируется. Он отлично работает для небольших чисел, как вы показали в своем вопросе, но не очень хорошо, когда вы работаете с числами большой величины (больше 10 000 000).

7 голосов
/ 30 декабря 2015

Ответ от @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 голосов
/ 07 января 2014

Стандартная библиотека GNU Make предоставляет целочисленные арифметические функции.

include gmsl

JPI = 4
JPJ = 2

JPIJ = $(call plus,$(JPI),$(JPJ))
2 голосов
/ 16 августа 2017

В GNU Make с поддержкой 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 Арифметические функции .

Возможная проверка на Guile:

ifeq (,$(filter guile,$(.FEATURES)))
  $(error Your Make version $(MAKE_VERSION) is not built with support for Guile)
endif
0 голосов
/ 09 октября 2018

Чтобы добавить поздний ответ в пул: Набор инструментов таблицы GNUmake содержит множество арифметических функций. Вы можете сложить, вычесть, умножить, разделить, взять модуль в базе 8,10 и 16. Также есть обычные бинарные операции and, or, xor и not. Числа могут быть около 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 голосов
/ 30 декабря 2012

С makepp это намного проще. Вы получаете прямой доступ к основному интерпретатору Perl. В этом случае функция makeperl выполняет раскрытие переменной перед оценкой как Perl, функция perl OTOH будет оценивать только:

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

Вы можете использовать команду buildin & echo вне правила как инструкцию.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...