2009-08-27 4 views
13

Я пытаюсь написать GNU make Makefile, который имеет нагрузку с аналогичными целями, где команды сборки немного различаются между ними. Я пытаюсь использовать target-specific variables для представления этих вариантов. Некоторые из этих значений переменных относятся к файлам, которые я хочу использовать в качестве предварительных условий. Например:Целевые переменные как предварительные условия в 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) 

Когда я называю сделать Target_1 ", я хочу, чтобы это сделать target1_prereq, если он не существует. На данный момент, похоже, не используется target1_prereq как обязательное условие, хотя команда build (do_something) вызывается с правильным параметром.

Я использую GNU Make 3.80.


Edit: Несколько больше осложнений от реальной системы. Некоторые из переменных сами основаны на значениях других переменных. Вручное указание предварительных условий не будет масштабироваться. Несколько более сложный пример:

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

Целевая переменная определяется только в командах цели (или в других целевых назначениях); он не может использоваться как один из целевых параметров. Я не думаю, что есть чистый способ сделать то, что вы хотите в Make, но есть несколько kludgey подходов, такие как следующие:

 
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,$^) 
+4

Воскрешая эту тему в интересах кого-то, кто наткнулся на нее. [Более элегантное решение] (http://stackoverflow.com/questions/9311743/make-using-target-specific-variables-in-prerequisites) использует вторичное расширение. – Seth

+0

@Seth, я согласен: 'target_1 target_2: common_filename $$ (special_filename_base) .exta $$ (special_filename_base) .extb ...' – Beta

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) 

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

+0

Я предполагаю, что решает конкретный случай, который я разместил, но я надеялся на более общее решение. Я отредактирую с более сложным примером. –

2

Я нашел довольно чистый способ бокового шагового этого ограничения , Он пошел бы что-то вроде этого:

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 целевых переменных, так что они будут доступны, когда мы повторно запустить make-файл.
  2. Создайте прокси-цель, у которой есть все исходные предпосылки target_1 target_2 и в target_1 target_2 снова вызовите Makefile с этой целью прокси. Поскольку цели конкретные переменные будет иметь значение, то (мы являемся в рецепте к тому времени) и они были export Е.Д., они будут доступны в target-proxy - вуаля :)

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