如何使用 GNU make 更新包含特定文件的所有子目录中的文件?

How to use GNU make to update files in all subdirectories containing a particular file?

在我的项目中,我有一组包含 package.yaml 个文件的子目录,例如:

A/package.yaml
B/package.yaml
C/package.yaml

如果我 运行 hpack A/package.yaml,将(重新)生成文件 A/A.cabal。此类目录的列表会随时间变化,因此我想使用 GNU make 查找包含 package.yaml 文件的所有直接子目录,并使用 hpack.

生成相应的 .cabal 文件

我根据 another question 尝试了这个,但没有成功:

HPACK_FILES := $(wildcard */package.yaml)
PKG_DIRS := $(subst /,,$(dir $(HPACK_FILES)))
CABAL_FILES := $(addsuffix .cabal,$(join $(dir $(HPACK_FILES)),$(PKG_DIRS)))

test:
    @echo $(CABAL_FILES)

update-cabal: $(CABAL_FILES)

%.cabal: package.yaml
    hpack $<

但是,make update-cabal 表示无事可做。 make test 但是会输出正确的 cabal 文件。我该如何解决这个问题?

干杯!

问题是这样的:

%.cabal: package.yaml

没有文件package.yaml。这些文件的名称类似于 A/package.yaml。那不是一回事。

因为先决条件不存在,make 决定此模式规则无法匹配,因此它会寻找另一个可能能够构建目标的规则。它没有找到任何可以构建目标的规则,所以 make 说没有什么可做的,因为所有的输出文件都已经存在。

不幸的是,使用 make 做您想要做的事一点也不容易,因为 make 最适合通过文件名和扩展名或类似的方式将输入和输出文件捆绑在一起。特别是,对于可变部分重复多次的关系(如 A/A.cabal 其中 A 重复),它真的很难处理。在 make 中没有简单的方法可以做到这一点。

您必须使用 eval 等高级功能才能执行此操作。类似于:

# How to build a cabal file
%.cabal:
        hpack $<

# Declare the prerequisites
$(foreach D,$(dir $(HPACK_FILES)),$(eval $D/$D.cabal: $D/package.yml))