0

我正在解决一个问题,如果指定了某个 Bazel 配置(通过“--config”),我只想创建一个特定规则。我们从 0.11 开始就一直在使用 Bazel,并且有一堆构建基础设施可以解决 Bazel 以前的限制。我正在逐步将我们移植到更新的版本。缺少的功能之一是编译器转换,因此我们使用配置和一些外部脚本推出了自己的功能。

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

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规则并使用选择?还是其他机制?

在此先感谢您的帮助!

4

1 回答 1

0

正如我在评论中指出的那样,我误解了 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]))]
于 2020-08-31T23:26:34.470 回答