如何将先决条件列表与Make中的目标列表相关联?

时间:2016-08-27 09:34:46

标签: makefile

说我有:

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

1 个答案:

答案 0 :(得分:2)

您可以使用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将其第二个参数设置为其第一个参数指定的目标的先决条件。剩下的就是在pairmap上调用gen-prereq,将目标作为第一个列表传递,将源作为第二个列表。

另一种可行且更简单的方法是:

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))

通过将目标和来源与:加在一起(先决条件)和评估每个目标和来源,可以起作用。