bazel remote cache 是将编译产物存至远端服务器以复用构建结果的机制,显著提升 c++ 等慢速语言在 ci 和多开发者场景下的构建效率,但无法规避头文件变更等语义级缓存失效。

bazel remote cache 是什么,为什么值得配
它不是魔法,是把编译产物(.o、lib、binary)存到远端服务器,下次相同输入时直接拉取,跳过本地编译。对 C++ 这种依赖多、编译慢的语言,效果立竿见影——尤其在 CI 或多开发者共享构建环境时。但别指望它解决头文件频繁修改带来的缓存失效,那是语义决定的,不是配置能绕过的。
如何启用 bazel remote cache(HTTP 协议最常用)
核心就两步:服务端跑起来 + 客户端告诉 bazel 去哪找。Bazel 本身不带 server,得用 buildbarn、bazel-remote 或 GCS/S3 等兼容 HTTP 缓存协议的后端。本地快速验证可用 bazel-remote:
bazel-remote -dir /tmp/bazel-cache -port 9092 -max_size_mb 5000
然后在 .bazelrc 里加:
build --remote_cache=http://localhost:9092 build --remote_upload_local_results=true
-
--remote_cache必须是完整 URL(含http://),少写协议会静默失败 -
--remote_upload_local_results=true表示本地编译完也上传,否则只下载不存,别人用不了 - CI 环境建议用
--remote_http_cache(旧名,已弃用但仍有效),新项目统一用--remote_cache
C++ 项目特别要注意的缓存失效点
头文件路径、宏定义、编译器版本、copts 微小变化都会让缓存 miss。常见踩坑:
- 用
genrule或cc_library的includes引入相对路径(如"../include"),不同工作目录下 action key 不同 → 改用$(GENDIR)或绝对 workspace-relative 路径 -
copts里写死绝对路径(如-I/home/user/project/include)→ 改用-I$(GENDIR)或-Iexternal/... - 没关掉
stamp = True的cc_binary,时间戳/构建信息进输出 → 默认禁用 stamp,除非真需要嵌入版本号 - 用了
local = True或tags = ["no-remote"]→ 检查 BUILD 文件,这类 target 完全不走远程缓存
调试缓存是否真生效
别只看 build 时间变短——那可能是别的优化。确认缓存命中,看 bazel 日志里的 Cache hit:
bazel build --remote_cache=http://localhost:9092 --subcommands //my:target
关键线索:
- 日志中出现
Remote cache hit for表示下载成功复用 - 出现
Uploading且没报错,说明上传也通了 - 如果全是
Local execution或Cache miss,先检查bazel-remote进程是否在运行、端口是否被占、URL 是否拼错 -
bazel clean --expunge后首次 build 必然 miss,第二次才可能 hit —— 别第一次就断定失败
缓存键是 action 输入的哈希,不是文件名也不是路径。改一行注释、换一个空格、增删一个未使用的 #include,都可能让整个 target 重新编译。所以别指望“差不多就行”,C++ 缓存敏感得像温度计。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











