The C based gRPC (C++, Python, Ruby, Objective-C, PHP, C#) https://grpc.io/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

230 lines
8.0 KiB

"""Utility functions for generating protobuf code."""
_PROTO_EXTENSION = ".proto"
[bazel][python] Support _virtual_imports input for py_proto_library and py_grpc_library rules `proto_library` targets are used as deps for `py_proto_library` and `py_grpc_library` rules. The `proto_library` targets can be configured using `import_prefix` and/or `strip_import_prefix` (which essentially move original location of the proto file and, as result, affects import path within proto files themselves and in the generated language-specific stubs). The biggest question to answer when generating stubs from moved protos is where to put result (this decision affects all downstream rules as well, because the location of file affects its import path). This PR tries to follow same logic as the native `cc_proto_library` (created and maintained by Bazel team). For example, if we have `firestore.proto` file, which is located under `google/firestore/v1beta1` Bazel package and want to move it under `google/cloud/firestore_v1beta1/proto` (this is axactly what happens in googleapis repository), it can be configured the following way: ```bzl proto_library( name = "firestore_moved_proto", srcs = ["firestore.proto"], import_prefix = "google/cloud/firestore_v1beta1/proto", strip_import_prefix = "google/firestore/v1beta1", ) ``` The rule above will first generate virtual `.proto` files (under new location) and only after that generate a binary descriptor from them. Specifically it will generate the following "virtual" file under `_virtual_imports` subdirectory of same package: ``` bazel-bin/google/firestore/v1beta1/_virtual_imports/firestore_moved_proto/google/cloud/firestore_v1beta1/proto/common.proto ``` When supplied to `cc_proto_library`, like the following: ```bzl cc_proto_library( name = "firestore_moved_cc_proto", deps = ["firestore_moved_proto"], ) ``` The rule will generate .cc and .h files like the following: ``` bazel-bin/google/firestore/v1beta1/_virtual_imports/firestore_moved_proto/google/cloud/firestore_v1beta1/proto/firestore.pb.h bazel-bin/google/firestore/v1beta1/_virtual_imports/firestore_moved_proto/google/cloud/firestore_v1beta1/proto/firestore.pb.cc ``` Notice, that each generated `.cc` and `.h` file is prefixed with `_virtual_imports/<name_of_proto_library_target>`. The python rules try to do same thing, so for the following py_proto_library rule: ```bzl py_proto_library( name = "firestore_moved_py_proto", deps = [":firestore_moved_proto"], ) ``` It wil generate the following file: ``` bazel-bin/google/firestore/v1beta1/_virtual_imports/firestore_moved_proto/google/cloud/firestore_v1beta1/proto/firestore_pb2.py ``` I.e in same path as cc_proto_library. This all woks, but an annoying part is that to use the generated library in some other py_library, in needs to specify the "_virtual_imports/proto_target" path as its "includes" parameter (and I can't make it better than that). Another option would be to skeep the `_virtual_imports/<name_of_proto_library_target>` the suffix for the generated python stubs, which will make the path look like the following: ``` bazel-bin/google/firestore/v1beta1/google/cloud/firestore_v1beta1/proto/firestore_pb2.py ``` That will make using generated stubs simpler and cleaner (no need to specify imports argument), but it will make it inconsistent with the other rules (like cc_proto_library) and also more susseptible to naming conflicts (if there is already something under the generated path).
5 years ago
_VIRTUAL_IMPORTS = "/_virtual_imports/"
def well_known_proto_libs():
return [
"@com_google_protobuf//:any_proto",
"@com_google_protobuf//:api_proto",
"@com_google_protobuf//:compiler_plugin_proto",
"@com_google_protobuf//:descriptor_proto",
"@com_google_protobuf//:duration_proto",
"@com_google_protobuf//:empty_proto",
"@com_google_protobuf//:field_mask_proto",
"@com_google_protobuf//:source_context_proto",
"@com_google_protobuf//:struct_proto",
"@com_google_protobuf//:timestamp_proto",
"@com_google_protobuf//:type_proto",
"@com_google_protobuf//:wrappers_proto",
]
def get_proto_root(workspace_root):
"""Gets the root protobuf directory.
Args:
workspace_root: context.label.workspace_root
Returns:
The directory relative to which generated include paths should be.
"""
if workspace_root:
return "/{}".format(workspace_root)
else:
return ""
def _strip_proto_extension(proto_filename):
if not proto_filename.endswith(_PROTO_EXTENSION):
fail('"{}" does not end with "{}"'.format(
proto_filename,
_PROTO_EXTENSION,
))
return proto_filename[:-len(_PROTO_EXTENSION)]
def proto_path_to_generated_filename(proto_path, fmt_str):
"""Calculates the name of a generated file for a protobuf path.
For example, "examples/protos/helloworld.proto" might map to
"helloworld.pb.h".
Args:
proto_path: The path to the .proto file.
fmt_str: A format string used to calculate the generated filename. For
example, "{}.pb.h" might be used to calculate a C++ header filename.
Returns:
The generated filename.
"""
return fmt_str.format(_strip_proto_extension(proto_path))
[bazel][python] Support _virtual_imports input for py_proto_library and py_grpc_library rules `proto_library` targets are used as deps for `py_proto_library` and `py_grpc_library` rules. The `proto_library` targets can be configured using `import_prefix` and/or `strip_import_prefix` (which essentially move original location of the proto file and, as result, affects import path within proto files themselves and in the generated language-specific stubs). The biggest question to answer when generating stubs from moved protos is where to put result (this decision affects all downstream rules as well, because the location of file affects its import path). This PR tries to follow same logic as the native `cc_proto_library` (created and maintained by Bazel team). For example, if we have `firestore.proto` file, which is located under `google/firestore/v1beta1` Bazel package and want to move it under `google/cloud/firestore_v1beta1/proto` (this is axactly what happens in googleapis repository), it can be configured the following way: ```bzl proto_library( name = "firestore_moved_proto", srcs = ["firestore.proto"], import_prefix = "google/cloud/firestore_v1beta1/proto", strip_import_prefix = "google/firestore/v1beta1", ) ``` The rule above will first generate virtual `.proto` files (under new location) and only after that generate a binary descriptor from them. Specifically it will generate the following "virtual" file under `_virtual_imports` subdirectory of same package: ``` bazel-bin/google/firestore/v1beta1/_virtual_imports/firestore_moved_proto/google/cloud/firestore_v1beta1/proto/common.proto ``` When supplied to `cc_proto_library`, like the following: ```bzl cc_proto_library( name = "firestore_moved_cc_proto", deps = ["firestore_moved_proto"], ) ``` The rule will generate .cc and .h files like the following: ``` bazel-bin/google/firestore/v1beta1/_virtual_imports/firestore_moved_proto/google/cloud/firestore_v1beta1/proto/firestore.pb.h bazel-bin/google/firestore/v1beta1/_virtual_imports/firestore_moved_proto/google/cloud/firestore_v1beta1/proto/firestore.pb.cc ``` Notice, that each generated `.cc` and `.h` file is prefixed with `_virtual_imports/<name_of_proto_library_target>`. The python rules try to do same thing, so for the following py_proto_library rule: ```bzl py_proto_library( name = "firestore_moved_py_proto", deps = [":firestore_moved_proto"], ) ``` It wil generate the following file: ``` bazel-bin/google/firestore/v1beta1/_virtual_imports/firestore_moved_proto/google/cloud/firestore_v1beta1/proto/firestore_pb2.py ``` I.e in same path as cc_proto_library. This all woks, but an annoying part is that to use the generated library in some other py_library, in needs to specify the "_virtual_imports/proto_target" path as its "includes" parameter (and I can't make it better than that). Another option would be to skeep the `_virtual_imports/<name_of_proto_library_target>` the suffix for the generated python stubs, which will make the path look like the following: ``` bazel-bin/google/firestore/v1beta1/google/cloud/firestore_v1beta1/proto/firestore_pb2.py ``` That will make using generated stubs simpler and cleaner (no need to specify imports argument), but it will make it inconsistent with the other rules (like cc_proto_library) and also more susseptible to naming conflicts (if there is already something under the generated path).
5 years ago
def get_include_directory(source_file):
"""Returns the include directory path for the source_file. I.e. all of the
include statements within the given source_file are calculated relative to
the directory returned by this method.
The returned directory path can be used as the "--proto_path=" argument
value.
Args:
source_file: A proto file.
Returns:
The include directory path for the source_file.
"""
directory = source_file.path
prefix_len = 0
[bazel][python] Support _virtual_imports input for py_proto_library and py_grpc_library rules `proto_library` targets are used as deps for `py_proto_library` and `py_grpc_library` rules. The `proto_library` targets can be configured using `import_prefix` and/or `strip_import_prefix` (which essentially move original location of the proto file and, as result, affects import path within proto files themselves and in the generated language-specific stubs). The biggest question to answer when generating stubs from moved protos is where to put result (this decision affects all downstream rules as well, because the location of file affects its import path). This PR tries to follow same logic as the native `cc_proto_library` (created and maintained by Bazel team). For example, if we have `firestore.proto` file, which is located under `google/firestore/v1beta1` Bazel package and want to move it under `google/cloud/firestore_v1beta1/proto` (this is axactly what happens in googleapis repository), it can be configured the following way: ```bzl proto_library( name = "firestore_moved_proto", srcs = ["firestore.proto"], import_prefix = "google/cloud/firestore_v1beta1/proto", strip_import_prefix = "google/firestore/v1beta1", ) ``` The rule above will first generate virtual `.proto` files (under new location) and only after that generate a binary descriptor from them. Specifically it will generate the following "virtual" file under `_virtual_imports` subdirectory of same package: ``` bazel-bin/google/firestore/v1beta1/_virtual_imports/firestore_moved_proto/google/cloud/firestore_v1beta1/proto/common.proto ``` When supplied to `cc_proto_library`, like the following: ```bzl cc_proto_library( name = "firestore_moved_cc_proto", deps = ["firestore_moved_proto"], ) ``` The rule will generate .cc and .h files like the following: ``` bazel-bin/google/firestore/v1beta1/_virtual_imports/firestore_moved_proto/google/cloud/firestore_v1beta1/proto/firestore.pb.h bazel-bin/google/firestore/v1beta1/_virtual_imports/firestore_moved_proto/google/cloud/firestore_v1beta1/proto/firestore.pb.cc ``` Notice, that each generated `.cc` and `.h` file is prefixed with `_virtual_imports/<name_of_proto_library_target>`. The python rules try to do same thing, so for the following py_proto_library rule: ```bzl py_proto_library( name = "firestore_moved_py_proto", deps = [":firestore_moved_proto"], ) ``` It wil generate the following file: ``` bazel-bin/google/firestore/v1beta1/_virtual_imports/firestore_moved_proto/google/cloud/firestore_v1beta1/proto/firestore_pb2.py ``` I.e in same path as cc_proto_library. This all woks, but an annoying part is that to use the generated library in some other py_library, in needs to specify the "_virtual_imports/proto_target" path as its "includes" parameter (and I can't make it better than that). Another option would be to skeep the `_virtual_imports/<name_of_proto_library_target>` the suffix for the generated python stubs, which will make the path look like the following: ``` bazel-bin/google/firestore/v1beta1/google/cloud/firestore_v1beta1/proto/firestore_pb2.py ``` That will make using generated stubs simpler and cleaner (no need to specify imports argument), but it will make it inconsistent with the other rules (like cc_proto_library) and also more susseptible to naming conflicts (if there is already something under the generated path).
5 years ago
if is_in_virtual_imports(source_file):
root, relative = source_file.path.split(_VIRTUAL_IMPORTS, 2)
result = root + _VIRTUAL_IMPORTS + relative.split("/", 1)[0]
return result
[bazel][python] Support _virtual_imports input for py_proto_library and py_grpc_library rules `proto_library` targets are used as deps for `py_proto_library` and `py_grpc_library` rules. The `proto_library` targets can be configured using `import_prefix` and/or `strip_import_prefix` (which essentially move original location of the proto file and, as result, affects import path within proto files themselves and in the generated language-specific stubs). The biggest question to answer when generating stubs from moved protos is where to put result (this decision affects all downstream rules as well, because the location of file affects its import path). This PR tries to follow same logic as the native `cc_proto_library` (created and maintained by Bazel team). For example, if we have `firestore.proto` file, which is located under `google/firestore/v1beta1` Bazel package and want to move it under `google/cloud/firestore_v1beta1/proto` (this is axactly what happens in googleapis repository), it can be configured the following way: ```bzl proto_library( name = "firestore_moved_proto", srcs = ["firestore.proto"], import_prefix = "google/cloud/firestore_v1beta1/proto", strip_import_prefix = "google/firestore/v1beta1", ) ``` The rule above will first generate virtual `.proto` files (under new location) and only after that generate a binary descriptor from them. Specifically it will generate the following "virtual" file under `_virtual_imports` subdirectory of same package: ``` bazel-bin/google/firestore/v1beta1/_virtual_imports/firestore_moved_proto/google/cloud/firestore_v1beta1/proto/common.proto ``` When supplied to `cc_proto_library`, like the following: ```bzl cc_proto_library( name = "firestore_moved_cc_proto", deps = ["firestore_moved_proto"], ) ``` The rule will generate .cc and .h files like the following: ``` bazel-bin/google/firestore/v1beta1/_virtual_imports/firestore_moved_proto/google/cloud/firestore_v1beta1/proto/firestore.pb.h bazel-bin/google/firestore/v1beta1/_virtual_imports/firestore_moved_proto/google/cloud/firestore_v1beta1/proto/firestore.pb.cc ``` Notice, that each generated `.cc` and `.h` file is prefixed with `_virtual_imports/<name_of_proto_library_target>`. The python rules try to do same thing, so for the following py_proto_library rule: ```bzl py_proto_library( name = "firestore_moved_py_proto", deps = [":firestore_moved_proto"], ) ``` It wil generate the following file: ``` bazel-bin/google/firestore/v1beta1/_virtual_imports/firestore_moved_proto/google/cloud/firestore_v1beta1/proto/firestore_pb2.py ``` I.e in same path as cc_proto_library. This all woks, but an annoying part is that to use the generated library in some other py_library, in needs to specify the "_virtual_imports/proto_target" path as its "includes" parameter (and I can't make it better than that). Another option would be to skeep the `_virtual_imports/<name_of_proto_library_target>` the suffix for the generated python stubs, which will make the path look like the following: ``` bazel-bin/google/firestore/v1beta1/google/cloud/firestore_v1beta1/proto/firestore_pb2.py ``` That will make using generated stubs simpler and cleaner (no need to specify imports argument), but it will make it inconsistent with the other rules (like cc_proto_library) and also more susseptible to naming conflicts (if there is already something under the generated path).
5 years ago
if not source_file.is_source and directory.startswith(source_file.root.path):
prefix_len = len(source_file.root.path) + 1
if directory.startswith("external", prefix_len):
external_separator = directory.find("/", prefix_len)
repository_separator = directory.find("/", external_separator + 1)
return directory[:repository_separator]
else:
[bazel][python] Support _virtual_imports input for py_proto_library and py_grpc_library rules `proto_library` targets are used as deps for `py_proto_library` and `py_grpc_library` rules. The `proto_library` targets can be configured using `import_prefix` and/or `strip_import_prefix` (which essentially move original location of the proto file and, as result, affects import path within proto files themselves and in the generated language-specific stubs). The biggest question to answer when generating stubs from moved protos is where to put result (this decision affects all downstream rules as well, because the location of file affects its import path). This PR tries to follow same logic as the native `cc_proto_library` (created and maintained by Bazel team). For example, if we have `firestore.proto` file, which is located under `google/firestore/v1beta1` Bazel package and want to move it under `google/cloud/firestore_v1beta1/proto` (this is axactly what happens in googleapis repository), it can be configured the following way: ```bzl proto_library( name = "firestore_moved_proto", srcs = ["firestore.proto"], import_prefix = "google/cloud/firestore_v1beta1/proto", strip_import_prefix = "google/firestore/v1beta1", ) ``` The rule above will first generate virtual `.proto` files (under new location) and only after that generate a binary descriptor from them. Specifically it will generate the following "virtual" file under `_virtual_imports` subdirectory of same package: ``` bazel-bin/google/firestore/v1beta1/_virtual_imports/firestore_moved_proto/google/cloud/firestore_v1beta1/proto/common.proto ``` When supplied to `cc_proto_library`, like the following: ```bzl cc_proto_library( name = "firestore_moved_cc_proto", deps = ["firestore_moved_proto"], ) ``` The rule will generate .cc and .h files like the following: ``` bazel-bin/google/firestore/v1beta1/_virtual_imports/firestore_moved_proto/google/cloud/firestore_v1beta1/proto/firestore.pb.h bazel-bin/google/firestore/v1beta1/_virtual_imports/firestore_moved_proto/google/cloud/firestore_v1beta1/proto/firestore.pb.cc ``` Notice, that each generated `.cc` and `.h` file is prefixed with `_virtual_imports/<name_of_proto_library_target>`. The python rules try to do same thing, so for the following py_proto_library rule: ```bzl py_proto_library( name = "firestore_moved_py_proto", deps = [":firestore_moved_proto"], ) ``` It wil generate the following file: ``` bazel-bin/google/firestore/v1beta1/_virtual_imports/firestore_moved_proto/google/cloud/firestore_v1beta1/proto/firestore_pb2.py ``` I.e in same path as cc_proto_library. This all woks, but an annoying part is that to use the generated library in some other py_library, in needs to specify the "_virtual_imports/proto_target" path as its "includes" parameter (and I can't make it better than that). Another option would be to skeep the `_virtual_imports/<name_of_proto_library_target>` the suffix for the generated python stubs, which will make the path look like the following: ``` bazel-bin/google/firestore/v1beta1/google/cloud/firestore_v1beta1/proto/firestore_pb2.py ``` That will make using generated stubs simpler and cleaner (no need to specify imports argument), but it will make it inconsistent with the other rules (like cc_proto_library) and also more susseptible to naming conflicts (if there is already something under the generated path).
5 years ago
return source_file.root.path if source_file.root.path else "."
def get_plugin_args(plugin, flags, dir_out, generate_mocks):
"""Returns arguments configuring protoc to use a plugin for a language.
Args:
plugin: An executable file to run as the protoc plugin.
flags: The plugin flags to be passed to protoc.
dir_out: The output directory for the plugin.
generate_mocks: A bool indicating whether to generate mocks.
Returns:
A list of protoc arguments configuring the plugin.
"""
augmented_flags = list(flags)
if generate_mocks:
augmented_flags.append("generate_mock_code=true")
return [
"--plugin=protoc-gen-PLUGIN=" + plugin.path,
"--PLUGIN_out=" + ",".join(augmented_flags) + ":" + dir_out,
]
5 years ago
def _get_staged_proto_file(context, source_file):
[bazel][python] Support _virtual_imports input for py_proto_library and py_grpc_library rules `proto_library` targets are used as deps for `py_proto_library` and `py_grpc_library` rules. The `proto_library` targets can be configured using `import_prefix` and/or `strip_import_prefix` (which essentially move original location of the proto file and, as result, affects import path within proto files themselves and in the generated language-specific stubs). The biggest question to answer when generating stubs from moved protos is where to put result (this decision affects all downstream rules as well, because the location of file affects its import path). This PR tries to follow same logic as the native `cc_proto_library` (created and maintained by Bazel team). For example, if we have `firestore.proto` file, which is located under `google/firestore/v1beta1` Bazel package and want to move it under `google/cloud/firestore_v1beta1/proto` (this is axactly what happens in googleapis repository), it can be configured the following way: ```bzl proto_library( name = "firestore_moved_proto", srcs = ["firestore.proto"], import_prefix = "google/cloud/firestore_v1beta1/proto", strip_import_prefix = "google/firestore/v1beta1", ) ``` The rule above will first generate virtual `.proto` files (under new location) and only after that generate a binary descriptor from them. Specifically it will generate the following "virtual" file under `_virtual_imports` subdirectory of same package: ``` bazel-bin/google/firestore/v1beta1/_virtual_imports/firestore_moved_proto/google/cloud/firestore_v1beta1/proto/common.proto ``` When supplied to `cc_proto_library`, like the following: ```bzl cc_proto_library( name = "firestore_moved_cc_proto", deps = ["firestore_moved_proto"], ) ``` The rule will generate .cc and .h files like the following: ``` bazel-bin/google/firestore/v1beta1/_virtual_imports/firestore_moved_proto/google/cloud/firestore_v1beta1/proto/firestore.pb.h bazel-bin/google/firestore/v1beta1/_virtual_imports/firestore_moved_proto/google/cloud/firestore_v1beta1/proto/firestore.pb.cc ``` Notice, that each generated `.cc` and `.h` file is prefixed with `_virtual_imports/<name_of_proto_library_target>`. The python rules try to do same thing, so for the following py_proto_library rule: ```bzl py_proto_library( name = "firestore_moved_py_proto", deps = [":firestore_moved_proto"], ) ``` It wil generate the following file: ``` bazel-bin/google/firestore/v1beta1/_virtual_imports/firestore_moved_proto/google/cloud/firestore_v1beta1/proto/firestore_pb2.py ``` I.e in same path as cc_proto_library. This all woks, but an annoying part is that to use the generated library in some other py_library, in needs to specify the "_virtual_imports/proto_target" path as its "includes" parameter (and I can't make it better than that). Another option would be to skeep the `_virtual_imports/<name_of_proto_library_target>` the suffix for the generated python stubs, which will make the path look like the following: ``` bazel-bin/google/firestore/v1beta1/google/cloud/firestore_v1beta1/proto/firestore_pb2.py ``` That will make using generated stubs simpler and cleaner (no need to specify imports argument), but it will make it inconsistent with the other rules (like cc_proto_library) and also more susseptible to naming conflicts (if there is already something under the generated path).
5 years ago
if source_file.dirname == context.label.package \
or is_in_virtual_imports(source_file):
# Current target and source_file are in same package
5 years ago
return source_file
else:
[bazel][python] Support _virtual_imports input for py_proto_library and py_grpc_library rules `proto_library` targets are used as deps for `py_proto_library` and `py_grpc_library` rules. The `proto_library` targets can be configured using `import_prefix` and/or `strip_import_prefix` (which essentially move original location of the proto file and, as result, affects import path within proto files themselves and in the generated language-specific stubs). The biggest question to answer when generating stubs from moved protos is where to put result (this decision affects all downstream rules as well, because the location of file affects its import path). This PR tries to follow same logic as the native `cc_proto_library` (created and maintained by Bazel team). For example, if we have `firestore.proto` file, which is located under `google/firestore/v1beta1` Bazel package and want to move it under `google/cloud/firestore_v1beta1/proto` (this is axactly what happens in googleapis repository), it can be configured the following way: ```bzl proto_library( name = "firestore_moved_proto", srcs = ["firestore.proto"], import_prefix = "google/cloud/firestore_v1beta1/proto", strip_import_prefix = "google/firestore/v1beta1", ) ``` The rule above will first generate virtual `.proto` files (under new location) and only after that generate a binary descriptor from them. Specifically it will generate the following "virtual" file under `_virtual_imports` subdirectory of same package: ``` bazel-bin/google/firestore/v1beta1/_virtual_imports/firestore_moved_proto/google/cloud/firestore_v1beta1/proto/common.proto ``` When supplied to `cc_proto_library`, like the following: ```bzl cc_proto_library( name = "firestore_moved_cc_proto", deps = ["firestore_moved_proto"], ) ``` The rule will generate .cc and .h files like the following: ``` bazel-bin/google/firestore/v1beta1/_virtual_imports/firestore_moved_proto/google/cloud/firestore_v1beta1/proto/firestore.pb.h bazel-bin/google/firestore/v1beta1/_virtual_imports/firestore_moved_proto/google/cloud/firestore_v1beta1/proto/firestore.pb.cc ``` Notice, that each generated `.cc` and `.h` file is prefixed with `_virtual_imports/<name_of_proto_library_target>`. The python rules try to do same thing, so for the following py_proto_library rule: ```bzl py_proto_library( name = "firestore_moved_py_proto", deps = [":firestore_moved_proto"], ) ``` It wil generate the following file: ``` bazel-bin/google/firestore/v1beta1/_virtual_imports/firestore_moved_proto/google/cloud/firestore_v1beta1/proto/firestore_pb2.py ``` I.e in same path as cc_proto_library. This all woks, but an annoying part is that to use the generated library in some other py_library, in needs to specify the "_virtual_imports/proto_target" path as its "includes" parameter (and I can't make it better than that). Another option would be to skeep the `_virtual_imports/<name_of_proto_library_target>` the suffix for the generated python stubs, which will make the path look like the following: ``` bazel-bin/google/firestore/v1beta1/google/cloud/firestore_v1beta1/proto/firestore_pb2.py ``` That will make using generated stubs simpler and cleaner (no need to specify imports argument), but it will make it inconsistent with the other rules (like cc_proto_library) and also more susseptible to naming conflicts (if there is already something under the generated path).
5 years ago
# Current target and source_file are in different packages (most
# probably even in different repositories)
5 years ago
copied_proto = context.actions.declare_file(source_file.basename)
context.actions.run_shell(
inputs = [source_file],
outputs = [copied_proto],
command = "cp {} {}".format(source_file.path, copied_proto.path),
mnemonic = "CopySourceProto",
)
return copied_proto
def protos_from_context(context):
"""Copies proto files to the appropriate location.
Args:
context: The ctx object for the rule.
Returns:
A list of the protos.
"""
protos = []
for src in context.attr.deps:
for file in src[ProtoInfo].direct_sources:
protos.append(_get_staged_proto_file(context, file))
return protos
def includes_from_deps(deps):
"""Get includes from rule dependencies."""
return [
file
for src in deps
for file in src[ProtoInfo].transitive_imports.to_list()
]
def get_proto_arguments(protos, genfiles_dir_path):
"""Get the protoc arguments specifying which protos to compile."""
arguments = []
for proto in protos:
massaged_path = proto.path
[bazel][python] Support _virtual_imports input for py_proto_library and py_grpc_library rules `proto_library` targets are used as deps for `py_proto_library` and `py_grpc_library` rules. The `proto_library` targets can be configured using `import_prefix` and/or `strip_import_prefix` (which essentially move original location of the proto file and, as result, affects import path within proto files themselves and in the generated language-specific stubs). The biggest question to answer when generating stubs from moved protos is where to put result (this decision affects all downstream rules as well, because the location of file affects its import path). This PR tries to follow same logic as the native `cc_proto_library` (created and maintained by Bazel team). For example, if we have `firestore.proto` file, which is located under `google/firestore/v1beta1` Bazel package and want to move it under `google/cloud/firestore_v1beta1/proto` (this is axactly what happens in googleapis repository), it can be configured the following way: ```bzl proto_library( name = "firestore_moved_proto", srcs = ["firestore.proto"], import_prefix = "google/cloud/firestore_v1beta1/proto", strip_import_prefix = "google/firestore/v1beta1", ) ``` The rule above will first generate virtual `.proto` files (under new location) and only after that generate a binary descriptor from them. Specifically it will generate the following "virtual" file under `_virtual_imports` subdirectory of same package: ``` bazel-bin/google/firestore/v1beta1/_virtual_imports/firestore_moved_proto/google/cloud/firestore_v1beta1/proto/common.proto ``` When supplied to `cc_proto_library`, like the following: ```bzl cc_proto_library( name = "firestore_moved_cc_proto", deps = ["firestore_moved_proto"], ) ``` The rule will generate .cc and .h files like the following: ``` bazel-bin/google/firestore/v1beta1/_virtual_imports/firestore_moved_proto/google/cloud/firestore_v1beta1/proto/firestore.pb.h bazel-bin/google/firestore/v1beta1/_virtual_imports/firestore_moved_proto/google/cloud/firestore_v1beta1/proto/firestore.pb.cc ``` Notice, that each generated `.cc` and `.h` file is prefixed with `_virtual_imports/<name_of_proto_library_target>`. The python rules try to do same thing, so for the following py_proto_library rule: ```bzl py_proto_library( name = "firestore_moved_py_proto", deps = [":firestore_moved_proto"], ) ``` It wil generate the following file: ``` bazel-bin/google/firestore/v1beta1/_virtual_imports/firestore_moved_proto/google/cloud/firestore_v1beta1/proto/firestore_pb2.py ``` I.e in same path as cc_proto_library. This all woks, but an annoying part is that to use the generated library in some other py_library, in needs to specify the "_virtual_imports/proto_target" path as its "includes" parameter (and I can't make it better than that). Another option would be to skeep the `_virtual_imports/<name_of_proto_library_target>` the suffix for the generated python stubs, which will make the path look like the following: ``` bazel-bin/google/firestore/v1beta1/google/cloud/firestore_v1beta1/proto/firestore_pb2.py ``` That will make using generated stubs simpler and cleaner (no need to specify imports argument), but it will make it inconsistent with the other rules (like cc_proto_library) and also more susseptible to naming conflicts (if there is already something under the generated path).
5 years ago
if is_in_virtual_imports(proto):
incl_directory = get_include_directory(proto)
if massaged_path.startswith(incl_directory):
massaged_path = massaged_path[len(incl_directory) + 1:]
elif massaged_path.startswith(genfiles_dir_path):
5 years ago
massaged_path = proto.path[len(genfiles_dir_path) + 1:]
arguments.append(massaged_path)
[bazel][python] Support _virtual_imports input for py_proto_library and py_grpc_library rules `proto_library` targets are used as deps for `py_proto_library` and `py_grpc_library` rules. The `proto_library` targets can be configured using `import_prefix` and/or `strip_import_prefix` (which essentially move original location of the proto file and, as result, affects import path within proto files themselves and in the generated language-specific stubs). The biggest question to answer when generating stubs from moved protos is where to put result (this decision affects all downstream rules as well, because the location of file affects its import path). This PR tries to follow same logic as the native `cc_proto_library` (created and maintained by Bazel team). For example, if we have `firestore.proto` file, which is located under `google/firestore/v1beta1` Bazel package and want to move it under `google/cloud/firestore_v1beta1/proto` (this is axactly what happens in googleapis repository), it can be configured the following way: ```bzl proto_library( name = "firestore_moved_proto", srcs = ["firestore.proto"], import_prefix = "google/cloud/firestore_v1beta1/proto", strip_import_prefix = "google/firestore/v1beta1", ) ``` The rule above will first generate virtual `.proto` files (under new location) and only after that generate a binary descriptor from them. Specifically it will generate the following "virtual" file under `_virtual_imports` subdirectory of same package: ``` bazel-bin/google/firestore/v1beta1/_virtual_imports/firestore_moved_proto/google/cloud/firestore_v1beta1/proto/common.proto ``` When supplied to `cc_proto_library`, like the following: ```bzl cc_proto_library( name = "firestore_moved_cc_proto", deps = ["firestore_moved_proto"], ) ``` The rule will generate .cc and .h files like the following: ``` bazel-bin/google/firestore/v1beta1/_virtual_imports/firestore_moved_proto/google/cloud/firestore_v1beta1/proto/firestore.pb.h bazel-bin/google/firestore/v1beta1/_virtual_imports/firestore_moved_proto/google/cloud/firestore_v1beta1/proto/firestore.pb.cc ``` Notice, that each generated `.cc` and `.h` file is prefixed with `_virtual_imports/<name_of_proto_library_target>`. The python rules try to do same thing, so for the following py_proto_library rule: ```bzl py_proto_library( name = "firestore_moved_py_proto", deps = [":firestore_moved_proto"], ) ``` It wil generate the following file: ``` bazel-bin/google/firestore/v1beta1/_virtual_imports/firestore_moved_proto/google/cloud/firestore_v1beta1/proto/firestore_pb2.py ``` I.e in same path as cc_proto_library. This all woks, but an annoying part is that to use the generated library in some other py_library, in needs to specify the "_virtual_imports/proto_target" path as its "includes" parameter (and I can't make it better than that). Another option would be to skeep the `_virtual_imports/<name_of_proto_library_target>` the suffix for the generated python stubs, which will make the path look like the following: ``` bazel-bin/google/firestore/v1beta1/google/cloud/firestore_v1beta1/proto/firestore_pb2.py ``` That will make using generated stubs simpler and cleaner (no need to specify imports argument), but it will make it inconsistent with the other rules (like cc_proto_library) and also more susseptible to naming conflicts (if there is already something under the generated path).
5 years ago
5 years ago
return arguments
def declare_out_files(protos, context, generated_file_format):
"""Declares and returns the files to be generated."""
[bazel][python] Support _virtual_imports input for py_proto_library and py_grpc_library rules `proto_library` targets are used as deps for `py_proto_library` and `py_grpc_library` rules. The `proto_library` targets can be configured using `import_prefix` and/or `strip_import_prefix` (which essentially move original location of the proto file and, as result, affects import path within proto files themselves and in the generated language-specific stubs). The biggest question to answer when generating stubs from moved protos is where to put result (this decision affects all downstream rules as well, because the location of file affects its import path). This PR tries to follow same logic as the native `cc_proto_library` (created and maintained by Bazel team). For example, if we have `firestore.proto` file, which is located under `google/firestore/v1beta1` Bazel package and want to move it under `google/cloud/firestore_v1beta1/proto` (this is axactly what happens in googleapis repository), it can be configured the following way: ```bzl proto_library( name = "firestore_moved_proto", srcs = ["firestore.proto"], import_prefix = "google/cloud/firestore_v1beta1/proto", strip_import_prefix = "google/firestore/v1beta1", ) ``` The rule above will first generate virtual `.proto` files (under new location) and only after that generate a binary descriptor from them. Specifically it will generate the following "virtual" file under `_virtual_imports` subdirectory of same package: ``` bazel-bin/google/firestore/v1beta1/_virtual_imports/firestore_moved_proto/google/cloud/firestore_v1beta1/proto/common.proto ``` When supplied to `cc_proto_library`, like the following: ```bzl cc_proto_library( name = "firestore_moved_cc_proto", deps = ["firestore_moved_proto"], ) ``` The rule will generate .cc and .h files like the following: ``` bazel-bin/google/firestore/v1beta1/_virtual_imports/firestore_moved_proto/google/cloud/firestore_v1beta1/proto/firestore.pb.h bazel-bin/google/firestore/v1beta1/_virtual_imports/firestore_moved_proto/google/cloud/firestore_v1beta1/proto/firestore.pb.cc ``` Notice, that each generated `.cc` and `.h` file is prefixed with `_virtual_imports/<name_of_proto_library_target>`. The python rules try to do same thing, so for the following py_proto_library rule: ```bzl py_proto_library( name = "firestore_moved_py_proto", deps = [":firestore_moved_proto"], ) ``` It wil generate the following file: ``` bazel-bin/google/firestore/v1beta1/_virtual_imports/firestore_moved_proto/google/cloud/firestore_v1beta1/proto/firestore_pb2.py ``` I.e in same path as cc_proto_library. This all woks, but an annoying part is that to use the generated library in some other py_library, in needs to specify the "_virtual_imports/proto_target" path as its "includes" parameter (and I can't make it better than that). Another option would be to skeep the `_virtual_imports/<name_of_proto_library_target>` the suffix for the generated python stubs, which will make the path look like the following: ``` bazel-bin/google/firestore/v1beta1/google/cloud/firestore_v1beta1/proto/firestore_pb2.py ``` That will make using generated stubs simpler and cleaner (no need to specify imports argument), but it will make it inconsistent with the other rules (like cc_proto_library) and also more susseptible to naming conflicts (if there is already something under the generated path).
5 years ago
out_file_paths = []
for proto in protos:
if not is_in_virtual_imports(proto):
out_file_paths.append(proto.basename)
else:
path = proto.path[proto.path.index(_VIRTUAL_IMPORTS) + 1:]
# TODO: uncomment if '.' path is chosen over
# `_virtual_imports/proto_library_target_name` as the output
# path = proto.path.split(_VIRTUAL_IMPORTS)[1].split("/", 1)[1]
out_file_paths.append(path)
5 years ago
return [
context.actions.declare_file(
proto_path_to_generated_filename(
[bazel][python] Support _virtual_imports input for py_proto_library and py_grpc_library rules `proto_library` targets are used as deps for `py_proto_library` and `py_grpc_library` rules. The `proto_library` targets can be configured using `import_prefix` and/or `strip_import_prefix` (which essentially move original location of the proto file and, as result, affects import path within proto files themselves and in the generated language-specific stubs). The biggest question to answer when generating stubs from moved protos is where to put result (this decision affects all downstream rules as well, because the location of file affects its import path). This PR tries to follow same logic as the native `cc_proto_library` (created and maintained by Bazel team). For example, if we have `firestore.proto` file, which is located under `google/firestore/v1beta1` Bazel package and want to move it under `google/cloud/firestore_v1beta1/proto` (this is axactly what happens in googleapis repository), it can be configured the following way: ```bzl proto_library( name = "firestore_moved_proto", srcs = ["firestore.proto"], import_prefix = "google/cloud/firestore_v1beta1/proto", strip_import_prefix = "google/firestore/v1beta1", ) ``` The rule above will first generate virtual `.proto` files (under new location) and only after that generate a binary descriptor from them. Specifically it will generate the following "virtual" file under `_virtual_imports` subdirectory of same package: ``` bazel-bin/google/firestore/v1beta1/_virtual_imports/firestore_moved_proto/google/cloud/firestore_v1beta1/proto/common.proto ``` When supplied to `cc_proto_library`, like the following: ```bzl cc_proto_library( name = "firestore_moved_cc_proto", deps = ["firestore_moved_proto"], ) ``` The rule will generate .cc and .h files like the following: ``` bazel-bin/google/firestore/v1beta1/_virtual_imports/firestore_moved_proto/google/cloud/firestore_v1beta1/proto/firestore.pb.h bazel-bin/google/firestore/v1beta1/_virtual_imports/firestore_moved_proto/google/cloud/firestore_v1beta1/proto/firestore.pb.cc ``` Notice, that each generated `.cc` and `.h` file is prefixed with `_virtual_imports/<name_of_proto_library_target>`. The python rules try to do same thing, so for the following py_proto_library rule: ```bzl py_proto_library( name = "firestore_moved_py_proto", deps = [":firestore_moved_proto"], ) ``` It wil generate the following file: ``` bazel-bin/google/firestore/v1beta1/_virtual_imports/firestore_moved_proto/google/cloud/firestore_v1beta1/proto/firestore_pb2.py ``` I.e in same path as cc_proto_library. This all woks, but an annoying part is that to use the generated library in some other py_library, in needs to specify the "_virtual_imports/proto_target" path as its "includes" parameter (and I can't make it better than that). Another option would be to skeep the `_virtual_imports/<name_of_proto_library_target>` the suffix for the generated python stubs, which will make the path look like the following: ``` bazel-bin/google/firestore/v1beta1/google/cloud/firestore_v1beta1/proto/firestore_pb2.py ``` That will make using generated stubs simpler and cleaner (no need to specify imports argument), but it will make it inconsistent with the other rules (like cc_proto_library) and also more susseptible to naming conflicts (if there is already something under the generated path).
5 years ago
out_file_path,
5 years ago
generated_file_format,
),
)
[bazel][python] Support _virtual_imports input for py_proto_library and py_grpc_library rules `proto_library` targets are used as deps for `py_proto_library` and `py_grpc_library` rules. The `proto_library` targets can be configured using `import_prefix` and/or `strip_import_prefix` (which essentially move original location of the proto file and, as result, affects import path within proto files themselves and in the generated language-specific stubs). The biggest question to answer when generating stubs from moved protos is where to put result (this decision affects all downstream rules as well, because the location of file affects its import path). This PR tries to follow same logic as the native `cc_proto_library` (created and maintained by Bazel team). For example, if we have `firestore.proto` file, which is located under `google/firestore/v1beta1` Bazel package and want to move it under `google/cloud/firestore_v1beta1/proto` (this is axactly what happens in googleapis repository), it can be configured the following way: ```bzl proto_library( name = "firestore_moved_proto", srcs = ["firestore.proto"], import_prefix = "google/cloud/firestore_v1beta1/proto", strip_import_prefix = "google/firestore/v1beta1", ) ``` The rule above will first generate virtual `.proto` files (under new location) and only after that generate a binary descriptor from them. Specifically it will generate the following "virtual" file under `_virtual_imports` subdirectory of same package: ``` bazel-bin/google/firestore/v1beta1/_virtual_imports/firestore_moved_proto/google/cloud/firestore_v1beta1/proto/common.proto ``` When supplied to `cc_proto_library`, like the following: ```bzl cc_proto_library( name = "firestore_moved_cc_proto", deps = ["firestore_moved_proto"], ) ``` The rule will generate .cc and .h files like the following: ``` bazel-bin/google/firestore/v1beta1/_virtual_imports/firestore_moved_proto/google/cloud/firestore_v1beta1/proto/firestore.pb.h bazel-bin/google/firestore/v1beta1/_virtual_imports/firestore_moved_proto/google/cloud/firestore_v1beta1/proto/firestore.pb.cc ``` Notice, that each generated `.cc` and `.h` file is prefixed with `_virtual_imports/<name_of_proto_library_target>`. The python rules try to do same thing, so for the following py_proto_library rule: ```bzl py_proto_library( name = "firestore_moved_py_proto", deps = [":firestore_moved_proto"], ) ``` It wil generate the following file: ``` bazel-bin/google/firestore/v1beta1/_virtual_imports/firestore_moved_proto/google/cloud/firestore_v1beta1/proto/firestore_pb2.py ``` I.e in same path as cc_proto_library. This all woks, but an annoying part is that to use the generated library in some other py_library, in needs to specify the "_virtual_imports/proto_target" path as its "includes" parameter (and I can't make it better than that). Another option would be to skeep the `_virtual_imports/<name_of_proto_library_target>` the suffix for the generated python stubs, which will make the path look like the following: ``` bazel-bin/google/firestore/v1beta1/google/cloud/firestore_v1beta1/proto/firestore_pb2.py ``` That will make using generated stubs simpler and cleaner (no need to specify imports argument), but it will make it inconsistent with the other rules (like cc_proto_library) and also more susseptible to naming conflicts (if there is already something under the generated path).
5 years ago
for out_file_path in out_file_paths
5 years ago
]
[bazel][python] Support _virtual_imports input for py_proto_library and py_grpc_library rules `proto_library` targets are used as deps for `py_proto_library` and `py_grpc_library` rules. The `proto_library` targets can be configured using `import_prefix` and/or `strip_import_prefix` (which essentially move original location of the proto file and, as result, affects import path within proto files themselves and in the generated language-specific stubs). The biggest question to answer when generating stubs from moved protos is where to put result (this decision affects all downstream rules as well, because the location of file affects its import path). This PR tries to follow same logic as the native `cc_proto_library` (created and maintained by Bazel team). For example, if we have `firestore.proto` file, which is located under `google/firestore/v1beta1` Bazel package and want to move it under `google/cloud/firestore_v1beta1/proto` (this is axactly what happens in googleapis repository), it can be configured the following way: ```bzl proto_library( name = "firestore_moved_proto", srcs = ["firestore.proto"], import_prefix = "google/cloud/firestore_v1beta1/proto", strip_import_prefix = "google/firestore/v1beta1", ) ``` The rule above will first generate virtual `.proto` files (under new location) and only after that generate a binary descriptor from them. Specifically it will generate the following "virtual" file under `_virtual_imports` subdirectory of same package: ``` bazel-bin/google/firestore/v1beta1/_virtual_imports/firestore_moved_proto/google/cloud/firestore_v1beta1/proto/common.proto ``` When supplied to `cc_proto_library`, like the following: ```bzl cc_proto_library( name = "firestore_moved_cc_proto", deps = ["firestore_moved_proto"], ) ``` The rule will generate .cc and .h files like the following: ``` bazel-bin/google/firestore/v1beta1/_virtual_imports/firestore_moved_proto/google/cloud/firestore_v1beta1/proto/firestore.pb.h bazel-bin/google/firestore/v1beta1/_virtual_imports/firestore_moved_proto/google/cloud/firestore_v1beta1/proto/firestore.pb.cc ``` Notice, that each generated `.cc` and `.h` file is prefixed with `_virtual_imports/<name_of_proto_library_target>`. The python rules try to do same thing, so for the following py_proto_library rule: ```bzl py_proto_library( name = "firestore_moved_py_proto", deps = [":firestore_moved_proto"], ) ``` It wil generate the following file: ``` bazel-bin/google/firestore/v1beta1/_virtual_imports/firestore_moved_proto/google/cloud/firestore_v1beta1/proto/firestore_pb2.py ``` I.e in same path as cc_proto_library. This all woks, but an annoying part is that to use the generated library in some other py_library, in needs to specify the "_virtual_imports/proto_target" path as its "includes" parameter (and I can't make it better than that). Another option would be to skeep the `_virtual_imports/<name_of_proto_library_target>` the suffix for the generated python stubs, which will make the path look like the following: ``` bazel-bin/google/firestore/v1beta1/google/cloud/firestore_v1beta1/proto/firestore_pb2.py ``` That will make using generated stubs simpler and cleaner (no need to specify imports argument), but it will make it inconsistent with the other rules (like cc_proto_library) and also more susseptible to naming conflicts (if there is already something under the generated path).
5 years ago
def get_out_dir(protos, context):
""" Returns the calcualted value for --<lang>_out= protoc argument based on
the input source proto files and current context.
Args:
protos: A list of protos to be used as source files in protoc command
context: A ctx object for the rule.
Returns:
The value of --<lang>_out= argument.
"""
at_least_one_virtual = 0
for proto in protos:
if is_in_virtual_imports(proto):
at_least_one_virtual = True
elif at_least_one_virtual:
fail("Proto sources must be either all virtual imports or all real")
if at_least_one_virtual:
return get_include_directory(protos[0])
# TODO: uncomment if '.' path is chosen over
# `_virtual_imports/proto_library_target_name` as the output path
# return "{}/{}".format(context.genfiles_dir.path, context.label.package)
return context.genfiles_dir.path
def is_in_virtual_imports(source_file, virtual_folder = _VIRTUAL_IMPORTS):
"""Determines if source_file is virtual (is placed in _virtual_imports
subdirectory). The output of all proto_library targets which use
import_prefix and/or strip_import_prefix arguments is placed under
_virtual_imports directory.
Args:
context: A ctx object for the rule.
virtual_folder: The virtual folder name (is set to "_virtual_imports"
by default)
Returns:
True if source_file is located under _virtual_imports, False otherwise.
"""
return not source_file.is_source and virtual_folder in source_file.path