首页 > 解决方案 > 在多个目录上并行执行

问题描述

我想用一个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

它运行良好,但test目标deploy是顺序的(因为 for 循环)并且它们可能是并行的。

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

但我不知道如何构造 aMakefile以使其成为这种方式。

任何想法 ?


说实话,任务deploy部署了一个GCP云函数,test本地运行函数

标签: makefile

解决方案


通常,构建生成文件以促进并行操作的最简单方法是定义可以并行处理的单独目标。然后,您可以使用make'-j选项来请求处理(最多)特定最大数量的并行任务的并行化。

例如:

deploy: deploy_a deploy_b

deploy_a: conf_a
    echo deploying conf_a

deploy_b: conf_b
    echo deploying conf_b

然后你可以make -j2 deploy和(可能)deploy_adeploy_b规则将被并行处理。但请注意,这可能没有多大帮助。即使您有两个部署的单独进程,如果您将两者都部署到同一个本地磁盘,那么它们将无法同时使用写入磁盘上的不同文件。因此,您可能不会看到明显更好的完成时间,甚至可能更糟。

还要注意,上面的示例避免动态确定可用的组件目录。这种活力对于 makefile 来说是非典型的,而且 IMO 很少提供净收益。尽管如此,GNU make(您已经依赖的特定实现)确实提供了机制,您可以通过这些机制动态生成所需的每个目录部署规则。


推荐阅读