Bazel 是由 Google 开源的一款构建工具,支持 C++ 等多种语言

我个人是不喜欢 CMake 或者 GNU Make 的,感觉语法太丑了(?)

最近看了几个项目用的都是 Bazel,看起来语法似乎还行?对我 xp

于是打算简单学一下,记录一点常见用法以后好抄


安装

对 Windows 系统,直接按照官网方法下载即可,也可以去 Github 上下载二进制文件自己配置环境变量。

如果在 VSCode 中使用了 Bazel 插件,似乎还要另外下载 buildtools

文件结构

想要使用 Bazel,只需在项目的根目录下新建一个 WORKSPACE 文件即可。

在项目中在不同地方会有一个或多个 BUILD 文件,用于表示项目的不同模块。

一个例子:

1
2
3
4
5
> project
> src
- main.cpp
- BUILD
- WORKSPACE

然后在 BUILD 文件中写上相应的配置:

1
2
3
4
cc_binary(
name = "main",
srcs = ["main.cpp"],
)

最后在根目录运行 bazel build //src:main 即可编译,这里 // 指根目录

编译后可以看到二进制文件生成的位置。

语法

  • cc_library

    声明一个库,参数:

    • name: 名字
    • srcs: cpp 源文件
    • hdrs: 头文件
  • cc_binary

    声明一个二进制编译入口,参数:

    • name: 名字
    • srcs: 源文件
    • deps: 依赖

一个直观的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
cc_library(
name = "lib",
srcs = ["lib.cpp"],
hdrs = ["lib.h"],
)

cc_binary(
name = "main",
srcs = ["main.cpp"],
deps = [
":lib",
],
)

于是 lib.h 中声明,lib.cpp 中实现,即可在 main.cpp 中直接 #include "lib.h"

一些其他的语法:

  • glob

    包含多个文件,如 srcs = glob(["*.h"])

  • 包含路径

    为了避免在包含文件时使用绝对路径的麻烦,可以使用 copts 指定包含路径(类似 gcc 的 -I 参数),如根目录下的文件 src/a/include/lib.h

    1
    2
    hdrs = ["include/lib.h"]
    copts = ["-Isrc/a/include"]
  • 引入外部依赖

    官方的 Googletest 例子

    WORKSPACE 中添加:

    1
    2
    3
    4
    5
    6
    7
    8
    load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")

    http_archive(
    name = "gtest",
    url = "https://github.com/google/googletest/archive/release-1.10.0.zip",
    sha256 = "94c634d499558a76fa649edb13721dce6e98fb1e7018dfaeba3cd7a083945e91",
    build_file = "@//:gtest.BUILD",
    )

    然后新建 gtest.BUILD 针对此项目进行设置(若外部依赖自带 BUILD 文件则不需要 build_file

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    cc_library(
    name = "main",
    srcs = glob(
    ["googletest-release-1.10.0/src/*.cc"],
    exclude = ["googletest-release-1.10.0/src/gtest-all.cc"]
    ),
    hdrs = glob([
    "googletest-release-1.10.0/include/**/*.h",
    "googletest-release-1.10.0/src/*.h"
    ]),
    copts = [
    "-Iexternal/gtest/googletest-release-1.10.0/include",
    "-Iexternal/gtest/googletest-release-1.10.0"
    ],
    linkopts = ["-pthread"],
    visibility = ["//visibility:public"],
    )

    可以通过 strip_prefix = "googletest-release-1.10.0" 移除 http_archive 的前缀以简化设置,变为

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    cc_library(
    name = "main",
    srcs = glob(
    ["src/*.cc"],
    exclude = ["src/gtest-all.cc"]
    ),
    hdrs = glob([
    "include/**/*.h",
    "src/*.h"
    ]),
    copts = ["-Iexternal/gtest/include"],
    linkopts = ["-pthread"],
    visibility = ["//visibility:public"],
    )

    一些相关的语法:

    • linkopts: 编译选项,linkopts = ["-pthread"]

    • visibility = ["//visibility:public"]: 设置允许不同文件夹下的项目引用(默认只有同一文件夹的 BUILD 文件可以引用)

    之后即可在其他 BUILD 文件的 deps 中添加 "@gtest//:main"

官方文档