| load(":functions.bzl", "label_workspace_path", "workspace_path") |
| load(":maven.bzl", "maven_java_library") |
| load(":utils.bzl", "java_jarjar") |
| load(":android.bzl", "select_android") |
| |
| # Enum-like values to determine the language the gen_proto rule will compile |
| # the .proto files to. |
| proto_languages = struct( |
| CPP = 0, |
| JAVA = 1, |
| ) |
| |
| PROTOC_VERSION = "3.10.0" |
| |
| ProtoPackageInfo = provider(fields = ["proto_src", "proto_path"]) |
| |
| def _gen_proto_impl(ctx): |
| inputs = [] |
| inputs += ctx.files.srcs + ctx.files.include |
| |
| args = [] |
| needs_label_path = False |
| for src_target in ctx.attr.srcs: |
| if ProtoPackageInfo in src_target: |
| args += ["--proto_path=" + workspace_path(src_target[ProtoPackageInfo].proto_path)] |
| else: |
| # if src_target doesn't have ProtoPackageInfo provider that should be used to look up proto files |
| # then we're going to path where BUILD is placed. |
| # Example: //rule/proto/BUILD -> --proto_path="rule/proto" |
| needs_label_path = True |
| |
| label_dir = label_workspace_path(ctx.label) |
| if needs_label_path: |
| args += ["--proto_path=" + label_dir] |
| |
| args += [ |
| "--proto_path=" + workspace_path("prebuilts/tools/common/m2/repository/com/google/protobuf/protobuf-java/" + ctx.attr.proto_include_version + "/include"), |
| ] |
| |
| for dep in ctx.attr.deps: |
| args += ["--proto_path=" + workspace_path(dep[ProtoPackageInfo].proto_path)] |
| inputs += dep[ProtoPackageInfo].proto_src |
| |
| args += [s.path for s in ctx.files.srcs] |
| |
| # Try to generate cc protos first. |
| if ctx.attr.target_language == proto_languages.CPP: |
| out_path = ctx.var["GENDIR"] + "/" + label_dir |
| args += [ |
| "--cpp_out=" + out_path, |
| ] |
| if ctx.executable.grpc_plugin != None and ctx.executable.grpc_plugin.path != None: |
| args += [ |
| "--grpc_out=" + out_path, |
| "--plugin=protoc-gen-grpc=" + ctx.executable.grpc_plugin.path, |
| ] |
| outs = ctx.outputs.outs |
| |
| # Try to generate java protos only if we won't generate cc protos |
| elif ctx.attr.target_language == proto_languages.JAVA: |
| srcjar = ctx.outputs.outs[0] # outputs.out size should be 1 |
| outs = [ctx.actions.declare_file(srcjar.basename + ".jar")] |
| |
| out_path = outs[0].path |
| args += [ |
| "--java_out=" + out_path, |
| ] |
| if ctx.executable.grpc_plugin != None: |
| args += [ |
| "--java_rpc_out=" + out_path, |
| "--plugin=protoc-gen-java_rpc=" + ctx.executable.grpc_plugin.path, |
| ] |
| |
| tools = [] |
| if ctx.executable.grpc_plugin != None: |
| tools += [ctx.executable.grpc_plugin] |
| |
| ctx.actions.run( |
| mnemonic = "GenProto", |
| inputs = inputs, |
| outputs = outs, |
| tools = tools, |
| arguments = args, |
| executable = ctx.executable.protoc, |
| ) |
| |
| if ctx.attr.target_language == proto_languages.JAVA: |
| # This is required because protoc only understands .jar extensions, but Bazel |
| # requires source JAR files end in .srcjar. |
| ctx.actions.run_shell( |
| mnemonic = "FixProtoSrcJar", |
| inputs = outs, |
| outputs = [srcjar], |
| command = "cp " + srcjar.path + ".jar" + " " + srcjar.path, |
| ) |
| |
| return ProtoPackageInfo( |
| proto_src = ctx.files.srcs, |
| proto_path = ctx.label.package, |
| ) |
| |
| _gen_proto_rule = rule( |
| attrs = { |
| "srcs": attr.label_list( |
| allow_files = [".proto"], |
| providers = [ProtoPackageInfo], |
| ), |
| "deps": attr.label_list( |
| allow_files = False, |
| providers = [ProtoPackageInfo], |
| ), |
| "include": attr.label( |
| allow_files = [".proto"], |
| ), |
| "proto_include_version": attr.string(), |
| "protoc": attr.label( |
| cfg = "host", |
| executable = True, |
| mandatory = True, |
| allow_single_file = True, |
| ), |
| "grpc_plugin": attr.label( |
| cfg = "host", |
| executable = True, |
| allow_single_file = True, |
| ), |
| "target_language": attr.int(), |
| "outs": attr.output_list(), |
| }, |
| output_to_genfiles = True, |
| implementation = _gen_proto_impl, |
| ) |
| |
| def java_proto_library( |
| name, |
| srcs = None, |
| proto_deps = [], |
| java_deps = [], |
| pom = None, |
| visibility = None, |
| grpc_support = False, |
| protoc_version = PROTOC_VERSION, |
| protoc_grpc_version = None, |
| proto_java_runtime_library = ["@//tools/base/third_party:com.google.protobuf_protobuf-java"], |
| **kwargs): |
| """Compiles protobuf into a .jar file and optionally creates a maven artifact. |
| |
| NOTE: Be cautious to use this rule. You may need to use android_java_proto_library instead. |
| See the comments in android_java_proto_library rule before using it. |
| |
| Args: |
| name: Name of the rule. |
| srcs: A list of file names of the protobuf definition to compile. |
| proto_deps: A list of dependent proto_library to compile the library. |
| java_deps: An additional java libraries to be packaged into the library. |
| pom: A label of maven_pom target. If present, the rule creates maven artifact of the library. |
| visibility: Visibility of the rule. |
| grpc_support: True if the proto library requires grpc protoc plugin. |
| protoc_version: The protoc version to use. |
| protoc_grpc_version: A version of the grpc protoc plugin to use. |
| proto_java_runtime_library: A label of java_library to be loaded at runtime. |
| """ |
| |
| # Targets that require grpc support should specify the version of protoc-gen-grpc-java plugin. |
| if grpc_support and not protoc_grpc_version: |
| fail("grpc support was requested, but the version of grpc java protoc plugin was not specified") |
| |
| srcs_name = name + "_srcs" |
| outs = [srcs_name + ".srcjar"] |
| _gen_proto_rule( |
| name = srcs_name, |
| srcs = srcs, |
| deps = proto_deps, |
| include = "@//prebuilts/tools/common/m2/repository/com/google/protobuf/protobuf-java/" + protoc_version + "/include", |
| outs = outs, |
| proto_include_version = protoc_version, |
| protoc = "@//prebuilts/tools/common/m2/repository/com/google/protobuf/protoc/" + protoc_version + ":exe", |
| grpc_plugin = |
| "@//prebuilts/tools/common/m2/repository/io/grpc/protoc-gen-grpc-java/" + protoc_grpc_version + ":exe" if grpc_support else None, |
| target_language = proto_languages.JAVA, |
| visibility = visibility, |
| ) |
| |
| java_deps = list(java_deps) |
| java_deps += proto_java_runtime_library |
| |
| if pom: |
| maven_java_library( |
| name = name, |
| pom = pom, |
| srcs = outs, |
| deps = java_deps, |
| baseline_coverage = False, |
| visibility = visibility, |
| **kwargs |
| ) |
| else: |
| native.java_library( |
| name = name, |
| srcs = outs, |
| deps = java_deps, |
| visibility = visibility, |
| **kwargs |
| ) |
| |
| def android_java_proto_library( |
| name, |
| srcs = None, |
| grpc_support = False, |
| protoc_grpc_version = None, |
| java_deps = [], |
| visibility = None): |
| """Compiles protobuf into a .jar file in Android Studio compatible runtime version. |
| |
| Unlike java_proto_library rule defined above, android_java_proto_library |
| repackage com.google.protobuf.* dependencies to com.android.tools.idea.protobuf |
| by applying JarJar tool after the protobuf compilation. This repackaging is necessary |
| in order to avoid version incompatibility to IntelliJ platform runtime dependencies. |
| |
| tl;dr; Use this rule if your proto library is linked to Android Studio, otherwise |
| use java_proto_library. |
| |
| NOTE: The repackaged runtime is at //tools/base/bazel:studio-proto. |
| |
| Args: |
| name: Name of the rule. |
| srcs: A list of file names of the protobuf definition to compile. |
| grpc_support: True if the proto library requires grpc protoc plugin. |
| protoc_grpc_version: A version of the grpc protoc plugin to use. |
| java_deps: An additional java libraries to be packaged into the library. |
| visibility: Visibility of the rule. |
| """ |
| internal_name = "_" + name + "_internal" |
| java_proto_library(name = internal_name, srcs = srcs, grpc_support = grpc_support, protoc_grpc_version = protoc_grpc_version, java_deps = java_deps) |
| java_jarjar( |
| name = name, |
| srcs = [":" + internal_name], |
| rules = "//tools/base/bazel:jarjar_rules.txt", |
| visibility = visibility, |
| ) |
| |
| def cc_grpc_proto_library(name, srcs = [], deps = [], includes = [], visibility = None, grpc_support = False, tags = None): |
| outs = [] |
| hdrs = [] |
| for src in srcs: |
| # .proto suffix should not be present in the output files |
| p_name = src[:-len(".proto")] |
| outs += [p_name + ".pb.cc"] |
| hdrs += [p_name + ".pb.h"] |
| if grpc_support: |
| outs += [p_name + ".grpc.pb.cc"] |
| hdrs += [p_name + ".grpc.pb.h"] |
| |
| _gen_proto_rule( |
| name = name + "_srcs", |
| srcs = srcs, |
| deps = deps, |
| outs = outs + hdrs, |
| proto_include_version = "3.0.0", |
| protoc = "//external:protoc", |
| grpc_plugin = "//external:grpc_cpp_plugin" if grpc_support else None, |
| target_language = proto_languages.CPP, |
| tags = tags, |
| ) |
| native.cc_library( |
| name = name, |
| srcs = outs, |
| deps = deps + ["//external:grpc++_unsecure", "//external:protobuf"], |
| includes = includes, |
| visibility = visibility, |
| tags = tags, |
| hdrs = hdrs, |
| copts = select_android(["-std=c++11"], []), |
| ) |