blob: 18042a4132cf4352fc6d65719c3acb8fc385441f [file] [log] [blame]
Jakob Buchgraber9205b252017-06-01 20:56:28 +02001"""BUILD rules to generate gRPC service interfaces.
2You need to load the rules in your BUILD file for use, like:
3load("//third_party/grpc:build_defs.bzl", "java_grpc_library")
4"""
Liam Miller-Cushon8caa7452018-04-16 15:31:09 +02005
Jakob Buchgraber9205b252017-06-01 20:56:28 +02006def _path_ignoring_repository(f):
Alexandre Rostovtsev458ab032019-02-06 15:43:21 -05007 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 Buchgraber9205b252017-06-01 20:56:28 +020013
14def _gensource_impl(ctx):
Alexandre Rostovtsev458ab032019-02-06 15:43:21 -050015 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 Buchgraber9205b252017-06-01 20:56:28 +020024
Alexandre Rostovtsev458ab032019-02-06 15:43:21 -050025 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 Buchgraber9205b252017-06-01 20:56:28 +020037
Alexandre Rostovtsev458ab032019-02-06 15:43:21 -050038 ctx.action(
39 command = "cp '%s' '%s'" % (srcdotjar.path, ctx.outputs.srcjar.path),
40 inputs = [srcdotjar],
41 outputs = [ctx.outputs.srcjar],
42 )
Jakob Buchgraber9205b252017-06-01 20:56:28 +020043
44_java_grpc_gensource = rule(
45 attrs = {
46 "srcs": attr.label_list(
47 mandatory = True,
Keith Smiley805a57f2018-11-27 11:42:09 -080048 allow_empty = False,
Jakob Buchgraber9205b252017-06-01 20:56:28 +020049 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 Smiley805a57f2018-11-27 11:42:09 -080058 allow_single_file = True,
Jakob Buchgraber9205b252017-06-01 20:56:28 +020059 ),
60 "_java_plugin": attr.label(
John Millikina59e60e2018-01-10 14:39:36 -080061 default = Label("@io_bazel//third_party/grpc:grpc-java-plugin"),
Jakob Buchgraber9205b252017-06-01 20:56:28 +020062 executable = True,
63 cfg = "host",
64 ),
65 },
66 outputs = {
67 "srcjar": "%{name}.srcjar",
68 },
69 implementation = _gensource_impl,
70)
71
Alexandre Rostovtsev458ab032019-02-06 15:43:21 -050072def 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
114def _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.
121def 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 )