Makefile ifeq lógico ou

92

Como você executa um OR lógico usando o ifeqoperador make ?

por exemplo, eu tenho (simplificado):

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

mas gostaria de consolidar essas linhas.

(sim, sim, autotools, configure, etc etc; muito pesado para a situação atual, gostaria de manter tudo dentro do Makefile aqui)

[o oposto lógico desta pergunta: Como usar a condição múltipla na instrução 'ifeq' ]

Pat
fonte
Possível duplicata de verificação de condições complexas no Makefile .
Peter Mortensen
1
Não pense que é um tolo, a questão vinculada está relacionada aos ifdefoperadores de encadeamento , esta questão está relacionada aos ifeqoperadores de encadeamento , semelhantes, mas as respostas são definitivamente diferentes.
Pat
Semelhante a Existe um ORoperador lógico para o ifneq?
JamesThomasMoon1979

Respostas:

103

Conforme encontrado no arquivo da lista de discussão,

pode-se usar a função de filtro .

Por exemplo

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

o filtro X, AB retornará aqueles de A, B que são iguais a X.

Uma variação disso é

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

onde uma comparação negativa com uma string vazia é usada (o filtro retornará uma string vazia se GCC_MINOR não corresponder aos argumentos)

A desvantagem desses métodos é que os argumentos precisam ser palavras isoladas.

misiu_mp
fonte
7
Uma observação tardia: nas duas variações que você tem acima, a primeira será verdadeira se $ (GCC_MINOR) estiver em branco, enquanto a segunda não (portanto, a segunda é a melhor solução genericamente).
João
1
Na verdade, deveria ser ifneq (,$(filter 4 5,$(GCC_MINOR))):)
Tuxdude
2
Talvez seja melhor deixar como está para simplificar?
Jason
Outra observação: isso não funciona como uma instrução OU geral . Temos algo que queremos verificar if(flagA == TRUE || flagB == true), mas se você fizer $(filter true, $(flagA) $(flagB)e ambos forem verdadeiros, você obteráifeq(true, true true)
Charlie Su
27

Você pode introduzir outra variável. Não consolida as duas verificações, mas pelo menos evita ter que colocar o corpo duas vezes:

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
fonte
7
A capacidade de manutenção disso em escala não parece muito boa para mim: / Então, novamente, uma vez que começamos a falar de escala, acho que estamos falando de ferramentas automáticas
Pat
2
@Pat: Prefiro essa abordagem onde posso separar a atribuição em um lugar no Makefile, possivelmente comparando com mais valores usando ifeq / else ifeq / else, em vez de usar a função de filtro que poderia tornar as linhas terrivelmente longas e difíceis de ler .
jcarballo
15

Não acho que exista uma forma concisa e sensata de fazer isso, mas existem formas verbosas e sensatas (como a de Foo Bah) e formas concisas e patológicas, como

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

(que executará o comando desde que a string $ (GCC_MINOR) apareça dentro da string 4-5).

Ruakh
fonte
4
Para melhor ou pior (provavelmente pior), exatamente o tipo de hack sujo que eu estava procurando; obrigado
Pat,
1
Eu não acho que isso seja patológico, exceto o fato de que tudo em um Makefile é patológico. É realmente muito elegante. Eu li quatro ou cinco maneiras diferentes de fazer isso, e a sua é de longe a mais fácil de entender.
Michael Geary
8

Variante aqui mais flexível: ele usa shell externo, mas permite verificar se há condições arbitrárias:

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

Outro que você pode considerar usar neste caso é:

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

Na verdade, eu uso o mesmo em meu código porque não quero manter um configou Configure.

Mas você tem que usar um portátil, não anêmico make, como o GNU make ( gmake), e não o Posix make.

E não aborda a questão do ANDe lógico OR.

jww
fonte