2

我正在开发一个基于 Qt 的大型项目,即使在 6 核机器上编译也需要几个小时。

这样做的原因是,当我make只运行一个内核编译源代码时:其他内核保持空闲状态。

解决方案是使用我机器的所有 6 个内核执行make选项-j(类似于make -j6)。

这样做的问题是make不要在递归中产生。

例如:

我有 4 个模块,A、B、C 和 D: - D 依赖于 A、B 和 C。 - B 依赖于 A。 - C 仅依赖于系统库。- A 仅依赖于系统库。

qmake应用程序为上述每个模块生成了一个 Makefile,并为编译所有模块生成了一个 Makefile。

当我运行时make -j6,这 6 个作业开始编译所有模块,而不是一一编译。这种行为是有问题的,因为当必须将模块 D 链接到其他模块时,这些模块可能还没有准备好,从而引发not found错误。

是否可以通过make选项更改此行为?这可能是软件工程的问题(模块没有很好地投影)?

4

3 回答 3

1

听起来您在递归 make 调用之间缺少依赖关系。您还没有向我们展示调用递归 make 的顶级 makefile,但我猜它看起来像这样:

all: A B C D

A B C D:
    $(MAKE) -C $@

您可以通过在递归 make 之间添加必要的依赖项来解决此问题:

all: A B C D

A B C D:
    $(MAKE) -C $@

B: A

D: A B C

这种策略将为您提供正确的并行构建,尽管以牺牲一些性能为代价——有很多工作可以在这些子构建之间安全地并行化,而仅仅为了一个或每个确实必须序列化的两个命令。更好的解决方案是使用非递归 make,这需要对你的 makefile 进行更严格的重构,或者使用Electric Make,它可以为你解决这个问题,而不需要你更改 makefile(甚至不需要添加额外的依赖项)。我已经在我的博客上写了关于Electric Make 如何修复递归 make的文章。

(免责声明:我是 Electric Make 的架构师)

于 2012-12-25T19:48:18.520 回答
1

Try building with makepp. That will unravel the recursion (see Recursive Make Considered Harmful) by piping the sub-make's targets back to the main process, as though the makefiles had been cleanly designed from the outset.

Then it will do its normal dependency analysis, not abstractly on a directory level, but by drilling down to the real per-file dependencies across your whole directory tree. So it can parallelize the maximum that's safely possible.

Actually I don't know why cmake generates makefiles... All they do is call cmake to do everything behind make's back. So much so, that makepp has some special handling for cmake to avoid endless recursion, for dependencies that make oversees. Now qmake is not exactly cmake, and I'd be delighted to hear if it's near enough to work!

于 2012-12-29T22:12:47.470 回答
0

我终于发现了如何使用qmake.

它再简单不过了:只需添加CONFIG += ordered.pro文件中,一切都会正常工作。有关此标志的更多信息,请参见 qmake 变量参考

请注意,它仅适用于subdirs项目模板,但这不是问题,因为并行编译仅在不同二进制文件之间存在依赖关系时才会出现问题。

例子:

# ABC.pro

TEMPLATE = subdirs

CONFIG += ordered

SUBDIRS += \
    A \
    B \
    C
于 2014-06-02T03:05:01.850 回答