Introduction to Bazel: Building a C++ Project
1. WORKSPACE
WORKSPACE文件主要就是命名workspace以及声明外部的依赖,这就包括外部依赖的获取方式及获取方法。WORKSPACE文件告诉Bazel如何去得到其他的工程源,然后package中的BUILD文件就可以根据WORKSPACE中的外部target名字写依赖关系。WORKSPACE文件允许用户的目标依赖其他文件系统的目标或者从网上下载的目标。除了通过bazel build可以自动获取外部依赖之外,还可以通过bazel fetch来获得。Bazel会缓存外部依赖,并且只有在WORKSPACE文件更改后才再次下载和更新。WORKSPACE文件的语法和BUILD文件一致,不过会用到一些特定的内置rule。所有的外部依赖会都下载到一个名为的软连接目录。具体的内容可以通过命令行获得:
ls $(bazel info output_base)/external
一共有三种外部依赖的主要类型:
1、依赖于其他Bazel工程
根据这个Bazel工程所处的位置不同,调用不同的内置rule来获得:
- local_repository:本地
- git_repository:git仓库
- http_archive:网络下载
2、依赖于其他非Bazel工程
还有一种情况是另外一个工程不是Bazel工程,那么就需要另外一种方法来添加依赖引用
- new_local_repository:本地
- new_git_repository:git仓库
- new_http_archive:网络下载
3、依赖于外部包
Maven仓库:Use the rule maven_jar (and optionally the rule maven_server) to download a jar from a Maven repository and make it available as a Java dependency.
例子:
(1) glog / gflags
目录结构
├── WORKSPACE
├── BUILD
└── main.cc
WORKSPACE
workspace(name = "bazel_test")
load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
git_repository(
name = "com_github_gflags_gflags",
commit = "f7388c6655e699f777a5a74a3c9880b9cfaabe59",
remote = "https://github.com/gflags/gflags.git",
)
git_repository(
name = "glog",
commit = "0a2e5931bd5ff22fd3bf8999eb8ce776f159cda6",
remote = "https://github.com/google/glog.git",
)
local_repository(
name = "base",
path = "build_tools/deps/base", // name对应的关键词代表了路径path
)
BUILD
cc_binary(
name = "bazel_test",
srcs = ["main.cc"],
deps = [
"@com_github_gflags_gflags//:gflags",
"@glog",
],
)
2. BUILD
└──stage3
├── main
│ ├── BUILD
│ ├── hello-world.cc
│ ├── hello-greet.cc
│ └── hello-greet.h
├── lib
│ ├── BUILD
│ ├── hello-time.cc
│ └── hello-time.h
└── WORKSPACE
lib/BUILD
file:
cc_library(
name = "hello-time",
srcs = ["hello-time.cc"],
hdrs = ["hello-time.h"],
visibility = ["//main:__pkg__"],
)
请注意,为了使build成功,我们使用visibility
属性使 lib/BUILD 中的 //lib:hello-time 目标对 main/BUILD 中的目标显式可见。这是因为默认情况下,目标仅对同一 BUILD 文件中的其他目标可见。 (Bazel 使用目标可见性来防止包含实现细节的库泄漏到公共 API 等问题。)
main/BUILD
file
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",
],
)
Bazel 通过 deps 属性,设置主包中的 hello-world 目标依赖于 lib 包中的 hello-time 目标(目标标签 //lib:hello-time)。
引用目标
在 BUILD 文件和命令行中,Bazel 使用标签来引用目标 - 例如,//main:hello-world 或 //lib:hello-time。语法是:
//path/to/package:target-name
如果目标是rule target:
- path/to/package: 包含 BUILD 文件的目录的路径;
- target-name: 在 BUILD 文件中命名目标的名称(name属性)
在存储库根目录引用目标时,包路径为空,只需使用 //:target-name。在同一个 BUILD 文件中引用目标时,甚至可以跳过 // 工作区根标识符而只使用 :target-name。
"@third_party//gtest:gtest_main"
@third_party:WORKSPACE中的“name”