blob: 050eafc5487d11ce76eb69913a42ec664406946b [file] [log] [blame]
Roger Chen7492b562018-10-29 21:58:47 -07001load("@bazel_skylib//lib:versions.bzl", "versions")
Yannic Bonenbergerd2d6ff52019-08-06 21:12:06 +02002load("@rules_cc//cc:defs.bzl", "cc_library")
Yannic Bonenberger723a85f2020-02-15 13:26:56 +01003load("@rules_proto//proto:defs.bzl", "ProtoInfo")
Yannic Bonenbergerd2d6ff52019-08-06 21:12:06 +02004load("@rules_python//python:defs.bzl", "py_library", "py_test")
Jingwen Chenb2a19082018-01-12 18:42:22 -05005
Damien Martin-Guillerez76547e52016-01-15 14:01:37 +01006def _GetPath(ctx, path):
Paul Yangcecba292018-12-14 16:05:03 -08007 if ctx.label.workspace_root:
8 return ctx.label.workspace_root + "/" + path
9 else:
10 return path
Damien Martin-Guillerez76547e52016-01-15 14:01:37 +010011
Kristina Chodorow4e7ecde2017-01-25 14:10:56 -050012def _IsNewExternal(ctx):
Paul Yangcecba292018-12-14 16:05:03 -080013 # Bazel 0.4.4 and older have genfiles paths that look like:
14 # bazel-out/local-fastbuild/genfiles/external/repo/foo
15 # After the exec root rearrangement, they look like:
16 # ../repo/bazel-out/local-fastbuild/genfiles/foo
17 return ctx.label.workspace_root.startswith("../")
Kristina Chodorow4e7ecde2017-01-25 14:10:56 -050018
Jisi Liu993fb702015-10-19 17:19:49 -070019def _GenDir(ctx):
Paul Yangcecba292018-12-14 16:05:03 -080020 if _IsNewExternal(ctx):
21 # We are using the fact that Bazel 0.4.4+ provides repository-relative paths
22 # for ctx.genfiles_dir.
23 return ctx.genfiles_dir.path + (
24 "/" + ctx.attr.includes[0] if ctx.attr.includes and ctx.attr.includes[0] else ""
Fahrzin Hemmatid1403e52018-03-16 13:23:34 -070025 )
Jisi Liu39362b32015-10-14 17:12:11 -070026
Paul Yangcecba292018-12-14 16:05:03 -080027 # This means that we're either in the old version OR the new version in the local repo.
28 # Either way, appending the source path to the genfiles dir works.
29 return ctx.var["GENDIR"] + "/" + _SourceDir(ctx)
30
31def _SourceDir(ctx):
32 if not ctx.attr.includes:
33 return ctx.label.workspace_root
34 if not ctx.attr.includes[0]:
35 return _GetPath(ctx, ctx.label.package)
36 if not ctx.label.package:
37 return _GetPath(ctx, ctx.attr.includes[0])
38 return _GetPath(ctx, ctx.label.package + "/" + ctx.attr.includes[0])
39
40def _CcHdrs(srcs, use_grpc_plugin = False):
41 ret = [s[:-len(".proto")] + ".pb.h" for s in srcs]
42 if use_grpc_plugin:
43 ret += [s[:-len(".proto")] + ".grpc.pb.h" for s in srcs]
44 return ret
45
46def _CcSrcs(srcs, use_grpc_plugin = False):
47 ret = [s[:-len(".proto")] + ".pb.cc" for s in srcs]
48 if use_grpc_plugin:
49 ret += [s[:-len(".proto")] + ".grpc.pb.cc" for s in srcs]
50 return ret
51
52def _CcOuts(srcs, use_grpc_plugin = False):
53 return _CcHdrs(srcs, use_grpc_plugin) + _CcSrcs(srcs, use_grpc_plugin)
54
55def _PyOuts(srcs, use_grpc_plugin = False):
56 ret = [s[:-len(".proto")] + "_pb2.py" for s in srcs]
57 if use_grpc_plugin:
58 ret += [s[:-len(".proto")] + "_pb2_grpc.py" for s in srcs]
59 return ret
60
61def _RelativeOutputPath(path, include, dest = ""):
62 if include == None:
63 return path
64
65 if not path.startswith(include):
66 fail("Include path %s isn't part of the path %s." % (include, path))
67
68 if include and include[-1] != "/":
69 include = include + "/"
70 if dest and dest[-1] != "/":
71 dest = dest + "/"
72
73 path = path[len(include):]
74 return dest + path
75
76def _proto_gen_impl(ctx):
77 """General implementation for generating protos"""
78 srcs = ctx.files.srcs
Harvey Tuch7cf3f7a2020-01-24 13:47:15 -050079 deps = depset(direct=ctx.files.srcs)
Paul Yangcecba292018-12-14 16:05:03 -080080 source_dir = _SourceDir(ctx)
81 gen_dir = _GenDir(ctx).rstrip("/")
82 if source_dir:
Harvey Tuch7cf3f7a2020-01-24 13:47:15 -050083 import_flags = depset(direct=["-I" + source_dir, "-I" + gen_dir])
Paul Yangcecba292018-12-14 16:05:03 -080084 else:
Harvey Tuch7cf3f7a2020-01-24 13:47:15 -050085 import_flags = depset(direct=["-I."])
Paul Yangcecba292018-12-14 16:05:03 -080086
87 for dep in ctx.attr.deps:
Harvey Tuche492e5a2020-05-26 14:27:56 -040088 if type(dep.proto.import_flags) == "list":
89 import_flags = depset(transitive=[import_flags], direct=dep.proto.import_flags)
90 else:
91 import_flags = depset(transitive=[import_flags, dep.proto.import_flags])
92 if type(dep.proto.deps) == "list":
93 deps = depset(transitive=[deps], direct=dep.proto.deps)
94 else:
95 deps = depset(transitive=[deps, dep.proto.deps])
Paul Yangcecba292018-12-14 16:05:03 -080096
97 if not ctx.attr.gen_cc and not ctx.attr.gen_py and not ctx.executable.plugin:
98 return struct(
99 proto = struct(
100 srcs = srcs,
101 import_flags = import_flags,
102 deps = deps,
103 ),
104 )
105
106 for src in srcs:
107 args = []
108
109 in_gen_dir = src.root.path == gen_dir
110 if in_gen_dir:
111 import_flags_real = []
Harvey Tuch7cf3f7a2020-01-24 13:47:15 -0500112 for f in import_flags.to_list():
Paul Yangcecba292018-12-14 16:05:03 -0800113 path = f.replace("-I", "")
114 import_flags_real.append("-I$(realpath -s %s)" % path)
115
116 outs = []
117 use_grpc_plugin = (ctx.attr.plugin_language == "grpc" and ctx.attr.plugin)
118 path_tpl = "$(realpath %s)" if in_gen_dir else "%s"
119 if ctx.attr.gen_cc:
120 args += [("--cpp_out=" + path_tpl) % gen_dir]
121 outs.extend(_CcOuts([src.basename], use_grpc_plugin = use_grpc_plugin))
122 if ctx.attr.gen_py:
123 args += [("--python_out=" + path_tpl) % gen_dir]
124 outs.extend(_PyOuts([src.basename], use_grpc_plugin = use_grpc_plugin))
125
126 outs = [ctx.actions.declare_file(out, sibling = src) for out in outs]
Harvey Tuch7cf3f7a2020-01-24 13:47:15 -0500127 inputs = [src] + deps.to_list()
Benjamin Peterson6153f802019-06-03 08:56:33 -0700128 tools = [ctx.executable.protoc]
Paul Yangcecba292018-12-14 16:05:03 -0800129 if ctx.executable.plugin:
130 plugin = ctx.executable.plugin
131 lang = ctx.attr.plugin_language
132 if not lang and plugin.basename.startswith("protoc-gen-"):
133 lang = plugin.basename[len("protoc-gen-"):]
134 if not lang:
135 fail("cannot infer the target language of plugin", "plugin_language")
136
137 outdir = "." if in_gen_dir else gen_dir
138
139 if ctx.attr.plugin_options:
140 outdir = ",".join(ctx.attr.plugin_options) + ":" + outdir
141 args += [("--plugin=protoc-gen-%s=" + path_tpl) % (lang, plugin.path)]
142 args += ["--%s_out=%s" % (lang, outdir)]
Benjamin Peterson6153f802019-06-03 08:56:33 -0700143 tools.append(plugin)
Paul Yangcecba292018-12-14 16:05:03 -0800144
145 if not in_gen_dir:
146 ctx.actions.run(
147 inputs = inputs,
Benjamin Peterson6153f802019-06-03 08:56:33 -0700148 tools = tools,
Paul Yangcecba292018-12-14 16:05:03 -0800149 outputs = outs,
Harvey Tuch7cf3f7a2020-01-24 13:47:15 -0500150 arguments = args + import_flags.to_list() + [src.path],
Paul Yangcecba292018-12-14 16:05:03 -0800151 executable = ctx.executable.protoc,
152 mnemonic = "ProtoCompile",
153 use_default_shell_env = True,
154 )
155 else:
156 for out in outs:
157 orig_command = " ".join(
158 ["$(realpath %s)" % ctx.executable.protoc.path] + args +
159 import_flags_real + ["-I.", src.basename],
160 )
161 command = ";".join([
162 'CMD="%s"' % orig_command,
163 "cd %s" % src.dirname,
164 "${CMD}",
165 "cd -",
166 ])
167 generated_out = "/".join([gen_dir, out.basename])
168 if generated_out != out.path:
169 command += ";mv %s %s" % (generated_out, out.path)
170 ctx.actions.run_shell(
Keith Smileyca3ead72019-05-21 17:31:34 -0700171 inputs = inputs,
Paul Yangcecba292018-12-14 16:05:03 -0800172 outputs = [out],
173 command = command,
174 mnemonic = "ProtoCompile",
Benjamin Peterson6153f802019-06-03 08:56:33 -0700175 tools = tools,
Paul Yangcecba292018-12-14 16:05:03 -0800176 use_default_shell_env = True,
177 )
178
179 return struct(
180 proto = struct(
181 srcs = srcs,
182 import_flags = import_flags,
183 deps = deps,
184 ),
185 )
Jisi Liu39362b32015-10-14 17:12:11 -0700186
Yuki Yugui Sonoda5977fb02016-06-01 16:23:15 +0900187proto_gen = rule(
Jisi Liu39362b32015-10-14 17:12:11 -0700188 attrs = {
Jisi Liuee8131a2015-10-14 17:20:05 -0700189 "srcs": attr.label_list(allow_files = True),
190 "deps": attr.label_list(providers = ["proto"]),
Jisi Liu53a56be2015-10-20 15:18:20 -0700191 "includes": attr.string_list(),
Jisi Liuee8131a2015-10-14 17:20:05 -0700192 "protoc": attr.label(
Vladimir Moskvaa86e6d82016-09-09 13:21:35 +0200193 cfg = "host",
Jisi Liuee8131a2015-10-14 17:20:05 -0700194 executable = True,
James Juddd5f0dac2018-08-14 21:55:35 -0600195 allow_single_file = True,
Jisi Liuee8131a2015-10-14 17:20:05 -0700196 mandatory = True,
197 ),
Yuki Yugui Sonoda5977fb02016-06-01 16:23:15 +0900198 "plugin": attr.label(
Vladimir Moskvaa86e6d82016-09-09 13:21:35 +0200199 cfg = "host",
Yuki Yugui Sonoda5977fb02016-06-01 16:23:15 +0900200 allow_files = True,
Manjunath Kudlurf0966a72016-02-22 14:30:43 -0800201 executable = True,
Manjunath Kudlurf0966a72016-02-22 14:30:43 -0800202 ),
Yuki Yugui Sonoda5977fb02016-06-01 16:23:15 +0900203 "plugin_language": attr.string(),
204 "plugin_options": attr.string_list(),
Jisi Liuee8131a2015-10-14 17:20:05 -0700205 "gen_cc": attr.bool(),
206 "gen_py": attr.bool(),
207 "outs": attr.output_list(),
208 },
209 output_to_genfiles = True,
Jisi Liu9c7d9c02015-10-15 10:51:32 -0700210 implementation = _proto_gen_impl,
Jisi Liu39362b32015-10-14 17:12:11 -0700211)
Yuki Yugui Sonoda5977fb02016-06-01 16:23:15 +0900212"""Generates codes from Protocol Buffers definitions.
213
214This rule helps you to implement Skylark macros specific to the target
215language. You should prefer more specific `cc_proto_library `,
216`py_proto_library` and others unless you are adding such wrapper macros.
217
218Args:
219 srcs: Protocol Buffers definition files (.proto) to run the protocol compiler
220 against.
221 deps: a list of dependency labels; must be other proto libraries.
222 includes: a list of include paths to .proto files.
223 protoc: the label of the protocol compiler to generate the sources.
224 plugin: the label of the protocol compiler plugin to be passed to the protocol
225 compiler.
226 plugin_language: the language of the generated sources
227 plugin_options: a list of options to be passed to the plugin
Kristina Chodorow4e7ecde2017-01-25 14:10:56 -0500228 gen_cc: generates C++ sources in addition to the ones from the plugin.
Yuki Yugui Sonoda5977fb02016-06-01 16:23:15 +0900229 gen_py: generates Python sources in addition to the ones from the plugin.
230 outs: a list of labels of the expected outputs from the protocol compiler.
231"""
Jisi Liu39362b32015-10-14 17:12:11 -0700232
Yannic Bonenberger723a85f2020-02-15 13:26:56 +0100233def _adapt_proto_library_impl(ctx):
234 deps = [dep[ProtoInfo] for dep in ctx.attr.deps]
235
236 srcs = [src for dep in deps for src in dep.direct_sources]
237 return struct(
238 proto = struct(
239 srcs = srcs,
240 import_flags = ["-I{}".format(path) for dep in deps for path in dep.transitive_proto_path.to_list()],
241 deps = srcs,
242 ),
243 )
244
245adapt_proto_library = rule(
246 implementation = _adapt_proto_library_impl,
247 attrs = {
248 "deps": attr.label_list(
249 mandatory = True,
250 providers = [ProtoInfo],
251 ),
252 },
253 doc = "Adapts `proto_library` from `@rules_proto` to be used with `{cc,py}_proto_library` from this file.",
254)
255
Jisi Liu39362b32015-10-14 17:12:11 -0700256def cc_proto_library(
Jisi Liu125a91b2015-10-14 17:37:39 -0700257 name,
Paul Yangcecba292018-12-14 16:05:03 -0800258 srcs = [],
259 deps = [],
260 cc_libs = [],
261 include = None,
262 protoc = "@com_google_protobuf//:protoc",
Paul Yangcecba292018-12-14 16:05:03 -0800263 use_grpc_plugin = False,
264 default_runtime = "@com_google_protobuf//:protobuf",
Jisi Liu125a91b2015-10-14 17:37:39 -0700265 **kargs):
Paul Yangcecba292018-12-14 16:05:03 -0800266 """Bazel rule to create a C++ protobuf library from proto source files
Jisi Liu3101e732015-10-16 12:46:26 -0700267
Paul Yangcecba292018-12-14 16:05:03 -0800268 NOTE: the rule is only an internal workaround to generate protos. The
269 interface may change and the rule may be removed when bazel has introduced
270 the native rule.
Jisi Liud4bef7d2015-11-02 12:24:32 -0800271
Paul Yangcecba292018-12-14 16:05:03 -0800272 Args:
273 name: the name of the cc_proto_library.
274 srcs: the .proto files of the cc_proto_library.
275 deps: a list of dependency labels; must be cc_proto_library.
276 cc_libs: a list of other cc_library targets depended by the generated
277 cc_library.
278 include: a string indicating the include path of the .proto files.
279 protoc: the label of the protocol compiler to generate the sources.
Paul Yangcecba292018-12-14 16:05:03 -0800280 use_grpc_plugin: a flag to indicate whether to call the grpc C++ plugin
281 when processing the proto files.
282 default_runtime: the implicitly default runtime which will be depended on by
283 the generated cc_library target.
284 **kargs: other keyword arguments that are passed to cc_library.
Paul Yangcecba292018-12-14 16:05:03 -0800285 """
Jisi Liu39362b32015-10-14 17:12:11 -0700286
Paul Yangcecba292018-12-14 16:05:03 -0800287 includes = []
288 if include != None:
289 includes = [include]
Jisi Liu53a56be2015-10-20 15:18:20 -0700290
Paul Yangcecba292018-12-14 16:05:03 -0800291 grpc_cpp_plugin = None
292 if use_grpc_plugin:
293 grpc_cpp_plugin = "//external:grpc_cpp_plugin"
294
295 gen_srcs = _CcSrcs(srcs, use_grpc_plugin)
296 gen_hdrs = _CcHdrs(srcs, use_grpc_plugin)
297 outs = gen_srcs + gen_hdrs
298
Yuki Yugui Sonoda5977fb02016-06-01 16:23:15 +0900299 proto_gen(
Paul Yangcecba292018-12-14 16:05:03 -0800300 name = name + "_genproto",
301 srcs = srcs,
302 deps = [s + "_genproto" for s in deps],
303 includes = includes,
304 protoc = protoc,
305 plugin = grpc_cpp_plugin,
306 plugin_language = "grpc",
307 gen_cc = 1,
308 outs = outs,
309 visibility = ["//visibility:public"],
Jisi Liu39362b32015-10-14 17:12:11 -0700310 )
Paul Yangcecba292018-12-14 16:05:03 -0800311
312 if default_runtime and not default_runtime in cc_libs:
313 cc_libs = cc_libs + [default_runtime]
314 if use_grpc_plugin:
315 cc_libs = cc_libs + ["//external:grpc_lib"]
Yannic Bonenbergerbf0c69e2019-07-26 13:14:19 +0200316 cc_library(
Paul Yangcecba292018-12-14 16:05:03 -0800317 name = name,
318 srcs = gen_srcs,
319 hdrs = gen_hdrs,
320 deps = cc_libs + deps,
321 includes = includes,
322 **kargs
323 )
Jisi Liu993fb702015-10-19 17:19:49 -0700324
Yannicf0cb9cd2020-02-13 22:04:14 +0100325def _internal_gen_well_known_protos_java_impl(ctx):
326 args = ctx.actions.args()
Steven Parkesea188662016-02-25 07:53:19 -0800327
Yannicf0cb9cd2020-02-13 22:04:14 +0100328 deps = [d[ProtoInfo] for d in ctx.attr.deps]
329
330 srcjar = ctx.actions.declare_file("{}.srcjar".format(ctx.attr.name))
331 args.add("--java_out", srcjar)
332
333 descriptors = depset(
334 transitive = [dep.transitive_descriptor_sets for dep in deps],
Paul Yangcecba292018-12-14 16:05:03 -0800335 )
Yannicf0cb9cd2020-02-13 22:04:14 +0100336 args.add_joined(
337 "--descriptor_set_in",
338 descriptors,
339 join_with = ctx.configuration.host_path_separator,
340 )
341
342 for dep in deps:
343 if "." == dep.proto_source_root:
344 args.add_all([src.path for src in dep.direct_sources])
345 else:
346 source_root = dep.proto_source_root
347 offset = len(source_root) + 1 # + '/'.
348 args.add_all([src.path[offset:] for src in dep.direct_sources])
349
350 ctx.actions.run(
351 executable = ctx.executable._protoc,
352 inputs = descriptors,
353 outputs = [srcjar],
354 arguments = [args],
355 )
356
357 return [
358 DefaultInfo(
359 files = depset([srcjar]),
360 ),
361 ]
362
363internal_gen_well_known_protos_java = rule(
364 implementation = _internal_gen_well_known_protos_java_impl,
365 attrs = {
366 "deps": attr.label_list(
367 mandatory = True,
368 providers = [ProtoInfo],
369 ),
370 "_protoc": attr.label(
371 executable = True,
372 cfg = "host",
373 default = "@com_google_protobuf//:protoc",
374 ),
375 },
376)
Steven Parkesea188662016-02-25 07:53:19 -0800377
David Z. Chen02cd45c2016-05-20 16:49:04 -0700378def internal_copied_filegroup(name, srcs, strip_prefix, dest, **kwargs):
Paul Yangcecba292018-12-14 16:05:03 -0800379 """Macro to copy files to a different directory and then create a filegroup.
David Z. Chen02cd45c2016-05-20 16:49:04 -0700380
Paul Yangcecba292018-12-14 16:05:03 -0800381 This is used by the //:protobuf_python py_proto_library target to work around
382 an issue caused by Python source files that are part of the same Python
383 package being in separate directories.
David Z. Chen02cd45c2016-05-20 16:49:04 -0700384
Paul Yangcecba292018-12-14 16:05:03 -0800385 Args:
386 srcs: The source files to copy and add to the filegroup.
387 strip_prefix: Path to the root of the files to copy.
388 dest: The directory to copy the source files into.
389 **kwargs: extra arguments that will be passesd to the filegroup.
390 """
391 outs = [_RelativeOutputPath(s, strip_prefix, dest) for s in srcs]
David Z. Chen02cd45c2016-05-20 16:49:04 -0700392
Paul Yangcecba292018-12-14 16:05:03 -0800393 native.genrule(
394 name = name + "_genrule",
395 srcs = srcs,
396 outs = outs,
397 cmd = " && ".join(
398 ["cp $(location %s) $(location %s)" %
399 (s, _RelativeOutputPath(s, strip_prefix, dest)) for s in srcs],
400 ),
401 )
David Z. Chen02cd45c2016-05-20 16:49:04 -0700402
Paul Yangcecba292018-12-14 16:05:03 -0800403 native.filegroup(
404 name = name,
405 srcs = outs,
406 **kwargs
407 )
David Z. Chen02cd45c2016-05-20 16:49:04 -0700408
Jisi Liu993fb702015-10-19 17:19:49 -0700409def py_proto_library(
410 name,
Paul Yangcecba292018-12-14 16:05:03 -0800411 srcs = [],
412 deps = [],
413 py_libs = [],
414 py_extra_srcs = [],
415 include = None,
416 default_runtime = "@com_google_protobuf//:protobuf_python",
417 protoc = "@com_google_protobuf//:protoc",
418 use_grpc_plugin = False,
Jisi Liu993fb702015-10-19 17:19:49 -0700419 **kargs):
Paul Yangcecba292018-12-14 16:05:03 -0800420 """Bazel rule to create a Python protobuf library from proto source files
Jisi Liu7b948cc2015-10-19 17:56:27 -0700421
Paul Yangcecba292018-12-14 16:05:03 -0800422 NOTE: the rule is only an internal workaround to generate protos. The
423 interface may change and the rule may be removed when bazel has introduced
424 the native rule.
Jisi Liud4bef7d2015-11-02 12:24:32 -0800425
Paul Yangcecba292018-12-14 16:05:03 -0800426 Args:
427 name: the name of the py_proto_library.
428 srcs: the .proto files of the py_proto_library.
429 deps: a list of dependency labels; must be py_proto_library.
430 py_libs: a list of other py_library targets depended by the generated
431 py_library.
432 py_extra_srcs: extra source files that will be added to the output
433 py_library. This attribute is used for internal bootstrapping.
434 include: a string indicating the include path of the .proto files.
435 default_runtime: the implicitly default runtime which will be depended on by
436 the generated py_library target.
437 protoc: the label of the protocol compiler to generate the sources.
438 use_grpc_plugin: a flag to indicate whether to call the Python C++ plugin
439 when processing the proto files.
Leo12236c62020-05-04 11:23:44 +0900440 **kargs: other keyword arguments that are passed to py_library.
Jisi Liu7b948cc2015-10-19 17:56:27 -0700441
Paul Yangcecba292018-12-14 16:05:03 -0800442 """
443 outs = _PyOuts(srcs, use_grpc_plugin)
Jisi Liu53a56be2015-10-20 15:18:20 -0700444
Paul Yangcecba292018-12-14 16:05:03 -0800445 includes = []
446 if include != None:
447 includes = [include]
Jisi Liu53a56be2015-10-20 15:18:20 -0700448
Paul Yangcecba292018-12-14 16:05:03 -0800449 grpc_python_plugin = None
450 if use_grpc_plugin:
451 grpc_python_plugin = "//external:grpc_python_plugin"
452 # Note: Generated grpc code depends on Python grpc module. This dependency
453 # is not explicitly listed in py_libs. Instead, host system is assumed to
454 # have grpc installed.
Wiktor Tomczak0fa31b22016-11-22 20:18:46 +0100455
Paul Yangcecba292018-12-14 16:05:03 -0800456 proto_gen(
457 name = name + "_genproto",
458 srcs = srcs,
459 deps = [s + "_genproto" for s in deps],
460 includes = includes,
461 protoc = protoc,
462 gen_py = 1,
463 outs = outs,
464 visibility = ["//visibility:public"],
465 plugin = grpc_python_plugin,
466 plugin_language = "grpc",
467 )
Jisi Liu993fb702015-10-19 17:19:49 -0700468
Paul Yangcecba292018-12-14 16:05:03 -0800469 if default_runtime and not default_runtime in py_libs + deps:
470 py_libs = py_libs + [default_runtime]
Yannic Bonenbergerd2d6ff52019-08-06 21:12:06 +0200471 py_library(
Paul Yangcecba292018-12-14 16:05:03 -0800472 name = name,
473 srcs = outs + py_extra_srcs,
474 deps = py_libs + deps,
475 imports = includes,
476 **kargs
477 )
Jisi Liu993fb702015-10-19 17:19:49 -0700478
479def internal_protobuf_py_tests(
Paul Yangcecba292018-12-14 16:05:03 -0800480 name,
481 modules = [],
482 **kargs):
483 """Bazel rules to create batch tests for protobuf internal.
Jisi Liu7b948cc2015-10-19 17:56:27 -0700484
Paul Yangcecba292018-12-14 16:05:03 -0800485 Args:
486 name: the name of the rule.
487 modules: a list of modules for tests. The macro will create a py_test for
488 each of the parameter with the source "google/protobuf/%s.py"
489 kargs: extra parameters that will be passed into the py_test.
Jisi Liu7b948cc2015-10-19 17:56:27 -0700490
Paul Yangcecba292018-12-14 16:05:03 -0800491 """
492 for m in modules:
493 s = "python/google/protobuf/internal/%s.py" % m
Yannic Bonenbergerd2d6ff52019-08-06 21:12:06 +0200494 py_test(
Paul Yangcecba292018-12-14 16:05:03 -0800495 name = "py_%s" % m,
496 srcs = [s],
497 main = s,
498 **kargs
499 )
Fahrzin Hemmati35119e32017-11-28 14:24:53 -0800500
501def check_protobuf_required_bazel_version():
Paul Yangcecba292018-12-14 16:05:03 -0800502 """For WORKSPACE files, to check the installed version of bazel.
Fahrzin Hemmati35119e32017-11-28 14:24:53 -0800503
Paul Yangcecba292018-12-14 16:05:03 -0800504 This ensures bazel supports our approach to proto_library() depending on a
505 copied filegroup. (Fixed in bazel 0.5.4)
506 """
507 versions.check(minimum_bazel_version = "0.5.4")