Подтвердить что ты не робот

Проверьте, существует ли каталог внутри 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?

4b9b3361

Ответ 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

Ответ 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 .