Makefile ifeq lógico o


92

¿Cómo se realiza un OR lógico con el ifeqoperador make ?

por ejemplo, tengo (simplificado):

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

pero quisiera consolidar estas líneas.

(sí, sí, autotools, configure, etc, etc; demasiado torpe para la situación actual, me gustaría mantener todo dentro del Makefile aquí)

[opuesto lógico de esta pregunta: cómo usar una condición múltiple en la declaración 'ifeq' ]



1
No crea que es un engaño, la pregunta vinculada se relaciona con el encadenamiento de ifdefoperadores, esta pregunta está relacionada con el encadenamiento de ifeqoperadores, similar, pero las respuestas son definitivamente diferentes.
Pat

Respuestas:


103

Como se encuentra en el archivo de la lista de correo,

se puede utilizar la función de filtro .

Por ejemplo

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

el filtro X, AB devolverá los de A, B que son iguales a X.

Una variación de esto es

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

donde se usa una comparación negativa con una cadena vacía (el filtro devolverá una cadena vacía si GCC_MINOR no coincide con los argumentos)

La desventaja de esos métodos es que los argumentos deben ser palabras sueltas.


7
Una nota tardía: en las dos variaciones que tiene arriba, la primera se resolverá como verdadera si $ (GCC_MINOR) está en blanco, mientras que la segunda no (por lo tanto, la segunda es la mejor solución genéricamente hablando).
John

1
En realidad, debería ser ifneq (,$(filter 4 5,$(GCC_MINOR))):)
Tuxdude

2
¿Quizás es mejor dejarlo como está por simplicidad?
Jason

Otra nota: esto no funciona como una declaración OR general . Tenemos algo que queremos verificar if(flagA == TRUE || flagB == true), pero si lo hace $(filter true, $(flagA) $(flagB)y ambos son ciertos, obtieneifeq(true, true true)
Charlie Su

27

Puede introducir otra variable. No consolida ambos controles, pero al menos evita tener que meter el cuerpo dos veces:

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 capacidad de mantenimiento de esto a escala no me parece muy buena: / Por otra parte, una vez que empezamos a hablar de escala, supongo que estamos hablando de autotools
Pat

2
@Pat: Prefiero este enfoque en el que puedo separar la asignación en un lugar en el Makefile, posiblemente comparando con más valores usando ifeq / else ifeq / else, en lugar de usar la función de filtro que podría hacer que las líneas sean terriblemente largas y difíciles de leer .
jcarballo

15

No creo que haya una forma concisa y sensata de hacer eso, pero hay formas detalladas y sensatas (como la de Foo Bah) y formas concisas y patológicas, como

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

(que ejecutará el comando siempre que la cadena $ (GCC_MINOR) aparezca dentro de la cadena 4-5).


4
Para bien o para mal (probablemente peor), el tipo de truco sucio que estaba buscando; gracias
Pat

1
No creo que esto sea patológico en absoluto, aparte del hecho de que todo en un Makefile es patológico. Realmente es bastante elegante. He leído cuatro o cinco formas diferentes de lograr esto, y la suya es, con mucho, la más fácil de entender.
Michael Geary

8

Aquí una variante más flexible: usa un shell externo, pero permite verificar condiciones arbitrarias:

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

Otro que puede considerar usar en este caso es:

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

En realidad yo uso el mismo en mi código porque no quiero mantener una por separado configoConfigure .

Pero tienes que usar un portátil, no anémico make, como GNU make ( gmake), y no el de Posix make.

Y no aborda la cuestión de la lógica ANDy OR.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.