Parallel Make - 多次调用子项目

Posted

技术标签:

【中文标题】Parallel Make - 多次调用子项目【英文标题】:Parallel Make - Sub-Projects called multiple times 【发布时间】:2016-10-26 09:59:50 【问题描述】:

问题已在文件级别得到解答。但是我有一个更大的项目,它有很多项目间依赖关系(由动态生成的 DBus 标头引起)。

我创建了以下示例(example files as ZIP - 真正的项目要复杂得多)。

***Makefile如下:

sub-%:
    $(MAKE) -C $(patsubst sub-%,%,$@)

default:
    $(MAKE) -j12 sub-p1 sub-p2 sub-p3

子项目的 Makefile 如下所示(p1p2p3):

all: p1

../lib/lib.a:
    $(MAKE) -C ../lib lib.a

p1: ../lib/lib.a
    cp -f ../lib/lib.a p1

lib 的 Makefile 看起来像这样:

lib.a:
    sleep 2
    date > $@
    echo Done with building $@

问题:该库是为每个p*-project 分别并行构建的 - 在本示例中这不是问题,但在我们的示例中它会导致无法解决的问题。

当我在顶层调用make 时,我得到以下输出:

$ make
make -j12 sub-p1 sub-p2 sub-p3
make[1]: Entering directory '/home/kkr/tmp/parallelmake'
make -C p1
make -C p2
make -C p3
make[2]: Entering directory '/home/kkr/tmp/parallelmake/p1'
make -C ../lib lib.a
make[2]: Entering directory '/home/kkr/tmp/parallelmake/p2'
make -C ../lib lib.a
make[2]: Entering directory '/home/kkr/tmp/parallelmake/p3'
make -C ../lib lib.a
make[3]: Entering directory '/home/kkr/tmp/parallelmake/lib'
make[3]: Entering directory '/home/kkr/tmp/parallelmake/lib'
make[3]: Entering directory '/home/kkr/tmp/parallelmake/lib'
sleep 2
sleep 2
sleep 2
date > lib.a
date > lib.a
date > lib.a
make[3]: Leaving directory '/home/kkr/tmp/parallelmake/lib'
make[3]: Leaving directory '/home/kkr/tmp/parallelmake/lib'
make[3]: Leaving directory '/home/kkr/tmp/parallelmake/lib'
cp -f ../lib/lib.a p3
cp -f ../lib/lib.a p1
cp -f ../lib/lib.a p2
make[2]: Leaving directory '/home/kkr/tmp/parallelmake/p3'
make[2]: Leaving directory '/home/kkr/tmp/parallelmake/p1'
make[2]: Leaving directory '/home/kkr/tmp/parallelmake/p2'
make[1]: Leaving directory '/home/kkr/tmp/parallelmake'

问题:是否可以以某种方式自动同步子项目?

由于real project 有 13 个子项目 - 其中大多数具有项目间依赖关系 - 手动同步将非常困难。

【问题讨论】:

【参考方案1】:

递归make系统显然没有办法“自动”同步它;它们是完全独立的进程,无法相互告知它们正在运行给定的目标。

你有两个选择。第一个是最好的,但可能需要做很多工作,就是重新设计您的构建系统,使其成为非递归的。如果你有一个构建整个系统的 make 调用,那么只有一个 make 实例,它将全局协调所有目标的创建。您根本不需要$(MAKE) -C ../lib lib.a 规则。

如果这不可行,那么您需要重写您的*** makefile,以便强制执行排序,这样您就不会同时开始创建两个依赖于同一外部目标的目录。例如,不要像上面显示的*** makefile,而是这样写:

default: p1 p2 p3

p%: ; $(MAKE) -C $@

.PHONY: default p1 p2 p3

现在假设您要确保 p1p2p3 之前运行,因为您希望 p1 构建所有共享目标;然后你会在*** makefile 中添加这样的规则:

p2 p3: p1

您可以根据需要添加其他订购。

【讨论】:

我花了几个小时试图让它与并行制作一起工作。你完全确定它有效吗?依赖于子项目库的链接规则是什么样的?我只能让它每次都重新链接,甚至在构建子项目后甚至不链接。没有-j,我的 Makefile 是完美的。 这个例子没有提供足够的细节来回答你的问题。这是一个抽象的高级设计。而且,对于这些解释,SO cmets 是不够的。如果您有详细的问题,我建议您提出一个更具体的新问题。 但是,这里的设计有效。如果您需要在根级别提供另一个目标来包装在各个目录级别完成的所有工作,那是完全不同的事情,这里不讨论或描述,因为这不是本问题所要问的。 我认为作为没有代码可看的评论很难回答,我将尝试将 SSCCE 放在一起并提出适当的问题。谢谢。

以上是关于Parallel Make - 多次调用子项目的主要内容,如果未能解决你的问题,请参考以下文章

Parallel.ForEach 之 MaxDegreeOfParallelism

Python Parallel SSH 仅获取命令输出

如何在 perl 中安装 parallel-forkmanager

提高性能异步 Parallel.Foreach

Parallel.ForEach 与 Task.Factory.StartNew

如何正确调用 Parallel.ForEach 循环中的调用异步方法[重复]