blob: d96eeb4c9a5c4bb852b01f12c2946eba7bd18e3d [file] [log] [blame]
Roger Chen7492b562018-10-29 21:58:47 -07001load("@bazel_skylib//lib:versions.bzl", "versions")
Mike Kruskal23f14812022-10-10 21:05:53 -07002load("@rules_cc//cc:defs.bzl", "objc_library")
Yannic Bonenberger723a85f2020-02-15 13:26:56 +01003load("@rules_proto//proto:defs.bzl", "ProtoInfo")
Mike Kruskal23f14812022-10-10 21:05:53 -07004load("@rules_python//python:defs.bzl", "py_library")
Mike Kruskal633e8f72023-01-03 12:11:31 -08005load("@rules_ruby//ruby:defs.bzl", "ruby_library")
Jingwen Chenb2a19082018-01-12 18:42:22 -05006
Damien Martin-Guillerez76547e52016-01-15 14:01:37 +01007def _GetPath(ctx, path):
Paul Yangcecba292018-12-14 16:05:03 -08008 if ctx.label.workspace_root:
9 return ctx.label.workspace_root + "/" + path
10 else:
11 return path
Damien Martin-Guillerez76547e52016-01-15 14:01:37 +010012
Kristina Chodorow4e7ecde2017-01-25 14:10:56 -050013def _IsNewExternal(ctx):
Paul Yangcecba292018-12-14 16:05:03 -080014 # Bazel 0.4.4 and older have genfiles paths that look like:
15 # bazel-out/local-fastbuild/genfiles/external/repo/foo
16 # After the exec root rearrangement, they look like:
17 # ../repo/bazel-out/local-fastbuild/genfiles/foo
18 return ctx.label.workspace_root.startswith("../")
Kristina Chodorow4e7ecde2017-01-25 14:10:56 -050019
Jisi Liu993fb702015-10-19 17:19:49 -070020def _GenDir(ctx):
Paul Yangcecba292018-12-14 16:05:03 -080021 if _IsNewExternal(ctx):
22 # We are using the fact that Bazel 0.4.4+ provides repository-relative paths
23 # for ctx.genfiles_dir.
24 return ctx.genfiles_dir.path + (
25 "/" + ctx.attr.includes[0] if ctx.attr.includes and ctx.attr.includes[0] else ""
Fahrzin Hemmatid1403e52018-03-16 13:23:34 -070026 )
Jisi Liu39362b32015-10-14 17:12:11 -070027
Paul Yangcecba292018-12-14 16:05:03 -080028 # This means that we're either in the old version OR the new version in the local repo.
29 # Either way, appending the source path to the genfiles dir works.
30 return ctx.var["GENDIR"] + "/" + _SourceDir(ctx)
31
32def _SourceDir(ctx):
33 if not ctx.attr.includes:
34 return ctx.label.workspace_root
35 if not ctx.attr.includes[0]:
36 return _GetPath(ctx, ctx.label.package)
37 if not ctx.label.package:
38 return _GetPath(ctx, ctx.attr.includes[0])
39 return _GetPath(ctx, ctx.label.package + "/" + ctx.attr.includes[0])
40
Mike Kruskaled5c57a2022-08-10 22:51:29 -070041def _ObjcBase(srcs):
42 return [
43 "".join([token.capitalize() for token in src[:-len(".proto")].split("_")])
Mike Kruskal23f14812022-10-10 21:05:53 -070044 for src in srcs
45 ]
Paul Yangcecba292018-12-14 16:05:03 -080046
Mike Kruskaled5c57a2022-08-10 22:51:29 -070047def _ObjcHdrs(srcs):
Mike Kruskal23f14812022-10-10 21:05:53 -070048 return [src + ".pbobjc.h" for src in _ObjcBase(srcs)]
Paul Yangcecba292018-12-14 16:05:03 -080049
Mike Kruskaled5c57a2022-08-10 22:51:29 -070050def _ObjcSrcs(srcs):
Mike Kruskal23f14812022-10-10 21:05:53 -070051 return [src + ".pbobjc.m" for src in _ObjcBase(srcs)]
Mike Kruskaled5c57a2022-08-10 22:51:29 -070052
53def _ObjcOuts(srcs, out_type):
54 if out_type == "hdrs":
55 return _ObjcHdrs(srcs)
56 if out_type == "srcs":
57 return _ObjcSrcs(srcs)
58 return _ObjcHdrs(srcs) + _ObjcSrcs(srcs)
Paul Yangcecba292018-12-14 16:05:03 -080059
60def _PyOuts(srcs, use_grpc_plugin = False):
61 ret = [s[:-len(".proto")] + "_pb2.py" for s in srcs]
62 if use_grpc_plugin:
63 ret += [s[:-len(".proto")] + "_pb2_grpc.py" for s in srcs]
64 return ret
65
Mike Kruskaled5c57a2022-08-10 22:51:29 -070066def _RubyOuts(srcs):
67 return [s[:-len(".proto")] + "_pb.rb" for s in srcs]
68
69def _CsharpOuts(srcs):
70 return [
71 "".join([token.capitalize() for token in src[:-len(".proto")].split("_")]) + ".cs"
Mike Kruskal23f14812022-10-10 21:05:53 -070072 for src in srcs
73 ]
Mike Kruskaled5c57a2022-08-10 22:51:29 -070074
David L. Jonesd60c0d22022-05-11 19:13:56 -070075ProtoGenInfo = provider(
76 fields = ["srcs", "import_flags", "deps"],
77)
78
Paul Yangcecba292018-12-14 16:05:03 -080079def _proto_gen_impl(ctx):
80 """General implementation for generating protos"""
81 srcs = ctx.files.srcs
Mike Kruskaled5c57a2022-08-10 22:51:29 -070082 langs = ctx.attr.langs or []
83 out_type = ctx.attr.out_type
David L. Jonesd60c0d22022-05-11 19:13:56 -070084 deps = depset(direct = ctx.files.srcs)
Paul Yangcecba292018-12-14 16:05:03 -080085 source_dir = _SourceDir(ctx)
86 gen_dir = _GenDir(ctx).rstrip("/")
Derek Perezb55c8e42022-04-06 11:35:10 -070087 import_flags = []
David L. Jonesd60c0d22022-05-11 19:13:56 -070088
Paul Yangcecba292018-12-14 16:05:03 -080089 if source_dir:
Ivo List15add1a2022-01-29 01:44:42 +010090 has_sources = any([src.is_source for src in srcs])
Ivo List15add1a2022-01-29 01:44:42 +010091 if has_sources:
92 import_flags += ["-I" + source_dir]
Paul Yangcecba292018-12-14 16:05:03 -080093 else:
Derek Perezb55c8e42022-04-06 11:35:10 -070094 import_flags += ["-I."]
95
96 has_generated = any([not src.is_source for src in srcs])
97 if has_generated:
98 import_flags += ["-I" + gen_dir]
99
Mike Kruskaled5c57a2022-08-10 22:51:29 -0700100 if ctx.attr.includes:
101 for include in ctx.attr.includes:
Mike Kruskal23f14812022-10-10 21:05:53 -0700102 import_flags += ["-I" + _GetPath(ctx, include)]
Mike Kruskaled5c57a2022-08-10 22:51:29 -0700103
David L. Jonesd60c0d22022-05-11 19:13:56 -0700104 import_flags = depset(direct = import_flags)
Paul Yangcecba292018-12-14 16:05:03 -0800105
106 for dep in ctx.attr.deps:
David L. Jonesd60c0d22022-05-11 19:13:56 -0700107 dep_proto = dep[ProtoGenInfo]
108 if type(dep_proto.import_flags) == "list":
109 import_flags = depset(
110 transitive = [import_flags],
111 direct = dep_proto.import_flags,
112 )
Harvey Tuche492e5a2020-05-26 14:27:56 -0400113 else:
David L. Jonesd60c0d22022-05-11 19:13:56 -0700114 import_flags = depset(
115 transitive = [import_flags, dep_proto.import_flags],
116 )
117 if type(dep_proto.deps) == "list":
118 deps = depset(transitive = [deps], direct = dep_proto.deps)
Harvey Tuche492e5a2020-05-26 14:27:56 -0400119 else:
David L. Jonesd60c0d22022-05-11 19:13:56 -0700120 deps = depset(transitive = [deps, dep_proto.deps])
Paul Yangcecba292018-12-14 16:05:03 -0800121
Mike Kruskaled5c57a2022-08-10 22:51:29 -0700122 if not langs and not ctx.executable.plugin:
David L. Jonesd60c0d22022-05-11 19:13:56 -0700123 return [
124 ProtoGenInfo(
Paul Yangcecba292018-12-14 16:05:03 -0800125 srcs = srcs,
126 import_flags = import_flags,
127 deps = deps,
128 ),
David L. Jonesd60c0d22022-05-11 19:13:56 -0700129 ]
Paul Yangcecba292018-12-14 16:05:03 -0800130
David L. Jonesd60c0d22022-05-11 19:13:56 -0700131 generated_files = []
Paul Yangcecba292018-12-14 16:05:03 -0800132 for src in srcs:
133 args = []
134
135 in_gen_dir = src.root.path == gen_dir
136 if in_gen_dir:
137 import_flags_real = []
Harvey Tuch7cf3f7a2020-01-24 13:47:15 -0500138 for f in import_flags.to_list():
Paul Yangcecba292018-12-14 16:05:03 -0800139 path = f.replace("-I", "")
140 import_flags_real.append("-I$(realpath -s %s)" % path)
141
Paul Yangcecba292018-12-14 16:05:03 -0800142 use_grpc_plugin = (ctx.attr.plugin_language == "grpc" and ctx.attr.plugin)
143 path_tpl = "$(realpath %s)" if in_gen_dir else "%s"
Paul Yangcecba292018-12-14 16:05:03 -0800144
Mike Kruskaled5c57a2022-08-10 22:51:29 -0700145 outs = []
146 for lang in langs:
147 if lang == "csharp":
148 outs.extend(_CsharpOuts([src.basename]))
149 elif lang == "objc":
150 outs.extend(_ObjcOuts([src.basename], out_type = out_type))
151 elif lang == "python":
152 outs.extend(_PyOuts([src.basename], use_grpc_plugin = use_grpc_plugin))
153 elif lang == "ruby":
154 outs.extend(_RubyOuts([src.basename]))
Mike Kruskal23f14812022-10-10 21:05:53 -0700155
Mike Kruskaled5c57a2022-08-10 22:51:29 -0700156 # Otherwise, rely on user-supplied outs.
157 args += [("--%s_out=" + path_tpl) % (lang, gen_dir)]
158
159 if ctx.attr.outs:
160 outs.extend(ctx.attr.outs)
Paul Yangcecba292018-12-14 16:05:03 -0800161 outs = [ctx.actions.declare_file(out, sibling = src) for out in outs]
David L. Jonesd60c0d22022-05-11 19:13:56 -0700162 generated_files.extend(outs)
163
Harvey Tuch7cf3f7a2020-01-24 13:47:15 -0500164 inputs = [src] + deps.to_list()
Benjamin Peterson6153f802019-06-03 08:56:33 -0700165 tools = [ctx.executable.protoc]
Paul Yangcecba292018-12-14 16:05:03 -0800166 if ctx.executable.plugin:
167 plugin = ctx.executable.plugin
168 lang = ctx.attr.plugin_language
169 if not lang and plugin.basename.startswith("protoc-gen-"):
170 lang = plugin.basename[len("protoc-gen-"):]
171 if not lang:
172 fail("cannot infer the target language of plugin", "plugin_language")
173
174 outdir = "." if in_gen_dir else gen_dir
175
176 if ctx.attr.plugin_options:
177 outdir = ",".join(ctx.attr.plugin_options) + ":" + outdir
178 args += [("--plugin=protoc-gen-%s=" + path_tpl) % (lang, plugin.path)]
179 args += ["--%s_out=%s" % (lang, outdir)]
Benjamin Peterson6153f802019-06-03 08:56:33 -0700180 tools.append(plugin)
Paul Yangcecba292018-12-14 16:05:03 -0800181
182 if not in_gen_dir:
183 ctx.actions.run(
184 inputs = inputs,
Benjamin Peterson6153f802019-06-03 08:56:33 -0700185 tools = tools,
Paul Yangcecba292018-12-14 16:05:03 -0800186 outputs = outs,
Harvey Tuch7cf3f7a2020-01-24 13:47:15 -0500187 arguments = args + import_flags.to_list() + [src.path],
Paul Yangcecba292018-12-14 16:05:03 -0800188 executable = ctx.executable.protoc,
189 mnemonic = "ProtoCompile",
190 use_default_shell_env = True,
191 )
192 else:
193 for out in outs:
194 orig_command = " ".join(
195 ["$(realpath %s)" % ctx.executable.protoc.path] + args +
Derek Perezb55c8e42022-04-06 11:35:10 -0700196 import_flags_real + [src.basename],
Paul Yangcecba292018-12-14 16:05:03 -0800197 )
198 command = ";".join([
199 'CMD="%s"' % orig_command,
200 "cd %s" % src.dirname,
201 "${CMD}",
202 "cd -",
203 ])
204 generated_out = "/".join([gen_dir, out.basename])
205 if generated_out != out.path:
206 command += ";mv %s %s" % (generated_out, out.path)
207 ctx.actions.run_shell(
Keith Smileyca3ead72019-05-21 17:31:34 -0700208 inputs = inputs,
Paul Yangcecba292018-12-14 16:05:03 -0800209 outputs = [out],
210 command = command,
211 mnemonic = "ProtoCompile",
Benjamin Peterson6153f802019-06-03 08:56:33 -0700212 tools = tools,
Paul Yangcecba292018-12-14 16:05:03 -0800213 use_default_shell_env = True,
214 )
215
David L. Jonesd60c0d22022-05-11 19:13:56 -0700216 return [
217 ProtoGenInfo(
Paul Yangcecba292018-12-14 16:05:03 -0800218 srcs = srcs,
219 import_flags = import_flags,
220 deps = deps,
221 ),
David L. Jonesd60c0d22022-05-11 19:13:56 -0700222 DefaultInfo(files = depset(generated_files)),
223 ]
Jisi Liu39362b32015-10-14 17:12:11 -0700224
Mike Kruskaled5c57a2022-08-10 22:51:29 -0700225"""Generates codes from Protocol Buffers definitions.
226
227This rule helps you to implement Skylark macros specific to the target
228language. You should prefer more specific `cc_proto_library `,
229`py_proto_library` and others unless you are adding such wrapper macros.
230
231Args:
232 srcs: Protocol Buffers definition files (.proto) to run the protocol compiler
233 against.
234 deps: a list of dependency labels; must be other proto libraries.
235 includes: a list of include paths to .proto files.
236 protoc: the label of the protocol compiler to generate the sources.
237 plugin: the label of the protocol compiler plugin to be passed to the protocol
238 compiler.
239 plugin_language: the language of the generated sources
240 plugin_options: a list of options to be passed to the plugin
241 langs: generates sources in addition to the ones from the plugin for each
242 specified language.
243 outs: a list of labels of the expected outputs from the protocol compiler.
244 out_type: only generated a single type of source file for languages that have
245 split sources (e.g. *.h and *.cc in C++)
246"""
247_proto_gen = rule(
Jisi Liu39362b32015-10-14 17:12:11 -0700248 attrs = {
Jisi Liuee8131a2015-10-14 17:20:05 -0700249 "srcs": attr.label_list(allow_files = True),
David L. Jonesd60c0d22022-05-11 19:13:56 -0700250 "deps": attr.label_list(providers = [ProtoGenInfo]),
Jisi Liu53a56be2015-10-20 15:18:20 -0700251 "includes": attr.string_list(),
Jisi Liuee8131a2015-10-14 17:20:05 -0700252 "protoc": attr.label(
Charles Mitaf1fe79d2021-05-19 20:11:13 +0200253 cfg = "exec",
Jisi Liuee8131a2015-10-14 17:20:05 -0700254 executable = True,
James Juddd5f0dac2018-08-14 21:55:35 -0600255 allow_single_file = True,
Jisi Liuee8131a2015-10-14 17:20:05 -0700256 mandatory = True,
257 ),
Yuki Yugui Sonoda5977fb02016-06-01 16:23:15 +0900258 "plugin": attr.label(
Charles Mitaf1fe79d2021-05-19 20:11:13 +0200259 cfg = "exec",
Yuki Yugui Sonoda5977fb02016-06-01 16:23:15 +0900260 allow_files = True,
Manjunath Kudlurf0966a72016-02-22 14:30:43 -0800261 executable = True,
Manjunath Kudlurf0966a72016-02-22 14:30:43 -0800262 ),
Yuki Yugui Sonoda5977fb02016-06-01 16:23:15 +0900263 "plugin_language": attr.string(),
264 "plugin_options": attr.string_list(),
Mike Kruskaled5c57a2022-08-10 22:51:29 -0700265 "langs": attr.string_list(),
266 "outs": attr.string_list(),
267 "out_type": attr.string(
Mike Kruskal23f14812022-10-10 21:05:53 -0700268 default = "all",
Mike Kruskaled5c57a2022-08-10 22:51:29 -0700269 ),
Jisi Liuee8131a2015-10-14 17:20:05 -0700270 },
271 output_to_genfiles = True,
Jisi Liu9c7d9c02015-10-15 10:51:32 -0700272 implementation = _proto_gen_impl,
Jisi Liu39362b32015-10-14 17:12:11 -0700273)
Jisi Liu993fb702015-10-19 17:19:49 -0700274
Yannicf0cb9cd2020-02-13 22:04:14 +0100275def _internal_gen_well_known_protos_java_impl(ctx):
276 args = ctx.actions.args()
Steven Parkesea188662016-02-25 07:53:19 -0800277
Yannicf0cb9cd2020-02-13 22:04:14 +0100278 deps = [d[ProtoInfo] for d in ctx.attr.deps]
279
280 srcjar = ctx.actions.declare_file("{}.srcjar".format(ctx.attr.name))
Derek Perezbc45f922021-04-20 11:36:32 -0700281 if ctx.attr.javalite:
282 java_out = "lite:%s" % srcjar.path
283 else:
284 java_out = srcjar
285
286 args.add("--java_out", java_out)
Yannicf0cb9cd2020-02-13 22:04:14 +0100287
288 descriptors = depset(
289 transitive = [dep.transitive_descriptor_sets for dep in deps],
Paul Yangcecba292018-12-14 16:05:03 -0800290 )
Yannicf0cb9cd2020-02-13 22:04:14 +0100291 args.add_joined(
292 "--descriptor_set_in",
293 descriptors,
294 join_with = ctx.configuration.host_path_separator,
295 )
296
297 for dep in deps:
298 if "." == dep.proto_source_root:
299 args.add_all([src.path for src in dep.direct_sources])
300 else:
301 source_root = dep.proto_source_root
302 offset = len(source_root) + 1 # + '/'.
303 args.add_all([src.path[offset:] for src in dep.direct_sources])
304
305 ctx.actions.run(
306 executable = ctx.executable._protoc,
307 inputs = descriptors,
308 outputs = [srcjar],
309 arguments = [args],
Tiago Quelhas80c3f952023-01-17 10:58:45 -0800310 mnemonic = "ProtoCompile",
Adam Yi88f3ef72020-07-29 16:49:52 +1000311 use_default_shell_env = True,
Yannicf0cb9cd2020-02-13 22:04:14 +0100312 )
313
314 return [
315 DefaultInfo(
316 files = depset([srcjar]),
317 ),
318 ]
319
320internal_gen_well_known_protos_java = rule(
321 implementation = _internal_gen_well_known_protos_java_impl,
322 attrs = {
323 "deps": attr.label_list(
324 mandatory = True,
325 providers = [ProtoInfo],
326 ),
Derek Perezbc45f922021-04-20 11:36:32 -0700327 "javalite": attr.bool(
328 default = False,
329 ),
Yannicf0cb9cd2020-02-13 22:04:14 +0100330 "_protoc": attr.label(
331 executable = True,
Charles Mitaf1fe79d2021-05-19 20:11:13 +0200332 cfg = "exec",
Protobuf Team Bot64ae02c2022-12-20 10:02:34 -0800333 default = "//:protoc",
Yannicf0cb9cd2020-02-13 22:04:14 +0100334 ),
335 },
336)
Steven Parkesea188662016-02-25 07:53:19 -0800337
Deanna Garcia67b74dd2022-02-15 22:45:56 +0000338def _internal_gen_kt_protos(ctx):
339 args = ctx.actions.args()
340
341 deps = [d[ProtoInfo] for d in ctx.attr.deps]
342
343 srcjar = ctx.actions.declare_file("{}.srcjar".format(ctx.attr.name))
344 if ctx.attr.lite:
345 out = "lite:%s" % srcjar.path
346 else:
347 out = srcjar
348
349 args.add("--kotlin_out", out)
350
351 descriptors = depset(
352 transitive = [dep.transitive_descriptor_sets for dep in deps],
353 )
354 args.add_joined(
355 "--descriptor_set_in",
356 descriptors,
357 join_with = ctx.configuration.host_path_separator,
358 )
359
360 for dep in deps:
361 if "." == dep.proto_source_root:
362 args.add_all([src.path for src in dep.direct_sources])
363 else:
364 source_root = dep.proto_source_root
365 offset = len(source_root) + 1 # + '/'.
366 args.add_all([src.path[offset:] for src in dep.direct_sources])
367
368 ctx.actions.run(
369 executable = ctx.executable._protoc,
370 inputs = descriptors,
371 outputs = [srcjar],
372 arguments = [args],
Tiago Quelhas80c3f952023-01-17 10:58:45 -0800373 mnemonic = "ProtoCompile",
Deanna Garcia67b74dd2022-02-15 22:45:56 +0000374 use_default_shell_env = True,
375 )
376
377 return [
378 DefaultInfo(
379 files = depset([srcjar]),
380 ),
381 ]
382
383internal_gen_kt_protos = rule(
384 implementation = _internal_gen_kt_protos,
385 attrs = {
386 "deps": attr.label_list(
387 mandatory = True,
388 providers = [ProtoInfo],
389 ),
390 "lite": attr.bool(
391 default = False,
392 ),
393 "_protoc": attr.label(
394 executable = True,
395 cfg = "exec",
396 default = "//:protoc",
397 ),
398 },
399)
400
Mike Kruskaled5c57a2022-08-10 22:51:29 -0700401def internal_objc_proto_library(
402 name,
403 srcs = [],
404 deps = [],
405 outs = [],
406 proto_deps = [],
407 includes = ["."],
Protobuf Team Bot64ae02c2022-12-20 10:02:34 -0800408 default_runtime = Label("//:protobuf_objc"),
409 protoc = Label("//:protoc"),
Mike Kruskaled5c57a2022-08-10 22:51:29 -0700410 testonly = None,
411 visibility = ["//visibility:public"],
412 **kwargs):
Mike Kruskal701dd832022-08-20 14:22:08 -0700413 """Bazel rule to create a Objective-C protobuf library from proto source
Mike Kruskaled5c57a2022-08-10 22:51:29 -0700414 files
415
416 NOTE: the rule is only an internal workaround to generate protos. The
417 interface may change and the rule may be removed when bazel has introduced
418 the native rule.
419
420 Args:
421 name: the name of the objc_proto_library.
422 srcs: the .proto files to compile.
423 deps: a list of dependency labels; must be objc_proto_library.
424 outs: a list of expected output files.
425 proto_deps: a list of proto file dependencies that don't have a
426 objc_proto_library rule.
427 include: a string indicating the include path of the .proto files.
428 default_runtime: the Objective-C Protobuf runtime
429 protoc: the label of the protocol compiler to generate the sources.
430 testonly: common rule attribute (see:
431 https://bazel.build/reference/be/common-definitions#common-attributes)
432 visibility: the visibility of the generated files.
433 **kwargs: other keyword arguments that are passed to py_library.
434
435 """
436 full_deps = [d + "_genproto" for d in deps]
437
438 if proto_deps:
439 _proto_gen(
440 name = name + "_deps_genproto",
441 testonly = testonly,
442 srcs = proto_deps,
443 protoc = protoc,
444 includes = includes,
445 )
446 full_deps.append(":%s_deps_genproto" % name)
447
448 # Note: we need to run the protoc build twice to get separate targets for
449 # the generated header and the source files.
450 _proto_gen(
451 name = name + "_genproto_hdrs",
452 srcs = srcs,
453 deps = full_deps,
454 langs = ["objc"],
455 out_type = "hdrs",
456 includes = includes,
457 protoc = protoc,
458 testonly = testonly,
459 visibility = visibility,
460 tags = ["manual"],
461 )
462
463 _proto_gen(
464 name = name + "_genproto",
465 srcs = srcs,
466 deps = full_deps,
467 langs = ["objc"],
468 out_type = "srcs",
469 includes = includes,
470 protoc = protoc,
471 testonly = testonly,
472 visibility = visibility,
473 tags = ["manual"],
474 )
475
476 objc_library(
477 name = name,
478 hdrs = [name + "_genproto_hdrs"],
479 non_arc_srcs = [name + "_genproto"],
480 deps = [default_runtime],
481 includes = includes,
482 testonly = testonly,
483 visibility = visibility,
484 # Don't auto-expand these targets until target_compatible_with
485 # works. See https://github.com/bazelbuild/bazel/issues/12897.
486 tags = ["manual"],
487 target_compatible_with = ["@platforms//os:osx"],
488 **kwargs
489 )
490
Mike Kruskal633e8f72023-01-03 12:11:31 -0800491def internal_ruby_proto_library(
492 name,
493 srcs = [],
494 deps = [],
495 includes = ["."],
496 default_runtime = "@com_google_protobuf//ruby:protobuf",
497 protoc = "@com_google_protobuf//:protoc",
498 testonly = None,
499 visibility = ["//visibility:public"],
500 **kwargs):
501 """Bazel rule to create a Ruby protobuf library from proto source files
502
503 NOTE: the rule is only an internal workaround to generate protos. The
504 interface may change and the rule may be removed when bazel has introduced
505 the native rule.
506
507 Args:
508 name: the name of the ruby_proto_library.
509 srcs: the .proto files to compile.
510 deps: a list of dependency labels; must be a internal_ruby_proto_library.
511 includes: a string indicating the include path of the .proto files.
512 default_runtime: the RubyProtobuf runtime
513 protoc: the label of the protocol compiler to generate the sources.
514 testonly: common rule attribute (see:
515 https://bazel.build/reference/be/common-definitions#common-attributes)
516 visibility: the visibility of the generated files.
517 **kwargs: other keyword arguments that are passed to ruby_library.
518
519 """
520
521 # Note: we need to run the protoc build twice to get separate targets for
522 # the generated header and the source files.
523 _proto_gen(
524 name = name + "_genproto",
525 srcs = srcs,
526 deps = [s + "_genproto" for s in deps],
527 langs = ["ruby"],
528 includes = includes,
529 protoc = protoc,
530 testonly = testonly,
531 visibility = visibility,
532 tags = ["manual"],
533 )
534
535 deps = []
536 if default_runtime:
537 deps.append(default_runtime)
538 ruby_library(
539 name = name,
540 srcs = [name + "_genproto"],
541 deps = deps,
542 testonly = testonly,
543 visibility = visibility,
544 includes = includes,
545 **kwargs
546 )
547
Protobuf Team Bot64ae02c2022-12-20 10:02:34 -0800548# When canonical labels are in use, use additional "@" prefix
549_canonical_label_prefix = "@" if str(Label("//:protoc")).startswith("@@") else ""
550
551def _to_label(label_str):
552 """Converts a string to a label using the repository of the calling thread"""
553 if type(label_str) == type(Label("//:foo")):
554 return label_str
555 return Label(_canonical_label_prefix + native.repository_name() + "//" + native.package_name() + ":foo").relative(label_str)
556
Mike Kruskaled5c57a2022-08-10 22:51:29 -0700557def internal_py_proto_library(
Jisi Liu993fb702015-10-19 17:19:49 -0700558 name,
Paul Yangcecba292018-12-14 16:05:03 -0800559 srcs = [],
560 deps = [],
561 py_libs = [],
562 py_extra_srcs = [],
563 include = None,
Protobuf Team Bot64ae02c2022-12-20 10:02:34 -0800564 default_runtime = Label("//:protobuf_python"),
565 protoc = Label("//:protoc"),
Paul Yangcecba292018-12-14 16:05:03 -0800566 use_grpc_plugin = False,
David L. Jones07303d62022-05-17 18:13:22 -0700567 testonly = None,
Jisi Liu993fb702015-10-19 17:19:49 -0700568 **kargs):
Paul Yangcecba292018-12-14 16:05:03 -0800569 """Bazel rule to create a Python protobuf library from proto source files
Jisi Liu7b948cc2015-10-19 17:56:27 -0700570
Paul Yangcecba292018-12-14 16:05:03 -0800571 NOTE: the rule is only an internal workaround to generate protos. The
572 interface may change and the rule may be removed when bazel has introduced
573 the native rule.
Jisi Liud4bef7d2015-11-02 12:24:32 -0800574
Paul Yangcecba292018-12-14 16:05:03 -0800575 Args:
576 name: the name of the py_proto_library.
577 srcs: the .proto files of the py_proto_library.
578 deps: a list of dependency labels; must be py_proto_library.
579 py_libs: a list of other py_library targets depended by the generated
580 py_library.
581 py_extra_srcs: extra source files that will be added to the output
582 py_library. This attribute is used for internal bootstrapping.
583 include: a string indicating the include path of the .proto files.
584 default_runtime: the implicitly default runtime which will be depended on by
585 the generated py_library target.
586 protoc: the label of the protocol compiler to generate the sources.
587 use_grpc_plugin: a flag to indicate whether to call the Python C++ plugin
588 when processing the proto files.
David L. Jones07303d62022-05-17 18:13:22 -0700589 testonly: common rule attribute (see:
590 https://bazel.build/reference/be/common-definitions#common-attributes)
Leo12236c62020-05-04 11:23:44 +0900591 **kargs: other keyword arguments that are passed to py_library.
Jisi Liu7b948cc2015-10-19 17:56:27 -0700592
Paul Yangcecba292018-12-14 16:05:03 -0800593 """
Paul Yangcecba292018-12-14 16:05:03 -0800594 includes = []
595 if include != None:
596 includes = [include]
Jisi Liu53a56be2015-10-20 15:18:20 -0700597
Paul Yangcecba292018-12-14 16:05:03 -0800598 grpc_python_plugin = None
599 if use_grpc_plugin:
600 grpc_python_plugin = "//external:grpc_python_plugin"
601 # Note: Generated grpc code depends on Python grpc module. This dependency
602 # is not explicitly listed in py_libs. Instead, host system is assumed to
603 # have grpc installed.
Wiktor Tomczak0fa31b22016-11-22 20:18:46 +0100604
Mike Kruskaled5c57a2022-08-10 22:51:29 -0700605 _proto_gen(
Paul Yangcecba292018-12-14 16:05:03 -0800606 name = name + "_genproto",
David L. Jones07303d62022-05-17 18:13:22 -0700607 testonly = testonly,
Paul Yangcecba292018-12-14 16:05:03 -0800608 srcs = srcs,
609 deps = [s + "_genproto" for s in deps],
610 includes = includes,
611 protoc = protoc,
Mike Kruskaled5c57a2022-08-10 22:51:29 -0700612 langs = ["python"],
Paul Yangcecba292018-12-14 16:05:03 -0800613 visibility = ["//visibility:public"],
614 plugin = grpc_python_plugin,
615 plugin_language = "grpc",
616 )
Jisi Liu993fb702015-10-19 17:19:49 -0700617
Protobuf Team Bot64ae02c2022-12-20 10:02:34 -0800618 if default_runtime:
619 # Resolve non-local labels
620 labels = [_to_label(lib) for lib in py_libs + deps]
621 if not _to_label(default_runtime) in labels:
622 py_libs = py_libs + [default_runtime]
623
Yannic Bonenbergerd2d6ff52019-08-06 21:12:06 +0200624 py_library(
Paul Yangcecba292018-12-14 16:05:03 -0800625 name = name,
David L. Jones07303d62022-05-17 18:13:22 -0700626 testonly = testonly,
David L. Jonesd60c0d22022-05-11 19:13:56 -0700627 srcs = [name + "_genproto"] + py_extra_srcs,
Paul Yangcecba292018-12-14 16:05:03 -0800628 deps = py_libs + deps,
629 imports = includes,
630 **kargs
631 )
Jisi Liu993fb702015-10-19 17:19:49 -0700632
Mike Kruskal15954172022-09-09 10:42:19 -0700633def py_proto_library(
634 *args,
635 **kwargs):
636 """Deprecated alias for use before Bazel 5.3.
637
638 Args:
639 *args: the name of the py_proto_library.
640 **kwargs: other keyword arguments that are passed to py_library.
641
642 Deprecated:
643 This is provided for backwards compatibility only. Bazel 5.3 will
644 introduce support for py_proto_library, which should be used instead.
645 """
646 internal_py_proto_library(*args, **kwargs)
647
Mike Kruskaled5c57a2022-08-10 22:51:29 -0700648def _source_proto_library(
649 name,
650 srcs = [],
651 deps = [],
652 proto_deps = [],
653 outs = [],
654 lang = None,
655 includes = ["."],
Protobuf Team Bot64ae02c2022-12-20 10:02:34 -0800656 protoc = Label("//:protoc"),
Mike Kruskaled5c57a2022-08-10 22:51:29 -0700657 testonly = None,
658 visibility = ["//visibility:public"],
659 **kwargs):
660 """Bazel rule to create generated protobuf code from proto source files for
661 languages not well supported by Bazel yet. This will output the generated
662 code as-is without any compilation. This is most useful for interpreted
663 languages that don't require it.
664
665 NOTE: the rule is only an internal workaround to generate protos. The
666 interface may change and the rule may be removed when bazel has introduced
667 the native rule.
668
669 Args:
670 name: the name of the unsupported_proto_library.
671 srcs: the .proto files to compile. Note, that for languages where out
672 needs to be provided, only a single source file is allowed.
673 deps: a list of dependency labels; must be unsupported_proto_library.
674 proto_deps: a list of proto file dependencies that don't have a
675 unsupported_proto_library rule.
676 lang: the language to (optionally) generate code for.
677 outs: a list of expected output files. This is only required for
678 languages where we can't predict the outputs.
679 includes: strings indicating the include path of the .proto files.
680 protoc: the label of the protocol compiler to generate the sources.
681 testonly: common rule attribute (see:
682 https://bazel.build/reference/be/common-definitions#common-attributes)
683 visibility: the visibility of the generated files.
684 **kwargs: other keyword arguments that are passed to py_library.
685
686 """
687 if outs and len(srcs) != 1:
688 fail("Custom outputs only allowed for single proto targets.")
689
690 langs = []
691 if lang != None:
692 langs = [lang]
693
694 full_deps = [d + "_genproto" for d in deps]
695
696 if proto_deps:
697 _proto_gen(
698 name = name + "_deps_genproto",
699 testonly = testonly,
700 srcs = proto_deps,
701 protoc = protoc,
702 includes = includes,
703 )
704 full_deps.append(":%s_deps_genproto" % name)
705
706 _proto_gen(
707 name = name + "_genproto",
708 srcs = srcs,
709 deps = full_deps,
710 langs = langs,
711 outs = outs,
712 includes = includes,
713 protoc = protoc,
714 testonly = testonly,
715 visibility = visibility,
716 )
717
718 native.filegroup(
719 name = name,
Mike Kruskal23f14812022-10-10 21:05:53 -0700720 srcs = [":%s_genproto" % name],
Mike Kruskaled5c57a2022-08-10 22:51:29 -0700721 testonly = testonly,
722 visibility = visibility,
723 **kwargs
724 )
725
726def internal_csharp_proto_library(**kwargs):
727 """Bazel rule to create a C# protobuf library from proto source files
728
729 NOTE: the rule is only an internal workaround to generate protos. The
730 interface may change and the rule may be removed when bazel has introduced
731 the native rule.
732
733 Args:
734 **kwargs: arguments that are passed to unsupported_proto_library.
735
736 """
737
738 _source_proto_library(
739 lang = "csharp",
740 **kwargs
741 )
742
743def internal_php_proto_library(**kwargs):
744 """Bazel rule to create a PHP protobuf library from proto source files
745
746 NOTE: the rule is only an internal workaround to generate protos. The
747 interface may change and the rule may be removed when bazel has introduced
748 the native rule.
749
750 Args:
751 **kwargs: arguments that are passed to unsupported_proto_library.
752
753 """
754 if not kwargs.get("outs"):
755 fail("Unable to predict the outputs for php_proto_library. Please specify them via `outs`.")
756
757 _source_proto_library(
758 lang = "php",
759 **kwargs
760 )
761
Fahrzin Hemmati35119e32017-11-28 14:24:53 -0800762def check_protobuf_required_bazel_version():
Paul Yangcecba292018-12-14 16:05:03 -0800763 """For WORKSPACE files, to check the installed version of bazel.
Fahrzin Hemmati35119e32017-11-28 14:24:53 -0800764
Paul Yangcecba292018-12-14 16:05:03 -0800765 This ensures bazel supports our approach to proto_library() depending on a
766 copied filegroup. (Fixed in bazel 0.5.4)
767 """
768 versions.check(minimum_bazel_version = "0.5.4")