R 为项目中跨目标的依赖关系创建规则;s子目录
我的论文研究软件的源代码树(R 为项目中跨目标的依赖关系创建规则;s子目录,r,makefile,dependencies,workflow,R,Makefile,Dependencies,Workflow,我的论文研究软件的源代码树(R)反映了传统的研究工作流程:“收集数据->准备数据->分析数据->收集结果->发布结果”。我使用make来建立和维护工作流(项目的大多数子目录包含Makefile文件) 但是,我经常需要通过项目子目录中的特定Makefile目标(而不是通过顶级Makefile)执行工作流的各个部分。这就产生了设置Makefile规则以维护工作流不同部分的目标之间的依赖关系的问题,换句话说,就是位于不同子目录中的Makefile文件中的目标之间的依赖关系 以下是我的论文项目的设置:
R
)反映了传统的研究工作流程:“收集数据->准备数据->分析数据->收集结果->发布结果”。我使用make
来建立和维护工作流(项目的大多数子目录包含Makefile
文件)
但是,我经常需要通过项目子目录中的特定Makefile目标(而不是通过顶级Makefile
)执行工作流的各个部分。这就产生了设置Makefile
规则以维护工作流不同部分的目标之间的依赖关系的问题,换句话说,就是位于不同子目录中的Makefile
文件中的目标之间的依赖关系
以下是我的论文项目的设置:
+-- diss-floss (Project's root)
|-- import (data collection)
|-- cache (R data objects (), representing different data sources, in sub-directories)
|-+ prepare (data cleaning, transformation, merging and sampling)
|-- R modules, including 'transform.R'
|-- analysis (data analyses, including exploratory data analysis (EDA))
|-- R modules, including 'eda.R'
|-+ results (results of the analyses, in sub-directories)
|-+ eda (*.svg, *.pdf, ...)
|-- ...
|-- present (auto-generated presentation for defense)
我的一些Makefile
文件中的目标片段:
importFLOSSmole: getFLOSSmoleDataXML.R FLOSSmole.RData
@$(RSCRIPT) $(R_OPTS) $<
@touch $@.done
(similar targets for other data sources)
IMPORT_DIR=../import
prepare: import \
transform \
cleanup \
merge \
sample
import: $IMPORT_DIR/importFLOSSmole.done # and/or other flag files, as needed
transform: transform.R import
@$(RSCRIPT) $(R_OPTS) $<
@touch $@.done
cleanup: cleanup.R transform
@$(RSCRIPT) $(R_OPTS) $<
@touch $@.done
merge: merge.R cleanup
@$(RSCRIPT) $(R_OPTS) $<
@touch $@.done
sample: sample.R merge
@$(RSCRIPT) $(R_OPTS) $<
@touch $@.done
PREP_DIR=../prepare
analysis: prepare \
eda \
efa \
cfa \
sem
prepare: $PREP_DIR/transform.done # and/or other flag files, as needed
eda: eda.R prepare
@$(RSCRIPT) $(R_OPTS) $<
@touch $@.done
efa: efa.R eda
@$(RSCRIPT) $(R_OPTS) $<
@touch $@.done
cfa: cfa.R efa
@$(RSCRIPT) $(R_OPTS) $<
@touch $@.done
sem: sem.R cfa
@$(RSCRIPT) $(R_OPTS) $<
@touch $@.done
“~/diss floss/Makefile”(几乎已满):
“~/diss floss/import/Makefile”:
importflossmoledataxml.R
@$(RSCRIPT)$(R_选项)$<
...
“~/diss floss/prepare/Makefile”:
transform:transform.R
$(RSCRIPT)$(R_选项)$<
...
“~/diss floss/analysis/Makefile”:
eda:eda.R
@$(RSCRIPT)$(R_选项)$<
目前,我关心的是创建以下依赖项:
通过从import
中的Makefile
生成目标来收集的数据,在通过例如eda.R
进行分析之前,始终需要通过从prepare
中的Makefile
生成相应目标来进行转换。如果我在import
中手动运行make
,然后忘记转换,在analyze
中运行make-eda
,事情就不太顺利了。因此,我的问题是:
如何使用
make
实用程序的功能(以尽可能简单的方式)为不同目录中的Makefile
文件中的目标之间的依赖关系建立和维护规则?您现在使用Makefile的问题是,您只将代码列为依赖关系,不是数据。这就是很多魔法发生的地方。如果“分析”知道要使用哪些文件,并且可以将这些文件列为依赖项,那么它可以回过头来查看它们是如何生成的以及它们有哪些依赖项。如果管道中的早期文件被更新,那么它可以运行所有必要的步骤来更新该文件。比如说
import: rawdata.csv
rawdata.csv:
scp remoteserver:/rawdata.csv .
transform: tansdata.csv
transdata.csv: gogo.pl rawdata.csv
perl gogo.pl $< > $@
plot: plot.png
plot.png: plot.R transdata.csv
Rscript plot.R
导入:rawdata.csv
rawdata.csv:
scp remoteserver:/rawdata.csv。
转换:tansdata.csv
transdata.csv:gogo.pl rawdata.csv
perl gogo.pl$<>$@
plot:plot.png
plot.png:plot.R transdata.csv
Rscript plot.R
因此,如果我执行
makeimport
,它将下载一个新的csv文件。然后,如果我运行makeplot
,它将尝试生成plot.png
,但这取决于transdata.csv
,这取决于rawdata.csv
,因为rawdata.csv
已更新,它需要更新transdata.csv
,然后它就可以运行R脚本了。若您并没有显式地设置很多文件依赖项,那个么您就失去了make的很多功能。但是如果失败了,有时要获得所有正确的依赖关系可能会很棘手(特别是如果您从一个步骤中生成多个输出)。以下是我的想法(来自@MrFlick的答案-谢谢)在将我的研究工作流程的数据依赖关系添加到项目的当前make
基础架构(带有代码片段)时。我还试图通过指定make
目标之间的依赖关系来反映所需的工作流
导入/生成文件:
importFLOSSmole: getFLOSSmoleDataXML.R FLOSSmole.RData
@$(RSCRIPT) $(R_OPTS) $<
@touch $@.done
(similar targets for other data sources)
IMPORT_DIR=../import
prepare: import \
transform \
cleanup \
merge \
sample
import: $IMPORT_DIR/importFLOSSmole.done # and/or other flag files, as needed
transform: transform.R import
@$(RSCRIPT) $(R_OPTS) $<
@touch $@.done
cleanup: cleanup.R transform
@$(RSCRIPT) $(R_OPTS) $<
@touch $@.done
merge: merge.R cleanup
@$(RSCRIPT) $(R_OPTS) $<
@touch $@.done
sample: sample.R merge
@$(RSCRIPT) $(R_OPTS) $<
@touch $@.done
PREP_DIR=../prepare
analysis: prepare \
eda \
efa \
cfa \
sem
prepare: $PREP_DIR/transform.done # and/or other flag files, as needed
eda: eda.R prepare
@$(RSCRIPT) $(R_OPTS) $<
@touch $@.done
efa: efa.R eda
@$(RSCRIPT) $(R_OPTS) $<
@touch $@.done
cfa: cfa.R efa
@$(RSCRIPT) $(R_OPTS) $<
@touch $@.done
sem: sem.R cfa
@$(RSCRIPT) $(R_OPTS) $<
@touch $@.done
importFLOSSmole:getFLOSSmoleDataXML.R FLOSSmole.RData
@$(RSCRIPT)$(R_选项)$<
@触摸$@。完成
(其他数据源的类似目标)
准备/Makefile:
importFLOSSmole: getFLOSSmoleDataXML.R FLOSSmole.RData
@$(RSCRIPT) $(R_OPTS) $<
@touch $@.done
(similar targets for other data sources)
IMPORT_DIR=../import
prepare: import \
transform \
cleanup \
merge \
sample
import: $IMPORT_DIR/importFLOSSmole.done # and/or other flag files, as needed
transform: transform.R import
@$(RSCRIPT) $(R_OPTS) $<
@touch $@.done
cleanup: cleanup.R transform
@$(RSCRIPT) $(R_OPTS) $<
@touch $@.done
merge: merge.R cleanup
@$(RSCRIPT) $(R_OPTS) $<
@touch $@.done
sample: sample.R merge
@$(RSCRIPT) $(R_OPTS) $<
@touch $@.done
PREP_DIR=../prepare
analysis: prepare \
eda \
efa \
cfa \
sem
prepare: $PREP_DIR/transform.done # and/or other flag files, as needed
eda: eda.R prepare
@$(RSCRIPT) $(R_OPTS) $<
@touch $@.done
efa: efa.R eda
@$(RSCRIPT) $(R_OPTS) $<
@touch $@.done
cfa: cfa.R efa
@$(RSCRIPT) $(R_OPTS) $<
@touch $@.done
sem: sem.R cfa
@$(RSCRIPT) $(R_OPTS) $<
@touch $@.done
IMPORT\u DIR=../IMPORT
准备:导入\
转化\
清理\
合并\
样品
导入:$import_DIR/importFLOSSmole.done#和/或其他标志文件(根据需要)
transform:transform.R导入
@$(RSCRIPT)$(R_选项)$<
@触摸$@。完成
清理:清理.R变换
@$(RSCRIPT)$(R_选项)$<
@触摸$@。完成
合并:合并.R清理
@$(RSCRIPT)$(R_选项)$<
@触摸$@。完成
示例:sample.R merge
@$(RSCRIPT)$(R_选项)$<
@触摸$@。完成
分析/Makefile:
importFLOSSmole: getFLOSSmoleDataXML.R FLOSSmole.RData
@$(RSCRIPT) $(R_OPTS) $<
@touch $@.done
(similar targets for other data sources)
IMPORT_DIR=../import
prepare: import \
transform \
cleanup \
merge \
sample
import: $IMPORT_DIR/importFLOSSmole.done # and/or other flag files, as needed
transform: transform.R import
@$(RSCRIPT) $(R_OPTS) $<
@touch $@.done
cleanup: cleanup.R transform
@$(RSCRIPT) $(R_OPTS) $<
@touch $@.done
merge: merge.R cleanup
@$(RSCRIPT) $(R_OPTS) $<
@touch $@.done
sample: sample.R merge
@$(RSCRIPT) $(R_OPTS) $<
@touch $@.done
PREP_DIR=../prepare
analysis: prepare \
eda \
efa \
cfa \
sem
prepare: $PREP_DIR/transform.done # and/or other flag files, as needed
eda: eda.R prepare
@$(RSCRIPT) $(R_OPTS) $<
@touch $@.done
efa: efa.R eda
@$(RSCRIPT) $(R_OPTS) $<
@touch $@.done
cfa: cfa.R efa
@$(RSCRIPT) $(R_OPTS) $<
@touch $@.done
sem: sem.R cfa
@$(RSCRIPT) $(R_OPTS) $<
@touch $@.done
PREP\u DIR=../prepare
分析:准备\
eda\
全民教育\
终审法院\
扫描电镜
准备:$PREP_DIR/transform.done#和/或其他标志文件(根据需要)
eda:eda.R准备
@$(RSCRIPT)$(R_选项)$<
@触摸$@。完成
全民教育:全民教育
@$(RSCRIPT)$(R_选项)$<
@触摸$@。完成
cfa:cfa.R全民教育
@$(RSCRIPT)$(R_选项)$<
@触摸$@。完成
sem:sem.R cfa
@$(RSCRIPT)$(R_选项)$<
@触摸$@。完成
目录results
和present
中Makefile
文件的内容仍然待定
我将非常感谢您对上述内容的想法和建议导入/Makefile的目标是什么,它实际产生了什么?
prepare/Makefile
中的目标是什么,它实际产生了什么?当您在analyze
中make eda
时,它会使用哪些文件作为输入?@Beta:很抱歉延迟-刚刚恢复联机。import/Makefile
中的每个目标,例如importFLOSSmole
,在cache/
子目录中生成一组.rds
文件(我正在考虑更改以生成单个.RData
文件)。相应地,每个焦油