Makefile GNU使单个目标生成多个文件

Makefile GNU使单个目标生成多个文件,makefile,gnu-make,Makefile,Gnu Make,我目前有一个工具,可以在一次输入的情况下生成多个文件。因此,给定一个文件“a.parent”,它将生成一组未知的命名文件,如“b.child”、“c.child”、“z.child”等。这都取决于“a.parent”中的内容 我的问题是,我如何正确地为此构建一个makefile目标,以便1)它不会多次运行该工具,因为一次运行将生成所有文件;2)如果删除任何生成的文件,它将再次重新运行该工具并重新生成所有文件;3)如果“a.parent”比其一个从属文件更新,它将重新运行该工具,并且4)我不必列出

我目前有一个工具,可以在一次输入的情况下生成多个文件。因此,给定一个文件“a.parent”,它将生成一组未知的命名文件,如“b.child”、“c.child”、“z.child”等。这都取决于“a.parent”中的内容

我的问题是,我如何正确地为此构建一个makefile目标,以便1)它不会多次运行该工具,因为一次运行将生成所有文件;2)如果删除任何生成的文件,它将再次重新运行该工具并重新生成所有文件;3)如果“a.parent”比其一个从属文件更新,它将重新运行该工具,并且4)我不必列出Makefile本身中的每个子文件,因为我真的不关心生成了什么,只关心生成了什么


问题是,至少对我来说,makefile是建立在确切知道最终状态的基础上的。但是,在这种情况下,我希望它只关心它是什么。

像下面这样的makefile就足够了

这就是想法:作为多个未指定的
*.child
文件的代理目标 您的工具可能会生成,请使用由创建的这些文件的清单 与创建文件的配方相同。配方将删除过时的
*。子项

文件和清单,然后在
a.parent
上运行工具以生成新的
*.child
文件, 然后为新的
*.child
文件创建一个新清单

制作此配方的规则是:

  • 清单不存在,或者
  • 现有清单早于父清单,或
  • 现有清单比某些
    *.child
    文件旧,或
  • 现有清单不真实,即中命名的
    *.child
    文件集 清单与存在的集合不同
评论中解释了详情:

.PHONY: all clean

# $(manifest) will be the space-punctuated list of files, if any, that are
# listed in 'manifest.txt', if it exists, else the empty string.
manifest = $(shell if [ -f manifest.txt ]; then cat manifest.txt; fi)

# $(outputs) will be the space-punctuated list of '*.child' files, if any, in
# the current directory, else the empty string
outputs = $(shell ls -1 *.child 2>/dev/null)

# Default target:
# If there is any mismatch between $(manifest) and $(outputs)
# then clean and remake. Else just make 'manifest.txt'
ifneq '$(outputs)' '$(manifest)'
all:
    $(MAKE) clean && $(MAKE)
else
all: manifest.txt
endif

manifest.txt : a.parent $(outputs)
    $(MAKE) clean && ./tool.sh a.parent && ls -1 *.child > $@

clean:
    rm -f *.child manifest.txt
manifest.txt
的配方中,
tool.sh
代表您需要的任何工具 正在
a.parent
上运行。为了测试makefile,我只使用了:

#!/bin/bash
# tool.sh

while read line
do
    echo "This is file $line" > $line
done < $1
(因此对于我的
tool.sh
manifest.txt
将只包含与
a.parent

当然,这个解决方案不是防弹的。例如,如果有人删除 文件系统和清单中的一些
*.child
文件 make不会注意到。此外,显式的
makemanifest.txt
也不会起任何作用 即使有人伪造了舱单。这个漏洞可以用一些方法来弥补 makefile的复杂性,但防止此类破坏的预防措施,如
这些可能性可能并不重要。

如果有办法让工具说出它将创建的文件的名称,您可能可以使用这种方法,您可以使用gcc
-MD
(和friends)函数生成
.d
make include文件来为您处理一些文件。prereqs的可变性可能会在某个时候影响到你,即使你这样做了。虽然我认为来自我们的常驻疯人院的高级自动dep技术在这里也可能有所帮助。这个问题似乎意味着它必须作为一个单一的目标来实现,但这似乎有点人为的限制。我应该认为,利用服务器检测何时运行该工具的多个目标会更容易。
b.child
c.child
d.child