首页 > 解决方案 > Makefile 目标运行并行目标并在执行更多操作之前等待它们完成

问题描述

我试图让“父目标”等待“并行子目标”完成,然后在“父目标”的“主体”中执行某些操作。

在以下示例中,应@echo "Print this only after *ALL* the previous PARALLEL tasks are done!"所有目标完成后才打印消息。foo-task1foo-task2foo-task3

如果我删除&这些“子目标”末尾的 & 符号 ( ) ,那么它们将变为 serial,但这不是预期的行为。它们的行为应该类似于“线程池”或“进程池”。我事先不知道哪些目标会最后完成,所以我无法&从瓶颈目标中删除与号 ( )。

这些目标代表对远程 REST API 的 HTTP 调用,可能需要不同的时间才能完成。我想等待这些“并行 REST 调用”,看看它们是否成功,然后再将最终消息打印到foo-parallel.

这些“并行目标”正在返回标准输出/标准错误,所以我希望父目标可以等待它们并在出现错误时失败。

我怎么能这样做?

foo-task1:
    @bash -c 'sleep 1 && echo "task1" &'

foo-task2:
    @bash -c 'sleep 1 && echo "task2" &'

foo-task3:
    @bash -c 'sleep 2 && echo "task3" &'

foo-parallel: foo-task3 foo-task2 foo-task1
    @echo "Print this only after *ALL* the previous PARALLEL tasks are done!"

命令make版本:

$ make --version
GNU Make 4.1
Built for x86_64-pc-linux-gnu
Copyright (C) 1988-2014 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

编辑:

这个稍微不同的目标定义(我更改了sleep时间只是为了确保消息以延迟顺序而不是代码中的顺序打印):

foo-parallel:
    @bash -c 'sleep 5 && echo "task1" & \
                        sleep 1 && echo "task2" & \
                        sleep 2 && echo "task3" & \
                        wait; \
                        echo "done here!"'

印刷:

$ make foo-parallel 
task2
task3
task1
done here!

但我需要将所有这些的逻辑task1放在task2task3一个目标中。我想将这些任务分成不同的目标。

标签: multithreadingmakefilethreadpoolgnu-make

解决方案


-j如果不使用 make 的选项,您将无法做到这一点。默认情况下,make 构建一个目标,等待它完成,然后构建下一个目标。只有-j这样它才会支持同时运行的多个目标。

foo-parallel: foo-task3 foo-task2 foo-task1
        @echo "Print this only after *ALL* the previous PARALLEL tasks are done!"

foo-task1:
        @sleep 1 && echo "task1"

foo-task2:
        @sleep 1 && echo "task2"

foo-task3:
        @sleep 2 && echo "task3"

然后运行:make -j 或者如果你想限制并行构建的数量,使用make -j2或者你想要的数量。

如果你真的想避免输入-j你可以使用递归make:

foo-parallel:
        @$(MAKE) -j foo-task1 foo-task2 foo-task3
        @echo "Print this only after *ALL* the previous PARALLEL tasks are done!"

foo-task1:
        @sleep 1 && echo "task1"

foo-task2:
        @sleep 1 && echo "task2"

foo-task3:
        @sleep 2 && echo "task3"

但是,如果有人调用make -j. 一般来说,我认为最好让调用make者来决定他们想要多少并行度,对于他们的特定系统。


推荐阅读