如何解决将 copts/defines 传播到目标的所有依赖项
我有一个项目,在一个相当复杂的构建系统中,它涉及单个 WORKSPACE 中的多个 BUILD 文件。简而言之,我的目标是:对于某些特定目标,与在任何其他目标中构建这些依赖目标时相比,我希望使用一组额外的属性 (copts
/defines
) 构建其所有递归依赖项大大地。我还没有找到一种干净利落的方法。
例如,目标 G 通常使用 copts = []
构建。如果目标 P 依赖于目标 G,并且我运行 bazel build :P
,我希望两个目标都使用 copts = ["-DMY_DEFINE"]
以及目标 G 的所有依赖项等构建。
cc_binary.defines 参数在 相反 方向传播:依赖某个目标 A 的所有目标都将收到目标 A 的所有 define
。
限制:
- 更喜欢避免自定义命令行标志,我无法控制人们如何调用
bazel {build,test}
- 复制整个依赖目标树是不切实际的
似乎无法从 BUILD 文件或目标中设置 config_setting
的值,因此基于 select
的解决方案似乎无法工作。
以前的工作:
- https://groups.google.com/g/bazel-discuss/c/rZps4nqYqt8/m/YS_pZD6oAQAJ - 2017 年,推荐“平行树”或自定义宏(其中我们已经有很多,将它们包装在另一个中会很有挑战性)
- Propagate copts to all dependencies in Bazel - 我相信这些都依赖于自定义命令行标志
解决方法
创建 user-defined build setting 不需要命令行标志。如果你设置了flag = False
,那么它实际上是不能在命令行中设置的。您可以改用 user-defined transition 来设置它。
我认为这样的事情可以满足您的要求(将其保存在 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
文件中:
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,这意味着使用相同的方法进行任何其他 C++ 库交换很简单。它的默认值实际上是一个“空”CcInfo
,它不会对依赖它的库做任何事情。
with_extra_copts
包装一组依赖项,配置为使用不同的 CcInfo
。这是实际更改值的规则,以创建具有不同标志的 G 的第二个版本。
_add_copts
是 with_extra_copts
用于更改 extra_copts
构建设置值的转换。它可以检查 attr
来做一些比添加硬编码列表更复杂的事情。
use_extra_copts
将 CcInfo
从 extra_copts
中取出,以便 cc_library
可以使用它们。
为了避免重写内置的 C++ 规则,这里使用包装器规则来拉出 copt 并进行转换。您可能想要创建宏来将包装器规则与相应的 cc_library 捆绑在一起。或者,您可以使用 rules_cc's my_c_archive 作为起点来创建自定义规则,这些规则重用内置 C++ 规则的核心实现,同时将构建设置的转换和使用集成到单个规则中。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。