GNU Make循环使用两个变量

10

我想写一些关于以下方面的内容:

$(foreach (var1, var2), ($(LIST1), $(LIST2)), cp $(var1) $(var2);)

如何在 GNU makefile 中实现这个?


同时,当我以冗长的方式编写这个东西时,我意识到我需要在规则之外使用它。 - Matthew Hoggan
4个回答

11

Beta 建议使用 join 是正确的方向,但问题在于如何以一种构建包含空格的命令行的方式来使用它,就像你最初想要的那样:

$(foreach (var1, var2), ($(LIST1), $(LIST2)), cp $(var1) $(var2);)

因为join可以将单词拼接在一起,它最初是用于构建文件名的。但是你可以使用一个技巧;以下是使用join以获得所需输出的示例:

$(subst ^, ,$(join $(addprefix cp^,$(LIST1)),$(patsubst %,^%;,$(LIST2))))

如果你认为你的列表可能包含^字符,那么选择其他内容。如果需要进一步解释,请告诉我。


3
LIST1 := a b c
LIST2 := 1 2 3

# outside a rule:
$(foreach var1, a b c, $(foreach var2, 1 2 3, $(info $(var1)_$(var2))))

# inside a rule: first line starts with a TAB, all the rest are spaces
all:
    @for x in $(LIST1);\
    do \
      for y in $(LIST2);\
      do\
        echo $$x $$y; \
      done \
    done

请注意,嵌套循环执行cp并没有太多意义。
编辑: 好的,你为什么不早说呢?
LIST3 := $(join $(LIST1),$(LIST2))

1
是的,因为我不想要叉积,我需要一对一的映射。这就是让我的大脑陷入循环的原因。 - Matthew Hoggan
所以...你把这个答案标记为正确的了。但它似乎并没有回答你原本想问的问题。这是你想要的吗?还是不是? - MadScientist
这不是我想要的答案,但是几天后没有人回答,所以我标记它为相对正确的答案。如果你有更好的答案,请发表。 - Matthew Hoggan
@MatthewHoggan,我没有理解你的评论。你的意思是要一个结果,像 a1 b2 c3 这样吗? - Beta
如果我有一个列表 (a, b, c) 和 (1, 2, 3),并且运行上述脚本,如果我错了,请纠正我,我会得到 a,1 a,2 a,3, b,1, b,2, b,3, ... 当我想要的是 a,1 b,2 c,3。 - Matthew Hoggan

1

这是一个很好的GNU Make标准库(gsml)候选项。您可以将文件__gmslgml放入当前目录(或/usr/gnu/include/usr/local/include/等),并在Makefile中添加include gsml行来包含它。它包括pairmap函数,该函数正是您想要的(即zipWith)。

include gmsl
cp2 = cp $1 $2;
zip = $1 : $2
$(LIST2):
    @echo $(call pairmap, zip, $(LIST1), $(LIST2))
    $(call pairmap, cp2, $(LIST1), $(LIST2))

输出

$ make 
A : 1 B : 2 C : 3 D : 4
cp A 1; cp B 2; cp C 3; cp D 4;

0
这是一篇有点老的文章,但我发现它可以完全满足你的需求。你需要使用 seq 工具,它是一个 Unix 工具,在 Linux 和 Mac 上都可以使用。
我写了一个打印变量的示例,但它也适用于复制。
# Two lists
LIST1 = a1 a2 a3 a4
LIST2 = b1 b2 b3 b4

# This will generate
# LISTSEQ=1 2 3 4
LISTSEQ=$(shell seq $(words $(LIST1)))

# Print variable for example
define printvar
$(info $(1))
$(info $(2))
endef

# First line loops through 1 2 3 4
# and next line prints the corresponding value from LIST1 and LIST2
$(foreach j, $(LISTSEQ), \
    $(call printvar,$(word $(j), $(LIST1)) $(word $(j), $(LIST2))) \
)

输出:

a1 b1

a2 b2

a3 b3

a4 b4

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接