使用ccache可提速2–5倍,通过缓存编译结果避免重复编译;关闭unity_build和precompiled_header以提升增量编译效率;用extern template减少模板实例化;禁用并精简头文件依赖。

用 ccache 缓存编译结果,别让重复编译吃掉你的时间
90% 的日常构建都是改了一两行就重新编译,ccache 能直接跳过已编译过的源文件,实测提速 2–5 倍。它不改变你的构建流程,只在编译器前面加一层缓存代理。
- 安装后把
ccache加进PATH,再用export CC="ccache gcc"和export CXX="ccache g++"(CMake 项目需额外传-DCMAKE_C_COMPILER=ccache等) - 默认缓存路径是
~/.ccache,磁盘空间不足时会自动清理,但建议手动设大小:运行ccache -M 10G - 注意:宏定义、头文件路径、编译器版本变化都会导致缓存失效——所以
ccache对 CI 或多环境开发特别友好,但本地频繁切分支时可能命中率下降 - 验证是否生效?改一行代码后执行
ccache -s,看cache hit rate是否明显上升
CMake 中关闭不必要的 UNITY_BUILD 和 PRECOMPILED_HEADER
这两个功能听起来很省事,但实际容易拖慢增量编译,尤其在大型项目中。
-
UNITY_BUILD把多个.cpp合并成一个编译单元,单次编译快了,但只要其中任一文件改动,整个合并单元就得重编——改一个测试文件,连带编译整个模块 -
PCH在头文件稳定时有效,但一旦std::vector或boost版本升级,所有依赖它的.cpp都得全量重编;Clang 下 PCH 兼容性也比 GCC 差 - 建议:仅对稳定不变的公共头(如自定义
base.h)启用 PCH;Unity Build 仅用于最终打包阶段,开发期关掉
减少模板实例化爆炸:用 extern template 和显式实例化
模板代码写得爽,编译器却要为每个类型组合生成一份代码,std::vector<int></int> 和 std::vector<double></double> 在不同文件里出现十次,就实例化二十次。
- 在头文件里声明:
extern template class std::vector<int>;</int>,告诉编译器“别在这儿实例化,去别处找” - 在某个
.cpp里写:template class std::vector<int>;</int>,集中生成一次 - 对自定义模板类更有效——比如
MyBuffer<t n></t>,在buffer.cpp里显式实例化常用组合:template class MyBuffer<char>;</char> - 没加
extern时,clang++ -ftime-trace会显示大量重复的模板解析耗时,加了之后能直接砍掉 15–30% 编译时间
避免 #include <bits></bits> 和过度头文件泛滥
这个万能头文件本质是把整个 libstdc++ 的实现头全拉进来,不仅增大预处理负担,还让依赖关系彻底失控。
立即学习“C++免费学习笔记(深入)”;
-
#include <bits></bits>在 GCC 下展开后常超 10 万行,Clang 下甚至无法缓存其预编译结果 - 用
clang++ -E -dD your_file.cpp | wc -l看预处理后行数,超过 20 万就要警惕 - 真实项目里,
#include "utils.h"却偷偷包含<opencv2></opencv2>,会导致所有引用utils.h的文件都重新编译——用include-what-you-use(iwyu)工具能揪出这类冗余 - 头文件里优先用前向声明:
class Widget;替代#include "widget.h",尤其在.h文件中
编译速度不是靠堆硬件解决的,而是靠控制依赖粒度和缓存边界。最常被忽略的一点是:改完 CMakeLists.txt 后,没人记得删掉 CMakeCache.txt 和 CMakeFiles/,结果新配置根本没生效——每次调参前先清构建目录,比调参数本身还重要。










