У меня есть проект с кучей фальшивых правил Makefile, которые зависят друг от друга и используют один и тот же базовый рецепт. (Этот Makefile используется больше для сопоставления зависимостей, чем для создания артефактов сборки.) Makefile выглядит примерно так:
.PHONY: foo bar baz qux
foo:
@echo $@
bar: foo
@echo $@
baz: foo
@echo $@
qux: bar baz
@echo $@
На самом деле Makefile определяет десятки правил, поэтому он стал довольно подробным. Вместо того, чтобы явно указывать один и тот же рецепт для каждого правила, я хотел бы следовать принципу DRY и определить рецепт по умолчанию для всех целей, в результате чего Makefile выглядит следующим образом:
.PHONY: foo bar baz qux
foo:
bar: foo
baz: foo
qux: bar baz
Часть, которую мне не хватает, - это то, как определить этот рецепт по умолчанию. Один «обходной путь», который я нашел, заключается в использовании подхода, основанного на макросах, но он приводит к большому количеству дублированного кода и делает правила гораздо менее читабельными:
define defrule
.PHONY: $1
$1: $2
@echo $$@
endef
$(eval $(call defrule,foo))
$(eval $(call defrule,bar,foo))
$(eval $(call defrule,baz,foo))
$(eval $(call defrule,qux,bar baz))
Мне интересно, может ли помочь правило match-anything, хотя я не добился в этом никакого успеха. Также обратите внимание, что меня не волнуют рецепты, запускаемые несколько раз (при нацеливании на qux
правило foo
запускается дважды, и это нормально для моего варианта использования).
Я хотел бы следовать принципу DRY и определить рецепт по умолчанию для всех целей.
Если вы хотите указать, что несколько целей должны быть построены по одному и тому же рецепту, просто назовите их все как цели одного и того же правила:
foo bar baz qux:
@echo $@
Это указывает на то, что каждая цель может быть построена путем запуска рецепта правила, а не то, что все они создаются с помощью одного запуска рецепта, что, я думаю, именно то, что вам нужно. $@
правильно отражает цель, построенную при любом выполнении рецепта.
Вы можете объявить их зависимости с помощью отдельных правил только для зависимостей:
bar: foo
baz: foo
qux: bar baz
. И, конечно же, вы все еще можете объявить их .PHONY:
.PHONY: foo bar baz qux
Идеальный! Несмотря на то, что я видел эту конструкцию раньше в руководстве, это первый раз, когда она применима ко мне.