我第一次尝试使用make
来运行一系列脚本。我有这样的树目录结构:
project
├── data
│ └── run1
│ └── pass
│ ├── 0
│ ├── 1
│ └── 2
├── include
│ └── variables.mk
├── Makefile
└── scripts
└── operations.sh
我有一个数据集run1
,它在pass
中有多个目录,所有数据集都包含txt
个文件。 operations.sh
脚本使用递归搜索命名目录的方法(此处为pass
)。我希望有更多数据(run2
,run3
等),并且希望能够在数据可用时以相同的方式处理它们。为此,我在include
上使用variables.mk
(不确定这是否合适但效果正常),定义$(INPUT_RUNS)
,我将在新的广告投放到达时更新。
我已经编写了一个测试Makefile
include $(CURDIR)/include/variables.mk
DATA_DIRS := $(addprefix $(CURDIR)/data/, $(foreach r, $(INPUT_RUNS), $(r))/pass)
OUT_DIRS := $(addprefix $(CURDIR)/analysis/, $(foreach r, $(INPUT_RUNS), $(r)))
##targets
all: operations_run
##operations
operations_run: $(OUT_DIRS) $(DATA_DIRS)
mkdir -p $</operations
sh scripts/operations.sh $</operations $(DATA_DIRS)
这指定了一组dirs(每次运行data
,analysis
。然后我可以创建一个运行operations.sh
的目标。这很好用。但它实际上并没有正确地使用make
。我想make
输出,然后如果重新运行make
,如果数据或分析的任何部分没有改变,则不重新生成输出。
因此我的问题是:通常,目标是文件。 operations.sh
脚本运行的方法不是我开发的,并且有关于输入和输出的特定规则(两者都是dirs,如图所示)。我想让目标成为operations.sh
生成的一组文件。我希望它能像
%.output.txt: $(DATA_DIRS)
sh operations.sh $< > $@
我想我理解如何使用%
来命名依赖项,尽管还没有对此进行测试。在$(DATA_DIRS)
目标文件的同时,我可以将make
作为依赖项吗?从概念上讲,我不知道从哪方面开始。
非常感谢任何帮助。
答案 0 :(得分:1)
如果您不知道脚本的实际输入是什么,则很难判断是否必须重新执行特定目标。 Make比较目标文件和必备文件的上次修改时间。目录更难以用于此分析,因为目录的上次修改时间具有不同的含义:它在添加或删除文件时更改,而不是在文件内容更改时更改。您应首先了解脚本的真实输入,然后表达输出文件和输入文件之间的依赖关系。
注意:您可以告诉make构建要处理的目录列表,例如:
DATA_DIR := $(shell find $(CURDIR)/data -type d -name pass)
答案 1 :(得分:1)
我认为规则应该是:
$(CURDIR)/analysis/%: $(CURDIR)/data/%/pass
sh operations.sh $< $@
基本上有个别户外规则。假设操作采用输入和输出目录。
虽然这可能&#34;思考&#34;输出目录因任何原因而被更改(想想来自查看器的临时文件)。我个人喜欢手动&#34;盖章&#34;完成。
$(CURDIR)/analysis/%/.done: $(CURDIR)/data/%/pass
sh operations.sh $< $(@:/.done=)
touch $@
这将在outdir中放置一个空的.done
文件,其中包含上次成功创建的时间戳。
和
operations_run: $(addsuffix /.done,$(OUT_DIRS))
运行整套。