如何编写与外部存储库一起工作的Bazel规则?

如何编写与外部存储库一起工作的Bazel规则?,bazel,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.bz

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
这个额外的外部/com_谷歌_协议似乎不知从何而来,它让我的规则失败了:

我告诉protoc生成ctx.genfiles_dir.path,即bazel out/k8 fastbuild/genfiles。 所以protoc生成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\u google\u protobuf/

我错过什么了吗?我怎样才能写下这条规则,而不觉得我一直在和巴泽尔战斗

我错过什么了吗

正如您已经意识到的,基本问题是您有两个路径名称空间——protoc看到的名称空间,即导入路径,以及bazel看到的名称空间,即您传递给声明文件的路径

需要注意的两件事:

1使用declare_文件声明的所有路径获取路径//

2所有操作都从执行,除非在这种情况下切换为您的示例

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

此代码从外部protobuf依赖项的上下文中运行 proto_path=google/a/b.proto output\u file=ctx.actions.declare\u fileproto\u路径 output_file.path将是`/external/protobuf/google/a/b.proto` 从output_file.path中删除已知的proto_路径 protoc_prefix=output_file.path[:-lenproto_path] printprotoc_前缀打印:/external/protobuf command={protoc}{proto_path}{cpp_out}{plugin}{plugin_options}{proto_file}.format ... cpp_out=-cpp_out=+protoc_前缀, ... 选择 您还可以使用ctx.bin_dir、ctx.label.workspace_name、ctx.label.package和ctx.label.name构建相同的路径

杂项。 proto_库最近获得了一个属性。使用时,上述情况不正确,因为所有从属文件都被符号链接到一个新目录中,从该目录中,它们具有以strip\u import\u前缀声明的相对路径

路径格式为:

<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的外部repo,它在根目录下包含一个名为b_proto的目标的构建文件,而b_proto又依赖于一个包装google/a/b.proto的proto_库,并使用strip_import_prefix属性。

我自己也发现了同样的解决方法:output_file.path[:-lenproto_path]东西。但这仍然像是我在和巴泽尔战斗。当ctx.genfiles\u dir.path和output\u filename都没有外部/com\u google\u protobuf时,ctx.new\u filectx.genfiles\u dir,output\u filename.path中包含外部/com\u google\u protobuf似乎仍然是错误的。我不明白为什么这对任何人都有用。似乎每个人都必须不断地重新发现这些解决方法。