Использование нескольких% в Makefile - PullRequest
3 голосов
/ 13 июля 2011

Я должен преобразовать набор файлов (скажем, формат fa) в другой формат (fb) с помощью команды (fa2fb). Каждый целевой fb зависит только от одного файла fa.

Структура данных в таком формате:

Источник:

./DATA/L1/fa/L1.fa
./DATA/L2/fa/L2.fa
...
./DATA/Ln/fa/Ln.fa

цель:

./DATA/L1/fb/L1.fb
./DATA/L2/fb/L2.fb
...
./DATA/Ln/fb/Ln.fb

Как я могу реализовать это с помощью make?

Я пробовал это, но, конечно, это не сработало:

./DATA/%/fb/%.fb :  ./DATA/%/fa/%.fb

    @fa2fb $< $@

Есть ли какое-нибудь простое решение без изменения каталогов данных?

Большое спасибо!

Ответы [ 3 ]

2 голосов
/ 13 июля 2011

Используйте вторичное расширение и функцию subst , чтобы создать правило, в котором предпосылки создаются как более сложная функция целевого имени:

.SECONDEXPANSION:
DATA/%.fb: $$(subst fb,fa,$$@)
    @fa2fb $< $@

Обратите внимание, что этот подход предполагает, что fb не будет встречаться где-либо еще в имени файла (что справедливо, если все ваши имена файлов имеют форму DATA/Ln/fb/Ln.fb для некоторого целого числа n).

1 голос
/ 13 июля 2011

Это может быть самый небрежный make-файл, который я когда-либо писал.

define template
 $(2) : $(1)
        echo hi
endef

sources=DATA/L1/fa/L1.fa DATA/L2/fa/L2.fa
$(foreach source,$(sources),$(eval $(call template,$(source),$(subst /fa/,/fb/,$(subst .fa,.fb,$(source))))))

Идея состоит в том, чтобы определить макрос для генерации ваших правил, а затем использовать foreach и eval + call, чтобы вызвать его один раз для каждого источника. Источник является первым аргументом call, поэтому он становится $(1) в макросе. Второй аргумент - это просто преобразование имени исходного файла в имя конечного файла; в макросе оно становится $(2).

Замените echo hi своим собственным правилом, и вы должны быть в порядке. И обязательно напишите хороший четкий комментарий, или когда-нибудь кто-нибудь обязательно появится у вашей двери с бейсбольной битой.

0 голосов
/ 13 июля 2011

Это в основном то же, что и ответ Немо. Я просто попытался сделать вызов foreach более читабельным, создав список модулей, содержащий просто L1 L2 ... Ln вместо списка полных имен источников.

MODULES := $(notdir $(wildcard ./DATA/L*))

define rule
./DATA/$(1)/fb/$(1).fb: ./DATA/$(1)/fa/$(1).fa
    @fa2fb $< $@
endef

$(foreach module, $(MODULES), $(eval $(call rule,$(module))))
...