правило, определенное в шаблоне Makefile, не работает - PullRequest
0 голосов
/ 26 февраля 2019

Я пытаюсь использовать шаблон с foreach для создания нескольких правил построения.Ниже приведен весь мой пример кода.

variable.mk:
    echo 'variable.mk'
    echo 'test variable.mk' > $@


FILES:=cpf dma
define generate_template
$(warning input is $(1) end)
$(1): variable.mk
    echo [CC] $(1)
    echo 'test $(1)' > $(1)
endef

$(foreach module,$(FILES),$(eval $(call generate_template,$(module))))

run.sh:cpf dma
    echo [CC] run.sh
    echo 'TEST run.sh' >$@

Но когда я запускаю make run.sh в командной строке, он показывает следующее сообщение об ошибке:

make: *** No rule to make target `cpf', needed by `run.sh'.  Stop.

Правило для cpf target isожидается, что он будет создан шаблоном generate_template в строке 14, но он не работает так, как ожидалось.Может ли кто-нибудь помочь мне выбраться из этой проблемы?Я искал вокруг Google, но я все еще не мог понять это.

1 Ответ

0 голосов
/ 26 февраля 2019

Типичная ошибка при попытке использовать $(eval ...) для сгенерированных правил: ваш генератор не генерирует окончательный конец строки, и поэтому make не анализирует сгенерированные правила, так как вы думаете, что они должны быть проанализированы.

Решение: Всегда конец многострочных макросов, определяющих правило (я) пустой строкой.Это гарантирует, что правила $(eval) будут правильными.

variable.mk:
    echo $@
    echo 'test $@' > $@

FILES := cpf dma

# the empty line at the end of the macro is on purpose 
define generate_template
$(warning input is $(1) end)
$(1): variable.mk
    echo [CC] $$@
    echo 'test $$@' > $$@

endef

$(foreach module,$(FILES),$(eval $(call generate_template,$(module))))

run.sh: cpf dma
    echo [CC] $@
    echo 'TEST $@' >$@

Тестовый прогон:

$ make run.sh
Makefile:14: input is cpf end
Makefile:14: input is dma end
echo variable.mk
variable.mk
echo 'test variable.mk' > variable.mk
echo [CC] cpf
[CC] cpf
echo 'test cpf' > cpf
echo [CC] dma
[CC] dma
echo 'test dma' > dma
echo [CC] run.sh
[CC] run.sh
echo 'TEST run.sh' >run.sh

$ cat variable.mk cpf dma run.sh 
test variable.mk
test cpf
test dma
TEST run.sh

Я бы также предложил переписать ваш макрос, чтобы выполнить толькооднократная оценка, т. е.

$(eval $(foreach module,$(FILES),$(call generate_template,$(module))))

СОВЕТ: в случае, если $(eval ...) не работает должным образом, я всегда изменяю его на $(info eval ...), чтобы точно узнать, что оценивается.Обычно это позволяет легко определять ошибки и опечатки в макросах генерации кода.

...