11

我目前正在开发一个项目,该项目需要将目录中的文件列表转换为 c++ 标头以存储有关资源的信息。例如:

/
update.py
resources.h
Makefile
/resources
  resource1.png
  /sub1
    /sub2
      resource2.png

我想要的是 Makefile 仅在目录树中任何位置的资源之一发生更改时才运行 update.py 。没有其他 makefile 会触及资源,只有 resources.h。我需要什么样的makefile才能做到这一点?

PS 从我读过的内容来看,使用 make 递归搜索是一个坏主意,但如果没有其他东西触及同一个文件,这会是一个问题吗?

4

3 回答 3

20

我不确定你读过什么,但在 make 中编写这样的规则没有问题:

RESOURCES := $(shell find . -name resource\*.png -print)
resources.h: update.py $(RESOURCES)
        ./update.py $(RESOURCES)

管他呢。

于 2013-06-24T15:52:02.740 回答
3

请注意,您也可以$(shell find)在没有变量的情况下对依赖项使用命令:

resources.h: $(shell find . -name 'resource*.png')
    ./update.py $^

因此,这就像@MadScientist 的答案,但您会在$^自动变量中获得依赖项列表。(update.py虽然在这种情况下不能轻易地将 包含在依赖项中。)

它的强大之处在于您可以使用模式,例如,如果您需要resourcesN.h从多个匹配目录 ( ) 编译为多个目标文件 ( resourcesN/):

targets: resources1.h resources2.h
%.h: $(shell find $*/ -name 'resource*.png')
    ./update.py $^

这里$*获取值resources1resources2,然后$^保存在相应目录中找到的依赖项列表。

于 2019-04-30T10:42:10.957 回答
2

我认为你错了:Recursive Make Considered Harmful解释说你不应该从另一个内部调用一个 make,因为它们都不会有完整的依赖关系概述。这迟早会导致错误的构建,您只能使用make clean.

makepp是一种替代方法,可以帮助您避免这种陷阱。它还使用递归(与上述递归无关)通配符解决了您的问题:

RESOURCES := **/resource\*.png
resources.h: $(RESOURCES)
    .$/update.py $(inputs)

如果文件还没有,这甚至可以工作,因为 makepp 的通配符考虑了可以根据您的规则构建的内容。注意它是如何自动注意到程序依赖的。有趣$/的东西会根据它运行的系统而倾斜,因此它更便携。

makepp 还有很多。除了做 GNU make 能做的几乎所有事情,还有很多有用的东西,你甚至可以用一些 Perl 编程来扩展你的 makefile。

于 2013-06-24T22:42:27.900 回答