目录
什么是bazelBazel的根本概念
WORKSPACE fileBUILD fileBazel的C++事例
单个目的,单个软件包单个软件包,多个目的多个软件包,多个目的
最后
什么是bazel
Bazel 是一款与 Make、Maven 和 Gradle 类似的开源构建和测试工具。 它使用人类可读懂的高级 build 语言。Bazel 支持使用多种语言的项目,并针对多个平台构建输出。Bazel 支持跨多个代码库和大量用户的大量代码库。
Bazel的根本概念
WORKSPACE file
在构建项目之前,我们需要先设置工作区,工作区的作用是存储项目的源文件和Bazel的构建输出的目录,其中WORKSPACE file就是将目录及其内容标识为Bazel工作区的文件,需要位于项目目录构造的根目录下,该文件可以为空,但是通常包含从网络或者本地文件系统中提取其他依赖项的外部代码库声明。
BUILD file
一个项目中包含一个或多个BUILD file,BUILD主要用于告知Bazel如何构建项目,工作区包含一个BUILD文件的目录就是一个软件包。在之前的文章提到过,Bazel是基于工件的构建系统,而工件就可以理解为Bazel根据Build文件中的编译规则编译该目录下的文件形成的,软件包可以包含子软件包或包含BUILD文件的子目录,从而形成软件包的层次。
BUILD文件中包含了一些适用于Bazel的不同类型的指令,每个BUILD文件都需要包含至少一条规则(如cc_library)作为一组指令,以指示Bazel如何构建所需要的输出,例如可执行文件或库。BUILD文件中的每一个build规则实例都称为目的,并指向一组特定的源文件和依赖项,一个目的也可以指向其他目的。以下就是一个简单的BUILD文件的例子。- cc_binary(
- name = "hello-world",
- srcs = ["hello-world.cc"],
- )
复制代码 在本示例中,hello-world 目的会实例化 Bazel 的内置 cc_binary rule。该规则会告知 Bazel 从 hello-world.cc 源文件构建不含依赖项的独立可执行文件。
Bazel的C++事例
该例子是Bazel官方提供的,github地址为git clone github.com/bazelbuild/…
单个目的,单个软件包
我们从最简单的例子开端,例子只包含一个源文件,需要将改源文件构建成一个可执行文件,其文件目录如下。- examples
- └── cpp-tutorial
- └──stage1
- ├── main
- │ ├── BUILD
- │ └── hello-world.cc
- └── WORKSPACE
复制代码 BUILD文件内容如下- load("@rules_cc//cc:defs.bzl", "cc_binary")
- cc_binary(
- name = "hello-world",
- srcs = ["hello-world.cc"],
- )
复制代码 然后进入该目录cpp-tutorial/stage1,运行以下命令构建- bazel build //main:hello-world
复制代码 会打印以下信息表示编译胜利- Starting local Bazel server and connecting to it...
- INFO: Analyzed target //main:hello-world (37 packages loaded, 255 targets configured).
- INFO: Found 1 target...
- Target //main:hello-world up-to-date:
- bazel-bin/main/hello-world
- INFO: Elapsed time: 28.089s, Critical Path: 2.78s
- INFO: 6 processes: 4 internal, 2 darwin-sandbox.
- INFO: Build completed successfully, 6 total actions
复制代码 然后可以使用以下命令测试,会打印Hello world- bazel-bin/main/hello-world
复制代码 其依赖关系如下
单个软件包,多个目的
虽然单个目的足以满足小型项目的需求,在实际的开发过程中可能需要将较大的项目拆分为多个目的和软件包。这样可以实现快速增量构建(即 Bazel 仅重建更改的内容,并通过一次性构建项目的多个部分来加快构建速度。在教程的这一阶段,您将添加目的,然后添加软件包。
下面的BUILD文件会告诉Bazel先构建hello-greet库(使用Bazel内置的cc_library)然后构建hello-world二进制文件,其中的deps属性告诉Bazel构建hello-world需要hello-greet库。- load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library")
- cc_library(
- name = "hello-greet",
- srcs = ["hello-greet.cc"],
- hdrs = ["hello-greet.h"],
- )
- cc_binary(
- name = "hello-world",
- srcs = ["hello-world.cc"],
- deps = [
- ":hello-greet",
- ],
- )
复制代码 编译情况如下- INFO: Analyzed target //main:hello-world (36 packages loaded, 258 targets configured).
- INFO: Found 1 target...
- Target //main:hello-world up-to-date:
- bazel-bin/main/hello-world
- INFO: Elapsed time: 15.548s, Critical Path: 2.39s
- INFO: 8 processes: 4 internal, 4 darwin-sandbox.
- INFO: Build completed successfully, 8 total actions
复制代码 假设如今修改 hello-greet.cc 并重新构建项目,Bazel 只会重新编译该文件,编译结果如下(通过-s选项可以打印详细编译过程)- INFO: Analyzed target //main:hello-world (0 packages loaded, 0 targets configured).
- INFO: Found 1 target...
- SUBCOMMAND: # //main:hello-greet [action 'Compiling main/hello-greet.cc', configuration: a42135a42aad3da7e3af209ce54745fb0d0306dc29e1f3dc84d7d58372421fc9, execution platform: @local_config_platform//:host]
- (cd /private/var/tmp/_bazel_qiming/e4d33fbb5ee1f924b3cb079f19abf4eb/execroot/__main__ && \
- exec env - \
- APPLE_SDK_PLATFORM=MacOSX \
- APPLE_SDK_VERSION_OVERRIDE=13.1 \
- PATH=/Users/qiming/Library/Caches/bazelisk/downloads/bazelbuild/bazel-6.0.0-darwin-x86_64/bin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Library/Apple/usr/bin \
- XCODE_VERSION_OVERRIDE=14.2.0.14C18 \
- ZERO_AR_DATE=1 \
- external/local_config_cc/wrapped_clang_pp '-D_FORTIFY_SOURCE=1' -fstack-protector -fcolor-diagnostics -Wall -Wthread-safety -Wself-assign -fno-omit-frame-pointer -O0 -DDEBUG '-std=c++11' 'DEBUG_PREFIX_MAP_PWD=.' -iquote . -iquote bazel-out/darwin-fastbuild/bin -MD -MF bazel-out/darwin-fastbuild/bin/main/_objs/hello-greet/hello-greet.d '-DBAZEL_CURRENT_REPOSITORY=""' '-frandom-seed=bazel-out/darwin-fastbuild/bin/main/_objs/hello-greet/hello-greet.o' -isysroot __BAZEL_XCODE_SDKROOT__ -F__BAZEL_XCODE_SDKROOT__/System/Library/Frameworks -F__BAZEL_XCODE_DEVELOPER_DIR__/Platforms/MacOSX.platform/Developer/Library/Frameworks -no-canonical-prefixes -pthread -no-canonical-prefixes -Wno-builtin-macro-redefined '-D__DATE__="redacted"' '-D__TIMESTAMP__="redacted"' '-D__TIME__="redacted"' -target x86_64-apple-macosx13.1 -c main/hello-greet.cc -o bazel-out/darwin-fastbuild/bin/main/_objs/hello-greet/hello-greet.o)
- # Configuration: a42135a42aad3da7e3af209ce54745fb0d0306dc29e1f3dc84d7d58372421fc9
- # Execution platform: @local_config_platform//:host
- Target //main:hello-world up-to-date:
- bazel-bin/main/hello-world
- INFO: Elapsed time: 0.750s, Critical Path: 0.58s
- INFO: 2 processes: 1 internal, 1 darwin-sandbox.
- INFO: Build completed successfully, 2 total actions
复制代码 其中依赖如下图
多个软件包,多个目的
在包含多个软件包的情况下又该如何编译呢?其构造如下:- └──stage3
- ├── main
- │ ├── BUILD
- │ ├── hello-world.cc
- │ ├── hello-greet.cc
- │ └── hello-greet.h
- ├── lib
- │ ├── BUILD
- │ ├── hello-time.cc
- │ └── hello-time.h
- └── WORKSPACE
复制代码 lib目录下的BUILD文件如下- load("@rules_cc//cc:defs.bzl", "cc_library")
- cc_library(
- name = "hello-time",
- srcs = ["hello-time.cc"],
- hdrs = ["hello-time.h"],
- visibility = ["//main:__pkg__"],
- )
复制代码 main目录下的BUILD文件如下- load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library")
- cc_library(
- name = "hello-greet",
- srcs = ["hello-greet.cc"],
- hdrs = ["hello-greet.h"],
- )
- cc_binary(
- name = "hello-world",
- srcs = ["hello-world.cc"],
- deps = [
- ":hello-greet",
- "//lib:hello-time",
- ],
- )
复制代码 主软件包中的 hello-world 目的依赖于 lib 软件包中的 hello-time 目的(因而是目的标签 //lib:hello-time)- Bazel 通过 deps 属性晓得这一点。依赖项图中反映了这一点:
为了顺利构建,请使用可见性属性使 lib/BUILD 中的 //lib:hello-time 目的明确对 main/BUILD 中的目的可见。这是因为默认情况下,目的仅对同一 BUILD 文件中的其他目的可见。Bazel 使用目的可见性来防止呈现包含实现细节的库泄露到公共 API 等问题。
最后
这篇文章主要介绍了构造系统bazel的简单使用,更多关于bazel构造系统的资料请关注网站其它相关文章! |
|