我正在开发一个基于 Qt 的大型项目,即使在 6 核机器上也需要几个小时才能编译。
原因是当我运行 make
时,只有一个核心编译源代码:其他核心保持空闲状态。
解决方案是使用 -j
选项(类似于 make -j6
)执行 make
,使用所有 6 个内核我的机器。
问题是 make
不会在递归中生成。
例如:
我有 4 个模块,A、B、C 和 D: - D 取决于 A、B 和 C。 - B 取决于 A。 - C 仅依赖于系统库。 - A 仅依赖于系统库。
qmake
应用程序为上述每个模块生成了一个 Makefile,并为编译所有模块生成了一个 Makefile。
当我运行make -j6
时,6个作业开始编译所有模块,而不是一个一个地编译。这种行为是有问题的,因为当模块 D 必须链接到其他模块时,这些模块可能尚未准备好,从而引发未找到
错误。
是否可以使用 make
选项更改此行为?这可能是软件工程的问题(模块设计得不好)?
最佳答案
听起来您缺少递归 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 fixes recursive make在我的博客上。
(免责声明:我是 Electric Make 的架构师)
关于makefile - 如何强制 make 仅生成递归作业,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14033327/