从顶层目录调用GNU Make

时间:2018-08-21 09:18:36

标签: makefile gnu-make

我有一个名为experiments的目录和一个带有单独实验的子目录,例如2018-08-202018-08-21。每个子目录都包含一个我使用以下命令在屏幕上运行的Python脚本:

screen -L -dm -S experiment python script.py

我想知道我是否可以在 Makefile 目录中有一个 experiments 来自动执行该命令。 我知道每个子目录中都可以有一个Makefile,但这会给git带来太多重复的内容。

1 个答案:

答案 0 :(得分:2)

可以。由于您没有提供太多详细信息,因此我认为:

    包含experiments python脚本的script.py
  1. 任何子目录是一个实验。
  2. 您希望在每次调用make时重新运行所有实验。

以下应该是一个很好的起点:

EXPDIRS := $(dir $(shell find . -maxdepth 2 -mindepth 2 -type f -name script.py))
EXPS    := $(addsuffix .done,$(EXPDIRS))

.PHONY: all $(EXPS)

all: $(EXPS)

$(EXPS): %.done:
    cd $* && screen -L -dm -S experiment python script.py

说明:

  • 使用EXPDIRS实用程序和find make函数设置dir make变量(以删除返回路径的文件名部分)。例如:./experimentC/ ./experimentA/
  • 通过向EXPS中的每个单词添加.done来设置EXPDIRS make变量。例如:./experimentC/.done ./experimentA/.done
  • EXPS中列出的目标以及all目标被声明为phony,这意味着即使具有该名称的文件已经存在并且是最新的,make也会重新运行其构建规则。
  • all取决于EXPS中列出的所有目标。如果仅运行makemake all,则make将运行所有实验的规则,如果您使用-j4选项调用make,并且有4个内核,则make可能并行运行在您的计算机上。
  • 最后,静态模式规则$(EXPS):...告诉进行该操作以构建EXPS中列出的目标:
    • 转到实验目录($*使自动变量随着%.done模式的茎而扩展)。
    • 运行您的python脚本。

可能的改进:

  1. 仅当尚未运行实验或自上次运行以来其输入数据已更改时,才运行实验。假设输入数据只是python脚本(如果需要,易于修改)。我们将使用一个名为experimentA/.done的空文件将实验标记为完成并记住何时进行。然后,以下应避免无用的实验运行:

    EXPDIRS := $(dir $(shell find . -maxdepth 2 -mindepth 2 -type f -name script.py))
    EXPS    := $(addsuffix .done,$(EXPDIRS))
    
    .PHONY: all
    
    all: $(EXPS)
    
    $(EXPS): %.done: %script.py
        cd $* && screen -L -dm -S experiment python script.py
        touch $@
    
    clean:
        rm -f $(EXPS)