Jakob Buchgraber | 9205b25 | 2017-06-01 20:56:28 +0200 | [diff] [blame] | 1 | """BUILD rules to generate gRPC service interfaces. |
| 2 | You need to load the rules in your BUILD file for use, like: |
| 3 | load("//third_party/grpc:build_defs.bzl", "java_grpc_library") |
| 4 | """ |
Liam Miller-Cushon | 8caa745 | 2018-04-16 15:31:09 +0200 | [diff] [blame] | 5 | |
Jakob Buchgraber | 9205b25 | 2017-06-01 20:56:28 +0200 | [diff] [blame] | 6 | def _path_ignoring_repository(f): |
Alexandre Rostovtsev | 458ab03 | 2019-02-06 15:43:21 -0500 | [diff] [blame] | 7 | if (len(f.owner.workspace_root) == 0): |
| 8 | return f.short_path |
| 9 | |
| 10 | # If |f| is a generated file, it will have "bazel-out/*/genfiles" prefix |
| 11 | # before "external/workspace", so we need to add the starting index of "external/workspace" |
| 12 | return f.path[f.path.find(f.owner.workspace_root) + len(f.owner.workspace_root) + 1:] |
Jakob Buchgraber | 9205b25 | 2017-06-01 20:56:28 +0200 | [diff] [blame] | 13 | |
| 14 | def _gensource_impl(ctx): |
Alexandre Rostovtsev | 458ab03 | 2019-02-06 15:43:21 -0500 | [diff] [blame] | 15 | if len(ctx.attr.srcs) > 1: |
| 16 | fail("Only one src value supported", "srcs") |
| 17 | for s in ctx.attr.srcs: |
| 18 | if s.label.package != ctx.label.package: |
| 19 | print(("in srcs attribute of {0}: Proto source with label {1} should be in " + |
| 20 | "same package as consuming rule").format(ctx.label, s.label)) |
| 21 | srcdotjar = ctx.new_file(ctx.label.name + ".jar") |
| 22 | srcs = [f for dep in ctx.attr.srcs for f in dep.proto.direct_sources] |
| 23 | includes = [f for dep in ctx.attr.srcs for f in dep.proto.transitive_imports.to_list()] |
Jakob Buchgraber | 9205b25 | 2017-06-01 20:56:28 +0200 | [diff] [blame] | 24 | |
Alexandre Rostovtsev | 458ab03 | 2019-02-06 15:43:21 -0500 | [diff] [blame] | 25 | ctx.action( |
| 26 | command = " ".join([ |
| 27 | ctx.executable._protoc.path, |
| 28 | "--plugin=protoc-gen-grpc-java={0}".format(ctx.executable._java_plugin.path), |
| 29 | "--grpc-java_out=enable_deprecated={0}:{1}".format(str(ctx.attr.enable_deprecated).lower(), srcdotjar.path), |
| 30 | ] + |
| 31 | ["-I{0}={1}".format(_path_ignoring_repository(include), include.path) for include in includes] + |
| 32 | [src.path for src in srcs]), |
| 33 | inputs = [ctx.executable._java_plugin, ctx.executable._protoc] + srcs + includes, |
| 34 | outputs = [srcdotjar], |
| 35 | use_default_shell_env = True, |
| 36 | ) |
Jakob Buchgraber | 9205b25 | 2017-06-01 20:56:28 +0200 | [diff] [blame] | 37 | |
Alexandre Rostovtsev | 458ab03 | 2019-02-06 15:43:21 -0500 | [diff] [blame] | 38 | ctx.action( |
| 39 | command = "cp '%s' '%s'" % (srcdotjar.path, ctx.outputs.srcjar.path), |
| 40 | inputs = [srcdotjar], |
| 41 | outputs = [ctx.outputs.srcjar], |
| 42 | ) |
Jakob Buchgraber | 9205b25 | 2017-06-01 20:56:28 +0200 | [diff] [blame] | 43 | |
| 44 | _java_grpc_gensource = rule( |
| 45 | attrs = { |
| 46 | "srcs": attr.label_list( |
| 47 | mandatory = True, |
Keith Smiley | 805a57f | 2018-11-27 11:42:09 -0800 | [diff] [blame] | 48 | allow_empty = False, |
Jakob Buchgraber | 9205b25 | 2017-06-01 20:56:28 +0200 | [diff] [blame] | 49 | providers = ["proto"], |
| 50 | ), |
| 51 | "enable_deprecated": attr.bool( |
| 52 | default = False, |
| 53 | ), |
| 54 | "_protoc": attr.label( |
| 55 | default = Label("@com_google_protobuf//:protoc"), |
| 56 | executable = True, |
| 57 | cfg = "host", |
Keith Smiley | 805a57f | 2018-11-27 11:42:09 -0800 | [diff] [blame] | 58 | allow_single_file = True, |
Jakob Buchgraber | 9205b25 | 2017-06-01 20:56:28 +0200 | [diff] [blame] | 59 | ), |
| 60 | "_java_plugin": attr.label( |
John Millikin | a59e60e | 2018-01-10 14:39:36 -0800 | [diff] [blame] | 61 | default = Label("@io_bazel//third_party/grpc:grpc-java-plugin"), |
Jakob Buchgraber | 9205b25 | 2017-06-01 20:56:28 +0200 | [diff] [blame] | 62 | executable = True, |
| 63 | cfg = "host", |
| 64 | ), |
| 65 | }, |
| 66 | outputs = { |
| 67 | "srcjar": "%{name}.srcjar", |
| 68 | }, |
| 69 | implementation = _gensource_impl, |
| 70 | ) |
| 71 | |
Alexandre Rostovtsev | 458ab03 | 2019-02-06 15:43:21 -0500 | [diff] [blame] | 72 | def java_grpc_library(name, srcs, deps, enable_deprecated = None, visibility = None, constraints = None, **kwargs): |
| 73 | """Generates and compiles gRPC Java sources for services defined in a proto |
| 74 | file. This rule is compatible with proto_library with java_api_version, |
| 75 | java_proto_library, and java_lite_proto_library. |
| 76 | Do note that this rule only scans through the proto file for RPC services. It |
| 77 | does not generate Java classes for proto messages. You will need a separate |
| 78 | proto_library with java_api_version, java_proto_library, or |
| 79 | java_lite_proto_library rule. |
| 80 | Args: |
| 81 | name: (str) A unique name for this rule. Required. |
| 82 | srcs: (list) a single proto_library target that contains the schema of the |
| 83 | service. Required. |
| 84 | deps: (list) a single java_proto_library target for the proto_library in |
| 85 | srcs. Required. |
| 86 | visibility: (list) the visibility list |
| 87 | **kwargs: Passed through to generated targets |
| 88 | """ |
| 89 | gensource_name = name + "_srcs" |
| 90 | _java_grpc_gensource( |
| 91 | name = gensource_name, |
| 92 | srcs = srcs, |
| 93 | enable_deprecated = enable_deprecated, |
| 94 | visibility = ["//visibility:private"], |
| 95 | tags = [ |
| 96 | "avoid_dep", |
| 97 | ], |
| 98 | **kwargs |
| 99 | ) |
| 100 | native.java_library( |
| 101 | name = name, |
| 102 | srcs = [gensource_name], |
| 103 | visibility = visibility, |
| 104 | deps = [ |
| 105 | "@io_bazel//third_party:javax_annotations", |
| 106 | "@io_bazel//third_party:jsr305", |
| 107 | "@io_bazel//third_party/grpc:grpc-jar", |
| 108 | "@io_bazel//third_party:guava", |
| 109 | "@com_google_protobuf//:protobuf_java", |
| 110 | ] + deps, |
| 111 | **kwargs |
| 112 | ) |
| 113 | |
| 114 | def _get_external_deps(external_deps): |
| 115 | ret = [] |
| 116 | for dep in external_deps: |
| 117 | ret += ["//third_party/" + dep] |
| 118 | return ret |
| 119 | |
| 120 | # Simplified version of gRPC upstream's grpc_cc_library. |
| 121 | def grpc_cc_library( |
| 122 | name, |
| 123 | srcs = [], |
| 124 | public_hdrs = [], |
| 125 | hdrs = [], |
| 126 | external_deps = [], |
| 127 | deps = [], |
| 128 | standalone = False, |
| 129 | language = "C++", |
| 130 | testonly = False, |
| 131 | visibility = None, |
| 132 | alwayslink = 0, |
| 133 | data = []): |
| 134 | copts = [] |
| 135 | if language.upper() == "C": |
| 136 | copts = select({ |
| 137 | "//conditions:default": [ |
| 138 | "-std=c99", |
| 139 | "-Wimplicit-function-declaration", |
| 140 | ], |
| 141 | ":windows": ["/we4013"], |
| 142 | }) |
| 143 | native.cc_library( |
| 144 | name = name, |
| 145 | srcs = srcs, |
| 146 | defines = ["GRPC_ARES=0"], # Our use case doesn't need ares. |
| 147 | hdrs = hdrs + public_hdrs, |
| 148 | deps = deps + _get_external_deps(external_deps), |
| 149 | copts = copts, |
| 150 | visibility = visibility, |
| 151 | testonly = testonly, |
| 152 | linkopts = select({ |
| 153 | "//conditions:default": ["-pthread"], |
| 154 | ":windows": [], |
| 155 | }), |
| 156 | includes = [ |
| 157 | ".", |
| 158 | "include", |
| 159 | ], |
| 160 | alwayslink = alwayslink, |
| 161 | data = data, |
| 162 | ) |