在Google Cloud Build中如何让CMake正确使用构建缓存避免全量重编译
解决方案
- 方案1:调整gsutil传输参数保留元数据
gsutil 本身支持保留文件修改时间、权限等元数据,只需在上传、下载缓存的命令中加上-P参数即可:
# 上传build目录到Cloud Storage gsutil cp -Pr build/ gs://<你的缓存桶路径>/ # 从Cloud Storage恢复build目录 gsutil cp -Pr gs://<你的缓存桶路径>/build/ ./
保留修改时间后,make的时间戳校验逻辑就能正常工作,不会触发全量重编译。
- 方案2:配置CMake使用内容哈希判断依赖更新
如果受环境限制无法使用-P参数保留时间戳,可以改用内容哈希作为依赖更新判断依据,CMake 3.14及以上版本支持该配置,只需在执行cmake命令时添加CMAKE_DEPENDS_USE_FILE_HASH参数:
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_DEPENDS_USE_FILE_HASH=ON ../ && \ cmake --build . --target all --config Release -- -j 25
开启该选项后,只要文件内容没有变化,哪怕修改时间更新,也不会触发重编译。
- 方案3:搭配ccache做编译缓存兜底
如果使用的CMake版本低于3.14,可以用ccache实现编译缓存,ccache默认基于文件内容哈希判断是否需要重编译,完全不受时间戳影响:
- 先在构建镜像中安装ccache
- 修改cmake命令添加编译器启动器配置:
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache ../ && \ cmake --build . --target all --config Release -- -j 25
ccache的缓存目录也可以一同上传到Cloud Storage保存,恢复后即可直接命中缓存。
- 额外注意事项
如果从git拉取源码后,源码文件的修改时间晚于缓存中编译产物的时间,也会触发重编译,可以执行以下命令将所有源码文件的修改时间改为最后一次提交的时间,避免误判:
git ls-files | xargs -I {} touch -d "$(git log -1 --format=%ci "{}")" "{}"
内容的提问来源于stack exchange,提问作者wcobalt
相关产品推荐
相关产品推荐

