如果你还在坚持CMake话,不妨尝试一下谷歌的高效编译工具--Bazel

  • 前言
  • 一、Bazel是什么?
  • 二、安装bazel
  • 三、介绍Bazel文件组成
    • 1. WORKSPACE(工作区)
    • 2. BUILD文件(packkage)
  • 四、Bazel编译初探
    • 1. 编译单个target
    • 2. 编译多个target
    • 3. 编译多个package
  • 总结

前言

最近,发现公司大佬们都在偷偷使用Bazel构建工程项目,此时,我发现我在学校学习的Make已经不香了,于是我决定上车。


提示:以下是本篇文章正文内容,下面案例可供参考

一、Bazel是什么?

Bazel 是一个类似于 Make 的工具,是 Google 为其内部软件开发的特点量身定制的工具,如今 Google 使用它来构建内部大多数的软件。它的功能有诸多亮点:

  • 多语言支持:目前 Bazel 默认支持 Java、Objective-C 和 C++,但可以被扩展到其他任何变成语言。
  • 高级构建描述语言:项目是使用一种叫 BUILD 的语言来描述的,它是一种简洁的文本语言,它把一个项目视为一个集合,这个集合由一些互相关联的库、二进制文件和测试用例组成。相反,像 Make 这样的工具,需要去描述每个文件如何调用编译器。
  • 多平台支持:同一套工具和相同的 BUILD 文件可以用来为不同的体系结构构建软件,甚至是不同的平台。在 Google,Bazel 被同时用在数据中心系统中的服务器应用和手机端的移动应用上。
  • 可重复性:在 BUILD 文件中,每个库、测试用例和二进制文件都需要明确指定它们的依赖关系。当一个源码文件被修改时,Bazel 凭这些依赖来判断哪些部分需要重新构建,以及哪些任务可以并行进行。这意味着所有构建都是增量的,并且相同构建总是产生一样的结果。
  • 可伸缩性:Bazel 可以处理大型项目;在 Google,一个服务器软件有十万行代码是很常见的,在什么都不改的前提下重新构建这样一个项目,大概只需要 200 毫秒。

对于为什么要重新发明一个构建工具而不直接使用 Make,Google 认为 Make 控制得太细,最终的结果完全依靠开发人员能正确编写规则。很久以前,Google 使用自动生成的臃肿的 Makefile 来构建他们的软件,速度太慢,结果不可靠,最终影响了研发人员的效率和公司的敏捷性。所以他们做了 Bazel。Bazel 的规则层次更高,比如,对于“Java 测试”、“C++ 二进制文件”,它都有定义好的内建规则,而这些规则都已经被无数的测试证明是正确和稳定的。

二、安装bazel

三、介绍Bazel文件组成

bazel中对于文件架构的概念有两个:workspace和package。

  • workspace是表示整个项目的,也叫repo,必须在项目的根目录下建一个WORKSPACE文件来定义项目的根目录,bazel会忽略所有项目子目录下的WORKSPACE文件。
  • package是项目中的模块,也就是一个一个包,包在组织上比较随意,可以根据项目需求来定,你想哪个文件夹中的东西成为一个包,就在那个文件夹的目录里创建一个BUILD文件即可,包的管理范围包括子目录里的东西,但不包括子包所包括的内容。比如:
.../project/WORKSPACElib/BUILD...src/BUILD...other1/BUILDother2/...

lib,src和other1分别为一个包,但是other1中含有一个BUILD,因此other1中有一个子包(上文提到:子包不属于父包),所以other1里面的东西不属于src包,但是other2里面的东西属于src包。

1. WORKSPACE(工作区)

WORKSPACE是Bazel一个概念,它实质上是一个目录。这个目录是bazel工作时的一个基准目录。
Bazel规定,项目源文件和Bazel构建出的目标文件,均放在此目录。要把一个目录设置为WORKSPACE, 则必须在此目录创建一个新的空文件,名为WORKSPACE. Bazel构建项目时,所有的输入项和依赖项,必须位于同一个工作区内。每个工作目录内,可以有多个项目(目录)。bazel 编译或者执行其它命令时,是在WORKSPACE中。

2. BUILD文件(packkage)

BUILD文件的作用类似 Makefile之于Make, xml文件之于Maven, gradle文件之于Gradle. BUILD文件中包含bazel的各种不同类型的指令,其中包含构建规则,它指出Bazel如何利用给定的输入,构建出指定的输出。如利用什么.cpp文件,构建出库或者可执行程序。BUILD文件中的每一条编译指令被称为一个target,它指向一系列的源文件和依赖,一个target也可以指向别的target。

举个例子,下面这个hello-world的target利用了Bazel内置的cc_binary编译指令,来从hello-world.cc源文件(没有其他依赖项)构建一个可执行二进制文件。指令里面有些属性是强制的,比如name,有些属性则是可选的,srcs表示的是源文件。

cc_binary(name = "hello-world",srcs = ["hello-world.cc"],

cc_binary即声明了一个构建规则,用于编译生成一个可执行文件。可执行文件名(目标名)由name属性指定,name属性的值的类型可以看出是string类型。srcs属性指定了源文件,srcs属性的值的类型可以看出是list of strings。
*_binary 规则:指定生成相应语言的可执行程序。cc_binary表示c++可执行程序,jave_binary表示java可执行程序。
*_library 规则:指定生成相应语言的库。
*_test 规则:是一个特殊的bianry规则,通常用于自动化测试。

四、Bazel编译初探

Bazel提供了一些编译的例子,在https://github.com/bazelbuild/examples/,可以clone到本地试一下。其中examples/cpp-tutorial目录下包含了这么些文件:

cpp-tutorial
│   ├── README.md
│   ├── stage1
│   │   ├── main
│   │   │   ├── BUILD
│   │   │   └── hello-world.cc
│   │   ├── README.md
│   │   └── WORKSPACE
│   ├── stage2
│   │   ├── main
│   │   │   ├── BUILD
│   │   │   ├── hello-greet.cc
│   │   │   ├── hello-greet.h
│   │   │   └── hello-world.cc
│   │   ├── README.md
│   │   └── WORKSPACE
│   └── stage3
│       ├── lib
│       │   ├── BUILD
│       │   ├── hello-time.cc
│       │   └── hello-time.h
│       ├── main
│       │   ├── BUILD
│       │   ├── hello-greet.cc
│       │   ├── hello-greet.h
│       │   └── hello-world.cc
│       ├── README.md
│       └── WORKSPACE

可以看到3个stage,分别为了三个项目例子,由简到繁。

1. 编译单个target

编译stage1:
首先进入到cpp-tutorial/stage1目录下,然后运行以下指令:

bazel build //main:hello-world

注意target中的//main:是BUILD文件相对于WORKSPACE文件的位置,hello-world则是我们在BUILD文件中命名好的target的名字。
然后Bazel就会有一些类似这样的输出:

至此,编译成功,编译结果输出在bazel-bin/main/文件夹中。
注:bazek clean 清空编译结果

查看依赖图

bazel query --nohost_deps --noimplicit_deps 'deps(//main:hello-world)' \--output graph

2. 编译多个target

在这个BUILD文件中,Bazel首先编译了hello-greet这个库(利用Bazel内置的cc_library编译指令),然后编译hello-world这个二进制文件。hello-world这个target的deps属性告诉Bazel,要构建hello-world这个二进制文件需要hello-greet这个库,编译过程同上,此处省略。。。
结论:发现hello-world在编译时候的结构和之前有所不同,现在是有两个targets。hello-world这个target从一个源文件编译而来,同时依赖于另一个target//main:hello-greet,这个target又是从两个源文件编译而来。

3. 编译多个package

编译过程省略。。。
结论:可以看出hello-world这个mainpackage中的target依赖于lib package中的hello-time target(即target label为://lib:hello-time)- Bazel是通过deps这个属性知道自己的依赖项的。


总结

以上内容就是对bazel的简单学习和总结,方便以后复习。总而言之:bazel的使用就是为了针对大的工程项目而提高效率的,并且可以发现,bazel相比写cmakelists简便多了。

Bazel编译教程(基础篇)相关推荐

  1. 基于c++和asio的网络编程框架asio2教程基础篇:1、基本概念和使用说明

    基于c++和asio的网络编程框架asio2教程基础篇:1.基本概念和使用说明 由于asio2没有写技术文档,因此打算写几篇文章介绍一下如何使用它,主要是针对新手. 1.asio2如何使用? asio ...

  2. ESP32-C3入门教程 基础篇⑪——Non-Volatile Storage (NVS) 非易失性存储参数的读写

    文章目录 一.前言 二.NVS介绍 三.操作流程 3.1 读操作流程 3.2 写操作流程 四.关键函数 五.随机整数 读写示例 六.对象/数组 读写示例 七.总结 八.参考 一.前言 本文基于VS C ...

  3. ESP32-C3入门教程 基础篇②——GPIO口输入,按键的长按和短按

    文章目录 一.前言 二.硬件准备 三.知识要点 3.1 GPIO使用 3.2 时钟节拍 四.参考例程 五.功能简述 六.源码实现 6.1 中断方式 6.2 定时扫描 七.源码详解 一.前言 本文基于V ...

  4. Midjourney|文心一格prompt教程[基础篇]:注册使用教程、风格设置、参数介绍、隐私模式等

    Midjourney|文心一格prompt教程[基础篇]:注册使用教程.风格设置.参数介绍.隐私模式等 开头讲一下为什么选择Midjourney和文心一格,首先Midjourney功能效果好不多阐述: ...

  5. 基于c++和asio的网络编程框架asio2教程基础篇:2、各个回调函数的触发顺序和执行流程

    基于c++和asio的网络编程框架asio2教程基础篇:2.各个回调函数的触发顺序和执行流程 以tcp举例: tcp服务端流程: #include <asio2/asio2.hpp>int ...

  6. 付呗聚合支付快速教程 基础篇①——基本介绍和配置

    文章目录 一.对接手册 二.商户后台 三.银行分账 四.其他介绍 一.对接手册 付呗聚合支付对接手册 第一步自然是商务对接 本专栏是作为付呗的普通级商户,商户后台 使用付呗开发平台的支付API,接入到 ...

  7. Redis进阶教程—基础篇-叶向阳-专题视频课程

    Redis进阶教程-基础篇-217人已学习 课程介绍         该系列教程涵盖了redis的方方面面,大亮点是实战经验分享总结.系列视频包含Redis基础篇.Redis提升篇.从零编写Redis ...

  8. 视频教程-Redis进阶教程—基础篇-NoSQL

    Redis进阶教程-基础篇 雅座Java架构师,架构开发公司百万级订单支付平台 叶向阳 ¥49.00 立即订阅 扫码下载「CSDN程序员学院APP」,1000+技术好课免费看 APP订阅课程,领取优惠 ...

  9. python人生苦短_人生苦短,我用Python(教程基础篇)

    人生苦短,我用Python(Python快速教程 - 基础篇) Life is short, you need Python 人生苦短,我用Python Python简介 本章将介绍Python的最基 ...

最新文章

  1. 如何在鼠标hover时改变标注的样式
  2. 在ElasticSearch之下(图解搜索的故事)
  3. 网络:HTTP报文格式
  4. Thread如何中断
  5. IPsec ***数据传输过程
  6. rsync同步工具学习笔记
  7. exchange系列(一)exchange2010邮件服务器的安装与规划
  8. MIT 最新 AI 医疗系统公布:“重症监护室干预” 与”电子医疗档案模型迁移“...
  9. 输电线路覆冰智能预测预警系统
  10. 重庆地区外卖店铺分析系统的设计与实现
  11. 25 | 业务安全体系:对比基础安全,业务安全有哪些不同?
  12. v-charts 如何更改文本颜色
  13. timed out waiting for to be synced
  14. 从Word中读取内容将word转换成txt
  15. Python 绘制圆柱体(3D图)
  16. 怎么下载老版本android,剪映旧版下载
  17. 【开源】一款PyQT+Pyserial开发的串口调试工具
  18. 【reactor模式】【proactor模式】
  19. python api调用百度ai平台_百度ai开放平台使用方法(附带详细案例步骤)
  20. 《Linux运维总结:内网服务器通过代理访问外网服务器(方法一)》

热门文章

  1. Unity3d中最简单物体的旋转移动
  2. cmmi实践访谈测试ppt_CMMI模型基础知识考试试题-(标准答案).xls
  3. 第1章第7节:如何通过大纲级别批量创建幻灯片 [PowerPoint精美幻灯片实战教程]
  4. 雷曼光电:LED行业黑马闪亮上市
  5. vue中加载腾讯地图(html形式)
  6. Java 变态面试题
  7. mount point / 挂载点
  8. 在360个人图书馆中实现复制
  9. facenet 人脸识别库的搭建和使用方法(二)
  10. 图片的高频与低频分量 初识 与 相关博客