Efectuarea de calcule mai mari decât mai puțin decât într-un Makefile

Încerc să fac asta într-un Makefile:

value = 2.0

if ${greaterthan ${value}, 1.50}
-> execute a rule
elseif ${lessthan ${value}, 0.50}
-> execute a rule
endif

Pare un lucru destul de obișnuit să vrei să faci. Care este cel mai bun mod de a face asta?


person Dan    schedule 09.08.2010    source sursă
comment
Posibil duplicat al Mai mare decât compararea șirurilor într-un Makefile< /i>.   -  person Peter Mortensen    schedule 27.06.2016
comment
Din titlul întrebării, nu este clar dacă doriți să faceți clauza if cu limba Makefile sau cu shell-ul de bază make is using (adică cu directive $(shell) sau în reţete) precum îl propune răspunsul selectat.   -  person jmon12    schedule 20.02.2020


Răspunsuri (4)


Similar cu această întrebare, dar, practic, puteți utiliza comenzi shell în interiorul unui Makefile. Deci următoarele sunt perfect legale:

foo:
    if [ ${value} -gt 2 ] ; then \
         #Do stuff;\
    fi

Editați pentru o mică declinare a răspunderii: IIRC, bash nu înțelege aritmetica în virgulă mobilă. Le poate interpreta ca șiruri, dar ar putea face lucrurile puțin ciudate. Asigurați-vă că luați în considerare acest lucru.

person eldarerathis    schedule 09.08.2010
comment
Ar funcționa asta pe Windows? Și/sau în MinGW? - person Peter Mortensen; 27.06.2016
comment
sh este shell-ul implicit folosit în GNU Makefile, cred. Dacă nu utilizați GNU Makefile, atunci ați dori să consultați documentația versiunii Makefile pentru a afla ce shell este utilizat. Sau, puteți pur și simplu să puneți o declarație precum SHELL:=/bin/bash în partea de sus a fișierului dvs. Makefile pentru a-l declara pentru utilizare, de ex. bash. Rețineți că acest lucru poate avea unele efecte subtile asupra modului în care mediul este transmis între comenzile Makefile. - person user5359531; 21.01.2019
comment
@PeterMortensen Nu va funcționa pe Windows brut, cum ar fi o regulă cu ls sau o directivă shell $(shell ls). GNU make (începând cu 3.81) pe Windows selectează întotdeauna SHELL=sh.exe din experiența mea și înțelege numai lotul Windows. Nu știu dacă acest shell poate înțelege bash dacă ai instalat Cygwin sau MinGW. - person jmon12; 20.02.2020

Incearca asta

În acest exemplu, VER este verificat pentru mai mult de 4

ifeq ($(shell test $(VER) -gt 4; echo $$?),0)
  IFLAGS += -I$(TOPDIR)/include
  LIBS += -L$(TOPDIR)/libs -lpcap
endif
person manpatha    schedule 05.02.2015
comment
Ce este implicat aici? Bash? Funcționează numai pe Linux (și Mac OS X)? - person Peter Mortensen; 27.06.2016
comment
acesta este de fapt sh, dar va funcționa și în bash - person user5359531; 21.01.2019

Modul meu preferat de a face acest lucru este:

value = 2.0
ifeq ($(shell expr $(value) \>= 1.5), 1)
   # execute a rule
else ifeq ($(shell expr $(value) \<= 0.5), 1)
   # execute a rule
endif
person Maciej Freudenheim    schedule 09.05.2017

Utilizarea comenzilor shell, așa cum este menționat în celelalte răspunsuri, ar trebui să fie suficientă pentru majoritatea cazurilor de utilizare:

if [ 1 -gt 0 ]; then \
    #do something \
fi

Cu toate acestea, dacă, ca mine, doriți să utilizați comparația mai mare decât pentru a apoi să setați o variabilă make prin comanda $(eval) a lui make, atunci veți descoperi că încercând să faceți acest lucru folosind modelul celuilalt răspuns:

if [ 1 -gt 0 ]; then \
    $(eval FOO := value) \
fi

generează o eroare:

if [ 1 -gt 0 ]; then  fi;
/bin/bash: -c: line 0: syntax error near unexpected token `fi'
/bin/bash: -c: line 0: `if [ 1 -gt 0 ]; then  fi;'
make: *** [clean] Error 2```

Motivul este că expresia $(eval) a lui make returnează șirul gol. Codul bash rezultat este apoi malformat.**

Am venit cu următoarea soluție (după ce am încercat multe abordări diferite!).

$(if $(shell [ $(FOO) -ge 1 ] && echo "OK"), \
    $(eval BAR := true), \
    $(eval BAR := false))

Este necesar să imprimați un șir după efectuarea comparației aritmetice (partea echo "OK") deoarece operatorul $(if) al lui make se bazează pe logica șirurilor goale:

$(dacă condiția, atunci-part[,else-part])

Funcția if oferă suport pentru extinderea condiționată într-un context funcțional (spre deosebire de GNU makefile condiționale, cum ar fi ifeq (vezi Sintaxa Condiționalelor).

Primul argument, condiția, are mai întâi toate spațiile albe anterioare și cele din urmă eliminate, apoi este extins. Dacă se extinde la orice șir nevid, atunci condiția este considerată adevărată. Dacă se extinde la un șir gol, condiția este considerată falsă.

Sursa: GNU Make Manual

Sper că acest lucru vă ajută!

** Notă: inițial, m-am gândit că problema ar putea fi rezolvată cu ușurință prin adăugarea unei comenzi bash care nu face nimic expresiei, cum ar fi true:

if [ $(VALUE) -ge 1 ]; then \
    true; $(eval BAR := GreaterOrEqualThan1) \
else \
    true; $(eval BAR := LowerThan1) \
fi

S-a dovedit a fi o idee groaznică. Încă nu mi-am dat seama de ce, dar ramura else este întotdeauna executată, independent de rezultatul comparației.

Cred că ar trebui să deschid o întrebare pentru acest caz.

person levelont    schedule 31.05.2017
comment
Acest lucru se datorează faptului că $(eval BAR := XXX) este un construct makefile evaluat la momentul de analiză makefile, în timp ce rețeta shell care testează condiția este o *rețetă asemănătoare shell evaluată la momentul execuției rețetei . - person qneill; 31.10.2018