2015-08-17 3 views
0

Я использую Make для организации анализа данных, и у меня есть несколько наборов входных данных, каждый из которых может быть проанализирован с помощью набора контрольных данных. Разумеется, для каждого из этих наборов данных требуется собственный бит предварительной обработки. То, что я хотел бы, чтобы иметь неявное правило, которое можно разобрать из относительно простую структуру каталогов, и использовать это, чтобы понять, какие предпосылки, чтобы сделать, так, например, если я хотел бежать:Makefile неявные правила с вызовами функций в зависимостях

make ref1/sample1_processed ref1/sample2_processed ref2/sample1_processed #...etc 

Я мог есть неявное правило, которое выглядит примерно так:

%_processed: $(dir %)/preprocessed samples/$(notdir %)_preprocessed 
    process_data --reference $(dir $*)/preprocessed --sample samples/$(notdir $*)_preprocessed 

который идеально сделать может интерпретировать, как:

ref1/sample1_processed -> (ref1/preprocessed, samples/sample1_preprocessed) 
ref1/sample2_processed -> (ref1/preprocessed, samples/sample2_preprocessed) 
ref2/sample1_processed -> (ref2/preprocessed, samples/sample1_preprocessed) 

(где -> будет означать зависит).

Однако, по-видимому, происходит то, что функция вызывает отказ в линии зависимостей (они, по-видимому, прекрасно работают в самом рецепте).

Вот минимальный нерабочим образец, который я думаю, сообщается, что я хотел бы, чтобы произошло:

%_processed: $(dir %)/preprocessed samples/$(notdir %)_preprocessed 
    echo $(dir $*) 
    echo $(notdir $*) 
    echo "Done" 

samples/%_preprocessed: samples/% 
    touch [email protected] 

%/preprocessed: | % 
    touch [email protected] 


ref%: 
    mkdir [email protected] 

и из командной строки:

$ mkdir samples/ 
$ touch samples/sample1 samples/sample2 
$ make ref1/sample1_processed 
make: *** No rule to make target `ref1/sample1_processed'. Stop. 

Но если вы закомментировать зависимых от% _processed, он работает нормально (хотя и не проверяет указанные зависимости):

$ make ref1/sample1_processed 
echo ref1/ 
ref1/ 
echo sample1 
sample1 
echo "Done" 
Done 

Любая помощь здесь была бы высоко оценена!

ответ

2

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

Там больше, чем один из способов решить эту проблему, но я хотел бы использовать Secondary Expansion и вытащить нужные переменные из целевого имени:

.SECONDEXPANSION: 

sample%_processed: samples/$$(subst processed,preprocessed,$$(notdir [email protected])) $$(dir [email protected])preprocessed 
    process_data --reference $(dir [email protected])preprocessed --sample $< 

(Обратите внимание, что есть больше чем один способ построения команды; получение первого prereq с $< намного проще, чем получение второго, поэтому я сделал уродливый первый.)

Смежные вопросы