基于--config有条件地创建一个Bazel规则



我正在处理一个问题,在这个问题中,我只想在指定了某个Bazel配置(通过'-config'(的情况下创建一个特定的规则。我们从0.11开始使用Bazel,并围绕Bazel以前的限制构建了一系列基础设施。我正在逐步将我们移植到更新的版本。缺少的功能之一是编译器转换,因此我们使用configs和一些外部脚本推出了自己的功能。

我解决问题的第一次尝试是这样的:

load("@rules_cc//cc:defs.bzl", "cc_library")
# use this with a select to pick targets to include/exclude based on config
# see __build_if_role for an example
def noop_impl(ctx):
pass
noop = rule(
implementation = noop_impl,
attrs = {
"deps": attr.label_list(),
},
)
def __sanitize(config):
if len(config) > 2 and config[:2] == "//":
config = config[2:]
return config.replace(":", "_").replace("/", "_")
def build_if_config(**kwargs):
config = kwargs['config']
kwargs.pop('config')
name = kwargs['name'] + '_' + __sanitize(config)
binary_target_name = kwargs['name']
kwargs['name'] = binary_target_name
cc_library(**kwargs)
noop(
name = name,
deps = select({
config: [ binary_target_name ],
"//conditions:default": [],
})
)

这几乎让我做到了,但问题是,如果我想构建一个库作为输出,那么它就会成为一个中间依赖项,因此会被删除或从未构建。

例如,如果我这样做:

build_if_config(
name="some_lib",
srcs=[ "foo.c" ],
config="//:my_config",
)

然后我运行

bazel build --config my_config //:some_lib

那么libsome_lib.a不会变成bazel-out,尽管如果我使用cc_library定义它,那么它会。

有没有一种方法可以直接在宏中创建适当的规则,而不是创建noop规则并使用select?还是另一种机制?

提前感谢您的帮助!

正如我在评论中所指出的,我误解了Bazel是如何计算其依赖关系的。规则教程的创建文件部分解释了一些细节,我在这里介绍了一些解决方案。

基本上,问题不在于构建的文件没有保留下来,而是它们从未被构建过。Bazel不知道查看deps变量并构建这些东西:似乎我必须创建一个使用deps的操作,然后通过返回DefaultInfo(列表(来注册一个操作

下面是我的新noop_impl功能

def noop_impl(ctx):
if len(ctx.attr.deps) == 0:
return None
# ctx.attr has the attributes of this rule
dep = ctx.attr.deps[0]
# DefaultInfo is apparently some sort of globally available
# class that can be used to index Target objects
infile = dep[DefaultInfo].files.to_list()[0]
outfile = ctx.actions.declare_file('lib' + ctx.label.name + '.a')
ctx.actions.run_shell(
inputs = [infile],
outputs = [outfile],
command = "cp %s %s" % (infile.path, outfile.path),
)
# we can also instantiate a DefaultInfo to indicate what output 
# we provide
return [DefaultInfo(files = depset([outfile]))]

相关内容

最新更新