假设我有以下内容:
TARGETS = a.o b.o c.o
SOURCES = F1/a.c F2/F3/b.c c.c
我希望获得:
a.o: F1/a.c
gcc $< -c
b.o: F2/F3/b.c
gcc $< -c
c.o: c.c
gcc $< -c
我希望有一个简洁的表达来完成这项工作,例如:
$(TARGETS): $(SOURCES)
#Appropriate compile command
假设我有以下内容:
TARGETS = a.o b.o c.o
SOURCES = F1/a.c F2/F3/b.c c.c
我希望获得:
a.o: F1/a.c
gcc $< -c
b.o: F2/F3/b.c
gcc $< -c
c.o: c.c
gcc $< -c
$(TARGETS): $(SOURCES)
#Appropriate compile command
VPATH
来告诉make源代码目录,然后使用简单的模式规则:TARGETS := a.o b.o c.o
VPATH := F1:F2/F3 # Use ; instead of : on Windows
%.o: %.c
$(CC) -c $< -o $@
如果您甚至可以省略规则,使隐式规则在这种情况下正常工作。
但是,如果您有在不同路径中以相同方式命名的文件,则无法使用此方法(它只会选择找到的第一个文件)。按照您的要求,将列表压缩即可解决此问题:
TARGETS := a.o b.o c.o
SOURCES := F1/a.c F2/F3/b.c c.c
$(TARGETS):
$(CC) -c $< -o $@
list-rem = $(wordlist 2,$(words $1),$1)
pairmap = $(and $(strip $2),$(strip $3),$(call \
$1,$(firstword $2),$(firstword $3))$(call \
pairmap,$1,$(call list-rem,$2),$(call list-rem,$3)))
gen-prereq = $(eval $1: $2)
$(call pairmap,gen-prereq,$(TARGETS),$(SOURCES))
pairmap
,它接受一个函数名和两个列表,并为每一对元素调用该函数。它是递归的,并通过list-rem
得到帮助,该函数从列表中取出第一个元素。gen-prereq
将其第二个参数设置为其第一个参数指定的目标的前提条件。然后只需要在gen-prereq
上调用pairmap
,将目标作为第一个列表传递,源作为第二个列表传递即可。TARGETS := a.o b.o c.o
SOURCES := F1/a.c F2/F3/b.c c.c
$(TARGETS):
gcc -c $< -o $@
$(foreach x,$(join $(addsuffix :,$(TARGETS)),$(SOURCES)),$(eval $x))
这个功能通过在目标和源之间使用 :
连接它们(前提条件),并对每个连接进行 eval 处理来实现。