30、构建系统未来趋势:Bazel集成、构建系统演进、社区动态
聊到构建系统的未来,我其实挺感慨的。十年前大家还在纠结用Make还是Python脚本,现在Bazel已经成了AOSP官方钦定的下一代构建引擎。这个转变不是拍脑袋决定的,背后是整个Android生态对构建速度、可复现性、跨平台能力的需求在倒逼。
为什么是Bazel?
说白了,Soong虽然比Make快了不少,但它本质上还是为单一代码仓库设计的。Google内部早就用Bazel(Blaze的开源版)管理着地球上最大的单体仓库之一。我参与过几个大型项目的迁移,最直观的感受是:Bazel的增量构建和远程缓存能力,能把全量编译从小时级压缩到分钟级。
核心优势对比
| 特性 | Make/Soong | Bazel |
|---|---|---|
| 增量构建 | 基于文件时间戳,容易误判 | 基于内容哈希,精确可靠 |
| 远程执行 | 需要额外工具链 | 原生支持,内置RBE |
| 依赖管理 | 全局变量,容易冲突 | 严格沙箱,隔离性好 |
| 跨平台 | Linux为主 | Linux/macOS/Windows全支持 |
Bazel集成现状与挑战
目前AOSP里已经能看到Bazel的痕迹了。比如build/bazel目录下就有官方的迁移工具和规则集。但说实话,完全替换Soong还需要时间。我去年帮一个团队做迁移时发现,最大的坑是第三方预编译库的依赖声明——Bazel要求每个输入都显式声明,而Soong里很多依赖是隐式的。
我的建议:如果你现在开始新项目,直接用Bazel的android_binary规则。对于存量项目,可以先用--experimental_bazel_mode跑一下,看看哪些模块能平滑迁移。
构建系统演进路线
从Make到Soong再到Bazel,这条演进路线其实反映了三个核心诉求:
- 速度:并行度从单机多核扩展到集群分布式
- 确定性:同样的输入必须产生同样的输出,杜绝"在我机器上能编译"
- 可审计性:每个构建产物都能追溯到源码和工具链版本
我记得有一次排查线上崩溃,发现是构建时链接了不同版本的libc++。如果是Bazel的沙箱模式,这种问题根本不会出现——它强制每个依赖都锁定版本。
社区动态与生态
社区这边,Google在2023年正式宣布了Bazel for Android的长期支持计划。几个值得关注的方向:
- Bazel 7.x:改进了Android规则集,支持了AGP 8.x的新特性
- rules_android:社区维护的规则库,比官方更激进地支持新API
- Bazelisk:版本管理工具,我建议团队统一用它,避免"你用的Bazel版本不对"这种低级错误
避坑指南:我曾经遇到过一个坑——Bazel的.bazelrc里配置了build --remote_cache,但没配认证信息,结果缓存一直没生效。排查了半天才发现是配置遗漏。记住:远程缓存一定要配好--tls_client_certificate或--google_credentials。
知识体系总览
下面这张图梳理了构建系统未来的核心脉络,你可以把它当作路线图来参考:
实际迁移建议
如果你团队正在考虑迁移到Bazel,我建议分三步走:
- 先跑通一个模块:选一个依赖简单、不涉及预编译库的模块,用
bazel build //path:target验证流程 - 配置远程缓存:搭建或接入已有的RBE服务,这一步能立刻看到构建速度提升
- 逐步扩大范围:每次增加10-20个模块,同时监控构建失败率。我见过一次性迁移太多导致回滚的案例
小技巧:在.bazelrc里加上build --verbose_failures和build --sandbox_debug,排查问题时能省不少时间。
嗯,构建系统的演进不会停。Bazel之后可能还会有更智能的构建引擎,但核心思想不会变——让开发者把精力花在写代码上,而不是等编译。我个人觉得,未来两年内Bazel会成为Android构建的事实标准,现在开始学绝对不亏。
公众号:蓝海资料掘金营,微信deep3321