Makefile ifeq logic или

94

Как выполнить логическое ИЛИ с помощью ifeqоператора make ?

например, у меня есть (упрощенно):

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

но хотелось бы закрепить эти строки.

(да, да, автоинструменты, настройка и т. д.; слишком тяжеловесны для текущей ситуации, хотелось бы сохранить все в Makefile здесь)

[логическая противоположность этого вопроса: как использовать множественное условие в выражении ifeq ]

Пэт
источник
Возможный дубликат проверки сложных условий в Makefile .
Питер Мортенсен
1
Не думайте, что это обман, связанный вопрос относится к ifdefоператорам цепочки , этот вопрос связан с ifeqоператорами цепочки , похож, но ответы определенно разные.
Пэт

Ответы:

104

Как видно из архива списка рассылки,

можно использовать функцию фильтра .

Например

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

filter X, AB вернет те из A, B, которые равны X.

Вариант этого

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

где вместо этого используется отрицательное сравнение с пустой строкой ( фильтр вернет пустую строку, если GCC_MINOR не соответствует аргументам)

Обратной стороной этих методов является то, что аргументы должны быть отдельными словами.

оборота misiu_mp
источник
7
Позднее примечание: в двух вариантах, которые у вас есть выше, первый будет разрешен в true, если $ (GCC_MINOR) пуст, а второй - нет (таким образом, второе решение в целом является лучшим решением).
Джон
1
Собственно, так и должно быть ifneq (,$(filter 4 5,$(GCC_MINOR))):)
Tuxdude 05
2
Может, для простоты лучше оставить как есть?
Джейсон
Еще одно замечание: это не работает как общее ИЛИ. У нас есть кое-что, что мы хотим проверить if(flagA == TRUE || flagB == true), но если вы это сделаете $(filter true, $(flagA) $(flagB)и оба они верны, вы получитеifeq(true, true true)
Чарли Су
27

Вы можете ввести другую переменную. Он не объединяет обе проверки, но, по крайней мере, избавляет от необходимости вставлять тело дважды:

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
Ремонтопригодность этого в масштабе не кажется мне очень хорошей: / С другой стороны, как только мы начнем говорить о масштабе, я думаю, мы говорим об автоинструментах
Пэт
2
@Pat: я предпочитаю этот подход, когда я могу разделить назначение в одном месте в Makefile, возможно, сравнивая с большим количеством значений с помощью ifeq / else ifeq / else, а не с помощью функции фильтра, которая может просто сделать очень длинные трудные для чтения строки .
jcarballo
15

Я не думаю, что есть краткий и разумный способ сделать это, но есть многословные, разумные способы (например, Фу Ба) и краткие, патологические способы, такие как

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

(который выполнит команду при условии, что строка $ (GCC_MINOR) появится внутри строки 4-5).

руах
источник
4
Хорошо это или плохо (возможно, хуже), но именно такой грязный хак я искал; спасибо
Пэт
1
Я не думаю, что это вообще патология, кроме того факта, что все в Makefile патологично. Это действительно довольно элегантно. Я прочитал четыре или пять различных способов добиться этого, и ваш, безусловно, самый простой для понимания.
Майкл Гири
8

Здесь более гибкий вариант: использует внешнюю оболочку, но позволяет проверять произвольные условия:

ifeq ($(shell test ".$(GCC_MINOR)" = .4  -o  \
                   ".$(GCC_MINOR)" = .5  -o  \
                   ".$(TODAY)"     = .Friday  &&  printf "true"), true)
    CFLAGS += -fno-strict-overflow
endif
sqr163
источник
1
ifeq ($(GCC_MINOR), 4)
    CFLAGS += -fno-strict-overflow
endif
ifeq ($(GCC_MINOR), 5)
    CFLAGS += -fno-strict-overflow
endif

Еще один вариант, который вы можете использовать в этом случае:

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

На самом деле я использую то же самое в своем коде, потому что не хочу поддерживать отдельный configили Configure.

Но вы должны использовать портативный, не анемичный make, такой как GNU make ( gmake), а не Posix make.

И это не решает проблему логического ANDи OR.

jww
источник