В Makefile deploy
рецепту нужна переменная окружения, которая ENV
должна быть настроена для правильного выполнения, в то время как другим все равно, например:
ENV =
.PHONY: deploy hello
deploy:
rsync . $(ENV).example.com:/var/www/myapp/
hello:
echo "I don't care about ENV, just saying hello!"
Как я могу убедиться, что эта переменная установлена, например: есть ли способ объявить эту переменную makefile как обязательное условие рецепта развертывания, например:
deploy: make-sure-ENV-variable-is-set
?
Спасибо.
make
он быть установлен, или выдавать предупреждение, или генерировать фатальную ошибку?make ENV=dev
но если он забудетENV=dev
,deploy
рецепт не удастся ...Ответы:
Это приведет к фатальной ошибке, если
ENV
она не определена и что-то нужно (в любом случае в GNUMake).(Обратите внимание, что ifndef и endif не имеют отступов - они управляют тем, что make «видит» , вступая в силу перед запуском Makefile. «$ (Error» имеет отступ с вкладкой, поэтому он запускается только в контексте правила.)
источник
ENV is undefined
когда запускаю задачу, у которой нет check-env в качестве предварительного условия.check-env
правиле; Make не будет расширять его до тех пор, пока не будет выполнено правило. Если он не начинается с TAB (как в примере @ rane), Make интерпретирует его как не входящий в правило, и оценивает его перед выполнением любого правила, независимо от цели.Вы можете создать неявную защитную цель, которая проверяет, что переменная в стебле определена, например так:
Затем вы добавляете
guard-ENVVAR
цель везде, где хотите утверждать, что переменная определена, например так:Если вы позвоните
make change-hostname
без добавленияHOSTNAME=somehostname
звонка, вы получите сообщение об ошибке, и сборка не удастся.источник
if [ -z '${${*}}' ]; then echo 'Environment variable $* not set' && exit 1; fi
DВстроенный вариант
В моих make-файлах я обычно использую выражение вроде:
Причины:
Не забудьте комментарий, который важен для отладки:
... заставляет вас искать Makefile, пока ...
... объясняет прямо, что не так
Глобальный вариант (для полноты, но не задан)
В верхней части вашего Makefile вы также можете написать:
Предупреждения:
clean
цель потерпит неудачу, если ENV не установлен. В противном случае см. Ответ Гудона, который является более сложнымисточник
@
. -> gnu.org/software/make/manual/make.html#Echoing@test -n "$(name)" || (echo 'A name must be defined for the backup. Ex: make backup name=xyz' && exit 1)
Пока что возможной проблемой с данными ответами является то, что порядок зависимости в make не определен. Например, работает:
когда
target
есть несколько зависимостей, это не гарантирует, что они будут работать в любом заданном порядке.Решением для этого (чтобы гарантировать, что ENV будет проверен до выбора рецептов) является проверка ENV во время первого прохода make вне любого рецепта:
Вы можете прочитать о различных функциях / переменных, используемых здесь, и
$()
это просто способ явно заявить, что мы сравниваем с «ничем».источник
Я обнаружил, что лучший ответ не может быть использован в качестве требования, за исключением других целей PHONY. Если используется как зависимость для цели, которая является реальным файлом, использование
check-env
заставит цель файла быть перестроенной.Другие ответы являются глобальными (например, переменная требуется для всех целей в Makefile) или используют оболочку, например, если ENV отсутствовал, make завершится независимо от цели.
Решение, которое я нашел для обеих проблем:
Выход выглядит как
value
есть некоторые страшные предостережения, но для этого простого использования я считаю, что это лучший выбор.источник
Как я вижу, самой команде нужна переменная ENV, чтобы вы могли проверить это в самой команде:
источник
deploy
это не единственный рецепт, которому нужна эта переменная. С этим решением я должен проверить состояниеENV
каждого из них ... в то время как я хотел бы иметь дело с ним как с одной (своего рода) предпосылкой.Я знаю, что это старо, но я подумала, что поделюсь своим собственным опытом для будущих посетителей, так как это немного аккуратнее ИМХО.
Как правило,
make
будет использоваться вsh
качестве оболочки по умолчанию ( устанавливается через специальнуюSHELL
переменную ). Вsh
и его производных, это тривиально выйти с сообщением об ошибке при извлечении переменного окружения , если он не установлен или нулевой , выполнив:${VAR?Variable VAR was not set or null}
.Расширяя это, мы можем написать повторно используемую цель make, которая может использоваться для сбоя других целей, если переменная окружения не была установлена:
Вещи примечания:
$$
) необходим для отсрочки расширения в оболочку, а не вmake
test
просто предотвращает попытки оболочки выполнить содержимоеVAR
(это не служит никакой другой важной цели).check-env-vars
может быть тривиально расширен для проверки большего количества переменных среды, каждая из которых добавляет только одну строку (например@test $${NEWENV?Please set environment variable NEWENV}
)источник
ENV
есть пробелы, это, кажется, неВы можете использовать
ifdef
вместо другой цели.источник
deploy
это не единственный рецепт проверкиENV
переменной состояния..PHONY: deploy
anddeploy:
перед блоком ifdef и удалите дублирование. (Кстати, я отредактировал ответ, чтобы отразить правильный метод)