有选择地使用构建标志编译库(放置在“target_known_with”中)的正确方法是什么?

Rob*_*bie 4 c++ build bazel bazel-rules

假设我有一个库实现,我只想在用户在构建时指定它时进行编译。

我应该使用features标志吗?

如果是这样,我如何使用 features 标志来限制编译,就像target_compatible_within cc_librarycc_test和 一样cc_binary

如果不是,限制这种情况的最佳方法是什么?调整platforms标志会干扰默认平台检测。

Bri*_*man 6

听起来您想要一个用户定义的构建设置,它是一个命令行标志。最简单的方法是使用常见的构建设置规则之一,并在 BUILD 文件中实例化它(flags/BUILD在本示例中调用它):

load("@bazel_skylib//rules:common_settings.bzl", "bool_flag")
bool_flag(
    name = "flag",
    build_setting_default = False,
    visibility = ["//visibility:public"],
)
Run Code Online (Sandbox Code Playgroud)

然后您可以使用命令行来设置它--//flags:flag。如果您想要不那么丑陋的语法,也可以使用构建设置别名。

一旦你有了可以触发config_setting 的东西,制作一个可选库就非常简单了。首先,您要在未设置标志时禁用库本身:

config_setting(
    name = "have_flag",
    flag_values = {
        "//flags:flag": "true",
    },
)

cc_library(
    name = "sometimes",
    target_compatible_with = select({
        ":have_flag": [],
        "//conditions:default": ["@platforms//:incompatible"],
    }),
)
Run Code Online (Sandbox Code Playgroud)

任何标记为需要的东西@platforms//:incompatible都永远不会与任何真实的平台兼容,因此当您bazel build //...没有该标志时,这将跳过该库,并使任何依赖它的东西成为错误。

我猜您在启用时还有其他依赖于该库的目标,可以类似地处理:

cc_binary(
    name = "thing",
    deps = [
        "//:something_else",
    ] + select({
        ":have_flag": [":sometimes"],
        "//conditions:default": [],
    }),
)
Run Code Online (Sandbox Code Playgroud)

如果您想定义一个预处理器宏来告诉依赖代码是否使用可选依赖项(或交换源文件,或更改链接选项等),那么您可以select像这样使用coptsdefinessrcs和大多数其他cc_library/cc_binary属性。