Makefile 生成文件依赖项迭代通用规则

Makefile 生成文件依赖项迭代通用规则,makefile,Makefile,我一直在浏览makefile语法手册,但没有找到任何真正有助于我在这里尝试实现的用例的东西 我有一个源文件列表,在一个公共目录下有不同的目录,如下所示: src/a.h src/b.h src/dir/c.h src/dir/dir/d.h 并希望make将这些单独用作最终创建以下内容的规则的依赖项: build/a.h build/b.h build/c.h build/d.h 然后将其单独用作更多规则的依赖项 到目前为止,我所拥有的: 什么不起作用: 没有规则将目标设置为“所有”所需的

我一直在浏览makefile语法手册,但没有找到任何真正有助于我在这里尝试实现的用例的东西

我有一个源文件列表,在一个公共目录下有不同的目录,如下所示:

src/a.h
src/b.h
src/dir/c.h
src/dir/dir/d.h
并希望
make
将这些单独用作最终创建以下内容的规则的依赖项:

build/a.h
build/b.h
build/c.h
build/d.h
然后将其单独用作更多规则的依赖项

到目前为止,我所拥有的: 什么不起作用:
没有规则将目标设置为“所有”所需的“构建/a.h”


我猜make在这一点上对我很生气,因为错误开始告诉我停止

基本上,我正在读取一个带有路径前缀的文件列表,该前缀与搜索路径和依赖项相关,并且只想在更新源文件时转储每个文件。在此之后,该目录中的这些文件将用作另一批规则的依赖项。我怎样才能做到这一点


注意:我是通过忽略依赖链来完成的,但这是行不通的。我还可以使用make来运行脚本,生成一个显式的makefile,可以正确地完成它,但这感觉像是过度使用和资源浪费,make应该能够创建一个自己完成这项工作的规则,尽管它很强大。我只是不知道如何创建通用规则,将重点放在依赖变量的文本匹配上,而不是目标上。

这里没有使用模式规则的好方法,因为所有的头(可能)都在不同的目录中,您希望将它们移到一个公共目录中。如果您使用的是GNU make,则可以编写一个宏规则,扩展到您需要的所有规则:

define copy_header_rule
build/$(notdir $(1)): $(1)
        cp $$< $$@
endef

$(foreach hdr,$(LIST),$(eval $(call copy_header_rule,$(hdr))))
define copy\u header\u规则
build/$(notdir$(1)):$(1)
cp$$<$$@
恩德夫
$(foreach hdr,$(LIST),$(eval$(call copy\u header\u rule,$(hdr)))

这将通过
$(列表)中的每个标题执行。
a创建一个规则,将其复制到生成目录中。

使用
vpath
可以使事情变得非常简单:

TARGS:= $(addprefix build/, $(notdir $(LIST)))

vpath %.h $(dir $(LIST))

all: $(TARGS)

build/%.h: %.h
    @echo building $@ from $<
    ...
TARGS:=$(addprefix build/,$(notdir$(LIST)))
vpath%.h$(目录$(列表))
全部:$(塔格)
生成/%.h:%.h
@回声大厦$@自$<
...

我将
enddef
更改为
endef
,出于某种原因,自动VAR
$必须转义
$是否有任何特殊原因需要在
build/
中复制头,而不是使用原始头?这会导致依赖项中存在歧义,这就是我以前没有使用此选项的原因。例如,假设文件结构中存在
src/d.h
,但不包括在标题列表中,而选择
src/dir/dir/d.h
。Make将扫描
vpath
中给出的每个目录,并在
src
中找到
d.h
,并使用它来代替显式给出的
src/dir/dir/d.h
@IronPhysco:True,这是一条依赖于唯一文件名的捷径。如果只有一个这样的冲突,您可以对列表的元素重新排序,但这将是一个脆弱的解决方案。
build/%.h: %.h
define copy_header_rule
build/$(notdir $(1)): $(1)
        cp $$< $$@
endef

$(foreach hdr,$(LIST),$(eval $(call copy_header_rule,$(hdr))))
TARGS:= $(addprefix build/, $(notdir $(LIST)))

vpath %.h $(dir $(LIST))

all: $(TARGS)

build/%.h: %.h
    @echo building $@ from $<
    ...