GNU Make Single Target生成多个文件

时间:2014-05-08 18:14:37

标签: makefile gnu-make

我目前有一个工具可以在单个输入下生成多个文件。所以给定一个文件" a.parent",它会生成一堆未知的命名文件,例如" b.child"," c.child",&# 34; z.child"等等。这完全取决于生活在" a.parent"中的内容。

我的问题是,如何正确构建一个makefile目标,以便1)它不会多次运行该工具,因为单个运行将生成所有这些,2)如果生成任何文件被删除,它将重新运行该工具并重新生成所有这些文件,3)如果" a.parent"它比其中一个家属更新,它将重新运行该工具,以及4)我不必在Makefile本身中列出每个子文件,因为我真的不关心生成的内容,只是它生成了

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

1 个答案:

答案 0 :(得分:2)

如下所示的makefile就足够了。

这是一个想法:作为多个未指定*.child个文件的代理目标 您的工具可能生成的,使用由其创建的那些文件的清单 创建文件的相同配方。配方删除过时*.child 文件和清单,然后在a.parent上运行您的工具以制作新的*.child文件, 然后创建新*.child文件的新清单。

制作此食谱的规则是:

  • 清单不存在,或
  • 现有清单早于a.parent
  • 现有清单比某些*.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

a.parent一起包含*.child个文件的名称 生成,每行一个,例如

b.child
c.child
d.child

(因此对于我的tool.shmanifest.txt只会包含相同的行 a.parent。)

当然,这种解决方案不是防弹的。例如,如果有人删除 来自清单中的文件系统的一些*.child文件 make不会注意到。此外,明确的make manifest.txt将不会做任何事情 即使有人伪造清单。这个漏洞可能会被一些人关闭 makefile的复杂性,但防止这种破坏的预防措施 因为这些可能并不重要。