我正在咨询一家公司如何加快他们的构建速度,我立即向他们指出了预编译 header 和统一构建 - 10 分钟的完整构建可以轻松缩短到 2-3 分钟。幸运的是 CMake 3.16 最近发布了 it supports both of those ,所以我告诉他们升级。
问题如下:从 CMake 2.6 切换到 3.16 后,运行 CMake 所需的时间从大约 20 秒跃升至 10 多分钟。大部分时间都花在生成阶段。如果您给它足够的时间并且使用 Unity 构建成功编译了代码,它确实会成功完成,但这个 CMake 时间是 Not Acceptable 。
这是他们的设置:
- CMake 2.6,带有全局标志/定义/包含的旧式 CMake - 不是现代的(基于目标)。没有什么太花哨的 - 没有自定义命令或构建规则和复杂的依赖关系。
- 使用的编译器是 GCC 7,生成 Makefile - 操作系统是 CentOS 7,内核:Linux 3.10.0-862.14.4.el7.x86_64
- 大约 2000 个
.cpp
文件分布在 100 个库和 600 个可执行文件中(其中大部分是测试可执行文件,其中包含一个.cpp
) - 大多数
.cpp
文件都是用aux_source_directory
收集/通配的- 我们知道不明确列出.cpp
文件是一种反模式,但这不是重点 - 我认为这是无关紧要的,因为这应该发生在配置步骤中而不是生成期间,对吗?
以下是我们观察到的情况:
- 我们对不同的 CMake 版本进行了二进制搜索,得出的结论是,巨大的减速发生在 3.15 和 3.16 之间 - 正是在添加预编译头和统一构建支持的时候,但我认为这些功能与速度放缓 - 我想不出它们产生如此影响的原因 - 一定是其他一些重构或改变......
- 我们禁用了所有测试(这意味着几乎所有 600 个可执行文件都被删除) - 将 CMake 目标的数量从 700 个减少到 100 个以上 - 运行 CMake 所需的时间显着下降,但仍然是几个对于所有 700 个目标,比使用 CMake 2.6 的时间长 1 倍。
- 我们使用
strace
观察了发生的情况,主要是lstat
和access
调用以及一些读取和写入 - 但这是无止境的- 看起来每秒有数百次操作,以非常可重复的方式进行。此外,还不断尝试查找 libgflags.so ,但始终失败。不幸的是我现在没有这样的日志。 - 我们创建了一个 callgrind 配置文件,运行几分钟后如下所示:/image/tEqaF.png (可以找到 callgrind 输出文件 here ) - 似乎大部分时间都花在
ComputeLinkLibs()
上并获取目标的全名和定义等等......有 700 个目标太多了?这是一个指数问题吗?为什么 CMake 3.15 没有问题?
我在互联网上找不到任何其他人遇到同样问题的报告...有什么想法下一步要尝试吗?也许使用 Perf 进行配置?尝试使用 Ninja 作为后端 ( report of that being faster )?
最佳答案
分析得很好。这对于 CMake 的开发人员会有帮助。但我怀疑你会在这里找到很多帮助。请开通issue .
如果您能提供一个最小的示例来展示您的问题,则可获得奖励积分。您可能会通过生成大量文件来得到这个。
关于makefile - 与旧版本相比,CMake 3.16 在 Makefile 的生成阶段慢了几个数量级,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60093679/