如何编写适用于外部存储库的Bazel规则?

时间:2019-04-22 14:45:49

标签: bazel

Bazel Starlark API对外部存储库中的文件执行奇怪的操作。我有以下Starlark片段:

    print(ctx.genfiles_dir)
    print(ctx.genfiles_dir.path)
    print(output_filename)
    ret = ctx.new_file(ctx.genfiles_dir, output_filename)
    print(ret.path)

它正在创建以下输出:

DEBUG: build_defs.bzl:292:5: <derived root>
DEBUG: build_defs.bzl:293:5: bazel-out/k8-fastbuild/genfiles
DEBUG: build_defs.bzl:294:5: google/protobuf/descriptor.upb.c
DEBUG: build_defs.bzl:296:5: bazel-out/k8-fastbuild/genfiles/external/com_google_protobuf/google/protobuf/descriptor.upb.c

多余的external/com_google_protobuf似乎无处不在,这使我的规则失败了:

  • 我告诉protoc生成为ctx.genfiles_dir.path(即bazel-out/k8-fastbuild/genfiles)。
  • 因此协议生成bazel-out/k8-fastbuild/genfiles/google/protobuf/descriptor.upb.c
  • Bazel失败,因为我没有生成bazel-out/k8-fastbuild/genfiles/external/com_google_protobuf/google/protobuf/descriptor.upb.c

同样,当我尝试从外部存储库中对源文件调用file.short_path时,会得到类似../com_google_protobuf/google/protobuf/descriptor.proto的结果。这似乎无济于事,所以我只写了一些手动代码来剥离开头的../com_google_protobuf/

我想念什么吗?我该如何以一种好像我并没有一直在与Bazel战斗的方式编写此规则?

1 个答案:

答案 0 :(得分:1)

  

我想念什么吗?

您已经意识到,基本问题是,您有两个路径“命名空间”,一个是protoc看到的路径(即,导入路径),另一个是bazel看到的路径(即,您传递到declare_file()的路径)。

2件事要注意:

1)用declare_file()声明的所有路径都获得路径<bin dir>/<package path incl. workspace>/<path you passed to declare_file()>

2)所有操作均从<bin dir>执行(除非是output_to_genfils=True,在这种情况下,如您的示例所示,该操作将切换为<gen dir>

尝试解决与您遇到的完全相同的问题,我采取了从output_file路径中剥离已知路径的方法,以确定将哪个目录作为p传递:

# This code is run from the context of the external protobuf dependency
proto_path = "google/a/b.proto"
output_file = ctx.actions.declare_file(proto_path)

# output_file.path would be `<gen_dir>/external/protobuf/google/a/b.proto`
# Strip the known proto_path from output_file.path
protoc_prefix = output_file.path[:-len(proto_path)]

print(protoc_prefix) # Prints: <gen_dir>/external/protobuf

command = "{protoc} {proto_paths} {cpp_out} {plugin} {plugin_options} {proto_file}".format(
        ...
        cpp_out = "--cpp_out=" + protoc_prefix,
        ...
)

替代项

您也许还可以使用ctx.bin_dirctx.label.workspace_namectx.label.packagectx.label.name构建相同的路径。

其他。

proto_library最近获得了属性strip_import_prefix。使用时,以上内容是不正确的,因为所有相关文件都被符号链接到一个新目录,在该目录中,它们具有用strip_import_prefix声明的相对路径。

路径格式为:

<bin dir>/<repo>/<package>/_virtual_base/<label name>/<path `import`ed in .proto files>
i.e.
<bin dir>/external/protobuf/_virtual_base/b_proto/google/a/b.proto

假设您要构建一个名为protobuf的外部存储库,该存储库的根目录包含一个BUILD文件,目标文件名为b_proto,而目标文件又依赖于一个{{1} }包装proto_library并使用google/a/b.proto属性。