Makefile ifeq logical lub


94

Jak wykonać logiczne OR przy użyciu ifeqoperatora make ?

np. mam (uproszczone):

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

ale chciałbym skonsolidować te linie.

(tak, tak, narzędzia automatyczne, konfiguracja itp.; zbyt ciężki w obecnej sytuacji, chciałbym zachować wszystko w pliku Makefile tutaj)

[logiczne przeciwieństwo tego pytania: jak używać warunku wielokrotnego w instrukcji „ifeq” ]



1
Nie myśl, że to oszustwo, połączone pytanie dotyczy ifdefoperatorów łańcuchowych , to pytanie dotyczy ifeqoperatorów łańcuchowych , podobnie, ale odpowiedzi są zdecydowanie inne.
Pat,

Odpowiedzi:


104

Jak stwierdzono w archiwum listy mailingowej,

można użyć funkcji filtru .

Na przykład

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

filtr X, AB zwróci te z A, B, które są równe X.

Odmiana tego jest

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

gdzie zamiast tego używane jest negatywne porównanie z pustym ciągiem ( filtr zwróci pusty ciąg, jeśli GCC_MINOR nie pasuje do argumentów)

Wadą tych metod jest to, że argumenty muszą być pojedynczymi słowami.


7
Późna uwaga: w dwóch wariantach, które masz powyżej, pierwsza rozwiąże się na true, jeśli $ (GCC_MINOR) jest pusta, podczas gdy druga nie (dlatego druga jest ogólnie lepszym rozwiązaniem).
John

1
Właściwie powinno być ifneq (,$(filter 4 5,$(GCC_MINOR))):)
Tuxdude

2
Może lepiej zostawić takie, jakie jest dla prostoty?
Jason

Kolejna uwaga: to nie działa jako ogólne stwierdzenie LUB. Mamy coś, co chcemy sprawdzić if(flagA == TRUE || flagB == true), ale jeśli to zrobisz $(filter true, $(flagA) $(flagB)i oba są prawdziwe, otrzymaszifeq(true, true true)
Charlie Su

27

Możesz wprowadzić inną zmienną. Nie konsoliduje obu kontroli, ale przynajmniej unika konieczności dwukrotnego umieszczania ciała:

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
Łatwość utrzymania tego w skali nie wydaje mi się zbyt dobra: / Z drugiej strony, kiedy zaczniemy mówić o skali, myślę, że mówimy o automatycznych narzędziach
Pat

2
@Pat: Wolę to podejście, w którym mogę oddzielić przypisanie w jednym miejscu w pliku Makefile, prawdopodobnie porównując z większą liczbą wartości przy użyciu ifeq / else ifeq / else, zamiast używać funkcji filtrującej, która może po prostu bardzo utrudnić odczytanie długich wierszy .
jcarballo

15

Nie sądzę, aby istniał zwięzły, rozsądny sposób, aby to zrobić, ale są rozwlekłe, rozsądne sposoby (takie jak Foo Bah) i zwięzłe, patologiczne sposoby, takie jak

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

(co wykona polecenie pod warunkiem, że ciąg $ (GCC_MINOR) pojawi się wewnątrz ciągu 4-5).


4
Na dobre lub na złe (prawdopodobnie gorsze), po prostu rodzaj brudnego hacka, którego szukałem; dzięki
Pat

1
Nie sądzę, żeby to było w ogóle patologiczne, poza faktem, że wszystko w pliku Makefile jest patologiczne. Jest naprawdę dość elegancki. Przeczytałem cztery lub pięć różnych sposobów osiągnięcia tego, a twój jest zdecydowanie najłatwiejszy do zrozumienia.
Michael Geary,

8

Tutaj wariant bardziej elastyczny: wykorzystuje zewnętrzną powłokę, ale pozwala sprawdzić dowolne warunki:

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

Innym, który możesz rozważyć w tym przypadku, jest:

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

Właściwie używam tego samego w moim kodzie, ponieważ nie chcę utrzymywać oddzielnego configlubConfigure .

Ale musisz użyć przenośnego, nie-anemicznego make, takiego jak GNU make ( gmake), a nie Posix make.

I nie rozwiązuje problemu logicznego ANDi OR.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.