Bazel-如何获取目标的所有传递源

标签 bazel bazel-aspect

我需要编写一个规则来压缩可执行文件的所有可传递配置文件( *.foo )(可以是自定义规则、java_binary 和 docker container_image)。
配置文件可以出现在 srcs 上可执行文件的任何属性的属性( tarsdepsruntime_deps 等)

这听起来应该很容易使用 aspect依附于我的规则,但我在各种示例之间迷失了方向。

最佳答案

sources_aspect.bzl :

SourceFiles = provider(
    fields = {
        'transitive_source_files' : 'list of transitive source files of a target'
    }
)

#add 'resources' ? if so _accumulate_transitive_config_files needs to check for dep in deps if ConfigFiles in dep
SourceAttr = ['tars','deps','runtime_deps','exports',]

def _accumulate_transitive_source_files(accumulated, deps):
  return depset(
        transitive = [dep[SourceFiles].transitive_source_files for dep in deps] + [accumulated])

def _collect_current_source_files(srcs):
    return [file for src in srcs for file in src.files.to_list()]

def _collect_source_files_aspect_impl(target, ctx):
    current_source_files = []
    if hasattr(ctx.rule.attr, 'srcs'):
      current_source_files = _collect_current_source_files(ctx.rule.attr.srcs)
    if hasattr(ctx.rule.attr, 'resources'):
      current_source_files = current_source_files + _collect_current_source_files(ctx.rule.attr.resources)

    accumulated_source_files = depset(current_source_files)
    for attr in SourceAttr:
      if hasattr(ctx.rule.attr, attr):
        accumulated_source_files = _accumulate_transitive_source_files(accumulated_source_files, getattr(ctx.rule.attr, attr))

    return [SourceFiles(transitive_source_files=accumulated_source_files)]


collect_source_files_aspect = aspect(implementation = _collect_source_files_aspect_impl,
  attr_aspects = SourceAttr,
)
sources.bzl
load("//sources/src/main:sources_aspect.bzl", "collect_source_files_aspect", "SourceFiles")

def _owner_to_bazel_file(fileLabel):
    workspace = fileLabel.workspace_root
    package = fileLabel.package
    if 0 < len(workspace):
      workspace = workspace + '/'
    if 0 < len(package):
     package = package + '/'
    return workspace + package + 'BUILD.bazel'


def _collect_source_files_rule_impl(ctx):
    metadata = [ctx.attr.group_id, ctx.attr.artifact_id]
    paths =  sorted([f.path for f in ctx.attr.main_artifact_name[SourceFiles].transitive_source_files.to_list()])
    owners =  sorted(depset([_owner_to_bazel_file(f.owner) for f in ctx.attr.main_artifact_name[SourceFiles].transitive_source_files.to_list()] + [_owner_to_bazel_file(ctx.label)]).to_list())

    ctx.actions.write(ctx.outputs.sources, "\n".join(metadata + paths + owners))
    ctx.actions.write(ctx.outputs.source_files, "{\"groupId\": \"%s\", \"artifactId\": \"%s\", \"sources\": %s, \"buildFiles\": %s}" % (ctx.attr.group_id, ctx.attr.artifact_id, paths, owners))
    return DefaultInfo(
          runfiles=ctx.runfiles(files=[ctx.outputs.sources, ctx.outputs.source_files])
      )

source_files = rule(
    implementation = _collect_source_files_rule_impl,
    attrs = {
        'main_artifact_name' : attr.label(aspects = [collect_source_files_aspect, ]),
        "group_id" : attr.string(mandatory=True),
        "artifact_id" : attr.string(mandatory=True),
    },
    outputs={"sources": "%{name}.sources.txt", "source_files": "%{name}.sources.json"},
)

关于Bazel-如何获取目标的所有传递源,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50083635/

相关文章:

java - 如何在 bazel 构建中调试 java_library 规则?

bazel - 使用 Bazel 创建和读取临时文件

android - 使用 tensorflow 作为存储库构建基于 tensorflow 的 android 应用程序

coq - 具有动态依赖关系的细粒度构建?

bazel - 如何使用方面检索 Bazel 工作区规则的属性

c++ - 如何将tensorflow作为外部依赖项添加到现有的bazel项目中

c++ - 无法通过 bazel 的 cc_library 规则成功包含外部头文件

bazel - 在测试目标上运行 bazel build 并不会产生测试输出 jar

bazel - 在 bazel 方面输出文件中积累数据的推荐策略