GNU делает условную функцию $ (if ...) внутри пользовательской функции всегда равной true - PullRequest
11 голосов
/ 25 января 2012

Я пытаюсь написать функцию make, чтобы коснуться / создать пустой файл и / или установить разрешения, пользователя и группу, где это возможно, или предупредить, если нет.Тем не менее, каждая условная проверка в моей функции, кажется, оценивается как true.

Основы моего Makefile:

INSTALL_USER  := fileUser
INSTALL_GROUP := fileGroup

.PHONY: test
test:
    $(call touchFile,~/test.ini)

define touchFile
$(eval fileName := $(strip $(1)))
-touch $(fileName)
-chmod -c 664 $(fileName)

$(info filename info $(fileName))
$(info $(shell stat -c "%a %U:%G" $(fileName)))

$(if ifeq  "foo" "bar", @echo match is broken, @echo match works)
$(if ifneq "foo" "bar", @echo match works, @echo match is broken)

$(if ifneq ($(shell stat -c %a $(fileName)),664), $(warning Error - $(fileName) does not have expected permissions of 664))
-chgrp -c $(INSTALL_GROUP) $(fileName)
$(if ifneq ($(shell stat -c %G $(fileName)),$(INSTALL_GROUP)), $(warning Error - $(fileName) does not belong to $(INSTALL_GROUP) group))
-chown -c $(INSTALL_USER) $(fileName)
$(if ifneq ($(shell stat -c %U $(fileName)),$(INSTALL_USER)), $(warning Error - $(fileName) does not belong to $(INSTALL_USER) user))
endef

Запуск make test выходных данных

filename info ~/test.ini
664 myUserName:myGroup
Makefile:7: Error - ~/test.ini does not have expected permissions of 664
Makefile:7: Error - ~/test.ini does not belong to common group
Makefile:7: Error - ~/test.ini does not belong to netserve user
touch ~/test.ini
chmod -c 664 ~/test.ini
match is broken
match works
chgrp -c fileGroup ~/test.ini
changed group of `/home/myUserName/test.ini' to fileGroup
chown -c fileUser ~/test.ini
chown: changing ownership of `/home/myUserName/test.ini': Operation not permitted
make: [test] Error 1 (ignored)

IМы рассмотрели / попробовали следующее:

  • $ (если ...) вычисляется во время компиляции, прежде чем функция будет вызвана с параметром.Но жестко ifeq "foo" "bar" также дает неверный результат.Кроме того, $(info ...) правильно оценивает $(fileName) во время компиляции.
  • Документация на самом деле не дает примеров, поэтому в дополнение к $(if ifeq...) я также попробовал $(ifeq ...), который, казалось, был проигнорирован.
  • "Нефункциональный" if (то есть ifeq без $(if...)) внутри функции дает /bin/sh: ifeq: command not found.

Может ли кто-нибудь помочь определить, почему мои условные выражения не работают так, как я ожидаю (или почему я ожидаю не того)?

Предостережение: Я знаю, что все еще есть ошибкинужно решить, если файл не существует, но это должно быть тривиально по сравнению с этим препятствием.

Ответы [ 4 ]

43 голосов
/ 25 января 2012

$(if ...) условная функция оценивается как true, когда первый переданный ей аргумент не пуст. В вашем случае это буквальный текст: ifeq "foo" "bar", который, очевидно, не пустой.

ifeq / ifneq условия фактически являются директивами, а не функциями. Их нельзя использовать внутри определения переменных и в функциях.

Возвращаясь к вашему примеру, чтобы проверить строку на равенство внутри условия, используйте такие функции, как filter и findstring:

$(if $(filter foo,bar),@echo match is broken,@echo match works)
$(if $(filter-out foo,bar),@echo match works,@echo match is broken)

Кстати, это также может быть преобразовано в встроенную форму для лучшей читаемости:

@echo match $(if $(filter foo,bar),is broken,works)
@echo match $(if $(filter-out foo,bar),works,is broken)
7 голосов
/ 16 июля 2015

Я столкнулся с этой проблемой и обнаружил, что вы можете использовать результат функции «filter» в части «condition» функции «if». Вот пример, полезный для открытия pdf в Linux (с «evince») или в OSX с «open»)

uname     :=$(shell uname -s)
is_darwin :=$(filter Darwin,$(uname))
viewpdf   :=$(if $(is_darwin), open, evince)
2 голосов
/ 25 января 2012

Вы, похоже, неправильно понимаете, как работает $(if.Из документации make info:

$ (если CONDITION, THEN-PART [, ELSE-PART]) Функция `if 'обеспечивает поддержку условного расширения в функциональном контексте

Первый аргумент, CONDITION, сначала удаляет все предшествующие и конечные пробелы, а затем расширяется.Если он расширяется до любой непустой строки, то условие считается истинным.Если оно раскрывается в пустую строку, условие считается ложным.

Во всех ваших примерах ваше условие выглядит как ifeq SOMETHING OTHERTHING - непустая строка (изifeq независимо от того, что есть другие вещи), и поэтому рассматривается как истина.

1 голос
/ 01 сентября 2017

, если вы хотите проверить, что ваша версия ОС является linux или другой, и если это Linux, то вы хотите напечатать некоторое сообщение, тогда вы можете выполнить следующие шаги:

ifneq ($(TARGETOS), Linux)
    target: server
    @echo
    @echo $(MSG) $(TARGETOS)
else
target: server
    @echo $(MSG) $(TARGET)
endif

, прежде чем я попытался с ifeq, ноон напечатал только остальную часть.моя операционная система Linux, Ubuntu.

Если кто-то обнаружит, что этот ответ следует изменить, чтобы он мог дать лучший ответ и для этого.

...