Makefile 如何将多个目标与其先决条件进行模式匹配?

Makefile 如何将多个目标与其先决条件进行模式匹配?,makefile,gnu-make,Makefile,Gnu Make,我从makefile开始,对模式是如何工作的有点困惑。我有多个不同的目标,每个目标都有一个名称匹配的先决条件。我希望有一个变量在顶部存储目标和先决条件的所有“词干”,然后只添加前缀/后缀和它们的通用配方。到目前为止,我已经尝试: names = stem1 stem2 stem3 all: $(names:%=dir/prefix_%.txt) $(names:%=dir/another_%.txt) $(names:%=dir/prefix_%.txt): $(names:%=source

我从makefile开始,对模式是如何工作的有点困惑。我有多个不同的目标,每个目标都有一个名称匹配的先决条件。我希望有一个变量在顶部存储目标和先决条件的所有“词干”,然后只添加前缀/后缀和它们的通用配方。到目前为止,我已经尝试:

names = stem1 stem2 stem3

all: $(names:%=dir/prefix_%.txt) $(names:%=dir/another_%.txt)

$(names:%=dir/prefix_%.txt): $(names:%=sourcedir/yetanother_%.xlsx)
    echo $@
    echo prerequisite_with_the_same_stem_as_current_target

尽管这会使所有目标逐个列出,但每个目标的先决条件都会列出,而不仅仅是与目标的当前
%(名称)
匹配的先决条件。我需要它匹配的原因是,我随后将当前目标及其单个先决条件提供给脚本,然后脚本生成目标。如何将每个先决条件与其一个目标进行模式匹配?

您的误解是关于
make
如何处理列表。如果您有一个变量:

names = stem1 stem2 stem3
然后
make
将其作为列表处理,但每次命名此变量时,都会同时实例化整个列表内容。它不会对列表内容执行一对一的操作,因为根据具体情况,这几乎是无法控制的。相反,它诉诸于简单的文本替换,因此您的行

all: $(names:%=dir/prefix_%.txt) $(names:%=dir/another_%.txt)
已解析变量并将其替换为非常简单的字符串:

all: dir/prefix_stem1.txt dir/prefix_stem2.txt dir/prefix_stem3.txt ...etc...
迭代列表处理仅在
$(名称:%=dir/prefix\u%.txt)
中进行,而行本身在变量替换后只是文本,将文本馈送到第二个解析步骤

按照你的规则:

$(names:%=dir/prefix_%.txt): $(names:%=sourcedir/yetanother_%.xlsx)
扩展到

dir/prefix_stem1.txt dir/prefix_stem2.txt dir/prefix_stem3.txt: sourcedir/yetanother_stem1.xlsx sourcedir/yetanother_stem2.xlsx sourcedir/yetanother_stem3.xlsx
这是三条规则的简写符号:

dir/prefix_stem1.txt: sourcedir/yetanother_stem1.xlsx sourcedir/yetanother_stem2.xlsx sourcedir/yetanother_stem3.xlsx
dir/prefix_stem2.txt: sourcedir/yetanother_stem1.xlsx sourcedir/yetanother_stem2.xlsx sourcedir/yetanother_stem3.xlsx
dir/prefix_stem3.txt: sourcedir/yetanother_stem1.xlsx sourcedir/yetanother_stem2.xlsx sourcedir/yetanother_stem3.xlsx
没有别的了。显然,您告诉make每个目标都取决于所有先决条件

不过,只要稍加调整,您就可以实现您的目标:

MY_TARGETS :=  $(names:%=dir/prefix_%.txt) # create full target names

$(MY_TARGETS) : dir/prefix_%.txt : sourcedir/yetanother_%.xslx

这很有效,非常感谢!在make中使用大写变量是常见的格式吗?嗯..我不知道。我从手册上找到了这种款式。然后,在我的库中,我做了相反的操作,主要是将库名与用户名分开。