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

What is the proper way to optionally compile a library with a build flag (to place in `target_compatible_with`)?

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

我应该使用 features 标志吗?

如果是这样,我如何使用功能标志来限制编译,就像在 cc_librarycc_testcc_binary 中使用 target_compatible_with 一样?

如果不是,最好的约束方法是什么?调整 platforms 标志会干扰默认平台检测。

使用标签 manual,例如:

cc_test(name = "my_test"
        ...
        tags = ["manual"]
)

听起来你想要一个 user-defined build setting that is a command-line flag. The easiest way is to use one of the common build settings rules,并在 BUILD 文件中实例化它(在这个例子中称之为 flags/BUILD):

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

那就可以设置了from the command line with --//flags:flag. If you want a less ugly syntax, build setting aliases也可以

一旦你有了可以触发 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"],
    }),
)

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

我猜你有其他目标在启用时依赖于这个库,可以类似地处理:

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

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