Bazel 可以依赖于其他项目中的目标。其他来源的依赖项 项目称为“外部依赖项”。
WORKSPACE
文件(或 WORKSPACE.bazel
文件)
工作区目录
告诉 Bazel 如何获取其他项目的来源。这些其他项目可以
包含一个或多个 BUILD
文件,这些文件具有自己的目标。BUILD
个文件
主项目可以使用这些外部目标的名称
WORKSPACE
文件。
例如,假设系统中有两个项目:
/
home/
user/
project1/
WORKSPACE
BUILD
srcs/
...
project2/
WORKSPACE
BUILD
my-libs/
如果 project1
想要依赖于 :foo
中定义的目标
/home/user/project2/BUILD
时,它可以指定名为
可以在 /home/user/project2
找到 project2
。然后定位
/home/user/project1/BUILD
可能依赖于 @project2//:foo
。
WORKSPACE
文件允许用户依赖于
或从互联网下载的它使用的语法与 BUILD
相同
但允许使用一组名为仓库规则(有时
(也称为“工作区规则”)。Bazel 附带有几个内置代码库
规则和一组嵌入式 Starlark 代码库
规则。用户还可以编写自定义代码库
规则来实现更复杂的行为。
支持的外部依赖项类型
您可以使用一些基本类型的外部依赖项:
依赖于其他 Bazel 项目
如果要使用另一个 Bazel 项目中的目标,您可以
使用
local_repository
、
git_repository
或 http_archive
从本地文件系统对其添加符号链接、引用 Git 代码库或下载
。
例如,假设您正在处理一个项目 my-project/
,并希望
依赖于同事项目 coworkers-project/
中的目标。两者都有
项目使用 Bazel,因此您可以将同事的项目添加为外部
依赖项,然后使用同事自行定义的任何目标
BUILD 文件。您需要将以下内容添加到 my_project/WORKSPACE
中:
local_repository(
name = "coworkers_project",
path = "/path/to/coworkers-project",
)
如果您同事的目标 //foo:bar
,则您的项目可以将其引用为
@coworkers_project//foo:bar
。外部项目名称必须
有效的工作区名称。
依赖于非 Bazel 项目
以 new_
为前缀的规则,例如
new_local_repository
,
允许您基于不使用 Bazel 的项目创建目标。
例如,假设您正在处理一个项目 my-project/
,并希望
依赖于您同事的项目 coworkers-project/
。您同事的
项目使用 make
进行构建,但您希望使用某个 .so 文件
生成的内容。为此,请将以下内容添加到 my_project/WORKSPACE
中:
new_local_repository(
name = "coworkers_project",
path = "/path/to/coworkers-project",
build_file = "coworker.BUILD",
)
build_file
用于指定要叠加到现有项目的 BUILD
文件,
示例:
cc_library(
name = "some-lib",
srcs = glob(["**"]),
visibility = ["//visibility:public"],
)
然后,您就可以依赖于项目中的 @coworkers_project//:some-lib
BUILD
个文件。
取决于外部软件包
Maven 制品和代码库
使用规则集 rules_jvm_external
从 Maven 代码库下载制品,并以 Java 形式提供它们
依赖项
提取依赖项
默认情况下,在 bazel build
期间,系统会根据需要提取外部依赖项。如果
如果您想预提取一组特定目标所需的依赖项,请使用
bazel fetch
。
如需无条件提取所有外部依赖项,请使用
bazel sync
。
由于提取的代码库存储在输出库中,因此
按工作区统计。
覆盖依赖项
我们建议您尽可能在一个版本政策中 项目。这对于您在编译时所针对并最终生成的依赖项而言是必需的 放在最终二进制文件中但如果情况并非如此,则您可以 影子依赖项。请考虑以下场景:
myproject/WORKSPACE
workspace(name = "myproject")
local_repository(
name = "A",
path = "../A",
)
local_repository(
name = "B",
path = "../B",
)
A/Workspace
workspace(name = "A")
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
name = "testrunner",
urls = ["https://github.com/testrunner/v1.zip"],
sha256 = "...",
)
B/工作区
workspace(name = "B")
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
name = "testrunner",
urls = ["https://github.com/testrunner/v2.zip"],
sha256 = "..."
)
A
和 B
依赖项均依赖于 testrunner
,但也依赖于它们
testrunner
的不同版本。这些测试运行程序没有理由
未在myproject
内和平共存,但会与每个
其他,因为它们的名称相同。要声明这两个依赖项,
更新 myproject/WORKSPACE:
workspace(name = "myproject")
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
name = "testrunner-v1",
urls = ["https://github.com/testrunner/v1.zip"],
sha256 = "..."
)
http_archive(
name = "testrunner-v2",
urls = ["https://github.com/testrunner/v2.zip"],
sha256 = "..."
)
local_repository(
name = "A",
path = "../A",
repo_mapping = {"@testrunner" : "@testrunner-v1"}
)
local_repository(
name = "B",
path = "../B",
repo_mapping = {"@testrunner" : "@testrunner-v2"}
)
此机制也可用于连接菱形。例如,如果 A
和 B
具有相同的依赖项,但以不同的名称对其进行调用,那么这些依赖项可以
添加到 myproject/WORKSPACE 中
从命令行替换代码库
如需从命令行使用本地代码库替换已声明的代码库,请执行以下操作:
使用
--override_repository
标志。使用此标志会更改外部代码库的内容
更改源代码
例如,如需将 @foo
替换成本地目录 /path/to/local/foo
,请使用以下代码:
传递 --override_repository=foo=/path/to/local/foo
标志。
部分用例包括:
- 调试问题。例如,您可以替换
http_archive
代码库 本地目录,以便您更轻松地进行更改 - 供应商开发。如果您处于无法进行网络调用的环境中, 覆盖基于网络的代码库规则以指向本地目录 。
使用代理
Bazel 将从 HTTPS_PROXY
和 HTTP_PROXY
中选择代理地址
环境变量,并使用这些变量下载 HTTP/HTTPS 文件(如果已指定)。
支持 IPv6
在仅支持 IPv6 的机器上,Bazel 将能够使用
没有变化。但在双栈 IPv4/IPv6 机器上,Bazel 遵循
Java 惯例:如果启用了 IPv4,则首选 IPv4。在某些情况下
例如当 IPv4 网络无法解析/访问外部地址时,
这可能会导致 Network unreachable
异常和构建失败。
在这些情况下,您可以替换 Bazel 的行为来首选 IPv6
通过使用 java.net.preferIPv6Addresses=true
系统属性来实现。
具体而言:
使用
--host_jvm_args=-Djava.net.preferIPv6Addresses=true
启动选项、 例如,将以下代码行添加到.bazelrc
文件:startup --host_jvm_args=-Djava.net.preferIPv6Addresses=true
如果您运行的 Java 构建目标需要连接到互联网 (集成测试有时需要这样做),也可使用
--jvmopt=-Djava.net.preferIPv6Addresses=true
工具标志,例如使用.bazelrc
文件中的下面这行代码:build --jvmopt=-Djava.net.preferIPv6Addresses
如果您使用的是 rules_jvm_external, 例如,对于依赖项版本解析,还要添加
-Djava.net.preferIPv6Addresses=true
后到达COURSIER_OPTS
环境变量,用于为 Coursier 提供 JVM 选项
传递依赖项
Bazel 只会读取 WORKSPACE
文件中列出的依赖项。如果您的项目
(A
) 依赖于另一个项目 (B
),而该项目列出了对第三个项目的依赖项
项目 (C
) 中,则必须在 WORKSPACE
文件中同时添加B
和 C
添加到项目的 WORKSPACE
文件中。此要求可将
WORKSPACE
文件大小,但会限制只有一个库的可能性
在 1.0 版中包含 C
,另一个在 2.0 版中包含 C
。
缓存外部依赖项
默认情况下,只有在以下情况下,Bazel 才会重新下载外部依赖项:
定义更改。对定义中引用的文件(如补丁)进行了更改
或 BUILD
文件)。
如需强制重新下载,请使用 bazel sync
。
布局
外部依赖项会全部下载到子目录下的某个目录中
输出库中的 external
。如果
本地代码库,则系统会创建一个符号链接
而不必创建新目录
您可以通过运行以下命令来查看 external
目录:
ls $(bazel info output_base)/external
请注意,运行 bazel clean
并不会实际删除
目录。如需移除所有外部工件,请使用 bazel clean --expunge
。
离线构建
有时需要或需要离线运行构建。对于
例如在飞机上旅行
prefetching所需的
使用 bazel fetch
或 bazel sync
的代码库就足够了;此外,
使用 --nofetch
选项,可以停用提取更多代码库的功能
构建容器。
对于需要完成所需文件的离线构建
bazel 以外的实体,bazel 支持
--distdir
。每当代码库规则要求 bazel 通过
ctx.download
或
ctx.download_and_extract
并提供文件的哈希值总和
bazel 将首先查看该选项指定的目录,
与提供的首个网址的基名匹配的文件,然后使用该本地副本
如果哈希值匹配。
Bazel 本身使用此技术从发行版
工件。
为此,它会收集所有必要的外部
依赖项
一个内部 IP 地址
distdir_tar
。
但是,bazel 允许在仓库规则中执行任意命令, 而不知道自己是否会向广告联盟发出调用请求因此,bazel 没有 强制构建完全离线测试构建能否正常运行 需要对网络进行外部屏蔽,就像 bazel 在其 引导测试
最佳做法
仓库规则
仓库规则通常应负责:
- 检测系统设置并将其写入文件。
- 查找系统其他位置的资源。
- 从网址下载资源。
- 生成 BUILD 文件或通过符号链接将其指向外部代码库目录。
尽可能避免使用 repository_ctx.execute
。例如,使用非 Bazel C++
包含使用 Make 的 build 的库,最好使用 repository_ctx.download()
,然后使用
编写一个 BUILD 文件来构建它,而不是运行 ctx.execute(["make"])
。
将 http_archive
设置为 git_repository
和
new_git_repository
。原因如下:
- Git 代码库规则依赖于系统
git(1)
,而 HTTP 下载程序是构建的 并且没有系统依赖项 http_archive
支持urls
列表作为镜像,git_repository
仅支持 单个remote
。http_archive
可与代码库缓存结合使用,但不适用于git_repository
。请参阅 #5116 了解详情。
请勿使用 bind()
。有关详情,请参阅考虑删除
绑定”长时间
讨论其问题和替代方案。