Makefile 寻找记录良好的Make输出
简短问题: 使目标具有作为依赖项的文件;假设一个依赖关系的例子是文件“D”。我希望遍历它的依赖关系图,对于每个“D”,也取决于成功记录在“D”配方的退出状态的日志文件(“D.status.log”;为了简单起见,只包括进程退出状态或字符串“Started”)。如果不亲自深入Make的源代码并修改图形逻辑,这是可能的吗?(即,是否有人已将此作为补丁或其他类似于Make的实用程序编写?) 详细信息: 我是一个使用Makefiles来运行数据处理工作流的爱好者。我并不孤单,因为搜索“makefile数据”会产生一些志同道合的人:Makefile 寻找记录良好的Make输出,makefile,workflow,data-processing,Makefile,Workflow,Data Processing,简短问题: 使目标具有作为依赖项的文件;假设一个依赖关系的例子是文件“D”。我希望遍历它的依赖关系图,对于每个“D”,也取决于成功记录在“D”配方的退出状态的日志文件(“D.status.log”;为了简单起见,只包括进程退出状态或字符串“Started”)。如果不亲自深入Make的源代码并修改图形逻辑,这是可能的吗?(即,是否有人已将此作为补丁或其他类似于Make的实用程序编写?) 详细信息: 我是一个使用Makefiles来运行数据处理工作流的爱好者。我并不孤单,因为搜索“makefile数
find。。。rm
命令,这感觉像是一种脆弱的数据管理策略
基本上,我想要一个记录良好的Make for data,它具有这种风格的界面:我将在下面称之为fantasymake
生成文件:
all: results1 results2
results1: script input1
script input1 >results1
results2: script input2
script input2 >results2
results2beyond: script results2
script results2 >results2beyond
之前的目录树示例:
Makefile
input1
input2
运行fantasymake
后的目录:
Makefile
input1
input2
results1
results1.err.log
results1.out.log
results1.status.log
results2
results2.err.log
results2.out.log
results2.status.log
results2beyond
results2beyond.err.log
results2beyond.out.log
results2beyond.status.log
目前,我可以通过这个Bash获取日志,但我还没有找到一种将这些包装器命令集成到Makefile规则中的好方法:
echo Started. >results.status.log
some_program >results.out.log 2>results.err.log
echo $? >results.status.log
(调用Makefile定义中的每个未连接行是一个单独的shell:Makefile包装器中的some\u program…
和echo$$?
之间会有一个连续行(反斜杠),以确保它们都在同一shell中执行。)
回到fantasymake
行为,这将是运行fantasymake clean
后的目录:
Makefile
input1
input2
Makefile
input1
input2
results1
results1.err.log
results1.out.log
results1.status.log
假设运行fantasymake
,results2
失败或终止。(假设我们没有fantasymakeclean
),则不会生成results2beyond
;在这里,我不认为我可以仅仅依靠未修改的Make:results2.status.log
记录results2
失败的日志,因此fantasymake
不会在下一次调用时继续执行results2beyond
为了完成构建,一个清除失败的规则可以清除错误的结果。如果您有一个数据库依赖项(或实时连接),那么您可能需要它,而这个数据库依赖项(或实时连接)更容易忽略。以下是运行fantasymakeclean失败
而不是fantasymakeclean
后目录的外观:
Makefile
input1
input2
Makefile
input1
input2
results1
results1.err.log
results1.out.log
results1.status.log
假设在运行fantasymake clean失败后,脚本更新。然后运行fantasymake
将重新生成results1
及其日志和results2
从维基百科(构建自动化软件列表)上看,似乎没有一个makepp
,omake
,或者cmake
能做到这一点。该页面上的列表(我再也没有链接的名声了)有点长,所以我求助于这个可爱的人群,他们已经帮助我很多次了
这是我必须破解的一个扩展,还是它已经存在了?对于包装器,如果使用GNU make,这是微不足道的。只需使用用户定义的函数:
TARGETS = one two three
# Invoke this with $(call LOG,<cmdline>)
define LOG
echo "$$(date): Started." >'$@'.status.log
($1) >'$@'.out.log 2>'$@'.err.log
echo "$$(date): Completed: $$?" >>'$@'.status.log
endef
all: $(TARGETS)
$(TARGETS):
$(call LOG, echo "$@ out"; echo "$@ error" 1>&2)
对我来说,您的其他需求听起来像是标准的make功能。我认为您可以通过常规make来实现这一点,您只需在设置规则方面稍微聪明一点。具体地说,在确定结果文件的完整性和一致性之前,不要将其放在适当的位置。按如下方式更改生成文件:
all: results1 results2
results1: script input1
script input1 >results1.tmp && mv results1.tmp results1
results2: script input2
script input2 >results2.tmp && mv results2.tmp results2
results2beyond: script results2
script results2 >results2beyond.tmp && mv results2beyond.tmp results2beyond
现在,如果电源断开或磁盘已满或类似情况,工作流将在停止的任何位置重新启动。存在的任何结果文件都保证是完整和一致的,因为除非上一个命令成功完成,否则shell不会执行mv
命令
更新:
如果您使用的是GNU make,则可以稍微简化make文件:
PROCESS=script $< > $@.tmp && mv $@.tmp $@
all: results1 results2
results%: input% script
$(PROCESS)
results2beyond: results2 script
$(PROCESS)
PROCESS=script$<>$@.tmp&&mv$@.tmp$@
全部:结果1结果2
结果%:输入%脚本
$(过程)
results2beyond:results2脚本
$(过程)
根据您的决心,您可能可以进一步简化此操作,但这是留给读者的一个练习。这很接近,在创建日志这一点上肯定很好(不过,我忘了连接命令外壳和退出状态行,所以在我们编写时,日志总是以“0”结尾)。但是,我不清楚“.status.log”:用于检测中间作业何时失败。我会更新这个问题,现在更新了。我很想知道遍历依赖关系图时的钩子是否是标准make功能的另一部分,但我查找并没有发现任何迹象表明这是如此。正确的,您必须在单个语句中编写命令才能使用这样的函数。至于清洁行为,一种方法是将每个目标列为下一个目标的先决条件,但这将失去所有并行性。唯一的另一种方法就是在壳里做。谢谢你,疯狂的科学家。听起来你好像在投票支持这是一个实施项目?这几乎就是我想要的。“帮助制作”邮件列表上的某个人认为这就是我问题的答案;所以,我认为我的问题还没有问对。好吧,我希望现在问得更好。我对你的回答有一个问题,那就是它不够通用,不能像@MadScientist建议的那样封装在函数中。依赖关系图将以大量的样板文件结束,这意味着所有这些额外代码都有一个编程解决方案。我是你的两个a