seivl@seivl-Default-string:~$ bazel --version
bazel 4.0.0
使用Bazel编译项目
其中 examples/cpp-tutorial
目录下包含了这么些文件:
seivl@seivl-Default-string:~/examples/cpp-tutorial$ tree -L 3
.
├── 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
以 stage1
来举例:
seivl@seivl-Default-string:~/examples/cpp-tutorial/stage1$ tree -L 2
.
├── main
│ ├── BUILD
│ └── hello-world.cc
├── README.md
└── WORKSPACE
WORKSPACE
存放名为 WORKSPACE
的文件的目录,是整个工程的根目录。换言之,整个工程的根目录由 WORKSPACE
来标识。整个工程的根目录也被叫做 workspace
WORKSPACE
文件为空即可
BUILD
在 workspace下,考虑每一个子目录:如果存放了名为 BUILD
的文件,那么这个目录就是一个 package,意思是一个包。
BUILD
文件内容:它的内容包括设定的编译 target,比如 cc_binary 表示一个可执行文件,cc_library 表示一个库;每个 target 里又包括 name 等字段:
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",
],
)
先看一下 cpp-tutorial/stage1/main/BUILD
文件:
load("@rules_cc//cc:defs.bzl", "cc_binary")
cc_binary(
name = "hello-world",
srcs = ["hello-world.cc"],
)
进入到 cpp-tutorial/stage1
目录下
在工程根目录,也就是包含 WORKSPACE 文件的那个目录,执行然后运行以下指令
执行 bazel 构建
sudo bazel build //main:hello-world
结果:
seivl@seivl-Default-string:~/examples/cpp-tutorial/stage1$ sudo bazel build //main:hello-world
INFO: Analyzed target //main:hello-world (0 packages loaded, 0 targets configured).
INFO: Found 1 target...
Target //main:hello-world up-to-date:
bazel-bin/main/hello-world
INFO: Elapsed time: 0.150s, Critical Path: 0.00s
INFO: 1 process: 1 internal.
INFO: Build completed successfully, 1 total action
看一下此时的目录,生成了一些文件:
seivl@seivl-Default-string:~/examples/cpp-tutorial/stage1$ tree -L 1
.
├── bazel-bin
├── bazel-out
├── bazel-stage1
├── bazel-testlogs
├── main
├── README.md
└── WORKSPACE
表示让 bazel 去构建 main 这个 package 下的 hello-world 这一 target
随后,会在当前 workspace_下,生成 bazel-bin bazel-out bazel-stage1 bazel-testlogs 这几个文件
然后运行:
bazel-bin/main/hello-world
结果
world
Hello world
Mon May 10 21:46:23 2021
├── stage2
├── main
│ ├── BUILD
│ ├── hello-greet.cc
│ ├── hello-greet.h
│ └── hello-world.cc
├── README.md
└── WORKSPACE
进入 stage2 看一下 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",
],
)
bazel 首先编译了 hello-greet
这个库(利用Bazel内置的cc_library编译指令),然后编译 hello-world
这个二进制文件。hello-world
这个 target
的 deps
属性告诉 bazel,要构建 hello-world
这个二进制文件需要 hello-greet
这个库。
编译一下
sudo bazel build //main:hello-world
seivl@seivl-Default-string:~/examples/cpp-tutorial/stage2$ sudo bazel build //main:hello-world
[sudo] seivl 的密码:
Starting local Bazel server and connecting to it...
INFO: Analyzed target //main:hello-world (15 packages loaded, 55 targets configured).
INFO: Found 1 target...
Target //main:hello-world up-to-date:
bazel-bin/main/hello-world
INFO: Elapsed time: 5.027s, Critical Path: 0.64s
INFO: 7 processes: 4 internal, 3 processwrapper-sandbox.
INFO: Build completed successfully, 7 total actions
seivl@seivl-Default-string:~/examples/cpp-tutorial/stage2$ tree -L 2.
├── bazel-bin
├── bazel-out
├── bazel-stage2
├── bazel-testlogs
├── main
│ ├── BUILD
│ ├── hello-greet.cc
│ ├── hello-greet.h
│ └── hello-world.cc
├── README.md
└── WORKSPACE
运行:
bazel-bin/main/hello-world
结果:
world
Hello world
Mon May 10 22:23:47 2021
└── stage3
├── lib
│ ├── BUILD
│ ├── hello-time.cc
│ └── hello-time.h
├── main
│ ├── BUILD
│ ├── hello-greet.cc
│ ├── hello-greet.h
│ └── hello-world.cc
├── README.md
└── WORKSPACE
现在有两个子目录了,每个子目录中都包含了 BUILD
文件
因此,对于 bazel 来说,整个工作区现在就包含了两个 package:lib 和 main
load("@rules_cc//cc:defs.bzl", "cc_library")
cc_library(
name = "hello-time",
srcs = ["hello-time.cc"],
hdrs = ["hello-time.h"],
visibility = ["//main:__pkg__"],
)
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 这个 main package 中的 target 依赖于 lib package 中的 hello-time target(即target label为://lib:hello-time
)
bazel 是通过 deps 这个属性知道自己的依赖项的。那么现在依赖图就变成了下图的样子:
ps:注意到 lib/BUILD
文件中 将 hello-time
这个 target
显式可见了(通过visibility
属性)。
这是因为默认情况下,targets 只对同一个 BUILD文件里的其他 targets 可见
编译一下:
sudo bazel build //main:hello-world
seivl@seivl-Default-string:~/examples/cpp-tutorial/stage3$ sudo bazel build //main:hello-world
Starting local Bazel server and connecting to it...
INFO: Analyzed target //main:hello-world (16 packages loaded, 58 targets configured).
INFO: Found 1 target...
Target //main:hello-world up-to-date:
bazel-bin/main/hello-world
INFO: Elapsed time: 5.268s, Critical Path: 0.63s
INFO: 8 processes: 4 internal, 4 processwrapper-sandbox.
INFO: Build completed successfully, 8 total actions
运行结果:
seivl@seivl-Default-string:~/examples/cpp-tutorial/stage3$ bazel-bin/main/hello-world
Hello world
Mon May 10 22:33:54 2021