【问题标题】:Make for identical workflow in separate directories在不同的目录中创建相同的工作流程
【发布时间】: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


    【解决方案1】:

    我认为,在您的情况下,没有必要为 .txt 文件而烦恼。如果script.py 更好并且可以按文件工作,那么编写单独的文件规则就会有价值。在这种情况下,我们需要为每个目录引入一个中间 .done 文件。

    DATA_DIRS := a b c
    # A directory/.done.analysis file means that `script.py` was run here.
    DONE_FILES := $(DATA_DIRS:%=%/*.done.analysis)
    
    # .done.analysis depends on all the source data files.
    # When a .dat file is added or changes, it will be newer than
    # a .done.analysis file; and the analysis would be re-run.
    $(DONE_FILES): %/.done.analysis: $(wildcard %/*.dat)
        python script.py $(@D)
    
    final_analysis_plot.png: $(DONE_FILES)
        python make_plot.py $(wildcard $(DATA_DIRS)/analysis_time_*.txt)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-07-04
      • 2012-11-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-20
      • 2019-12-29
      • 1970-01-01
      相关资源
      最近更新 更多