Makefile дает разные результаты при запуске во второй раз
У меня есть такое правило в make-файле:
target : dependencies
rm -rd somedirectory
runcodecoverage.exe # this generates somefile
$(eval COVERAGE=$(shell grep "blah" somefile))
@echo $(COVERAGE)
Когда я запускаю этот файл в первый раз (после очистки), эхо ничего не печатает. Но второй и раз после этого он печатает правильный результат. Если я заменю строку $(eval ..) просто grep "blah" somefile
Я получаю желаемый результат, поэтому проблема заключается в использовании $(eval) и $(shell). Почему это происходит?
Изменить: я решил это, добавив новую зависимость, так что теперь это выглядит так:
generatesomefile :
runcodecoverage.exe # this generates somefile
target : dependencies generatesomefile
rm -rd somedirectory
$(eval COVERAGE=$(shell grep "blah" somefile))
@echo $(COVERAGE)
Кажется, что $(eval) был заменен результатом grep, как только цель target была введена, хотя я хотел, чтобы она запускалась после запуска runcodecoverage.exe. В этом смысле ответ, который я принял как правильный, был не совсем верным - в документах говорится о расширении переменных:
Определение правила
Правило всегда раскрывается одинаково, независимо от формы:
немедленно: немедленно; отложенный отложенный
2 ответа
eval
функция работает не так, как вы думаете.
При первом запуске Make он расширяет eval
функция и выполняет присвоение переменной перед выполнением любого правила. А так как нет somefile
, grep
ничего не возвращает и COVERAGE
остается пустым Когда Make выполняет правило, оно передает пустую переменную echo
который должным образом ничего не сообщает.
Во второй раз, когда вы запускаете Make, он снова расширяет eval
функция, выполняет grep
на somefile
(который был построен при первом запуске) и сохраняет результат в COVERAGE
, Затем он выполняет правило и передает COVERAGE
к echo
, который ставит его на вашем экране.
$(eval ...)
запускается при разборе вашего Makefile, а не при выполнении рецепта.
Мне не ясно, что вы ожидаете; установка переменной Make из рецепта не выглядит устойчивым подходом, но она во многом зависит от того, где и как вам нужно использовать эту переменную. Если все, что вам нужно, это вывести покрытие из того же рецепта, замените последние пару строк просто
grep "blah" somefile