Is het mogelijk om bepaalde bewerkingen uit te voeren op variabelen in een makefile?
Bijvoorbeeld het definiëren van
JPI=4
JPJ=2
is het mogelijk om in dezelfde makefile een variabele JPIJ
te definiëren die gelijk is aan de uitgebreide waarde van $(JPI)*$(JPJ)
?
Antwoord 1, autoriteit 100%
Met behulp van Bash rekenkundige uitbreiding:
SHELL=/bin/bash
JPI=4
JPJ=2
all:
echo $$(( $(JPI) * $(JPJ) ))
De eerste regel is om in plaats daarvan de Bash-shell te kiezen van de standaard (sh). Doorgaans ondersteunt sh geen rekenkundige uitbreiding. In Ubuntu wordt /bin/sh echter geleverd door Dash, dat deze functie ondersteunt. Dus die regel kan worden overgeslagen.
Het dubbele dollartekenis omdat we de uitbreiding die door de schaal moet worden gedaan. Opmerking: de JPI- en JPJ-variabelen worden eerst uitgebreid met make, daarna wordt de uitdrukking als volgt aan bash doorgegeven:
$(( 4 * 2 ))
Antwoord 2, autoriteit 42%
Als je GNU make
gebruikt en bc
op je systeem hebt geïnstalleerd, kun je zoiets als dit gebruiken:
JPI=4
JPJ=2
FOO=$(shell echo $(JPI)\*$(JPJ) | bc)
all:
echo $(FOO)
Antwoord 3, autoriteit 42%
Antwoord van @mrkj is geweldig, maar zoals @Daniel vermeldt, hebben niet alle systemen bc
(ik heb het bijvoorbeeld niet op MSys).
Ik heb de twee volgende methoden gevonden, beide met behulp van shell: $$(( … ))en 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))
Merk op dat wanneer u expr
gebruikt, u zalspaties rond de +
plaatst, anders wordt 4+2
. Dit is niet vereist bij gebruik van $$
.
.
Als je bc
beschikbaar hebt, kun je daar zeker mee akkoord gaan. Ik vond de volgende pagina erg interessant: http://www.humbug.in/2010/makefile-tricks-arithmetic-addition-subtraction-multiplication-division-modulo-comparison/
Antwoord 4, autoriteit 29%
Het is onhandig (of briljant, afhankelijk van je perspectief), maar je kunt direct rekenen in GNU make. Zie GNU Make-functies leren met rekenkunde. Houd er echter rekening mee dat deze methode niet goed schaalt. Het zal geweldig werken voor kleine getallen, zoals je in je vraag hebt laten zien, maar het werkt niet goed als je werkt met getallen met een grote omvang (groter dan 10.000.000).
Antwoord 5, autoriteit 16%
In GNU Make met Guile-ondersteuning ( dwz sinds versie 4.0) is het gemakkelijk om de taal van het schema te gebruiken voor rekenkundige of andere berekeningen. Het wordt gedaan zonder een subshell of onderliggend proces te maken.
Een voorbeeld
JP-I := 4
JP-J := 2
JP-IJ := $(guile (* $(JP-I) $(JP-J) ))
$(info JP-IJ = $(JP-IJ) )
# prints: JP-IJ = 8
Zie ook de handleiding voor Guile Rekenkundige functies.
Een mogelijke cheque voor Guile:
ifeq (,$(filter guile,$(.FEATURES)))
$(error Your Make version $(MAKE_VERSION) is not built with support for Guile)
endif
Antwoord 6, autoriteit 8%
De GNU Make Standard Librarybiedt rekenkundige functies voor gehele getallen.
include gmsl
JPI = 4
JPJ = 2
JPIJ = $(call plus,$(JPI),$(JPJ))
Antwoord 7
Met makeppis het veel gemakkelijker. U krijgt direct toegang tot de onderliggende Perl-interpreter. In dit geval voert de makeperl-functie een variabele expansie uit voordat deze wordt geëvalueerd als Perl, de perl-functie OTOH zou alleen evalueren:
JPI=4
JPJ=2
JPIJ = $(makeperl $(JPI)*$(JPJ))
&echo result: $(JPIJ)
U kunt het ingebouwde &echo-commando buiten een regel als statement gebruiken.
Antwoord 8
Om een laat antwoord aan de pool toe te voegen: De GNUmake-tabeltoolkitbevat veel rekenkundige functies. Je kunt optellen, aftrekken, vermenigvuldigen, delen, de modulus nemen in grondtal 8,10 en 16. Ook zijn er de gebruikelijke binaire bewerkingen and
, or
, xor
en not
. Nummers kunnen rond de 60 cijfers zijn, maar u kunt dit aanpassen als u meer nodig heeft. De code is pure GNUmake-syntaxis en daarom overdraagbaar tussen Windows en Unix, in tegenstelling tot shell-scripts – voor het geval je nummercrunch wilt, zijn er natuurlijk betere oplossingen 😉 natuurlijk.
Hier is een voorbeeld:
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)))
Uitvoer:
$ make
-11408436074749638553944155
-13377233522715221100940623
-12199490762401735834920873237276176262117128241026
-12
-580050110938934545463581