【发布时间】:2020-06-01 21:03:14
【问题描述】:
我正在使用 make 来自动化我的一些数据分析。我有几个目录,每个目录都包含不同的数据实现,其中包含表示给定时间数据状态的多个文件,如下所示:
├── a
│ ├── time_01.dat
│ ├── time_02.dat
│ ├── time_03.dat
│ └── ...
├── b
│ ├── time_01.dat
│ └── ...
├── c
│ ├── time_01.dat
│ └── ...
├── ...
每个目录的数据文件数量未知,可以随时添加更多。每个目录中的文件都具有相同的命名约定。
我想使用 make 在每个目录中运行完全相同的配方集(以分别且统一地分析每个数据集)。特别是,有一个脚本应该在添加新数据文件时运行,并为目录中的每个数据文件创建一个输出文件 (analysis_time_XX.txt)。此脚本不会更新之前创建的任何文件,但会创建所有丢失的文件。不幸的是,重构这个脚本是不可能的。
所以我有一个创建许多目标的配方,但它必须为每个目录单独运行。我发现使用一个配方创建多个目标的解决方案(例如here)在我的情况下不起作用,因为我需要一个规则来分别为不同目录中的多组文件执行此操作。
这些中间文件本身就是必需的(因为它们有助于验证收集的数据),但也用于创建数据集之间的最终比较图。
我目前的设置是功能和.SECONDEXPANSION的丑陋组合
dirs = a b c
datafiles = $(foreach dir,$(dirs),$(wildcard $(dir)/*.dat))
df_to_analysis = $(subst .dat,.txt,$(subst time_,analysis_time_,$(1)))
analysis_to_df = $(subst .txt,.dat,$(subst analysis_time_,time_,$(1)))
analysis_files = $(foreach df,$(datafiles),$(call df_to_analysis,$(df)))
all: final_analysis_plot.png
.SECONDEXPANSION:
$(analysis_files): %: $$(call analysis_to_df,%)
python script.py $(dir $@)
final_analysis_plot.png: $(analysis_files)
python make_plot.py $(analysis_files)
注意script.py 在给定目录中创建所有analysis_time_XX.txt 文件。这种设置的缺陷是 make 不知道第一个脚本会生成所有目标,因此在使用并行 make 时会不必要地运行。对于我的应用程序来说,并行 make 是必要的,因为这些脚本的运行时间很长,而并行化可以节省大量时间,因为设置是“令人尴尬的并行”。
有没有优雅的方法来解决这个问题?甚至是清理我现在拥有的代码的优雅方式?我在这里展示了一个简单的示例,它已经需要进行大量设置,并且为几个不同的脚本执行此操作很快就会变得笨拙。
【问题讨论】:
标签: makefile