Целевые переменные как предварительные условия в Makefile
Я пытаюсь написать GNU make Makefile, который имеет нагрузку с аналогичными целями, где команды сборки немного отличаются друг от друга.
Я пытаюсь использовать целевые переменные для представления этих вариантов. Некоторые из этих значений переменных относятся к файлам, которые я хочу использовать в качестве предварительных условий. Например:
target_1:special_filename=target1_prereq
target_2:special_filename=target2_prereq
target_1 target_2: common_filename $(special_filename)
do_something common_filename --a-weird-option=$(special_filename)
Когда я вызываю 'make target_1', я хочу, чтобы он сделал target1_prereq, если он не существует. На данный момент, как представляется, в качестве предпосылки не используется target1_prereq, хотя команда build (do_something) вызывается с правильным параметром.
Я использую GNU Make 3.80.
Изменить:
Еще несколько осложнений от реальной системы. Некоторые из переменных сами основаны на значениях других переменных. Вручное указание предварительных условий не будет масштабироваться.
Несколько более сложный пример:
target_1:special_filename_base=target1_prereq
target_2:special_filename_base=target2_prereq
some_filename_a = $(special_filename_base).exta
some_filename_b = $(special_filename_base).extb
target_1 target_2: common_filename $(special_filename_b) $(special_filename_a)
do_something common_filename --a-weird-option=$(special_filename_a) --second=$(special_filename_b)
Ответы
Ответ 1
Целевая переменная определяется только в целевых командах (или в других целевых назначениях); он не может использоваться как один из целевых пререксов. Я не думаю, что есть чистый способ сделать то, что вы хотите в Make, но есть несколько подходов, таких как:
EXTENSIONS = .exta .extb
target_1: $(addprefix target1_prereq,$(EXTENSIONS))
target_2: $(addprefix target2_prereq,$(EXTENSIONS))
target_1 target_2: common_filename
do_something common_filename --a-weird-option=$(filter %.exta,$^) --second=$(filter %.extb,$^)
Ответ 2
В качестве простого обходного пути:
target_1:special_filename=target1_prereq
target_1:target1_prereq
target_2:special_filename=target2_prereq
target_2:target2_prereq
target_1 target_2: common_filename $(special_filename)
do_something common_filename --a-weird-option=$(special_filename)
Существует некоторая избыточность, но она локализована, поэтому это не так уж плохо.
Ответ 3
Я нашел довольно чистый способ пошагового ограничения этого ограничения. Было бы так:
target_1:export special_filename_base=target1_prereq
target_2:export special_filename_base=target2_prereq
some_filename_a = $(special_filename_base).exta
some_filename_b = $(special_filename_base).extb
target_1 target_2:
$(MAKE) -f $(firstword $(MAKEFILE_LIST)) target-proxy
target-proxy: common_filename $(special_filename_b) $(special_filename_a)
do_something common_filename --a-weird-option=$(special_filename_a) --second=$(special_filename_b)
Два важных момента:
-
export
целевые переменные, чтобы они были доступны, когда мы повторно запускаем Makefile.
- Создайте прокси-цель, у которой есть все исходные предпосылки
target_1 target_2
и в target_1 target_2
снова вызовите Makefile с этой целью прокси. Поскольку целевые конкретные переменные будут иметь значения к тому времени (мы в рецепте к тому времени), и они были export
ed, они будут доступны в target-proxy
- voila:)
Недостатком этого подхода является то, что мы создаем еще один процесс make
- если он просто другой, то он, вероятно, хорошо, но YMMV, так что будьте осторожны.