GNU制作相应的列表

时间:2014-09-18 18:44:06

标签: gnu-make

我有一个产品清单:

  • 1,2,3,4 ......

这取决于不同的来源列表:

  • z,y,x,w ......

依赖性是一对一的(第一个列表的第n个元素将第二个列表的第n个元素作为其源),并且配方在所有情况下都是相同的。出于所有意图和目的,列表中没有结构 - 不可能编写允许从n生成列表的第n个元素的简单表达式。我知道的解决方案是

1 : z
   [recipe]

2 : y 
   [identical recipe]

3 : x
   [identical recipe]

4 : w
   [identical recipe]

...但我不喜欢这样,因为它在修改列表或配方时更容易出错。我更愿意利用对应模式并以

开头
SRCLIST = z y x w
DSTLIST = 1 2 3 4

然后以某种方式有像

这样的一般规则
DSTLIST_n : SRCLIST_n
    [recipe]

有没有办法做这样的事情?

3 个答案:

答案 0 :(得分:1)

这有点难看,但我相信它应该有用。 (可能会有更好的方法,但这是我想出的第一件事。)

SRCLIST = z y x w
DSTLIST = 1 2 3 4
# Create a list of : the length of SRCLIST
MIDLIST = $(foreach s,$(SRCLIST),:)

$(info SRCLIST:$(SRCLIST))
$(info DSTLIST:$(DSTLIST))
$(info MIDLIST:$(MIDLIST))

# Join the three lists together (in two passes since $(join) only takes two lists)
JOINLIST = $(join $(join $(DSTLIST),$(MIDLIST)),$(SRCLIST))
$(info joined:$(JOINLIST))

# eval each of the created strings to create the prerequisite entries
$(foreach r,$(JOINLIST),$(eval $r))

# Set the rules to build all the targets.
$(DSTLIST):
    echo '$@ for $^'

$ touch z y x w
$ make
SRCLIST:z y x w
DSTLIST:1 2 3 4
MIDLIST:: : : :
joined:1:z 2:y 3:x 4:w
echo '1 for z'
1 for z
echo '2 for y'
2 for y
echo '3 for x'
3 for x
echo '4 for w'
4 for w

我应该注意,这根本不会处理任何条目中的空格(但通常情况下,这对于此解决方案而言并非特定)。

你也可以随时创建一个Canned Recipe然后将其粘贴在每个明确写出的目标中,就像你原来的想法一样。

答案 1 :(得分:1)

受Etan的启发,这是我发现的工作:

SRCLIST = z y x w
DSTLIST = 1 2 3 4

# Make a list of ":" for combining
SEPARATOR = $(foreach s,$(SRCLIST),:)

# Define a parameterized rule which accepts the dst:src info as an argument
define dst-src

$1
   [rule]

endef

# Define the list of dependencies
DST_SRC_RELNS = $(join $(join $(DSTCLIST),$(SEPARATOR)),$(SRCLIST))
# ^ DST_SRC_RELNS evaluates to z:1 y:2 x:3 w:4

# Print a preview of the rules the makefile generates itself
$(info $(foreach r,$(DST_SRC_RELNS),$(call dst-src,$r)))

# Generate the rules
$(foreach r,$(DST_SRC_RELNS),$(eval $(call dst-src,$r)))

我认为你可以通过在dst-src内部实际编写规则来定义参数化规则$(eval ...),但我不喜欢这样做有两个原因:

  • 您需要为结果定义一个newline宏,使其成为可以识别的规则
  • $(foreach ...)中添加更多文字,让人类读者更难找出真正发生的事情

答案 2 :(得分:1)

好的问题。您没有提到您正在使用的 make 版本,但.SECONDEXPANSION通常适用于这些类型的源查找表。

草图:

srcs := z x y w
targets := 1 2 3 4

.SECONDEXPANSION:

pairs := $(join ${targets},$(addprefix :,${srcs}))
lookup-src = $(patsubst $1:%,%,$(filter $1:%,${pairs}))

${targets}: $$(call lookup-src,$$@)
    echo '[$^] -> [$@]'