创建一个用户定义的构建设置 https://docs.bazel.build/versions/master/skylark/config.html#user-defined-build-settings不需要命令行标志。如果你设置flag = False
,那么实际上无法在命令行上设置。您可以使用用户定义的转换 https://docs.bazel.build/versions/master/skylark/config.html#user-defined-transitions来设置它。
我认为这样的东西可以满足您的需求(将其保存在extra_copts.bzl
):
def _extra_copts_impl(ctx):
context = cc_common.create_compilation_context(
defines = depset(ctx.build_setting_value)
)
return [CcInfo(compilation_context = context)]
extra_copts = rule(
implementation = _extra_copts_impl,
build_setting = config.string_list(flag = False),
)
def _use_extra_copts_implementation(ctx):
return [ctx.attr._copts[CcInfo]]
use_extra_copts = rule(
implementation = _use_extra_copts_implementation,
attrs = "_copts": attr.label(default = "//:extra_copts")},
)
def _add_copts_impl(settings, attr):
return {"//:extra_copts": ["MY_DEFINE"]}
_add_copts = transition(
implementation = _add_copts_impl,
inputs = [],
outputs = ["//:extra_copts"],
)
def _with_extra_copts_implementation(ctx):
infos = [d[CcInfo] for d in ctx.attr.deps]
return [cc_common.merge_cc_infos(cc_infos = infos)]
with_extra_copts = rule(
implementation = _with_extra_copts_implementation,
attrs = {
"deps": attr.label_list(cfg = _add_copts),
"_allowlist_function_transition": attr.label(
default = "@bazel_tools//tools/allowlists/function_transition_allowlist"
)
},
)
然后在BUILD
file:
load("//:extra_copts.bzl", "extra_copts", "use_extra_copts", "with_extra_copts")
extra_copts(name = "extra_copts", build_setting_default = [])
use_extra_copts(name = "use_extra_copts")
cc_library(
name = "G",
deps = [":use_extra_copts"],
)
with_extra_copts(
name = "P_deps",
deps = [":G"],
)
cc_library(
name = "P",
deps = [":P_deps"],
)
extra_copts
是构建设置。它返回一个CcInfo https://docs.bazel.build/versions/master/skylark/lib/CcInfo.html直接,这意味着使用相同的方法可以直接进行任何其他 C++ 库交换。它的默认值实际上是“空”CcInfo
这不会对依赖它的库做任何事情。
with_extra_copts
包装一组依赖项,配置为使用不同的CcInfo
。这是实际更改值的规则,以创建具有不同标志的 G 的第二个版本。
_add_copts
是一个过渡with_extra_copts
用于改变的值extra_copts
构建设置。它可以检查attr
做一些比添加硬编码列表更复杂的事情。
use_extra_copts
拉动CcInfo
out of extra_copts
so a cc_library
可以使用它们。
为了避免重写内置的 C++ 规则,它使用包装器规则来拉出 copt 并进行转换。您可能想要创建宏来将包装器规则与相应的 cc_library 捆绑在一起。或者,您可以使用rules_cc 的 my_c_archive https://github.com/bazelbuild/rules_cc/blob/master/examples/my_c_archive/my_c_archive.bzl作为创建自定义规则的起点,这些规则重用内置 C++ 规则的核心实现,同时将构建设置的转换和使用集成到单个规则中。