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
Другие вопросы по тегам