我是 bazel 的新手,正在尝试具有依赖项的 monorepo 和 multirepo 构建。
我成功设置了 monorepo,但无法让 multrepo 正常工作。
对于 multirepo,我创建了两个 C++ 存储库,其中 repo app2 依赖于 repo lib2 当我构建 app2 时,我希望 bazel 获取 lib2。为了实现这一目标,我在我的工作空间中添加了 git_repository 定义。 我的问题是,当我运行 bazel build //app2:app bazel 抱怨它找不到 lib2 标头
INFO: Analyzed target //app2:app2 (0 packages loaded, 0 targets configured).
ERROR: /home/bazel/.cache/bazel/_bazel_bazel/36a4e7d3b3c11620f7fa4375ad21cf55/external/lib2/BUILD.bazel:6:11: Compiling time_util.cpp failed: (Exit 1): gcc failed: error executing CppCompile command (from target @@lib2//:time_util) /usr/bin/gcc -U_FORTIFY_SOURCE -fstack-protector -Wall -Wunused-but-set-parameter -Wno-free-nonheap-object -fno-omit-frame-pointer '-std=c++11' -MD -MF ... (remaining 21 arguments skipped)
Use --sandbox_debug to see verbose messages from the sandbox and retain the sandbox build root for debugging
external/lib2/time_util.cpp:1:10: fatal error: lib2/time_util.h: No such file or directory
1 | #include "lib2/time_util.h"
| ^~~~~~~~~~~~~~~~~~
compilation terminated.
ERROR: /home/bazel/testing/app2/BUILD.bazel:7:10: Compiling app2/app.cpp failed: (Exit 1): gcc failed: error executing CppCompile command (from target //app2:app2) /usr/bin/gcc -U_FORTIFY_SOURCE -fstack-protector -Wall -Wunused-but-set-parameter -Wno-free-nonheap-object -fno-omit-frame-pointer '-std=c++11' -MD -MF ... (remaining 32 arguments skipped)
Use --sandbox_debug to see verbose messages from the sandbox and retain the sandbox build root for debugging
app2/app.cpp:1:10: fatal error: lib2/time_util.h: No such file or directory
1 | #include "lib2/time_util.h"
| ^~~~~~~~~~~~~~~~~~
compilation terminated.
我的bazel文件如下
工作空间.bazel
load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
git_repository(
name = "lib2",
remote = "https://[email protected]/szarmach/lib2.git",
branch = "main", # branch, tag, commit, hash
)
app2/BUILD.bazel
load("@rules_cc//cc:defs.bzl", "cc_binary")
cc_binary(
name = "app",
srcs = ["app.cpp"],
#deps = ["//lib2:time_util"],
deps = ["@lib2//:time_util"],
visibility = ["//visibility:public"],
)
lib2/BUILD.bazel
load("@rules_cc//cc:defs.bzl", "cc_library")
cc_library(
name = "time_util",
srcs = ["time_util.cpp"],
hdrs = ["time_util.h"],
#hdrs = glob(["**/*.h"]),
copts = ["-Ilib1"],
includes = ["."],
visibility = ["//visibility:public"],
)
搜索堆栈溢出我已经看到了几乎相同问题的各种解决方案,但我无法成功应用它们。
对于构建 bazel 的多仓库案例,我缺少什么?
看起来您只有一个
WORKSPACE.bazel
文件,这意味着您将拥有一个存储库 - 要拥有两个存储库,您需要两个 WORKSPACE.bazel
文件。如果我克隆你的两个存储库(app2
和lib2
),并将你提到的WORKSPACE.bazel
文件放在根目录中,然后运行bazel query //...
,我会得到两个目标:
//app2:app
//lib2:time_util
顺便说明一下,由于您使用的是 Bazel 7,因此您可能需要切换到使用
MODULE.bzl
而不是 WORKSPACE.bazel
文件。因此,您可以使用 Bazel 模块执行类似的操作,这是管理依赖项的现代方式。
创建文件
app2/MODULE.bazel
:
bazel_dep(name = "rules_cc", version = "0.0.9")
non_module_dependencies = use_extension("//:extensions.bzl", "non_module_dependencies")
use_repo(non_module_dependencies, "lib2")
然后创建
app2/extensions.bzl
文件:
"""Registers any non-module dependencies here."""
load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
def _non_module_dependencies_impl(_ctx):
git_repository(
name = "lib2",
remote = "https://[email protected]/szarmach/lib2.git",
branch = "main", # branch, tag, commit, hash
)
non_module_dependencies = module_extension(
implementation = _non_module_dependencies_impl,
)
name = lib2
arg 中的 git_repository
是您需要在 use_repo
中的 MODULE.bazel
调用中添加的内容,以使其可用作模块依赖项。
您还需要
rules_cc
,它直接来自 BCR。
现在您已经设置了依赖项,您需要按如下方式更改
app2/BUILD.bazel
:
load("@rules_cc//cc:defs.bzl", "cc_binary")
cc_binary(
name = "app",
srcs = ["app.cpp"],
deps = ["@lib2//:time_util"]
)
请注意,现在我们使用
@lib2//:time_util
而不是 //lib2:time_util
。
您不再需要根目录中的
WORKSPACE.bazel
文件,因为那里没有包根目录。每个存储库都有自己的包根目录。
完成所有设置后,您会发现构建仍然会失败。这是因为在
app.cpp
中,您像这样引用库:
#include "lib2/time_util.h"
您需要将其更改为:
#include "time_util.h"
这是因为,虽然之前您需要工作空间根目录的完整路径,但现在每个工作空间都有自己的根目录,并且在
lib2
中,time_util.h
实际上位于根目录,而不是在子包下。
您可以看到,如果调用
bazel build //:app
,C 编译器会添加 -iquote external/_main~non_module_dependencies~lib2
标志。这本质上意味着 lib2
下的任何内容都可以使用引号进行 #include
d。
请注意,在
lib2
中,您还需要更改 #include
中的 time_util.cpp
,并且不要忘记提交并推送更改,或者在本地开发多个模块时使用本地覆盖。