Проверьте, существует ли каталог внутри make файла
В ответе @Grundlefleck объясняет, как проверить, существует ли каталог или нет. Я попытался использовать это внутри makefile
следующим образом:
foo.bak: foo.bar
echo "foo"
if [ -d "~/Dropbox" ]; then
echo "Dir exists"
fi
Запуск make foo.bak
(при условии, что foo.bar
существует) дает следующую ошибку:
echo "foo"
foo
if [ -d "~/Dropbox" ]; then
/bin/sh: -c: line 1: syntax error: unexpected end of file
make: *** [foo.bak] Error 2
Обходной путь, который я сделал, состоял в том, чтобы иметь автономный bash script, где был реализован тест, и я вызвал script из makefile
. Это, однако, звучит очень громоздко. Есть ли лучший способ проверить, существует ли каталог из makefile
?
Ответы
Ответ 1
Выполнять команды, если команда оболочки должна находиться в одной строке или быть в нескольких строках, используя обратную косую черту для расширения строки. Таким образом, этот подход будет работать:
foo.bak: foo.bar
echo "foo"
if [ -d "~/Dropbox" ]; then echo "Dir exists"; fi
или
foo.bak: foo.bar
echo "foo"
if [ -d "~/Dropbox" ]; then \
echo "Dir exists"; \
fi
Ответ 2
Этот подход работает с минимальным echos:
.PHONY: all
all:
ifneq ($(wildcard ~/Dropbox/.*),)
@echo "Found ~/Dropbox."
else
@echo "Did not find ~/Dropbox."
endif
Ответ 3
Попробуйте следующее:
.PHONY: all
something:
echo "hi"
all:
test -d "Documents" && something
Это будет выполнять команды под something
, только если Documents
существует.
Чтобы решить проблему отмеченную в комментариях, вы можете сделать такую переменную:
PATH_TEST = ~/SomeDirectory
test -d $(PATH_TEST) && something
Ответ 4
Действовать при отсутствии каталога
Если вам нужно только знать, существует ли каталог и не хочет действовать, например, создав его, вы можете использовать обычные цели Makefile:
directory = ~/Dropbox
all: | $(directory)
@echo "Continuation regardless of existence of ~/Dropbox"
$(directory):
@echo "Folder $(directory) does not exist"
mkdir -p [email protected]
.PHONY: all
Примечания:
-
|
указывает, что make не должен заботиться о метке времени (это только для заказа).
- Вместо записи
mkdir -p [email protected]
вы можете написать false
для выхода или решить ваш вопрос по-другому.
Если вам также нужно выполнить определенную серию инструкций в существовании каталога, вы не можете использовать вышеприведенное. Другими словами, это эквивалентно:
if [ ! -d "~/Dropbox" ]; then
echo "The ~/Dropbox folder does not exist"
fi
Нет инструкции else
.
Действовать при наличии каталога
Если вам нужна противоположная if-statement, это также возможно:
directory = $(wildcard ~/Dropbox)
all: | $(directory)
@echo "Continuation regardless of existence of ~/Dropbox"
$(directory):
@echo "Folder $(directory) exists"
.PHONY: all $(directory)
Это эквивалентно:
if [ -d "~/Dropbox" ]; then
echo "The ~/Dropbox folder does exist"
fi
Опять же, нет инструкции else
.
Действуйте как при наличии, так и в отсутствии каталога
Это становится немного более громоздким, но в конце дает вам хорошие цели для обоих случаев:
directory = ~/Dropbox
dir_target = $(directory)-$(wildcard $(directory))
dir_present = $(directory)-$(directory)
dir_absent = $(directory)-
all: | $(dir_target)
@echo "Continuation regardless of existence of ~/Dropbox"
$(dir_present):
@echo "Folder $(directory) exists"
$(dir_absent):
@echo "Folder $(directory) does not exist"
.PHONY: all
Это эквивалентно:
if [ -d "~/Dropbox" ]; then
echo "The ~/Dropbox folder does exist"
else
echo "The ~/Dropbox folder does not exist"
fi
Естественно, расширение подстановки может быть медленнее, чем оператор if-else. Однако третий случай, вероятно, довольно редок и просто добавлен для полноты.
Ответ 5
У меня был случай, когда я хотел определить переменную на основе теста, существует ли каталог или нет на самом верхнем уровне Makefile
, где описанные выше подходы не работают. Я нашел здесь приятное решение, которое можно использовать следующим образом:
MY_DIRNAME=../External
ifneq "$(wildcard $(MY_DIRNAME) )" ""
# if directory MY_DIRNAME exists:
INCLUDES += -I../External
else
# if it doesn't:
INCLUDES += -I$(HOME)/Code/External
endif
Это изменит переменную INCLUDES
на основе того, существует или нет каталог, хранящийся в MY_DIRNAME
.
(Мотивация: в моем случае эта переменная будет использоваться в другом Makefile
, включенном позже первым:
include $(SFRAME_DIR)/Makefile.common
Я хотел бы, чтобы один и тот же Makefile
работал в двух разных средах простым способом.)
Ответ 6
Существует совсем другой ответ, который позволяет использовать ваши операторы if
, как вы предполагали, в одной оболочке:
.ONESHELL:
foo.bak: foo.bar
echo "foo"
if [ -d "~/Dropbox" ]; then
echo "Dir exists"
fi
Обратите внимание, что единственное отличие состоит в том, что специальная цель ONESHELL .