我目前有一个工具可以在单个输入下生成多个文件。所以给定一个文件" a.parent",它会生成一堆未知的命名文件,例如" b.child"," c.child",&# 34; z.child"等等。这完全取决于生活在" a.parent"中的内容。
我的问题是,如何正确构建一个makefile目标,以便1)它不会多次运行该工具,因为单个运行将生成所有这些,2)如果生成任何文件被删除,它将重新运行该工具并重新生成所有这些文件,3)如果" a.parent"它比其中一个家属更新,它将重新运行该工具,以及4)我不必在Makefile本身中列出每个子文件,因为我真的不关心生成的内容,只是它生成了
问题,至少在我看来,Makefiles是建立在确切知道你的最终状态应该是什么的基础上的。但是,在这种情况下,我希望它只关心它是什么。
答案 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.sh
,manifest.txt
只会包含相同的行
a.parent
。)
当然,这种解决方案不是防弹的。例如,如果有人删除
来自清单中的文件系统和的一些*.child
文件
make不会注意到。此外,明确的make manifest.txt
将不会做任何事情
即使有人伪造清单。这个漏洞可能会被一些人关闭
makefile的复杂性,但防止这种破坏的预防措施
因为这些可能并不重要。