Makefile规则依赖于目录内容的变化

17
使用Make,有没有一种很好的方法来依赖于目录中的内容。
本质上,我有一些应用代码依赖的生成代码。生成的代码只需要在目录内容更改时更改,并不一定需要更改其中的文件内容。所以如果删除、添加或重命名文件,我需要运行规则。
我首先想到的是生成目录的文本文件列表,并将其与上次列表进行比较。更改意味着重新运行构建。我认为我必须将生成和差异部分交给一个bash脚本。
我希望他们能以无限的智慧找到更简单的解决方法。

3个回答

24

向 gjulianm 致敬,他让我找到了正确的方向。他的解决方案完美地适用于单个目录。

为了让它可以递归地工作,我做了以下操作。

ASSET_DIRS = $(shell find ../../assets/ -type d)
ASSET_FILES = $(shell find ../../assets/ -type f -name '*')

codegen: ../../assets/ $(ASSET_DIRS) $(ASSET_FILES)
     generate-my-code

现在似乎对目录或文件进行任何更改(添加、删除、重命名、修改)都会导致运行此规则。这里可能存在文件名称的问题(空格可能会导致问题)。


这对删除操作有效吗?我还没有测试过,但我认为删除操作只会将该文件作为依赖项删除。编辑:当然,在删除操作的情况下,目录也会更新。我明白了。 - Zoey Hewll
也许“-name'*'”不是必要的,因为find命令已经可以找到所有文件了? - Andrew Mackenzie
请注意,"*" 可以防止包含隐藏文件,这可能是理想的。 - Cireo

7
假设您的目录名为dir,那么这个makefile将会实现您想要的功能:
FILES = $(wildcard dir/*)

codegen: dir # Add $(FILES) here if you want the rule to run on file changes too.
    generate-my-code

如评论所说,如果你想让代码也依赖于文件内容,你还可以添加FILES变量。


这个可以运行,但它不具备递归功能。问题目录内部还有其他目录。 - Halsafar

1
一个依赖于目录的规则的缺点是,目录中的任何更改都会使规则过时 - 包括在该目录中创建生成的文件。因此,除非您将源文件和目标文件分隔到不同的目录中,否则规则将在每次make时触发。
这里有一种替代方法,允许您指定一组文件,对于这些文件的添加、删除和更改是相关的。例如,假设只有*.foo文件是相关的。
# replace indentation with tabs if copy-pasting

.PHONY: codegen
codegen:
        find . -name '*.foo' |sort >.filelist.new
        diff .filelist.current .filelist.new || cp -f .filelist.new .filelist.current
        rm -f .filelist.new
        $(MAKE) generate

generate: .filelist.current $(shell cat .filelist.current)
        generate-my-code

.PHONY: clean
clean:
        rm -f .filelist.*

代码生成规则中的第二行确保只有在相关文件列表发生变化时才会修改.filelist.current,避免触发generate规则的误报。

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