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

时间:2020-08-03 23:40:27

标签: makefile gnu-make

在我的项目中,我有一组包含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确实输出正确的阴谋文件。我该如何解决?

干杯!

1 个答案:

答案 0 :(得分:1)

问题是这样的:

%.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))