Как сделать прерывание команды $(shell)
У меня есть Makefile, который начинается с запуска инструмента перед применением правил сборки (который этот инструмент пишет для меня). Если этот инструмент, который является python script, завершается с не нулевым кодом состояния, я хочу, чтобы GNU Make останавливался прямо там и не продолжал строить программу.
В настоящее время я делаю что-то вроде этого (верхний уровень, т.е. столбец 1):
$(info Generating build rules...)
$(shell python collect_sources.py)
include BuildRules.mk
Но это не останавливается, если collect_sources.py
завершает работу с кодом состояния 1. Это также фиксирует стандартный вывод collect_sources.py
, но не распечатывает его, поэтому у меня такое чувство, что я искал неправильные направление.
Если это вообще возможно, решение должно работать даже тогда, когда простая оболочка MS-DOS является стандартной системной оболочкой.
Любое предложение?
Ответы
Ответ 1
Хорошо, вот мое собственное решение, которое, к сожалению, не основано на коде состояния collect_sources.py script, но который работает для меня (TM) и позволяет мне видеть любой вывод, который создает script:
SHELL_OUTPUT := $(shell python collect_sources.py 2>&1)
ifeq ($(filter error: [Errno %],$(SHELL_OUTPUT)),)
$(info $(SHELL_OUTPUT))
else
$(error $(SHELL_OUTPUT))
endif
script записывается так, чтобы любая ошибка выдавала результат, начинающийся с "collect_sources: error:"
. Кроме того, если python не может найти или выполнить заданный script, он выдает сообщение об ошибке, содержащее сообщение "[Errno 2]"
или подобное. Таким образом, этот маленький фрагмент кода просто захватывает вывод (перенаправляет stderr в stdout) и ищет сообщения об ошибках. Если ни один не найден, он просто использует $(info)
для печати вывода, в противном случае он использует $(error)
, что эффективно делает остановку.
Обратите внимание, что отступ в ifeq ... endif
выполняется с пробелами. Если используются вкладки, Make думает, что вы пытаетесь вызвать команду и жалуетесь на нее.
Ответ 2
Там может быть лучший способ, но я попробовал следующее, и он работает:
$(if $(shell if your_command; then echo ok; fi), , $(error your_command failed))
Здесь я предположил, что your_command
не дает никакого вывода, но не должно быть трудно обойти такую ситуацию.
Изменить. Чтобы заставить его работать с оболочкой Windows по умолчанию (и, возможно, с любой подходящей оболочкой), вы можете написать your_command && echo ok
вместо if
в функции shell
. Я не думаю, что это возможно для (старых) оболочек DOS. Для этого вы, вероятно, захотите адаптировать your_command
или написать обертку script, чтобы напечатать что-то по ошибке (или успеху).
Ответ 3
Вы должны использовать обычную цель для создания BuildRules.mk:
BuildRules.mk: collect_sources.py
python $< >[email protected]
include BuildRules.mk
Это стандартный трюк для автоматического создания зависимостей.
Ответ 4
Исправление fooobar.com/questions/280310/...
.PHONY: BuildRules.mk
BuildRules.mk: collect_sources.py
echo Generating build rules...)
python $< >[email protected]
$(MAKE) -f BuildRules.mk
Ответ 5
Убедитесь, что вы не вызываете make/gmake с опцией -k.