Makefile ifeq logique ou

92

Comment effectuer un OU logique en utilisant l' ifeqopérateur make ?

par exemple, j'ai (simplifié):

ifeq ($(GCC_MINOR), 4)
    CFLAGS += -fno-strict-overflow
endif
ifeq ($(GCC_MINOR), 5)
    CFLAGS += -fno-strict-overflow
endif

mais souhaite consolider ces lignes.

(oui, oui, autotools, configure, etc etc; trop lourd pour la situation actuelle, aimerait tout garder dans le Makefile ici)

[l'opposé logique de cette question: Comment utiliser une condition multiple dans l'instruction 'ifeq' ]

Tapoter
la source
Copie possible de l' archivage des conditions complexes dans Makefile .
Peter Mortensen le
1
Ne pensez pas que c'est une dupe, la question liée concerne les ifdefopérateurs de chaînage , cette question est liée aux ifeqopérateurs de chaînage , similaire, mais les réponses sont définitivement différentes.
Pat le
Similaire à Y a-t-il un ORopérateur logique pour le ifneq?
JamesThomasMoon1979

Réponses:

103

Comme trouvé dans l'archive de la liste de diffusion,

on peut utiliser la fonction de filtre .

Par exemple

 ifeq ($(GCC_MINOR),$(filter $(GCC_MINOR),4 5))

le filtre X, AB renverra ceux de A, B égaux à X.

Une variante de ceci est

 ifneq (,$(filter $(GCC_MINOR),4 5))

où une comparaison négative avec une chaîne vide est utilisée à la place (le filtre retournera une chaîne vide si GCC_MINOR ne correspond pas aux arguments)

L'inconvénient de ces méthodes est que les arguments doivent être des mots uniques.

misiu_mp
la source
7
Une note tardive: dans les deux variantes que vous avez ci-dessus, la première se résoudra à true si $ (GCC_MINOR) est vide, alors que la seconde ne le sera pas (donc la seconde est la meilleure solution génériquement).
John
1
En fait, ça devrait être ifneq (,$(filter 4 5,$(GCC_MINOR))):)
Tuxdude
2
Peut-être vaut-il mieux laisser tel quel pour plus de simplicité?
Jason le
Une autre note: Cela ne fonctionne pas comme général déclaration OR. Nous voulons vérifier quelque chose if(flagA == TRUE || flagB == true), mais si vous le faites $(filter true, $(flagA) $(flagB)et que les deux sont vrais, vous obtenezifeq(true, true true)
Charlie Su
27

Vous pouvez introduire une autre variable. Cela ne consolide pas les deux contrôles, mais cela évite au moins d'avoir à remettre le corps en deux:

do_it = 
ifeq ($(GCC_MINOR), 4)
    do_it = yes
endif
ifeq ($(GCC_MINOR), 5)
    do_it = yes
endif
ifdef do_it
    CFLAGS += -fno-strict-overflow
endif
Foo Bah
la source
7
La maintenabilité de ceci à l'échelle ne me semble pas très bonne: / Encore une fois, une fois que nous avons commencé à parler d'échelle, je suppose que nous parlons d'autotools
Pat
2
@Pat: Je préfère cette approche où je peux séparer l'affectation en un seul endroit dans le Makefile, éventuellement en la comparant à plus de valeurs en utilisant ifeq / else ifeq / else, plutôt que d'utiliser la fonction de filtre qui pourrait simplement rendre les lignes extrêmement longues et difficiles à lire .
jcarballo
15

Je ne pense pas qu'il existe une manière concise et sensée de le faire, mais il existe des moyens verbeux et sensés (comme celui de Foo Bah) et des moyens concis et pathologiques, tels que

ifneq (,$(findstring $(GCC_MINOR),4-5))
    CFLAGS += -fno-strict-overflow
endif

(qui exécutera la commande à condition que la chaîne $ (GCC_MINOR) apparaisse à l'intérieur de la chaîne 4-5).

Ruakh
la source
4
Pour le meilleur ou pour le pire (probablement pour le pire), juste le genre de bidouillage que je recherchais; merci
Pat
1
Je ne pense pas que ce soit pathologique du tout, à part le fait que tout dans un Makefile est pathologique. C'est vraiment assez élégant. J'ai lu quatre ou cinq façons différentes d'y parvenir, et la vôtre est de loin la plus simple à comprendre.
Michael Geary
8

Voici une variante plus flexible: elle utilise un shell externe, mais permet de vérifier les conditions arbitraires:

ifeq ($(shell test ".$(GCC_MINOR)" = .4  -o  \
                   ".$(GCC_MINOR)" = .5  -o  \
                   ".$(TODAY)"     = .Friday  &&  printf "true"), true)
    CFLAGS += -fno-strict-overflow
endif
sqr163
la source
1
ifeq ($(GCC_MINOR), 4)
    CFLAGS += -fno-strict-overflow
endif
ifeq ($(GCC_MINOR), 5)
    CFLAGS += -fno-strict-overflow
endif

Un autre que vous pouvez envisager d'utiliser dans ce cas est:

GCC42_OR_LATER = $(shell $(CXX) -v 2>&1 | $(EGREP) -c "^gcc version (4.[2-9]|[5-9])")

# -Wstrict-overflow: http://www.airs.com/blog/archives/120
ifeq ($(GCC42_OR_LATER),1)
  CFLAGS += -Wstrict-overflow
endif

J'utilise en fait la même chose dans mon code parce que je ne veux pas maintenir un fichier configou Configure.

Mais vous devez utiliser un portable, non anémique make, comme GNU make ( gmake), et pas celui de Posix make.

Et il n'aborde pas la question du logique ANDet OR.

jww
la source