在Makefile中使用多个%s

在Makefile中使用多个%s,makefile,file-conversion,Makefile,File Conversion,我必须通过命令(fa2fb)将一组文件(比如fa格式)转换成另一种格式(fb)。每个目标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

我必须通过命令(fa2fb)将一组文件(比如fa格式)转换成另一种格式(fb)。每个目标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 $< $@
/DATA/%/fb/%.fb:./DATA/%/fa/%.fb
@fa2fb$<$@
有没有不更改数据目录的简单解决方案


非常感谢

这可能是我写过的最草率的makefile

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
为每个源调用它一次。源是
调用的第一个参数
,因此它在宏中变为
$(1)
。第二个参数只是从源文件名到目标文件名的转换;它在宏中变为
$(2)

用您自己的规则替换
echo hi
,您就可以开始了。并且一定要写一个清晰的评论,否则有一天肯定会有人拿着棒球棒出现在你的门口。

使用和创建一个规则,其中先决条件被构造为目标名称的更复杂的函数:

.SECONDEXPANSION:
DATA/%.fb: $$(subst fb,fa,$$@)
    @fa2fb $< $@
。第二次扩展:
数据/%.fb:$$(子fb,fa,$$@)
@fa2fb$<$@

注意,这种方法假设
fb
不会出现在文件名的其他任何地方(如果您的所有文件名的格式都是
DATA/Ln/fb/Ln.fb
,对于某些整数
n
)。

这与Nemo的答案基本相同。我只是试图通过创建一个模块列表,简单地包含
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))))
MODULES:=$(notdir$(通配符/DATA/L*))
定义规则
/DATA/$(1)/fb/$(1).fb:/DATA/$(1)/fa/$(1).fa
@fa2fb$<$@
恩德夫
$(foreach模块,$(模块),$(eval$(调用规则,$(模块)))

谢谢。对我来说效果很好。我将了解如何检查文件名中是否不存在fa(或fb?)。在实际情况下,它可能会发生。谢谢你的建议。它有点复杂,但可能比另一个更健壮。目前我将坚持第一个建议。关于评论的信息很清楚!