Makefile ifeq логічний або


92

Як ви виконуєте логічне АБО за допомогою 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операторів, подібне, але відповіді, безумовно, різні.
Пет

Відповіді:


103

Як знайдено в архіві списків розсилки,

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

Наприклад

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

фільтр X, AB поверне значення A, B, які дорівнюють X.

Варіацією цього є

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

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

Недоліком цих методів є аргументи, які мають бути окремими словами.


7
Пізня примітка: у двох варіантах, які ви мали вище, перший перетвориться на істину, якщо $ (GCC_MINOR) порожній, тоді як другий ні, (отже, другий є кращим рішенням загалом).
Джон

1
Власне, так і повинно бути ifneq (,$(filter 4 5,$(GCC_MINOR))):)
Tuxdude

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
На краще чи гірше (можливо гірше), саме такий брудний хак, який я шукав; спасибі
Pat

1
Я не думаю, що це взагалі патологічно, крім того, що все у Makefile є патологічним. Це справді досить елегантно. Я прочитав чотири-п’ять різних способів досягти цього, і ваш, безумовно, найпростіший для розуміння.
Michael Geary

8

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

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

Ще одним варіантом, який ви можете розглянути в цьому випадку, є:

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.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.