ccache 能显著加速 C++ 项目重复编译,但需正确配置编译器路径、缓存目录、预处理器行为及 CMAKE_CXX_COMPILER_LAUNCHER 等关键项,否则可能失效或引发链接错误。

ccache 能显著加速 C++ 项目的重复编译,前提是正确配置编译器路径、缓存目录和预处理器行为;否则它可能完全不生效,甚至导致链接错误或缓存污染。
确认 ccache 是否真正介入编译过程
很多项目看似用了 ccache,实际编译命令绕过了它。关键看 g++ 或 clang++ 是否被 ccache 包装——不是靠 alias,而是靠 PATH 优先级或显式前缀。
- 运行
which g++,输出应为类似/usr/lib/ccache/g++(Debian/Ubuntu)或/usr/local/bin/g++(若你软链了 ccache) - 检查编译日志中实际执行的命令:如果看到
ccache g++ -c ...或/usr/lib/ccache/g++ -c ...,说明生效;若只有裸g++,ccache 没起作用 - CMake 项目需显式设置:
cmake -DCMAKE_CXX_COMPILER_LAUNCHER=ccache ...;仅设CMAKE_CXX_COMPILER为ccache是错的
避免因预处理差异导致缓存未命中
ccache 对输入源做哈希,任何影响预处理结果的变量(如绝对路径、时间宏、随机 salt)都会让哈希值变化,强制重编译。
- 禁用
__DATE__/__TIME__:在编译选项中加-frecord-gcc-switches无用,应统一用-D__DATE__=\"redacted\" -D__TIME__=\"redacted\" - 避免绝对路径泄露:CMake 中用
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)生成的compile_commands.json含绝对路径,但 ccache 不读它;真正要管的是-I/path/to/include—— 若路径随 workspace 变化,考虑用符号链接固定位置 - 禁止
-fdebug-prefix-map或-frecord-gcc-switches等引入非确定性信息的 flag(除非你明确需要调试信息且接受缓存失效)
合理配置缓存大小与位置
默认缓存位置(~/.ccache)可能空间不足或 I/O 慢;缓存满时 ccache 会自动清理,但策略偏保守,容易卡在 5GB 上限不动。
立即学习“C++免费学习笔记(深入)”;
- 用
ccache -s查看当前状态,重点关注cache size和max cache size - 增大上限:
ccache -M 20G(注意是大写M);清空缓存:ccache -C - 把缓存放 SSD 或内存盘:
export CCACHE_DIR="/fast/ssd/ccache-$(whoami)",并确保该路径有读写权限 - 启用压缩节省空间(小幅增加 CPU 开销):
ccache -o compression=true -o compression_level=6
识别并修复“假命中”和静默失败
ccache 有时会返回旧缓存对象而不报错,尤其在头文件变更但未被依赖分析捕获时——这会导致奇怪的运行时错误。
- 开启严格模式验证:设
export CCACHE_SLOPPINESS="pch_defines,time_macros,include_file_mtime,include_file_ctime,env_vars"(慎用,会降低命中率) - 临时禁用缓存调试问题:
CCACHE_DISABLE=1 make,对比产物是否一致 - 检查 ccache 日志:
export CCACHE_LOGFILE="/tmp/ccache.log"; export CCACHE_DEBUG=1,然后复现一次编译,查看日志里是否有hash mismatch或preprocessing failed
export CCACHE_DIR="$HOME/.ccache" export CCACHE_BASEDIR="$PWD" export CCACHE_SLOPPINESS="file_stat_matches" alias g++='ccache g++' alias clang++='ccache clang++'
最易被忽略的是 CCACHE_BASEDIR:它让 ccache 归一化源文件路径哈希,否则同一份代码在不同路径下编译,缓存完全不共享。还有就是 CMake 的 CMAKE_CXX_COMPILER_LAUNCHER 必须设对,不是所有构建系统都认 CC/CXX 环境变量里的 ccache。这些点没踩准,ccache 就只是个摆设。











