Windows平台MSVC配合CMake如何正确配置使用4.6.1+版本ccache
自ccache 4.6.1版本起,ccache已正式支持MSVC编译器的编译缓存能力,但不少用户在Windows环境下配置时会遇到ccache能被CMake检测到,但实际完全不被调用、ccache -s统计全0的问题,具体解决方法如下:
核心失效原因
你当前配置不生效的根本原因是:RULE_LAUNCH_COMPILE全局属性仅对Ninja、Makefile这类命令行驱动的生成器生效,你在preset里选的Visual Studio 17 2022是MSBuild驱动的IDE生成器,完全不会读取这个launch规则,ccache从始至终没被调用,所以ccache -s统计全0是正常现象。
另外你配置里给链接阶段加ccache的操作完全无效,ccache不处理链接逻辑,留着这行反而可能拖慢构建速度,直接删掉即可。
正确配置方法
推荐优先选Ninja生成器方案,稳定性最高,是经过大量验证的可行路径:
方案1:使用Ninja生成器(推荐)
- 修改根目录CMakeLists.txt的ccache检测逻辑,不要用全局RULE_LAUNCH属性,改用编译器launcher变量,兼容性更好:
find_program(CCACHE_PATH ccache) if(CCACHE_PATH) message(STATUS "Found ccache: ${CCACHE_PATH}") set(CMAKE_C_COMPILER_LAUNCHER ${CCACHE_PATH}) set(CMAKE_CXX_COMPILER_LAUNCHER ${CCACHE_PATH}) else() message(STATUS "ccache not found, build will run without cache acceleration") endif()
- 修改CMakePresets.json配置,替换生成器、补全MSVC兼容ccache必须的编译参数:
{ "name": "x64-release-ccache", "hidden": false, "generator": "Ninja", "architecture": { "value": "x64", "strategy": "external" }, "cacheVariables": { "CMAKE_C_COMPILER": "cl.exe", "CMAKE_CXX_COMPILER": "cl.exe", "CMAKE_INSTALL_PREFIX": "${sourceDir}/out/install/${presetName}", "CMAKE_TOOLCHAIN_FILE": { "value": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake", "type": "FILEPATH" }, "VCPKG_INSTALLED_DIR": "${sourceDir}/build/packages", "VCPKG_TARGET_TRIPLET": "x64-windows-static-md", "CMAKE_C_FLAGS": "/Z7 /FS", "CMAKE_CXX_FLAGS": "/Z7 /FS" }, "vendor": { "microsoft.com/VisualStudioSettings/CMake/1.0": { "hostOS": [ "Windows" ] } } }
- 配置前必须清空旧的build目录,避免之前VS生成器产生的缓存文件干扰。
这里两个编译参数是MSVC下ccache正常工作的必要条件:
/Z7:把调试信息直接嵌入obj文件,替代默认的/Zi(单独生成PDB文件),避免PDB文件锁、路径不一致导致的缓存失效/FS:强制同步PDB写入逻辑,避免并行编译时的文件访问冲突
另外建议提前在系统环境变量里加CCACHE_SLOPPINESS=pch_defines,time_macros,include_file_mtime,include_file_ctime,适配MSVC的预编译头、时间宏这类容易导致不必要缓存不命中的场景。
方案2:保留Visual Studio生成器的配置方法
如果必须用VS生成器,不能依赖CMake的launcher属性,需要手动通过VS的编译自定义规则把cl.exe调用包在ccache外面,或者安装第三方的VS ccache插件,这个方案坑很多,MSBuild会隐式加很多编译参数,很容易出现缓存命中率极低甚至完全不命中的问题,不推荐普通用户使用。
调试排查方法
要确认ccache是否正常工作、调用链路是否正确,可以用下面几个手段:
- 开构建详细日志:执行构建命令时加
--verbose参数,比如cmake --build out/build/x64-release-ccache --verbose,直接看输出的每一条编译命令前有没有ccache前缀,没有就说明ccache根本没被注入到编译流程里 - 开ccache调试日志:构建前在当前终端设置环境变量,cmd环境执行
set CCACHE_DEBUG=1,PowerShell环境执行$env:CCACHE_DEBUG=1,之后构建时ccache会在每个生成的obj文件同目录下输出.ccache-debug日志,里面会完整记录拿到的编译参数、缓存命中/不命中的具体原因、后端编译器调用情况 - 验证缓存效果:第一次完整构建后执行
ccache -s,统计里的cache miss数应该和你编译的源文件数量基本一致;删掉整个build目录重新跑配置和构建,第二次构建的cache hit率应该在90%以上才算配置正常。
内容的提问来源于stack exchange,提问作者Elad Maimoni

