当前位置: 首页 > news >正文

bazel介绍以及其发展历史

简介

Bazel Google开源的,是一款与 Make、Maven 和 Gradle 类似的开源构建和测试工具。 它使用人类可读的高级构建语言。Bazel 支持多种语言的项目,可为多个平台构建输出。Bazel支持任意大小的构建目标,并支持跨多个代码库和大量用户的大型代码库。是Google主推的一种构建工具。

Googl的bazel历史和计划

 Timeline

上面这张图主要讲述了 Bazel 和 AOSP 的发展时间线。这里解读一下,基本上对 Bazel 和 AOSP 的构建相关的历史可以有一个大致的了解。

大家可能知道,与世界上 99.99% 的公司不同,Google 将几乎整个公司所有项目(据说不包括 Chrome 和 Android),数十亿行代码都放在一个代码仓库中,这个仓库我们就叫它 monorepo。从上面得图上可见,这个 monorepo 项目的时间大致起始于 2003 年。

而 Android 项目,即我们本文中的 AOSP,在 Google 公司内部代码仓库的建立起始于 2005 年,也正是在这一年,Google 花了五千万美金收购了 Andy Rubin 创建的 Android Inc.。和所有很多其他软件项目一样,早期的 Android 的构建系统也是基于 Make 建立的,那还是在有点遥远的 2006 年,到了 2015 年的时候随着 Android 代码体积的迅速膨胀,Google 发现 Make 已经不堪大用,于是发起了 Soong 项目来替代 Make。当然整个替代过程比我们想象的要复杂的多,有关这些内容,下文还会谈到,也可以参考我们以前发布的另外一篇介绍 Soong 的文章 "AOSP Build 背后涉及的相关知识汇总"。

而那时 Bazel 项目还没有开始,直到 2007 年,才开始有了创建一个公司内部的构建系统(也就是 Blaze)的想法。Blaze 作为 Google 公司内部使用构建工具,目前已经发展成为 Google 的整个 momorepo 生态链中不可或缺,乃至最重要的一环。因为整个 Google 的 monorepo 代码库有几百万个代码文件,几十 TB 的数据,加上大家是代码级依赖,如果按照传统的开发和编译方法,即使只 check out 直接和间接依赖的代码,其数据规模和编译时间也不可接受。而 Blaze 配合 CitC 可以做到开发时只需 check out 需要修改的代码,编译时将所有依赖进行分布式编译,编译上万 C++ 文件也只需几分钟。Blaze还有一个好处就是为全公司提供了整齐划一的编译环境,使得编译器、三方库版本等都不再是问题。到了 2015 年的时候,Google 在 Blaze 的基础上发布了其开源移植版本,并命名为 Bazel。

时间到了 2019 年,Google 又发起了一个将 Android 的 Build 系统迁移到 Bazel 的计划。在此不得不对 Google 工程师的文化翘起我的大拇指,敢于创新,追求卓越已经深深地根植在这家公司的文化精髓中。但由于 Android 系统构建的复杂性,此迁移尚处于早期阶段。从 AOSP 12 开始,会发现 AOSP 的源码仓库下出现了一些和 bazel 有关的内容,这引起了我的好奇心,找了些资料来看了一下,于是总结了这篇文章与大家分享。

before

 看一下没有加入 Bazel 支持之前 AOSP 项目的构建系统组成和构建的大致过程。如下图所示:

这张图上内容分成三部分,其中灰色的模块是 AOSP 构建系统的组成部分,我们可以发现包含了 Kati,Soong 和 ninja 好几个东东,还是比较复杂的。黄色的可以认为是整个构建过程中各个构建组件的输出和输入:

  • 最左边的内容指得是对 “产品配置信息” 的处理。所谓产品,就是形如我们在执行 lunch aosp_arm-eng 时指定的 aosp_arm-eng 就是一个 product。这个 product 定义了我们要构建的系统 image 中具体的组成内容。定义的内容目前是按照 Makefile 的语法写在一系列 Product.mk 文件中,然后通过 Kati 系统处理后输出生成一系列的配置信息(图上的 Config Vars),以 Make 变量和环境变量的形式保存下来并作为中间部分的输入。Kati 系统是 Google 为了提高构建速度,自己采用 C++ 开发的用来代替 Make 的一套构建系统,但是后来又给 Soong 替代了,只可惜一直到现在为止 Soong 都没有能够完全替换 Kati。所以就成了目前这个尴尬的局面。

  • 中间部分体现的是对 “模块构建动作(action)” 的处理。总体上就是输入构建软件模块的描述,输出是供 ninja 读取的 .ninja 文件。而 .ninja 文件中的内容可以理解为就是实际的构建动作(action)描述,简单的打个比方就好像我们自己在命令行中输入的那些形如 gcc ... -o a.out xxx.c 这些命令,这些命令驱动了 ninja 完成最终的编译链接动作。在中间部分的处理上存在两套并行的处理系统。一套是 Soong,这是 Google 采用自家的 Go lang 编写的第二代构建系统(如果把 Kati 看成是第一代的话)。其输入的描述信息采用的是遵循 Blueprint 语法的定义,和上面我们介绍的 Bazel 系统的 BUILD 文件中的语法非常类似。这些 Blueprint 格式的描述存放在 AOSP 源码树下各个模块的子目录下的 Android.bp 文件中,每一个 Android.bp 描述了本模块构建的规则。和 Soong 并行的另外一套系统就是 Kati,它承接了剩下的那些还没有完全转为采用 Android.bp 描述的模块,这些没有完成的模块仍然采用 Makefile 语法描述的 .mk 文件来描述自身的构建规则,然后作为输入被 Kati 读取,输出供 ninja 使用的 .ninja 文件。同时在 Soong 和 Kati 以上的转化过程中还会参考左边产品配置信息构建产生的 Config vars 信息,决定哪些模块需要处理,哪些不需要。

  • 最右边指的就是最终的 “实际构建动作的执行”,这部分在目前 AOSP 上在第一代 Kati 系统时已经采用了 ninja 并一直延续到现在。ninja 读入 Soong 和 Kati 生成的 .ninja 描述文件,驱动实际的工具链程序完成最终模块的构架和系统 Image 的组装。

 after

在 Google Open Source Live "Bazel day" 中 Google 希望的第三代基于 Bazel 的 AOSP 构建系统完成后整个构建过程是变成如下情况,见下图所示:

也就是说上一节中涉及的 “产品配置信息” 的定义信息(见图中左边下部标注为 “product config” )和涉及 “模块构建动作(action)”(见图中左边上部标注为 “code” )统一采用 BUILD 文件进行描述和定义。由 Bazel 统一处理后,并由 Bazel 负责驱动实现上一节中的第三部分 “实际构建动作的执行”(ninjia 也不再需要了)。整个构建过程全部统一由 Bazel 完成。

而且根据 Bazel 的文档说明,现有 AOSP 中的自动化测试部分的驱动组件也由 Bazel 系统承接,整个替换是全方位的,更详细的针对 Android buid system component 执行 Bazel 替换的对比,可以看 android.googlesource.com

 now

虽然理想很丰满,但现实却是骨感的。完整的替换过程相当的复杂,不仅仅在于现有 Android 构建系统的复杂性,也在于 Android 系统本身就是一个巨型复杂系统。

Google 的计划是逐步完成这个过程的替换,就像当初从 Kati 到 Soong 的转变一样。替换的方案还是从上面提到的三个方向入手:

  • 对 “产品配置信息” 的处理
  • 对 “模块构建动作(action)” 的处理
  • 最终的 “实际构建动作的执行”

而且为了保证替换不会影响现有用户的使用体验,包括构建速度和使用习惯。

大致的替换方案如下图所示,我根据我的而理解解释一下,如果有什么不对的地方请大家不吝指出。其中注意下图中增加啊的绿色部分就是为实现 Bazel 替换引入的新组件。

  • 在对 “产品配置信息” 的处理上,Google 会引入两个新的工具 convert 和 product_configconvert 负责将含有产品配置信息处理的 .mk 文件转换为以 Starlark 语法描述的替代文件,在图上标识为后缀为 .bzl 的 文件,我理解就是对应 图(4) 中标识为(product config)的 BUILD 文件。而 product_config 则负责将 .bzl 文件进一步转化为 Config vars。我猜想分成两步的方式可能是为了在演变成最终的 图 (4) 后,.bzl 文件可以作为包含 product config 信息的 BUILD 文件保留下来。

  • 在对 “模块构建动作(action)” 的处理上,Google 会新开发一个叫做 bp2build 的工具,负责将现有系统中的 Android.bp 文件转化为 BUILD 文件。而为了兼容目前在该阶段生成 .ninja 文件的需要,Bazel 系统还要改造一下,能够输入 BUILD 文件,输出 .ninja 文件(目前的 Bazel,读入 BUILD 就直接驱动构建了,并没有 ninja 的介入)。从图上来看,会存在一段时间,AOSP 构建系统中将同时存在三套处理系统。是不是很复杂 :(。

  • 在对最终的 “实际构建动作的执行”上,同样需要改动 Bazel,使其能够像 ninja 一样读入 .ninja 文件,即基于 .ninja 文件驱动实际的构建动作。也就是说在过渡阶段,AOSP 的构建系统将同时支持两种构建模式:一种是 legacy mode with ninja;另一种是 the new mode with Bazel。

  • Bazel for AOSP 进展状态

    仍然是基于 Google Open Source Live "Bazel day" , 注意视频时间标注为 2021 年 4 月 2 日 。所以不能说是最新的,而是截至本文完成前一年的状态,我看了一下大致和我们移植 AOSP 12 的 aosp-riscv 采用的 tag:android-12.0.0_r3 差不多的时间。

    从当时的进展来看,只能说 “任重而道远” 啊!不多说了,大家可以对照上面的介绍估计一下 Google 的进度。最近的状态我们还是要等 13 的代码放出来再看。也希望本文的介绍能对大家了解 Bazel for AOSP 有所帮助。

​优劣势

优势

官方说明:

  • 高级构建语言。Bazel 使用人类可读的抽象语言,在较高的语义级别描述项目的构建属性。与其他工具不同,Bazel 的运作涉及库、二进制文件、脚本和数据集的概念,可以避免将单个调用编写到编译器和链接器等工具的复杂性。

  • Bazel 既快速又可靠。Bazel 会缓存之前完成的所有工作,并跟踪文件内容和 build 命令的更改。这样,Bazel 就会知道何时需要重新构建应用,并且只会重新构建。为了进一步加快构建速度,您可以将项目设置为以高度并行的方式进行构建。

  • Bazel 是多平台的。Bazel 可在 Linux、macOS 和 Windows 上运行。Bazel 可以从同一项目为多个平台(包括桌面设备、服务器和移动设备)构建二进制文件和可部署软件包。

  • Bazel 支持扩缩。在处理包含 10 万个以上源文件的构建时,Bazel 可保持敏捷性。它可以处理数以万计的多个代码库和用户群。

  • Bazel 可扩展。它支持许多语言,您可以扩展 Bazel,以支持任何其他语言或框架。

其它人总结:

  • 很方便地获取第三方依赖;

  • 构建多语言的软件系统,One Tool,All Languages;

  • 优秀的缓存和依赖计算,编译速度非常优异;

  • DevOps部署云构建,可极大复用宝贵的计算资源;

快(Fast)

Bazel的构建过程很快,它集合了之前构建系统的加速的一些常见做法。包括:

1.增量编译。只重新编译必须的部分,即通过依赖分析,只编译修改过的部分及其影响的路径。

2. 并行编译。将没有依赖的部分进行并行执行,可以通过--jobs来指定并行流的个数,一般可以是你机器CPU的个数。遇到大项目马力全开时,Bazel能把你机器的CPU各个核都吃满。

3. 本地缓存+远程缓存。Bazel将构建过程视为函数式的,只要输入给定,那么输出就是一定的。而不会随着构建环境的不同而改变(当然这需要做一些限制),这样就可以分布式的缓存/复用不同模块,这点对于超大项目的速度提升极为明显。

4. 远程构建。默认情况下,Bazel 会在本地机器上执行构建和测试。通过 Bazel 构建的远程执行,您可以将构建和测试操作分散到多个机器(例如数据中心)。

可伸缩(scalable)

Bazel号称无论什么量级的项目都可以应对,无论是超大型单体项目monorepo、还是超多库的分布式项目multirepo。Bazel还可以很方便的集成CD/CI ,并在云端利用分布式环境进行构建。

它使用沙箱机制进行编译,即将所有编译依赖隔绝在一个沙箱中,比如编译golang项目时,不会依赖你本机的GOPATH,从而做到同样源码、跨环境编译、输出相同,即构建的确定性。

跨语言(multi-language)

如果一个项目不同模块使用不同的语言,利用Bazel可以使用一致的风格来管理项目外部依赖和内部依赖。典型的项目如 Ray。该项目使用C++构建Ray的核心调度组件、通过Python/Java来提供多语言的API,并将上述所有模块用单个repo进行管理。如此组织使其项目整合相当困难,但Bazel在此处理的游刃有余,大家可以去该repo一探究竟。

可扩展(extensible)

Bazel使用的语法是基于Python裁剪而成的一门语言:Startlark。其表达能力强大,往小了说,可以使用户自定义一些rules(类似一般语言中的函数)对构建逻辑进行复用;往大了说,可以支持第三方编写适配新的语言或平台的rules集,比如rules go。 Bazel并不原生支持构建golang工程,但通过引入rules go ,就能以比较一致的风格来管理golang工程。

劣势

  • 隔离未遵循程惯例:从策略上看,Bazel从其他遗留库获取代码,这是必须的,否则Bazel自己完蛋了;其他库要想从Bazel获取,用户也必须使用Bazel,用户真的被强绑定了。

  • 依赖于JVM。

本文属于如下文章中的子章节

bazel学习系列章节汇总_m0_74043383的博客-CSDN博客

相关文章:

bazel介绍以及其发展历史

简介 Bazel Google开源的,是一款与 Make、Maven 和 Gradle 类似的开源构建和测试工具。 它使用人类可读的高级构建语言。Bazel 支持多种语言的项目,可为多个平台构建输出。Bazel支持任意大小的构建目标,并支持跨多个代码库和大量用户的大型代…...

固定资产管理分析怎么写?

对企业内的固定资产进行全面的统计和分析,包括设备、装修、维修等方面的信息,有助于企业进行资产管理和风险控制。  通过该软件,用户可以实现对资产的跟踪和管理,如实时监测设备的使用情况,提高设备利用率和维护效率…...

【项目源码】一套基于springboot+Uniapp框架开发的智慧医院3D人体导诊系统源码

智慧医院3D人体导诊系统源码 开发语言:java 开发工具:IDEA 前端框架:Uniapp 后端框架:springboot 数 据 库:mysql 移 动 端:微信小程序、H5 “智慧导诊”以人工智能手段为依托,为…...

可能的二分法 -- 二分图判定【DFS、BFS分别实现】

886. 可能的二分法 class PossibleBipartition:"""可能的二分法「其实考察的就是二分图的判定」用dfs和bfs 两种方法分别实现https://leetcode.cn/problems/possible-bipartition/"""def __init__(self):self.success Trueself.color []self.…...

六级翻译备考

classical 经典的 Chinese literature 中国文学 朝代dynasty 统治 rule 社会稳定 steady society 治理有序 orderly governance 伟大的greatest 时代 times或者periods 被人们描绘成人类历史上伴随着治理有序,社会稳定的最伟大的时代之一 more and more越来越多 …...

Vue框架--Vue中的数据绑定

Vue中有两种数据绑定的方式 1.单向数据绑定(v-band):数据只能够从data流向页面 2.双向数据绑定(v-model):数据不仅仅能够从data流向页面,也可以从页面流向data。 备注: 1.双向绑定一般都应用在表单类元素上。(如:input、select等有value属性值的标签上) 2.…...

Unity——热更新浅析

热更新的思想从本质上来讲,要考虑一些问题。例如,一个完整的游戏最多可以有多大比例的资源通过网络加载?能否让尽可能多的资源通过网络加载? 通过网络加载有很多好处,不仅可以极大减小安装包的体积,而且有…...

IMPLEMENT_DYNCREATE的分析

一、介绍 IMPLEMENT_DYNCREATE 是一个宏(macro),通常与DECLARE_DYNCREATE宏一起在MFC框架中使用。它的作用是为一个派生自 CObject 的MFC类提供运行时类型信息(RTTI)和对象的动态创建支持。 具体来说,IMP…...

Java实现根据短连接获取1688商品详情数据,1688淘口令接口,1688API接口封装方法

要通过1688的API获取商品详情数据,您可以使用1688开放平台提供的接口来实现。以下是一种使用Java编程语言实现的示例,展示如何通过1688开放平台API获取商品详情属性数据接口: 首先,确保您已注册成为1688开放平台的开发者&#xf…...

ABAP FICO 凭证替代 凭证校验

凭证校验 1.T-CODE--->GGX2--->GBLR-->ZRGGBR000 2.将程序RGGBR000 复制为ZRGGBR000 3.GGB0--》财务会计--》凭证抬头或者行项目维护检验规则 4.OB28 维护特定的公司代码和调用点和确认,活动等级设置为1 5.GGB4-->激活校验 凭证替代 1.T-CODE--->GG…...

项目验收有哪些流程?

验收流程 科技计划项目验收/课题验收测试服务的被测对象是国家重大专项、科研课题的软件成果物,可以是一个模块、软件或系统等,也可以是软件套件或软件原型等。测试范围主要来源于课题的合同书/可行吧报告/申报书中的技术指标要求。所出具的科技项目验收…...

C++,类的继承

一、继承的基本概念 继承使得C能够从已有的类派生出新的类,而派生类继承了原有类的特征,包括方法。被继承者称为父类或基类,继承者称为子类或派生类。 继承的目的: 实现代码的重用性建立父类和子类之间的联系在实现多态的时候&a…...

作业33333333

一、正向解析 在开启DNS服务之前先将防火墙关闭。 systemctl stop firewalld.service 开启DNS服务,需要开启端先进行安装主软件,以及配置包管理软件 配置包管理软件一般会跟随主软件一起安装,如果没有手动安装一次就可以了。 安装完成之后&…...

Spring Cloud--从零开始搭建微服务基础环境【二】

😀前言 本篇博文是关于Spring Cloud–从零开始搭建微服务基础环境【二】,希望你能够喜欢 🏠个人主页:晨犀主页 🧑个人简介:大家好,我是晨犀,希望我的文章可以帮助到大家,…...

算法工程题(中序遍历)

* 题意说明: * 给定一个二叉树的根节点 root ,返回 它的 中序 遍历 。 * * 示例 1: * 输入:root [1,null,2,3] * 输出:[1,3,2] * * 示例 2: * 输入:root [] * 输出:[] * *…...

jsch网页版ssh

使用依赖 implementation com.jcraft:jsch:0.1.55Server端代码 import com.jcraft.jsch.Channel; import com.jcraft.jsch.JSch; import com.jcraft.jsch.Session; import java.io.InputStream; import java.io.OutputStream; import java.util.concurrent.TimeUnit; import o…...

教程i.MX8MPlus开发板SPI转CAN操作

飞凌嵌入式OKMX8MP-C核心板有两路原生CAN总线,但用户在开发产品时可能需要用到更多的CAN,这该如何解决呢?今天小编将为大家介绍一种SPI转CAN的方法,供各位工程师小伙伴参考。 说明 OKMX8MP-C核心板有两路原生的SPI总线&#xff0c…...

Docker中容器的随机命名方式

使用 docker 创建容器时,如果没有用 --name 指定,docker 会为用户选择一个名称, 格式是两个带有下划线的单词,如xxx_yyyy 其相关的实现在此处 pkg/namesgenerator/names-generator.go[1] 源码中有两个数组,第一个是一个…...

大数据Flink实时计算技术

1、架构 2、应用场景 Flink 功能强大,支持开发和运行多种不同种类的应用程序。它的主要特性包括:批流一体化、精密的状态管理、事件时间支持以及精确一次的状态一致性保障等。在启用高可用选项的情况下,它不存在单点失效问题。事实证明&#…...

数学中的自由与我们的生活

数学中的这些自由可以帮助我们养成很多优秀的品格。具体来说,知识的自由使我们变得足智多谋,让我们可以根据问题的具体情况选择恰当的工具和方法。探索的自由使我们在集体讨论时敢于大声发言,积极提问,让我们在为探索发现而欢呼雀…...

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目:3442. 奇偶频次间的最大差值 I 思路 :哈希,时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况,哈希表这里用数组即可实现。 C版本: class Solution { public:int maxDifference(string s) {int a[26]…...

Ubuntu系统下交叉编译openssl

一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机:Ubuntu 20.04.6 LTSHost:ARM32位交叉编译器:arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…...

linux之kylin系统nginx的安装

一、nginx的作用 1.可做高性能的web服务器 直接处理静态资源(HTML/CSS/图片等),响应速度远超传统服务器类似apache支持高并发连接 2.反向代理服务器 隐藏后端服务器IP地址,提高安全性 3.负载均衡服务器 支持多种策略分发流量…...

深入理解JavaScript设计模式之单例模式

目录 什么是单例模式为什么需要单例模式常见应用场景包括 单例模式实现透明单例模式实现不透明单例模式用代理实现单例模式javaScript中的单例模式使用命名空间使用闭包封装私有变量 惰性单例通用的惰性单例 结语 什么是单例模式 单例模式(Singleton Pattern&#…...

Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器

第一章 引言:语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域,文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量,支撑着搜索引擎、推荐系统、…...

《通信之道——从微积分到 5G》读书总结

第1章 绪 论 1.1 这是一本什么样的书 通信技术,说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号(调制) 把信息从信号中抽取出来&am…...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院查看报告小程序

一、开发环境准备 ​​工具安装​​: 下载安装DevEco Studio 4.0(支持HarmonyOS 5)配置HarmonyOS SDK 5.0确保Node.js版本≥14 ​​项目初始化​​: ohpm init harmony/hospital-report-app 二、核心功能模块实现 1. 报告列表…...

Module Federation 和 Native Federation 的比较

前言 Module Federation 是 Webpack 5 引入的微前端架构方案,允许不同独立构建的应用在运行时动态共享模块。 Native Federation 是 Angular 官方基于 Module Federation 理念实现的专为 Angular 优化的微前端方案。 概念解析 Module Federation (模块联邦) Modul…...

SiFli 52把Imagie图片,Font字体资源放在指定位置,编译成指定img.bin和font.bin的问题

分区配置 (ptab.json) img 属性介绍: img 属性指定分区存放的 image 名称,指定的 image 名称必须是当前工程生成的 binary 。 如果 binary 有多个文件,则以 proj_name:binary_name 格式指定文件名, proj_name 为工程 名&…...

浪潮交换机配置track检测实现高速公路收费网络主备切换NQA

浪潮交换机track配置 项目背景高速网络拓扑网络情况分析通信线路收费网络路由 收费汇聚交换机相应配置收费汇聚track配置 项目背景 在实施省内一条高速公路时遇到的需求,本次涉及的主要是收费汇聚交换机的配置,浪潮网络设备在高速项目很少,通…...