如何在 Bazel 工作区中仅构建 header 个 C++ 库?
How to build header only C++ library within Bazel workspace?
我正在做一个 C++ 项目,我需要像 C++ 中的数组和功能一样的 Numpy。我找到了一些替代方案,例如 xtensor, NumCpp 等。这些都是 header 的库。问题是我是第一次尝试使用 Bazel,所以我不知道如何将 header only 库添加到 Bazel 工作区。关于 Bazel 的其他问题,有一些建议,例如 genrule-environment、rules-foreign-cc。我已将 http_archive 添加到 WORKSPACE 文件,但我不确定要在 BUILD 文件中添加什么。
工作空间文件
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
all_content = """filegroup(name = "all", srcs = glob(["**"]), visibility = ["//visibility:public"])"""
http_archive(
name = "xtensor",
build_file_content = all_content,
strip_prefix = "xtensor-master",
urls = ["https://github.com/xtensor-stack/xtensor/archive/refs/heads/master.zip"],
)
http_archive(
name = "NumCpp",
build_file_content = all_content,
strip_prefix = "NumCpp-master",
urls = ["https://github.com/dpilger26/NumCpp/archive/refs/heads/master.zip"],
)
http_archive(
name = "rules_foreign_cc",
sha256 = "c2cdcf55ffaf49366725639e45dedd449b8c3fe22b54e31625eb80ce3a240f1e",
strip_prefix = "rules_foreign_cc-0.1.0",
url = "https://github.com/bazelbuild/rules_foreign_cc/archive/0.1.0.zip",
)
load("@rules_foreign_cc//:workspace_definitions.bzl", "rules_foreign_cc_dependencies")
rules_foreign_cc_dependencies()
我尝试按照文档进行操作,但每次都失败了。一些帮助将不胜感激。
对于像 header-only 库这样简单的东西,我会自己编写 BUILD 文件,而不使用 rules_foreign_cc。只写一个cc_library
,没有srcs
。像这样:
http_archive(
name = "xtensor",
build_file_content = all_content,
strip_prefix = "xtensor-master",
urls = ["https://github.com/xtensor-stack/xtensor/archive/refs/heads/master.zip"],
build_file_content = """
cc_library(
name = "xtensor",
visibility = ["//visibility:public"],
hdrs = glob(["xtensor/*.hpp"]),
defines = [
"XTENSOR_ENABLE_ASSERT",
],
deps = [
"@tbb",
],
)
""",
)
@xtensor
将是您的 Bazel 存储库。 build_file_content
将用于在其中创建一个 BUILD.bazel
文件。这意味着您的代码可以通过 @xtensor//:xtensor
依赖它,它可以缩短为 @xtensor
。你也可以把它放在一个单独的文件中(比如 build/BUILD.xtensor.bazel
),然后使用 build_file = "@build//:BUILD.xtensor.bazel"
而不是通过 build_file_content
.
将它内联到 WORKSPACE
中
rules_foreign_cc 如果你设置它会生成一些等效的东西,但对我来说这似乎比你自己写要麻烦得多。我根据对 CMakeLists.txt 的扫描设置 defines
和 deps
,您需要根据自己的配置方式进行自定义。
我看到 CMakeLists 唯一做的另一件事(除了查找依赖项和设置一些 -D
标志,其翻译如上所示)是生成一个 #include 所有其他文件。如果你想这样做,我会做这样的事情(在 @xtensor
的 BUILD 文件中):
genrule(
name = "gen_single_include",
outs = ["xtensor.hpp"],
cmd = "\n".join([
"cat > $@ <<'END'",
"#ifndef XTENSOR",
"#define XTENSOR",
] + ["#include \"%s\"" % h[len("xtensor/"):]
for h in glob(["xtensor/*.hpp"])
if h not in [
"xtensor/xexpression_holder.hpp",
"xtensor/xjson.hpp",
"xtensor/xmime.hpp",
"xtensor/xnpy.hpp",
]] + [
"#endif",
"END",
]),
我可能还没有把这里的一切都做到完美,但我的想法是使用 cat
构建文件以将 stdin 复制到它,一个 bash here 文档来提供内容,并且Python-style 列出理解以实际构建内容。
我正在做一个 C++ 项目,我需要像 C++ 中的数组和功能一样的 Numpy。我找到了一些替代方案,例如 xtensor, NumCpp 等。这些都是 header 的库。问题是我是第一次尝试使用 Bazel,所以我不知道如何将 header only 库添加到 Bazel 工作区。关于 Bazel 的其他问题,有一些建议,例如 genrule-environment、rules-foreign-cc。我已将 http_archive 添加到 WORKSPACE 文件,但我不确定要在 BUILD 文件中添加什么。
工作空间文件
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
all_content = """filegroup(name = "all", srcs = glob(["**"]), visibility = ["//visibility:public"])"""
http_archive(
name = "xtensor",
build_file_content = all_content,
strip_prefix = "xtensor-master",
urls = ["https://github.com/xtensor-stack/xtensor/archive/refs/heads/master.zip"],
)
http_archive(
name = "NumCpp",
build_file_content = all_content,
strip_prefix = "NumCpp-master",
urls = ["https://github.com/dpilger26/NumCpp/archive/refs/heads/master.zip"],
)
http_archive(
name = "rules_foreign_cc",
sha256 = "c2cdcf55ffaf49366725639e45dedd449b8c3fe22b54e31625eb80ce3a240f1e",
strip_prefix = "rules_foreign_cc-0.1.0",
url = "https://github.com/bazelbuild/rules_foreign_cc/archive/0.1.0.zip",
)
load("@rules_foreign_cc//:workspace_definitions.bzl", "rules_foreign_cc_dependencies")
rules_foreign_cc_dependencies()
我尝试按照文档进行操作,但每次都失败了。一些帮助将不胜感激。
对于像 header-only 库这样简单的东西,我会自己编写 BUILD 文件,而不使用 rules_foreign_cc。只写一个cc_library
,没有srcs
。像这样:
http_archive(
name = "xtensor",
build_file_content = all_content,
strip_prefix = "xtensor-master",
urls = ["https://github.com/xtensor-stack/xtensor/archive/refs/heads/master.zip"],
build_file_content = """
cc_library(
name = "xtensor",
visibility = ["//visibility:public"],
hdrs = glob(["xtensor/*.hpp"]),
defines = [
"XTENSOR_ENABLE_ASSERT",
],
deps = [
"@tbb",
],
)
""",
)
@xtensor
将是您的 Bazel 存储库。 build_file_content
将用于在其中创建一个 BUILD.bazel
文件。这意味着您的代码可以通过 @xtensor//:xtensor
依赖它,它可以缩短为 @xtensor
。你也可以把它放在一个单独的文件中(比如 build/BUILD.xtensor.bazel
),然后使用 build_file = "@build//:BUILD.xtensor.bazel"
而不是通过 build_file_content
.
WORKSPACE
中
rules_foreign_cc 如果你设置它会生成一些等效的东西,但对我来说这似乎比你自己写要麻烦得多。我根据对 CMakeLists.txt 的扫描设置 defines
和 deps
,您需要根据自己的配置方式进行自定义。
我看到 CMakeLists 唯一做的另一件事(除了查找依赖项和设置一些 -D
标志,其翻译如上所示)是生成一个 #include 所有其他文件。如果你想这样做,我会做这样的事情(在 @xtensor
的 BUILD 文件中):
genrule(
name = "gen_single_include",
outs = ["xtensor.hpp"],
cmd = "\n".join([
"cat > $@ <<'END'",
"#ifndef XTENSOR",
"#define XTENSOR",
] + ["#include \"%s\"" % h[len("xtensor/"):]
for h in glob(["xtensor/*.hpp"])
if h not in [
"xtensor/xexpression_holder.hpp",
"xtensor/xjson.hpp",
"xtensor/xmime.hpp",
"xtensor/xnpy.hpp",
]] + [
"#endif",
"END",
]),
我可能还没有把这里的一切都做到完美,但我的想法是使用 cat
构建文件以将 stdin 复制到它,一个 bash here 文档来提供内容,并且Python-style 列出理解以实际构建内容。