共计 2497 个字符,预计需要花费 7 分钟才能阅读完成。
bazel 的基础概念与原理是什么,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面丸趣 TV 小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。
0x01 背景
bazel 目前已广泛用于云计算领域的开源软件的构建如 k8s、kubevirt 等,本文以一个新手的角度分享下 bazel 的基础知识,其存在的价值。对比下,它与其他已经存在的构建系统的差别,以及它适用于什么场景。
0x02 构建系统
构建对应的英文是 BUILD,也就是大家所说的编译打包,就是将编写出的代码经过编译器处理,产生二进制,形成一个可以正常运行的软件包(如 deb 或者 rpm)。对于编译型语言来说,构建几乎是日常工作的一部分。
是一个辅助过程,它本身不产生价值。
又是必须的一个过程,没有它 CI 是空谈。
基于这两个特点来说,我们希望理想的构建系统具备以下特点:
尽可能地快。可以方便开发人员,编写代码后快速出包验证改动。
方便维护,可以清晰地展示依赖关系,在系统中添加一个模块,或者减少一个模块,可以非常容易维护。
对比理想系统,我们看下构建技术的发民。软件构建技术的发展和 IT 技术的发展保持同步,历经了初期、中期和现代化三个阶段(纯粹个人理解)。
一、初期
软件规模小,软件工程的概念还未被提出。
这时对构建的要求很低,或者说不需要。编写出的代码可以经过汇编编译后直接执行,也没有流水线。这时期的代码就是 makefile,或者是直接自己写脚本进行编译执行。软件的特点是,单语言小规模,对构建基本上没有要求。
二、中期
软件规模开始增大。已有的 makefile 机制已经难以满足需要。以 Linux 内核为例,makefile 已经无法满足,所以内核开发者在内核中添加了自己的构建扩展,以满足日渐增大的内核代码。同时,也涌现出了 cmake 这样较现代化的构建工具。主要原因是,代码规模增大后,构建这一不增值过程开始消耗掉大量开发人员的精力,以 cmake 为代表的工具可以半自动化管理依赖,生成 makefile,提高编译人员的生产力,减少了重复劳动;此时的构建系统基本上可以满足要求,但已经开始显现不足了。
三、现代化
软件规模增大的同时,大型系统开始转向多语言协作。使用运行高效率的编译型语言(C、C++、Java 等)编写低层(数据面),使用开发高效率的动态非编译型语言编写上层(管理面)。多语言对于 cmake 来说,无能为力。此时以 bazel 为代表的现代构建系统出现,可以很好地解决 cmake 无法解决的问题。
在一个机构逐步增大的过程中,大公司在 IT 上经历的问题,你同样会遇到,所以了解一门技术的驱动力一定是问题,而不是 Google 出品的一定就是适合你的。这里也一样,我去了解 Bazel 是因为遇到了现有技术无法解决的问题。
[bazel](https://www.bazel.build/](https://www.bazel.build/) Google 开源的构建工具。它通过将构建过程进行抽象建模,实现了一个接近理解的构建系统。
快速构建。
bazel 支持增量式编译,支持缓存,支持分布式扩展。这 3 点就可以满足快速建构。只要有投入足够多的硬件资源,你的构建就可以很快。
清晰的依赖关系。
虽然 makefile 也可以定义出来。但 makefile 定义的规则,全部需要人工维护,特别是分散在多个代码仓库中的依赖,很难有人能全局把握好依赖关系。但 bazel 可以清晰地以依赖关系图的方式展现出当前的依赖关系。而且是自动建立地,可查询。
除了以上两个优点,最重要的一点是 bazel 支持多语言构建。以下将通过介绍 bazel 的基本对象(概念),来阐述 bazel 是如何对构建过程进行建模的。
0x03 概念
3.1 构建
构建过程是一个动作。有输入输出,如下图所示。
一个大型系统中有许多构建过程,有顶层的负责产生最终产出物。有底层负责某个小模块的构建。不同的构建之间,有相互依赖。A 的产生物是 B 的输入,那么 B 就依赖 A,构建上则要求 A 先于 B 构建。这些依赖最终在大模块里出的就是一个依赖网。如下图,A 依赖 B C D,但 B 也依赖 C。
3.2 Bazel 中主要的概念如下。
名称解释 WORKSPACE 每一个工程都需要定义的一个文件,位于工程的根目录下。可以是空文件,也可以加载一些外部依赖。actionrule 中定义的构建动作。全部在运行阶段执行。BUILD 存在每个小代码仓库中,定义当前仓库中的构建要素。输入、输出和构建行为。是最小的构建单位。bzl 自定义的规则后缀。external rulebazel 约定的其他规则库,用 skylark 语言(Python 的子集)编写。rulebazel 的构建规则,位于 BUILD 文件中。每个规则中包含输入和输出,以及构建动作。目前已有 C /C++、Java、Golang、Python 等成熟的构建规则库,可以方便地从 github 上获取。见官方文档已有规则库 package 在 BUILD 文件中定义的一系统目标。包具有可见性属性,可用来控制对外暴露的属性。build graph 构建依赖图,就是前文提到的依赖关系图。由定义在各个 BUILD 文件中的目标构成。0x04 原理
有了基础概念之后,解释下 bazel 的工作原理。bazel 以 client/server 模式工作,server 在闲置一段时间后会自动退出。以 WORKSPACE[#WORKSPACE] 和 BUILD 文件将整个构建过程模型化。bazel 工作分以下三个阶段 (phase)。也就是执行了 bazel build … 之后发生的事情。
loading phase 加载阶段
bazel 遍历当前工程下,所有子文件夹,找到其中的 BUILD 文件,加载外部依赖,生成一个个 package 和 target。
analysis phase 分析阶段
根据各个 BUILD 中定义的目标和输入输出信息,建立一个内存中的 build graph。
executing phase 执行阶段
根据 build graph 逐个运行各个规则定义的动作,产生最终的目标。
看完上述内容是否对您有帮助呢?如果还想对相关知识有进一步的了解或阅读更多相关文章,请关注丸趣 TV 行业资讯频道,感谢您对丸趣 TV 的支持。