ccache 在 CI 中失效的主因是缓存键不一致;需固定头文件路径、禁用影响稳定性的编译选项、统一编译器版本、使用 CMAKE_CXX_COMPILER_LAUNCHER 启用、关闭 hash_dir、显式设置 base_dir。

ccache 能显著加速 CI 构建,但默认配置下大概率不生效——根本原因不是没装,而是缓存键(cache key)每次都不一致,导致 0% 命中率。
CI 中 ccache 不命中:编译选项和路径是最大陷阱
CI 环境里 ccache 失效最常见的情况是:每次构建都生成全新路径(比如 /tmp/build-abc123/),而头文件搜索路径里含这个临时目录。ccache 会把整个 -I 路径内容纳入哈希计算,路径一变,key 就变,缓存直接失效。
- 避免使用
-I/tmp/xxx、-I$PWD/build这类带随机/时间戳/流水线 ID 的路径;改用固定前缀,如-I${WORKSPACE}/include,并在 CI 启动时确保该路径存在且内容稳定 -
-fprofile-generate、-fcoverage-mapping、-ftime-trace这类影响输出稳定性的选项,ccache 会自动绕过缓存——CI 打包或测试阶段若启用这些,对应目标文件不会进缓存 - 确保所有构建节点使用完全相同的编译器版本:
g++ --version输出必须一字不差;不同 minor 版本(如 12.2 vs 12.3)也会导致 key 不匹配
CMake 项目在 CI 中正确启用 ccache 的唯一可靠方式
别设 CXX=ccache g++,也别改 CMAKE_CXX_COMPILER 指向 ccache 包装脚本——这两种方式在 Ninja 多配置生成、交叉编译或子项目嵌套时极易漏掉部分编译命令。
- 始终用
CMAKE_CXX_COMPILER_LAUNCHER=ccache(CMake 3.4+ 支持),它会在所有编译规则中注入 launcher,覆盖 100% 的.cpp → .o步骤 - CI 脚本中显式导出环境变量:
export CCACHE_DIR=/cache/ccache,并确保该路径在所有 job 中可持久化(如挂载为 volume 或 NFS) - 运行
ccache -s检查状态,重点关注cache hit rate和files in cache;如果cache hit rate长期低于 20%,优先检查编译参数一致性,而不是调大缓存容量
分布式 CI 场景下必须禁用的 ccache 行为
ccache 默认开启 hash_dir = true,即把源文件所在绝对路径纳入哈希——这在单机开发没问题,但在多节点 CI 中,同一份代码检出到 /home/user/project 和 /workspace/project 就算内容完全一样,缓存也绝不复用。
- CI 配置中必须关闭该行为:
ccache --set-config=hash_dir=false,或在$CCACHE_DIR/ccache.conf中写入hash_dir = false - 禁用
base_dir自动推导(ccache 会尝试从源路径提取“项目根”用于相对化),改为显式设置:ccache --set-config=base_dir=/workspace,所有节点统一 - 调试时加
-v参数观察实际哈希输入:ccache -v g++ -c foo.cpp,确认输出中不再出现绝对路径片段
真正卡住团队 CI 速度的,从来不是 ccache 装没装,而是谁在改 -I 路径、谁悄悄加了 -frecord-gcc-switches、谁让不同 runner 用了不同 patch 版本的 clang。缓存本身很老实,它只认输入是否完全一致——你给它飘忽不定的输入,它就只能每次都重算。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











