Целевые переменные как предпосылки в Makefile - PullRequest
14 голосов
/ 27 августа 2009

Я пытаюсь написать 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 в качестве предварительного условия, хотя команда сборки (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)

Ответы [ 3 ]

3 голосов
/ 31 августа 2009

Переменная, специфичная для цели, определяется только в командах цели (или в других назначениях, специфичных для цели); это не может быть использовано в качестве одного из требований цели. Я не думаю, что есть простой способ сделать то, что вы хотите в 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,$^)
3 голосов
/ 27 августа 2009

Как простой обходной путь:

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)

Существует некоторая избыточность, но она локализована, так что это не так уж плохо.

2 голосов
/ 01 марта 2011

Я нашел довольно чистый способ обойти это ограничение. Было бы что-то вроде этого:

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)

Два важных момента:

  1. export целевые переменные, чтобы они были доступны при повторном запуске Makefile.
  2. Создайте цель прокси, которая имеет все исходные предпосылки target_1 target_2, и в target_1 target_2 снова вызовите Makefile с этой целью прокси. Поскольку целевые переменные будут иметь значения к тому времени (мы будем в рецепте к тому времени) и они были export ed, они будут доступны в target-proxy - вуаля:)

Недостатком этого подхода является то, что мы создаем еще один процесс make - если это просто еще один, то, вероятно, все в порядке, но YMMV, поэтому будьте особенно осторожны.

...