我将从 Rust 中的 Bazel 项目开始,没有 Cargo。我正在尝试设置一个功能门控的可选依赖项。
我设置了
crates_vendor
:
crates_vendor(
name = "crates_io",
cargo_lockfile = ":Cargo.Bazel.lock",
mode = "remote",
packages = {
"tonic": crate.spec(version = "*"),
"serde": crate.spec(version = "1.0"),
"serde_json": crate.spec(version = "1.0"),
},
repository_name = "crates_io",
tags = ["manual"],
)
现在我的 Rust 库定义为:
rust_library(
name = "foo",
srcs = glob("**/*.rs"),
deps = [
"@crates_io//:serde",
"@crates_io//:serde_json",
],
)
我想要功能门的是
@crates_io//:serde_json
。
Cargo.toml
代码是:
[dependencies]
serde_json = { version = "1.0", optional = true }
[features]
json = ["dep:serde_json"]
但是,正如我提到的,这是一个非 Cargo 项目。
实现这一目标的正确方法是什么?尝试通过文档进行挖掘,但无法弄清楚。
在 Bazel 中,您无法在库的使用者中选择库的功能,功能应在库本身中定义。
因此,就您的情况而言,您有两种选择。
1。为每个功能集定义不同的库。
您可以使用相同的源但具有不同的依赖项来定义库。
rust_library(
name = "foo",
srcs = glob("**/*.rs"),
deps = [
"@crates_io//:serde",
],
)
rust_library(
name = "foo_json",
crate_name = "foo",
crate_features = ["foo_json"],
srcs = glob("**/*.rs"),
deps = [
"@crates_io//:serde",
"@crates_io//:serde_json",
],
)
注意,如果 Bazel 目标名称与 crate 名称不同,则需要传递
crate_name
。
另请注意,您可能还必须在库上设置功能,因为 rustc
也应该了解启用的功能。
这是使用功能的直接且相当稳健的方式。
2。使用可配置属性
这将允许您的库仅定义一次。并在构建时打开和关闭功能。 其缺点是这些功能只能全局启用。
foo
库的所有用法都将使用带或不带 json 的版本。
load("@rules_rust//rust:defs.bzl", "rust_library")
load("@bazel_skylib//rules:common_settings.bzl", "bool_flag")
# Here we define a boolean flag, that can later use on command line
bool_flag(
name = "use_json",
build_setting_default = False,
)
# The flag from above turn on and off the named config setting
config_setting(
name = "foo_json",
flag_values = {":use_json": "true"},
)
# based on the config setting we can select features
# we will pass to the compiler...
foo_features = select({
":foo_json": ["json"],
"//conditions:default": [],
})
# .. and the dependncies, that we need.
foo_optional_deps = select({
":foo_json": [
# "@crates_io//:serde_json",
],
"//conditions:default": [],
})
# After we selected features and dependencies, we
# define the library using them.
rust_library(
name = "foo",
srcs = ["src/lib.rs"],
crate_features = foo_features,
deps = [
] + foo_optional_deps
)
例如如果我有一个依赖于
foo
库的工具,
rust_binary(
name = "tool",
srcs = ["src/main.rs"],
deps = [
"//foo:foo",
],
)
此示例打开
json
功能,您可以使用命令行:
bazel run //tool:tool --//foo:use_json
如何选择?
如果您想为不同的下游项目使用
foo
的不同功能,那么第一种方法是可行的。
如果您构建的软件具有全局切换的某些功能(例如免费版本,禁用了某些功能),则第二种方法可能会更好。