本文主要包含两个方面的内容: 1) 演示Bazel的基本使用流程 2) 介绍Bazel使用过程中的一些基本概念

参看:

1. 使用Bazel来构建一个C++工程

执行如下命令从Bazel GitHub仓库克隆出一个sample:

# mkdir bazel-workspace
# cd bazel-workspace
# git clone https://github.com/bazelbuild/examples

我们来看看本节所需要用到的examples/cpp-tutorial目录:

# tree examples/cpp-tutorial
examples
└── cpp-tutorial
    ├──stage1
    │  ├── main
    │  │   ├── BUILD
    │  │   └── hello-world.cc
    │  └── MODULE.bazel
    ├──stage2
    │  ├── main
    │  │   ├── BUILD
    │  │   ├── hello-world.cc
    │  │   ├── hello-greet.cc
    │  │   └── hello-greet.h
    │  └── MODULE.bazel
    └──stage3
       ├── main
       │   ├── BUILD
       │   ├── hello-world.cc
       │   ├── hello-greet.cc
       │   └── hello-greet.h
       ├── lib
       │   ├── BUILD
       │   ├── hello-time.cc
       │   └── hello-time.h
       └── MODULE.bazel

从上面我们看到cpp-turorial包含3个stage文件夹,本文也分3个stage来进行讲解。在stage1中,我们会从单个package中构建单个target; 在stage2中,我们会从单个package中构建两个target: binary和library; 在stage3中,我们从多个package中构建多个targets。

1.1 预备知识

在我们开始build一个project之前,首先需要创建一个workspace。一个worksapce含有工程源文件和bazel输出的目录,此外目录中通常还会包含如下一些典型的文件:

  • MODULE.bazel文件:用于标识该目录是一个bazel workspace,放置于工程的根目录中, 可以在该文件中指定所需的外部依赖;

  • 一个或多个BUILD文件:用于告诉Bazel如何构建工程的不同部分。工程中包含BUILD文件的目录称为package

1) Understand BUILD file

一个BUILD文件中可以包含许多不同类型的Bazel指令。每个BUILD文件都至少需要设置一个rule,用于告诉bazel如何构建构建你想要的输出。BUILD文件中的每一个rule实例称为target,其指定了构建相应的输出所需要的源文件和依赖项。此外,一个target也可以指向多个其他的targets。

下面我们来看看cpp-tutorial/stage1/main目录下的BUILD文件:

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

在我们的例子中,hello-world这个target实例化了bazel的内置cc_binary rule。通过该规则,bazel就知道了需要通过源文件hello-world.cc来构建一个自包含的可执行文件,并且构建时没有其他依赖。

1.2 Stage 1: single target, single package

接下来我们使用bazel来构建stage1这一工程,先来看看该工程的目录结构:

examples
└── cpp-tutorial
    └──stage1
       ├── main
       │   ├── BUILD
       │   └── hello-world.cc
       └── MODULE.bazel

进入到该目录执行如下命令:

# cd cpp-tutorial/stage1
# bazel build //main:hello-world                                                                       
2024/12/04 14:19:23 Warning: used fallback version "8.0.0rc6"
2024/12/04 14:19:23 Downloading https://releases.bazel.build/8.0.0/rc6/bazel-8.0.0rc6-linux-x86_64...
2024/12/04 14:19:23 Skipping basic authentication for releases.bazel.build because no credentials found in /root/.netrc
Downloading: 61 MB out of 61 MB (100%) 
Extracting Bazel installation...
Starting local Bazel server and connecting to it...
WARNING: Couldn't auto load rules or symbols, because no dependency on module/repository 'rules_android' found. This will result in a failure if there's a reference to those rules or symbols.
INFO: Analyzed target //main:hello-world (68 packages loaded, 468 targets configured).
INFO: Found 1 target...
Target //main:hello-world up-to-date:
  bazel-bin/main/hello-world
INFO: Elapsed time: 29.465s, Critical Path: 0.27s
INFO: 6 processes: 4 internal, 2 linux-sandbox.
INFO: Build completed successfully, 6 total actions

命令执行后我们来看看所产生的output:

# tree
.
├── bazel-bin -> /root/.cache/bazel/_bazel_root/63b5237301a1c80ee5b3af8a4d0a90e9/execroot/_main/bazel-out/k8-fastbuild/bin
├── bazel-out -> /root/.cache/bazel/_bazel_root/63b5237301a1c80ee5b3af8a4d0a90e9/execroot/_main/bazel-out
├── bazel-stage1 -> /root/.cache/bazel/_bazel_root/63b5237301a1c80ee5b3af8a4d0a90e9/execroot/_main
├── bazel-testlogs -> /root/.cache/bazel/_bazel_root/63b5237301a1c80ee5b3af8a4d0a90e9/execroot/_main/bazel-out/k8-fastbuild/testlogs
├── main
│   ├── BUILD
│   └── hello-world.cc
├── MODULE.bazel
├── MODULE.bazel.lock
└── README.md

5 directories, 5 files

# tree bazel-bin
bazel-bin
└── main
    ├── hello-world
    ├── hello-world-0.params
    ├── hello-world.repo_mapping
    ├── hello-world.runfiles
    │   ├── _main
    │   │   └── main
    │   │       └── hello-world -> /root/.cache/bazel/_bazel_root/63b5237301a1c80ee5b3af8a4d0a90e9/execroot/_main/bazel-out/k8-fastbuild/bin/main/hello-world
    │   ├── MANIFEST -> /root/.cache/bazel/_bazel_root/63b5237301a1c80ee5b3af8a4d0a90e9/execroot/_main/bazel-out/k8-fastbuild/bin/main/hello-world.runfiles_manifest
    │   └── _repo_mapping -> /root/.cache/bazel/_bazel_root/63b5237301a1c80ee5b3af8a4d0a90e9/execroot/_main/bazel-out/k8-fastbuild/bin/main/hello-world.repo_mapping
    ├── hello-world.runfiles_manifest
    └── _objs
        └── hello-world
            ├── hello-world.pic.d
            └── hello-world.pic.o

6 directories, 9 files

# tree bazel-out
bazel-out
├── k8-fastbuild
│   ├── bin
│   │   └── main
│   │       ├── hello-world
│   │       ├── hello-world-0.params
│   │       ├── hello-world.repo_mapping
│   │       ├── hello-world.runfiles
│   │       │   ├── _main
│   │       │   │   └── main
│   │       │   │       └── hello-world -> /root/.cache/bazel/_bazel_root/63b5237301a1c80ee5b3af8a4d0a90e9/execroot/_main/bazel-out/k8-fastbuild/bin/main/hello-world
│   │       │   ├── MANIFEST -> /root/.cache/bazel/_bazel_root/63b5237301a1c80ee5b3af8a4d0a90e9/execroot/_main/bazel-out/k8-fastbuild/bin/main/hello-world.runfiles_manifest
│   │       │   └── _repo_mapping -> /root/.cache/bazel/_bazel_root/63b5237301a1c80ee5b3af8a4d0a90e9/execroot/_main/bazel-out/k8-fastbuild/bin/main/hello-world.repo_mapping
│   │       ├── hello-world.runfiles_manifest
│   │       └── _objs
│   │           └── hello-world
│   │               ├── hello-world.pic.d
│   │               └── hello-world.pic.o
│   └── testlogs
├── stable-status.txt
├── _tmp
│   └── actions
│       ├── stderr-5
│       ├── stderr-7
│       ├── stdout-5
│       └── stdout-7
└── volatile-status.txt

11 directories, 15 files

# tree bazel-stage1
bazel-stage1
├── bazel-out
│   ├── k8-fastbuild
│   │   ├── bin
│   │   │   └── main
│   │   │       ├── hello-world
│   │   │       ├── hello-world-0.params
│   │   │       ├── hello-world.repo_mapping
│   │   │       ├── hello-world.runfiles
│   │   │       │   ├── _main
│   │   │       │   │   └── main
│   │   │       │   │       └── hello-world -> /root/.cache/bazel/_bazel_root/63b5237301a1c80ee5b3af8a4d0a90e9/execroot/_main/bazel-out/k8-fastbuild/bin/main/hello-world
│   │   │       │   ├── MANIFEST -> /root/.cache/bazel/_bazel_root/63b5237301a1c80ee5b3af8a4d0a90e9/execroot/_main/bazel-out/k8-fastbuild/bin/main/hello-world.runfiles_manifest
│   │   │       │   └── _repo_mapping -> /root/.cache/bazel/_bazel_root/63b5237301a1c80ee5b3af8a4d0a90e9/execroot/_main/bazel-out/k8-fastbuild/bin/main/hello-world.repo_mapping
│   │   │       ├── hello-world.runfiles_manifest
│   │   │       └── _objs
│   │   │           └── hello-world
│   │   │               ├── hello-world.pic.d
│   │   │               └── hello-world.pic.o
│   │   └── testlogs
│   ├── stable-status.txt
│   ├── _tmp
│   │   └── actions
│   │       ├── stderr-5
│   │       ├── stderr-7
│   │       ├── stdout-5
│   │       └── stdout-7
│   └── volatile-status.txt
├── external
│   ├── bazel_tools -> /root/.cache/bazel/_bazel_root/63b5237301a1c80ee5b3af8a4d0a90e9/external/bazel_tools
│   ├── bazel_tools+xcode_configure_extension+local_config_xcode -> /root/.cache/bazel/_bazel_root/63b5237301a1c80ee5b3af8a4d0a90e9/external/bazel_tools+xcode_configure_extension+local_config_xcode
│   ├── platforms -> /root/.cache/bazel/_bazel_root/63b5237301a1c80ee5b3af8a4d0a90e9/external/platforms
│   ├── rules_cc+ -> /root/.cache/bazel/_bazel_root/63b5237301a1c80ee5b3af8a4d0a90e9/external/rules_cc+
│   └── rules_cc++cc_configure_extension+local_config_cc -> /root/.cache/bazel/_bazel_root/63b5237301a1c80ee5b3af8a4d0a90e9/external/rules_cc++cc_configure_extension+local_config_cc
├── main -> /workspace/cpp_proj/bazel-workspace/examples/cpp-tutorial/stage1/main
├── MODULE.bazel -> /workspace/cpp_proj/bazel-workspace/examples/cpp-tutorial/stage1/MODULE.bazel
├── MODULE.bazel.lock -> /workspace/cpp_proj/bazel-workspace/examples/cpp-tutorial/stage1/MODULE.bazel.lock
└── README.md -> /workspace/cpp_proj/bazel-workspace/examples/cpp-tutorial/stage1/README.md

19 directories, 18 files

# tree bazel-testlogs
bazel-testlogs

0 directories, 0 files

通过前面的编译日志,我们了解到最终的编译输出放在bazel-bin目录。执行如下命令看看编译出来的可执行程序是否正常运行:

# ./bazel-bin/main/hello-world
Hello world
Wed Dec  4 14:33:03 2024

2. 使用Bazel来构建一个Golang工程

3. Bazel基本概念