规则调用脚本时如何定义Makefile目标?

时间:2017-07-19 22:13:15

标签: bash makefile gnu-make

我第一次尝试使用make来运行一系列脚本。我有这样的树目录结构:

project
├── data
│   └── run1
│       └── pass
│            ├── 0
│            ├── 1
│            └── 2
├── include
│   └── variables.mk
├── Makefile
└── scripts
    └── operations.sh

我有一个数据集run1,它在pass中有多个目录,所有数据集都包含txt个文件。 operations.sh脚本使用递归搜索命名目录的方法(此处为pass)。我希望有更多数据(run2run3等),并且希望能够在数据可用时以相同的方式处理它们。为此,我在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(每次运行dataanalysis。然后我可以创建一个运行operations.sh的目标。这很好用。但它实际上并没有正确地使用make。我想make输出,然后如果重新运行make,如果数据或分析的任何部分没有改变,则不重新生成输出。

因此我的问题是:通常,目标是文件。 operations.sh脚本运行的方法不是我开发的,并且有关于输入和输出的特定规则(两者都是dirs,如图所示)。我想让目标成为operations.sh生成的一组文件。我希望它能像

那样工作
%.output.txt: $(DATA_DIRS)
    sh operations.sh $< > $@

我想我理解如何使用%来命名依赖项,尽管还没有对此进行测试。在$(DATA_DIRS)目标文件的同时,我可以将make作为依赖项吗?从概念上讲,我不知道从哪方面开始。

非常感谢任何帮助。

2 个答案:

答案 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))

运行整套。