我第一次尝试使用make
来运行一系列脚本。我有一个像这样的树目录结构:
project
├── data
│ └── run1
│ └── pass
│ ├── 0
│ ├── 1
│ └── 2
├── include
│ └── variables.mk
├── Makefile
└── scripts
└── operations.sh
我有一个数据集 run1
,它在 pass
中有多个目录,所有目录都保存 txt
文件。 operations.sh
脚本使用递归搜索指定目录(此处为 pass
)的方法。我期望更多数据(run2
、run3
等),并且希望能够在数据可用时以相同的方式处理它们。为此,我在 variables.mk
上使用 include
(不确定这是否合适,但效果很好),定义 $(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)
这指定了一组目录(每次运行的数据
、分析
)。然后我可以创建一个用于运行 operations.sh
的目标。这很好用。但在我看来,它实际上并没有正确使用 make
。我想要 make
输出,然后如果重新运行 make
,如果数据或分析没有任何部分发生更改,则不重新生成输出。
因此我的问题是:通常,目标是一个文件。 Operations.sh 脚本运行的方法不是我开发的,并且对输入和输出有特定的规则(两者都是所见的目录)。我想让目标成为由 operations.sh
生成的一组文件。我希望它能像这样工作
%.output.txt: $(DATA_DIRS)
sh operations.sh $< > $@
我想我了解如何使用 %
来命名依赖项,但尚未对此进行测试。我可以在 make
目标文件时将 $(DATA_DIRS)
作为依赖项吗?从概念上讲,我不知道从哪里开始这方面。
非常感谢任何帮助。
最佳答案
我认为规则应该是这样的:
$(CURDIR)/analysis/%: $(CURDIR)/data/%/pass
sh operations.sh $< $@
基本上对个人的外行行为有一个规则。假设操作需要一个输入和输出目录。
尽管这可能“认为”输出目录由于某种原因而被更改(认为来自查看器的临时文件等)。我个人喜欢手动“标记”完成。
$(CURDIR)/analysis/%/.done: $(CURDIR)/data/%/pass
sh operations.sh $< $(@:/.done=)
touch $@
这将在 outdir 中放置一个空的 .done
文件,并带有上次成功创建的时间戳。
和
operations_run: $(addsuffix /.done,$(OUT_DIRS))
运行整个集合。
关于bash - 当规则调用脚本时如何定义 Makefile 目标?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45201919/