blob: 74cb9ad54c142a56c86d9846374e15fbbb4b6bb5 [file] [log] [blame]
Jisi Liu39362b32015-10-14 17:12:11 -07001# -*- mode: python; -*- PYTHON-PREPROCESSING-REQUIRED
2
Damien Martin-Guillerez76547e52016-01-15 14:01:37 +01003def _GetPath(ctx, path):
4 if ctx.label.workspace_root:
5 return ctx.label.workspace_root + '/' + path
6 else:
7 return path
8
Jisi Liu993fb702015-10-19 17:19:49 -07009def _GenDir(ctx):
Jisi Liu53a56be2015-10-20 15:18:20 -070010 if not ctx.attr.includes:
Damien Martin-Guillerez76547e52016-01-15 14:01:37 +010011 return ctx.label.workspace_root
Jisi Liu53a56be2015-10-20 15:18:20 -070012 if not ctx.attr.includes[0]:
Damien Martin-Guillerez76547e52016-01-15 14:01:37 +010013 return _GetPath(ctx, ctx.label.package)
Jisi Liu39362b32015-10-14 17:12:11 -070014 if not ctx.label.package:
Damien Martin-Guillerez76547e52016-01-15 14:01:37 +010015 return _GetPath(ctx, ctx.attr.includes[0])
16 return _GetPath(ctx, ctx.label.package + '/' + ctx.attr.includes[0])
Jisi Liu39362b32015-10-14 17:12:11 -070017
Andreas Bergmeierbbeb9832016-08-15 16:57:30 +020018def _CcHdrs(srcs, use_grpc_plugin=False):
19 ret = [s[:-len(".proto")] + ".pb.h" for s in srcs]
Manjunath Kudlurf5c73632016-02-25 08:50:50 -080020 if use_grpc_plugin:
Andreas Bergmeierbbeb9832016-08-15 16:57:30 +020021 ret += [s[:-len(".proto")] + ".grpc.pb.h" for s in srcs]
Manjunath Kudlurf5c73632016-02-25 08:50:50 -080022 return ret
Jisi Liu39362b32015-10-14 17:12:11 -070023
Andreas Bergmeierbbeb9832016-08-15 16:57:30 +020024def _CcSrcs(srcs, use_grpc_plugin=False):
25 ret = [s[:-len(".proto")] + ".pb.cc" for s in srcs]
26 if use_grpc_plugin:
27 ret += [s[:-len(".proto")] + ".grpc.pb.cc" for s in srcs]
28 return ret
29
30def _CcOuts(srcs, use_grpc_plugin=False):
31 return _CcHdrs(srcs, use_grpc_plugin) + _CcSrcs(srcs, use_grpc_plugin)
32
Jisi Liu993fb702015-10-19 17:19:49 -070033def _PyOuts(srcs):
Jisi Liu125a91b2015-10-14 17:37:39 -070034 return [s[:-len(".proto")] + "_pb2.py" for s in srcs]
Jisi Liu39362b32015-10-14 17:12:11 -070035
David Z. Chen02cd45c2016-05-20 16:49:04 -070036def _RelativeOutputPath(path, include, dest=""):
Jisi Liu993fb702015-10-19 17:19:49 -070037 if include == None:
38 return path
39
40 if not path.startswith(include):
41 fail("Include path %s isn't part of the path %s." % (include, path))
42
43 if include and include[-1] != '/':
44 include = include + '/'
David Z. Chen02cd45c2016-05-20 16:49:04 -070045 if dest and dest[-1] != '/':
46 dest = dest + '/'
Jisi Liu993fb702015-10-19 17:19:49 -070047
48 path = path[len(include):]
David Z. Chen02cd45c2016-05-20 16:49:04 -070049 return dest + path
Jisi Liu993fb702015-10-19 17:19:49 -070050
Jisi Liu9c7d9c02015-10-15 10:51:32 -070051def _proto_gen_impl(ctx):
52 """General implementation for generating protos"""
Jisi Liu39362b32015-10-14 17:12:11 -070053 srcs = ctx.files.srcs
54 deps = []
55 deps += ctx.files.srcs
Jisi Liu993fb702015-10-19 17:19:49 -070056 gen_dir = _GenDir(ctx)
Jisi Liu53a56be2015-10-20 15:18:20 -070057 if gen_dir:
David Z. Chen02cd45c2016-05-20 16:49:04 -070058 import_flags = ["-I" + gen_dir, "-I" + ctx.var["GENDIR"] + "/" + gen_dir]
Jisi Liu53a56be2015-10-20 15:18:20 -070059 else:
60 import_flags = ["-I."]
61
Jisi Liu39362b32015-10-14 17:12:11 -070062 for dep in ctx.attr.deps:
63 import_flags += dep.proto.import_flags
64 deps += dep.proto.deps
65
66 args = []
67 if ctx.attr.gen_cc:
68 args += ["--cpp_out=" + ctx.var["GENDIR"] + "/" + gen_dir]
69 if ctx.attr.gen_py:
70 args += ["--python_out=" + ctx.var["GENDIR"] + "/" + gen_dir]
71
Florian Weikertc2b3e702016-10-12 14:03:07 +020072 inputs = srcs + deps
Yuki Yugui Sonoda5977fb02016-06-01 16:23:15 +090073 if ctx.executable.plugin:
74 plugin = ctx.executable.plugin
75 lang = ctx.attr.plugin_language
76 if not lang and plugin.basename.startswith('protoc-gen-'):
77 lang = plugin.basename[len('protoc-gen-'):]
78 if not lang:
79 fail("cannot infer the target language of plugin", "plugin_language")
80
81 outdir = ctx.var["GENDIR"] + "/" + gen_dir
82 if ctx.attr.plugin_options:
83 outdir = ",".join(ctx.attr.plugin_options) + ":" + outdir
84 args += ["--plugin=protoc-gen-%s=%s" % (lang, plugin.path)]
85 args += ["--%s_out=%s" % (lang, outdir)]
Florian Weikertc2b3e702016-10-12 14:03:07 +020086 inputs += [plugin]
Manjunath Kudlurf0966a72016-02-22 14:30:43 -080087
Jisi Liu39362b32015-10-14 17:12:11 -070088 if args:
89 ctx.action(
Florian Weikertc2b3e702016-10-12 14:03:07 +020090 inputs=inputs,
Jisi Liu39362b32015-10-14 17:12:11 -070091 outputs=ctx.outputs.outs,
Jisi Liu125a91b2015-10-14 17:37:39 -070092 arguments=args + import_flags + [s.path for s in srcs],
Jisi Liu9c7d9c02015-10-15 10:51:32 -070093 executable=ctx.executable.protoc,
Yuki Yugui Sonoda5977fb02016-06-01 16:23:15 +090094 mnemonic="ProtoCompile",
Jisi Liu39362b32015-10-14 17:12:11 -070095 )
96
97 return struct(
98 proto=struct(
Jisi Liu125a91b2015-10-14 17:37:39 -070099 srcs=srcs,
100 import_flags=import_flags,
101 deps=deps,
102 ),
103 )
Jisi Liu39362b32015-10-14 17:12:11 -0700104
Yuki Yugui Sonoda5977fb02016-06-01 16:23:15 +0900105proto_gen = rule(
Jisi Liu39362b32015-10-14 17:12:11 -0700106 attrs = {
Jisi Liuee8131a2015-10-14 17:20:05 -0700107 "srcs": attr.label_list(allow_files = True),
108 "deps": attr.label_list(providers = ["proto"]),
Jisi Liu53a56be2015-10-20 15:18:20 -0700109 "includes": attr.string_list(),
Jisi Liuee8131a2015-10-14 17:20:05 -0700110 "protoc": attr.label(
Vladimir Moskvaa86e6d82016-09-09 13:21:35 +0200111 cfg = "host",
Jisi Liuee8131a2015-10-14 17:20:05 -0700112 executable = True,
113 single_file = True,
114 mandatory = True,
115 ),
Yuki Yugui Sonoda5977fb02016-06-01 16:23:15 +0900116 "plugin": attr.label(
Vladimir Moskvaa86e6d82016-09-09 13:21:35 +0200117 cfg = "host",
Yuki Yugui Sonoda5977fb02016-06-01 16:23:15 +0900118 allow_files = True,
Manjunath Kudlurf0966a72016-02-22 14:30:43 -0800119 executable = True,
Manjunath Kudlurf0966a72016-02-22 14:30:43 -0800120 ),
Yuki Yugui Sonoda5977fb02016-06-01 16:23:15 +0900121 "plugin_language": attr.string(),
122 "plugin_options": attr.string_list(),
Jisi Liuee8131a2015-10-14 17:20:05 -0700123 "gen_cc": attr.bool(),
124 "gen_py": attr.bool(),
125 "outs": attr.output_list(),
126 },
127 output_to_genfiles = True,
Jisi Liu9c7d9c02015-10-15 10:51:32 -0700128 implementation = _proto_gen_impl,
Jisi Liu39362b32015-10-14 17:12:11 -0700129)
Yuki Yugui Sonoda5977fb02016-06-01 16:23:15 +0900130"""Generates codes from Protocol Buffers definitions.
131
132This rule helps you to implement Skylark macros specific to the target
133language. You should prefer more specific `cc_proto_library `,
134`py_proto_library` and others unless you are adding such wrapper macros.
135
136Args:
137 srcs: Protocol Buffers definition files (.proto) to run the protocol compiler
138 against.
139 deps: a list of dependency labels; must be other proto libraries.
140 includes: a list of include paths to .proto files.
141 protoc: the label of the protocol compiler to generate the sources.
142 plugin: the label of the protocol compiler plugin to be passed to the protocol
143 compiler.
144 plugin_language: the language of the generated sources
145 plugin_options: a list of options to be passed to the plugin
146 gen_cc: generates C++ sources in addition to the ones from the plugin.
147 gen_py: generates Python sources in addition to the ones from the plugin.
148 outs: a list of labels of the expected outputs from the protocol compiler.
149"""
Jisi Liu39362b32015-10-14 17:12:11 -0700150
151def cc_proto_library(
Jisi Liu125a91b2015-10-14 17:37:39 -0700152 name,
153 srcs=[],
Jisi Liu125a91b2015-10-14 17:37:39 -0700154 deps=[],
Jisi Liud8701b52015-10-16 11:44:21 -0700155 cc_libs=[],
Jisi Liu6dac0822015-10-19 14:41:00 -0700156 include=None,
David Z. Chen985c9682016-02-11 18:11:10 -0800157 protoc="//:protoc",
Jisi Liu3101e732015-10-16 12:46:26 -0700158 internal_bootstrap_hack=False,
Manjunath Kudlurf0966a72016-02-22 14:30:43 -0800159 use_grpc_plugin=False,
David Z. Chen985c9682016-02-11 18:11:10 -0800160 default_runtime="//:protobuf",
Jisi Liu125a91b2015-10-14 17:37:39 -0700161 **kargs):
Jisi Liu3101e732015-10-16 12:46:26 -0700162 """Bazel rule to create a C++ protobuf library from proto source files
163
Jisi Liud4bef7d2015-11-02 12:24:32 -0800164 NOTE: the rule is only an internal workaround to generate protos. The
165 interface may change and the rule may be removed when bazel has introduced
166 the native rule.
167
Jisi Liu3101e732015-10-16 12:46:26 -0700168 Args:
169 name: the name of the cc_proto_library.
170 srcs: the .proto files of the cc_proto_library.
171 deps: a list of dependency labels; must be cc_proto_library.
172 cc_libs: a list of other cc_library targets depended by the generated
173 cc_library.
174 include: a string indicating the include path of the .proto files.
175 protoc: the label of the protocol compiler to generate the sources.
176 internal_bootstrap_hack: a flag indicate the cc_proto_library is used only
177 for bootstraping. When it is set to True, no files will be generated.
178 The rule will simply be a provider for .proto files, so that other
179 cc_proto_library can depend on it.
Manjunath Kudlurf0966a72016-02-22 14:30:43 -0800180 use_grpc_plugin: a flag to indicate whether to call the grpc C++ plugin
181 when processing the proto files.
Jisi Liube92ffb2015-10-27 15:11:38 -0700182 default_runtime: the implicitly default runtime which will be depended on by
183 the generated cc_library target.
Jisi Liu3101e732015-10-16 12:46:26 -0700184 **kargs: other keyword arguments that are passed to cc_library.
185
186 """
Jisi Liu39362b32015-10-14 17:12:11 -0700187
Jisi Liu53a56be2015-10-20 15:18:20 -0700188 includes = []
189 if include != None:
190 includes = [include]
191
Jisi Liu39362b32015-10-14 17:12:11 -0700192 if internal_bootstrap_hack:
193 # For pre-checked-in generated files, we add the internal_bootstrap_hack
194 # which will skip the codegen action.
Yuki Yugui Sonoda5977fb02016-06-01 16:23:15 +0900195 proto_gen(
Jisi Liu125a91b2015-10-14 17:37:39 -0700196 name=name + "_genproto",
197 srcs=srcs,
Jisi Liud8701b52015-10-16 11:44:21 -0700198 deps=[s + "_genproto" for s in deps],
Jisi Liu53a56be2015-10-20 15:18:20 -0700199 includes=includes,
Jisi Liu125a91b2015-10-14 17:37:39 -0700200 protoc=protoc,
Martin Maly8e0c9a32015-12-04 17:44:58 -0800201 visibility=["//visibility:public"],
Jisi Liu39362b32015-10-14 17:12:11 -0700202 )
203 # An empty cc_library to make rule dependency consistent.
204 native.cc_library(
Jisi Liu125a91b2015-10-14 17:37:39 -0700205 name=name,
Jisi Liud8701b52015-10-16 11:44:21 -0700206 **kargs)
Jisi Liu39362b32015-10-14 17:12:11 -0700207 return
208
Manjunath Kudlurf0966a72016-02-22 14:30:43 -0800209 grpc_cpp_plugin = None
210 if use_grpc_plugin:
211 grpc_cpp_plugin = "//external:grpc_cpp_plugin"
212
Andreas Bergmeierbbeb9832016-08-15 16:57:30 +0200213 gen_srcs = _CcSrcs(srcs, use_grpc_plugin)
214 gen_hdrs = _CcHdrs(srcs, use_grpc_plugin)
215 outs = gen_srcs + gen_hdrs
Manjunath Kudlurf5c73632016-02-25 08:50:50 -0800216
Yuki Yugui Sonoda5977fb02016-06-01 16:23:15 +0900217 proto_gen(
Jisi Liu125a91b2015-10-14 17:37:39 -0700218 name=name + "_genproto",
219 srcs=srcs,
Jisi Liud8701b52015-10-16 11:44:21 -0700220 deps=[s + "_genproto" for s in deps],
Jisi Liu53a56be2015-10-20 15:18:20 -0700221 includes=includes,
Jisi Liu125a91b2015-10-14 17:37:39 -0700222 protoc=protoc,
Yuki Yugui Sonoda5977fb02016-06-01 16:23:15 +0900223 plugin=grpc_cpp_plugin,
224 plugin_language="grpc",
Jisi Liu125a91b2015-10-14 17:37:39 -0700225 gen_cc=1,
226 outs=outs,
Martin Maly8e0c9a32015-12-04 17:44:58 -0800227 visibility=["//visibility:public"],
Jisi Liu39362b32015-10-14 17:12:11 -0700228 )
229
Jisi Liube92ffb2015-10-27 15:11:38 -0700230 if default_runtime and not default_runtime in cc_libs:
231 cc_libs += [default_runtime]
Manjunath Kudlurf5c73632016-02-25 08:50:50 -0800232 if use_grpc_plugin:
233 cc_libs += ["//external:grpc_lib"]
Jisi Liu6dac0822015-10-19 14:41:00 -0700234
Jisi Liu39362b32015-10-14 17:12:11 -0700235 native.cc_library(
Jisi Liu125a91b2015-10-14 17:37:39 -0700236 name=name,
Andreas Bergmeierbbeb9832016-08-15 16:57:30 +0200237 srcs=gen_srcs,
238 hdrs=gen_hdrs,
Jisi Liud8701b52015-10-16 11:44:21 -0700239 deps=cc_libs + deps,
Jisi Liu6dac0822015-10-19 14:41:00 -0700240 includes=includes,
Jisi Liud8701b52015-10-16 11:44:21 -0700241 **kargs)
Jisi Liu993fb702015-10-19 17:19:49 -0700242
Steven Parkesea188662016-02-25 07:53:19 -0800243
244def internal_gen_well_known_protos_java(srcs):
245 """Bazel rule to generate the gen_well_known_protos_java genrule
246
247 Args:
248 srcs: the well known protos
249 """
250 root = Label("%s//protobuf_java" % (REPOSITORY_NAME)).workspace_root
251 if root == "":
252 include = " -Isrc "
253 else:
254 include = " -I%s/src " % root
255 native.genrule(
256 name = "gen_well_known_protos_java",
257 srcs = srcs,
258 outs = [
259 "wellknown.srcjar",
260 ],
261 cmd = "$(location :protoc) --java_out=$(@D)/wellknown.jar" +
262 " %s $(SRCS) " % include +
263 " && mv $(@D)/wellknown.jar $(@D)/wellknown.srcjar",
264 tools = [":protoc"],
265 )
266
267
David Z. Chen02cd45c2016-05-20 16:49:04 -0700268def internal_copied_filegroup(name, srcs, strip_prefix, dest, **kwargs):
269 """Macro to copy files to a different directory and then create a filegroup.
270
271 This is used by the //:protobuf_python py_proto_library target to work around
272 an issue caused by Python source files that are part of the same Python
273 package being in separate directories.
274
275 Args:
276 srcs: The source files to copy and add to the filegroup.
277 strip_prefix: Path to the root of the files to copy.
278 dest: The directory to copy the source files into.
279 **kwargs: extra arguments that will be passesd to the filegroup.
280 """
281 outs = [_RelativeOutputPath(s, strip_prefix, dest) for s in srcs]
282
283 native.genrule(
284 name = name + "_genrule",
285 srcs = srcs,
286 outs = outs,
287 cmd = " && ".join(
288 ["cp $(location %s) $(location %s)" %
289 (s, _RelativeOutputPath(s, strip_prefix, dest)) for s in srcs]),
290 )
291
292 native.filegroup(
293 name = name,
294 srcs = outs,
295 **kwargs)
296
297
Jisi Liu993fb702015-10-19 17:19:49 -0700298def py_proto_library(
299 name,
300 srcs=[],
301 deps=[],
302 py_libs=[],
303 py_extra_srcs=[],
304 include=None,
David Z. Chen985c9682016-02-11 18:11:10 -0800305 default_runtime="//:protobuf_python",
306 protoc="//:protoc",
Wiktor Tomczak0fa31b22016-11-22 20:18:46 +0100307 use_grpc_plugin=False,
Jisi Liu993fb702015-10-19 17:19:49 -0700308 **kargs):
Jisi Liu7b948cc2015-10-19 17:56:27 -0700309 """Bazel rule to create a Python protobuf library from proto source files
310
Jisi Liud4bef7d2015-11-02 12:24:32 -0800311 NOTE: the rule is only an internal workaround to generate protos. The
312 interface may change and the rule may be removed when bazel has introduced
313 the native rule.
314
Jisi Liu7b948cc2015-10-19 17:56:27 -0700315 Args:
316 name: the name of the py_proto_library.
317 srcs: the .proto files of the py_proto_library.
318 deps: a list of dependency labels; must be py_proto_library.
319 py_libs: a list of other py_library targets depended by the generated
320 py_library.
321 py_extra_srcs: extra source files that will be added to the output
322 py_library. This attribute is used for internal bootstrapping.
323 include: a string indicating the include path of the .proto files.
Jisi Liube92ffb2015-10-27 15:11:38 -0700324 default_runtime: the implicitly default runtime which will be depended on by
325 the generated py_library target.
Jisi Liu7b948cc2015-10-19 17:56:27 -0700326 protoc: the label of the protocol compiler to generate the sources.
Wiktor Tomczak0fa31b22016-11-22 20:18:46 +0100327 use_grpc_plugin: a flag to indicate whether to call the Python C++ plugin
328 when processing the proto files.
Jisi Liu7b948cc2015-10-19 17:56:27 -0700329 **kargs: other keyword arguments that are passed to cc_library.
330
331 """
Jisi Liu993fb702015-10-19 17:19:49 -0700332 outs = _PyOuts(srcs)
Jisi Liu53a56be2015-10-20 15:18:20 -0700333
334 includes = []
335 if include != None:
336 includes = [include]
337
Wiktor Tomczak0fa31b22016-11-22 20:18:46 +0100338 grpc_python_plugin = None
339 if use_grpc_plugin:
340 grpc_python_plugin = "//external:grpc_python_plugin"
341 # Note: Generated grpc code depends on Python grpc module. This dependency
342 # is not explicitly listed in py_libs. Instead, host system is assumed to
343 # have grpc installed.
344
Yuki Yugui Sonoda5977fb02016-06-01 16:23:15 +0900345 proto_gen(
Jisi Liu993fb702015-10-19 17:19:49 -0700346 name=name + "_genproto",
347 srcs=srcs,
348 deps=[s + "_genproto" for s in deps],
Jisi Liu53a56be2015-10-20 15:18:20 -0700349 includes=includes,
Jisi Liu993fb702015-10-19 17:19:49 -0700350 protoc=protoc,
351 gen_py=1,
352 outs=outs,
Martin Maly8e0c9a32015-12-04 17:44:58 -0800353 visibility=["//visibility:public"],
Wiktor Tomczak0fa31b22016-11-22 20:18:46 +0100354 plugin=grpc_python_plugin,
355 plugin_language="grpc"
Jisi Liu993fb702015-10-19 17:19:49 -0700356 )
357
Jisi Liube92ffb2015-10-27 15:11:38 -0700358 if default_runtime and not default_runtime in py_libs + deps:
359 py_libs += [default_runtime]
360
Jisi Liu993fb702015-10-19 17:19:49 -0700361 native.py_library(
362 name=name,
Jisi Liua33fa8e2015-10-20 15:30:44 -0700363 srcs=outs+py_extra_srcs,
364 deps=py_libs+deps,
David Z. Chen985c9682016-02-11 18:11:10 -0800365 imports=includes,
Jisi Liu993fb702015-10-19 17:19:49 -0700366 **kargs)
367
368def internal_protobuf_py_tests(
369 name,
370 modules=[],
371 **kargs):
Jisi Liu7b948cc2015-10-19 17:56:27 -0700372 """Bazel rules to create batch tests for protobuf internal.
373
374 Args:
375 name: the name of the rule.
376 modules: a list of modules for tests. The macro will create a py_test for
377 each of the parameter with the source "google/protobuf/%s.py"
378 kargs: extra parameters that will be passed into the py_test.
379
380 """
Jisi Liu993fb702015-10-19 17:19:49 -0700381 for m in modules:
David Z. Chen985c9682016-02-11 18:11:10 -0800382 s = "python/google/protobuf/internal/%s.py" % m
Jisi Liu993fb702015-10-19 17:19:49 -0700383 native.py_test(
384 name="py_%s" % m,
Jisi Liu7b948cc2015-10-19 17:56:27 -0700385 srcs=[s],
386 main=s,
Jisi Liu993fb702015-10-19 17:19:49 -0700387 **kargs)