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' ]



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

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.


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

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


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

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.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.