Ответ 1
TL; DR: Если вы хотите запрограммировать make, отмените GNU Make в пользу BSD Make.
Это персональная рекомендация. В то время как BSD Make кажется более ограниченным, чем GNU Make, поскольку он предлагает меньше программных возможностей, намного проще программировать и имеет несколько уникальных функций убийцы. Вот почему я предлагаю решение с GNU Make и другое решение для BSD Make:
Выполнение этого в GNU Make
Используя GNU Make, вы можете написать макрос для определения цели. Канонический способ определения последовательности в Makefile состоит в том, чтобы добавить этапы последовательности как зависимости к цели, как показано ниже:
vars= hello world
define something_t =
something: something-$(1)
something-$(1):
@echo $(1)
endef
$(foreach _,$(vars),$(eval $(call something_t,$_)))
Рекомендуется использовать эту организацию (а не определять только одну цель), потому что вы можете работать над ней, чтобы сделать задачу легко возобновленной, если прервать последовательность. Makefile описывает работу, продвижение которой полностью описывается состоянием файловой системы. Затем задача легко возобновляется, если каждый шаг связан с файлом, обычно объектом компиляции, но иногда также и пустым файлом, который используется для указания того, что важные контрольные точки переданы.
Использование вспомогательного макроса - это гибкое решение, которое может быть адаптировано к более сложным задачам, чем просто повторение имени. Обратите внимание, что это работает с новейшими версиями GNU Make (4.1). В GNU Make 3.81 вы должны удалить знак равенства из определения макроса.
Адаптация вашего примера для BSD Make
Если это вариант для вас, я рекомендую отказаться от использования GNU Make и заменить его на BSD Make, который прост в программировании: it имеет короткую и точную документацию, в то время как документация GNU Make очень многословна и несколько неясна, BSD Make имеет примеры промышленной прочности сложных наборов правил (система сборки FreeBSD или BSD Owl) и он имеет простой и предсказуемый макроязык.
vars= hello world
something:
.for _var in ${vars}
echo ${_var}
.endfor
Это может эволюционировать для поддержки более сложных задач, просто заменив echo
на адаптированные команды или используя промежуточные шаги.
Разрешить пользователю переопределять некоторые задачи, а также в BSD Make
В этом чуть более расширенном варианте мы разрешаем пользователю переопределять наши собственные рецепты для создания целей something-hello
и something-world
.
Для каждого элемента в нашем списке цель something-*
создается, если она еще не существует, и добавляется к зависимостям something
. Вся операция определения этих целей происходит только в том случае, если something
осталось undefined. Поэтому пользователи этих макросов могут:
- Переопределить рецепты для
something-hello
иsomething-world
- Отмените полную процедуру, связанную с
something
.
Реализация таких возможностей настройки является обязательной, если мы хотим написать полезные, многоразовые макросы для Make. К несчастью, настройка этого вида почти невозможна в GNU Make.
vars = hello world
.if!target(depend)
.for _var in ${vars}
.if!target(something-${_var})
something-${_var}:
echo ${_var}
.endif
something: something-${_var}
.endfor
.endif