在多个目录上并行执行

时间:2019-07-09 15:18:40

标签: makefile

我想用一个makefile创建带有某些文件的多个目录。

我有这样的目录结构:

conf_a/conf.json
conf_b/conf.json
main.py
Makefile
requirements.txt

并想输入make conf_a并新建一个这样的目录:

build/conf_a/conf.json
build/conf_a/main.py
build/conf_a/requirements.txt
conf_a/conf.json
conf_b/conf.json
main.py
Makefile
requirements.txt

或者类似make conf_b之类的东西,并具有如下所示的新目录:

build/conf_b/conf.json
build/conf_b/main.py
build/conf_b/requirements.txt
conf_a/conf.json
conf_b/conf.json
main.py
Makefile
requirements.txt

所以我制作了一个这样的Makefile:

# Disable built-in rules and variables
MAKEFLAGS += --no-builtin-rules
MAKEFLAGS += --no-builtin-variables
.ONESHELL:
.SHELLFLAGS: -ec
.SILENT:

BUILD_DIR := $(CURDIR)/build
CONF_FILE := conf.json
FILES_TO_COPY := requirements.txt main.py

FUNCTION_DIRS := $(shell ls */$(CONF_FILE) | xargs -n 1 -I {} dirname {})
HIDDEN_FUNCTION_DIRS := $(shell ls .*/$(CONF_FILE) 2> /dev/null | xargs -n 1 -I {} dirname {})


clean:
    rm -rf $(BUILD_DIR)

all: clean $(FUNCTION_DIRS) deploy

$(FUNCTION_DIRS) $(HIDDEN_FUNCTION_DIRS):
    tmp=$@
    FUNCTION_DIR=$${tmp%/}
    export FUNCTION=$${FUNCTION_DIR#.}
    mkdir -p $(BUILD_DIR)/$$FUNCTION
    cp -f $(FILES_TO_COPY) $$FUNCTION_DIR/$(CONF_FILE) $(BUILD_DIR)/$$FUNCTION/

test:
    for FUNCTION in $(shell ls $(BUILD_DIR))
    do
        echo "Testing $$FUNCTION"
    done

deploy:
    for FUNCTION in $(shell ls $(BUILD_DIR))
    do
        echo "Deploying $$FUNCTION"
    done

嗯,行得通...

因此,如果我想测试conf,请执行:make conf_a test。 如果我要部署:make conf_b deploy

它运行得很好,但是testdeploy目标是顺序的(因为for循环),它们可能是并行的。

我的问题是我的配置目录太多了,因为并行部署速度很慢,所以本来可以好很多。

但是我不知道如何构造Makefile来做到这一点。

有什么想法吗?


实际上,任务deploy部署了GCP云功能,而test仅在本地运行了该功能

1 个答案:

答案 0 :(得分:0)

通常,构造makefile以便于并行操作的最简单方法是定义可以并行处理的单独目标。然后,您可以使用make的{​​{1}}选项来请求 处理(最多)特定数量的并行任务中的并行化。

例如:

-j

然后您可以deploy: deploy_a deploy_b deploy_a: conf_a echo deploying conf_a deploy_b: conf_b echo deploying conf_b 和(可能)make -j2 deploydeploy_a规则将被并行处理。但是请注意,这可能无济于事。即使您为这两个部署使用单独的进程,但是如果将两者都部署到同一本地磁盘上,则它们将无法同时使用对磁盘上不同文件的写入。结果,您可能看不到明显更长的完成时间,甚至可能更糟。

也请注意,上面的示例避开了动态确定可用组件目录的过程。这种动态性是makefile的典型特征,而IMO则很少提供净收益。尽管如此,GNU deploy_b(您已经在依靠它的特定实现)确实提供了一些机制,通过它们您可以动态生成所需的每目录部署规则。