xref: /third_party/protobuf/protobuf.bzl (revision ffe3c632)
1ffe3c632Sopenharmony_ciload("@bazel_skylib//lib:versions.bzl", "versions")
2ffe3c632Sopenharmony_ciload("@rules_cc//cc:defs.bzl", "cc_library")
3ffe3c632Sopenharmony_ciload("@rules_proto//proto:defs.bzl", "ProtoInfo")
4ffe3c632Sopenharmony_ciload("@rules_python//python:defs.bzl", "py_library", "py_test")
5ffe3c632Sopenharmony_ci
6ffe3c632Sopenharmony_cidef _GetPath(ctx, path):
7ffe3c632Sopenharmony_ci    if ctx.label.workspace_root:
8ffe3c632Sopenharmony_ci        return ctx.label.workspace_root + "/" + path
9ffe3c632Sopenharmony_ci    else:
10ffe3c632Sopenharmony_ci        return path
11ffe3c632Sopenharmony_ci
12ffe3c632Sopenharmony_cidef _IsNewExternal(ctx):
13ffe3c632Sopenharmony_ci    # Bazel 0.4.4 and older have genfiles paths that look like:
14ffe3c632Sopenharmony_ci    #   bazel-out/local-fastbuild/genfiles/external/repo/foo
15ffe3c632Sopenharmony_ci    # After the exec root rearrangement, they look like:
16ffe3c632Sopenharmony_ci    #   ../repo/bazel-out/local-fastbuild/genfiles/foo
17ffe3c632Sopenharmony_ci    return ctx.label.workspace_root.startswith("../")
18ffe3c632Sopenharmony_ci
19ffe3c632Sopenharmony_cidef _GenDir(ctx):
20ffe3c632Sopenharmony_ci    if _IsNewExternal(ctx):
21ffe3c632Sopenharmony_ci        # We are using the fact that Bazel 0.4.4+ provides repository-relative paths
22ffe3c632Sopenharmony_ci        # for ctx.genfiles_dir.
23ffe3c632Sopenharmony_ci        return ctx.genfiles_dir.path + (
24ffe3c632Sopenharmony_ci            "/" + ctx.attr.includes[0] if ctx.attr.includes and ctx.attr.includes[0] else ""
25ffe3c632Sopenharmony_ci        )
26ffe3c632Sopenharmony_ci
27ffe3c632Sopenharmony_ci    # This means that we're either in the old version OR the new version in the local repo.
28ffe3c632Sopenharmony_ci    # Either way, appending the source path to the genfiles dir works.
29ffe3c632Sopenharmony_ci    return ctx.var["GENDIR"] + "/" + _SourceDir(ctx)
30ffe3c632Sopenharmony_ci
31ffe3c632Sopenharmony_cidef _SourceDir(ctx):
32ffe3c632Sopenharmony_ci    if not ctx.attr.includes:
33ffe3c632Sopenharmony_ci        return ctx.label.workspace_root
34ffe3c632Sopenharmony_ci    if not ctx.attr.includes[0]:
35ffe3c632Sopenharmony_ci        return _GetPath(ctx, ctx.label.package)
36ffe3c632Sopenharmony_ci    if not ctx.label.package:
37ffe3c632Sopenharmony_ci        return _GetPath(ctx, ctx.attr.includes[0])
38ffe3c632Sopenharmony_ci    return _GetPath(ctx, ctx.label.package + "/" + ctx.attr.includes[0])
39ffe3c632Sopenharmony_ci
40ffe3c632Sopenharmony_cidef _CcHdrs(srcs, use_grpc_plugin = False):
41ffe3c632Sopenharmony_ci    ret = [s[:-len(".proto")] + ".pb.h" for s in srcs]
42ffe3c632Sopenharmony_ci    if use_grpc_plugin:
43ffe3c632Sopenharmony_ci        ret += [s[:-len(".proto")] + ".grpc.pb.h" for s in srcs]
44ffe3c632Sopenharmony_ci    return ret
45ffe3c632Sopenharmony_ci
46ffe3c632Sopenharmony_cidef _CcSrcs(srcs, use_grpc_plugin = False):
47ffe3c632Sopenharmony_ci    ret = [s[:-len(".proto")] + ".pb.cc" for s in srcs]
48ffe3c632Sopenharmony_ci    if use_grpc_plugin:
49ffe3c632Sopenharmony_ci        ret += [s[:-len(".proto")] + ".grpc.pb.cc" for s in srcs]
50ffe3c632Sopenharmony_ci    return ret
51ffe3c632Sopenharmony_ci
52ffe3c632Sopenharmony_cidef _CcOuts(srcs, use_grpc_plugin = False):
53ffe3c632Sopenharmony_ci    return _CcHdrs(srcs, use_grpc_plugin) + _CcSrcs(srcs, use_grpc_plugin)
54ffe3c632Sopenharmony_ci
55ffe3c632Sopenharmony_cidef _PyOuts(srcs, use_grpc_plugin = False):
56ffe3c632Sopenharmony_ci    ret = [s[:-len(".proto")] + "_pb2.py" for s in srcs]
57ffe3c632Sopenharmony_ci    if use_grpc_plugin:
58ffe3c632Sopenharmony_ci        ret += [s[:-len(".proto")] + "_pb2_grpc.py" for s in srcs]
59ffe3c632Sopenharmony_ci    return ret
60ffe3c632Sopenharmony_ci
61ffe3c632Sopenharmony_cidef _RelativeOutputPath(path, include, dest = ""):
62ffe3c632Sopenharmony_ci    if include == None:
63ffe3c632Sopenharmony_ci        return path
64ffe3c632Sopenharmony_ci
65ffe3c632Sopenharmony_ci    if not path.startswith(include):
66ffe3c632Sopenharmony_ci        fail("Include path %s isn't part of the path %s." % (include, path))
67ffe3c632Sopenharmony_ci
68ffe3c632Sopenharmony_ci    if include and include[-1] != "/":
69ffe3c632Sopenharmony_ci        include = include + "/"
70ffe3c632Sopenharmony_ci    if dest and dest[-1] != "/":
71ffe3c632Sopenharmony_ci        dest = dest + "/"
72ffe3c632Sopenharmony_ci
73ffe3c632Sopenharmony_ci    path = path[len(include):]
74ffe3c632Sopenharmony_ci    return dest + path
75ffe3c632Sopenharmony_ci
76ffe3c632Sopenharmony_cidef _proto_gen_impl(ctx):
77ffe3c632Sopenharmony_ci    """General implementation for generating protos"""
78ffe3c632Sopenharmony_ci    srcs = ctx.files.srcs
79ffe3c632Sopenharmony_ci    deps = depset(direct=ctx.files.srcs)
80ffe3c632Sopenharmony_ci    source_dir = _SourceDir(ctx)
81ffe3c632Sopenharmony_ci    gen_dir = _GenDir(ctx).rstrip("/")
82ffe3c632Sopenharmony_ci    if source_dir:
83ffe3c632Sopenharmony_ci        import_flags = depset(direct=["-I" + source_dir, "-I" + gen_dir])
84ffe3c632Sopenharmony_ci    else:
85ffe3c632Sopenharmony_ci        import_flags = depset(direct=["-I."])
86ffe3c632Sopenharmony_ci
87ffe3c632Sopenharmony_ci    for dep in ctx.attr.deps:
88ffe3c632Sopenharmony_ci        if type(dep.proto.import_flags) == "list":
89ffe3c632Sopenharmony_ci            import_flags = depset(transitive=[import_flags], direct=dep.proto.import_flags)
90ffe3c632Sopenharmony_ci        else:
91ffe3c632Sopenharmony_ci            import_flags = depset(transitive=[import_flags, dep.proto.import_flags])
92ffe3c632Sopenharmony_ci        if type(dep.proto.deps) == "list":
93ffe3c632Sopenharmony_ci            deps = depset(transitive=[deps], direct=dep.proto.deps)
94ffe3c632Sopenharmony_ci        else:
95ffe3c632Sopenharmony_ci            deps = depset(transitive=[deps, dep.proto.deps])
96ffe3c632Sopenharmony_ci
97ffe3c632Sopenharmony_ci    if not ctx.attr.gen_cc and not ctx.attr.gen_py and not ctx.executable.plugin:
98ffe3c632Sopenharmony_ci        return struct(
99ffe3c632Sopenharmony_ci            proto = struct(
100ffe3c632Sopenharmony_ci                srcs = srcs,
101ffe3c632Sopenharmony_ci                import_flags = import_flags,
102ffe3c632Sopenharmony_ci                deps = deps,
103ffe3c632Sopenharmony_ci            ),
104ffe3c632Sopenharmony_ci        )
105ffe3c632Sopenharmony_ci
106ffe3c632Sopenharmony_ci    for src in srcs:
107ffe3c632Sopenharmony_ci        args = []
108ffe3c632Sopenharmony_ci
109ffe3c632Sopenharmony_ci        in_gen_dir = src.root.path == gen_dir
110ffe3c632Sopenharmony_ci        if in_gen_dir:
111ffe3c632Sopenharmony_ci            import_flags_real = []
112ffe3c632Sopenharmony_ci            for f in import_flags.to_list():
113ffe3c632Sopenharmony_ci                path = f.replace("-I", "")
114ffe3c632Sopenharmony_ci                import_flags_real.append("-I$(realpath -s %s)" % path)
115ffe3c632Sopenharmony_ci
116ffe3c632Sopenharmony_ci        outs = []
117ffe3c632Sopenharmony_ci        use_grpc_plugin = (ctx.attr.plugin_language == "grpc" and ctx.attr.plugin)
118ffe3c632Sopenharmony_ci        path_tpl = "$(realpath %s)" if in_gen_dir else "%s"
119ffe3c632Sopenharmony_ci        if ctx.attr.gen_cc:
120ffe3c632Sopenharmony_ci            args += [("--cpp_out=" + path_tpl) % gen_dir]
121ffe3c632Sopenharmony_ci            outs.extend(_CcOuts([src.basename], use_grpc_plugin = use_grpc_plugin))
122ffe3c632Sopenharmony_ci        if ctx.attr.gen_py:
123ffe3c632Sopenharmony_ci            args += [("--python_out=" + path_tpl) % gen_dir]
124ffe3c632Sopenharmony_ci            outs.extend(_PyOuts([src.basename], use_grpc_plugin = use_grpc_plugin))
125ffe3c632Sopenharmony_ci
126ffe3c632Sopenharmony_ci        outs = [ctx.actions.declare_file(out, sibling = src) for out in outs]
127ffe3c632Sopenharmony_ci        inputs = [src] + deps.to_list()
128ffe3c632Sopenharmony_ci        tools = [ctx.executable.protoc]
129ffe3c632Sopenharmony_ci        if ctx.executable.plugin:
130ffe3c632Sopenharmony_ci            plugin = ctx.executable.plugin
131ffe3c632Sopenharmony_ci            lang = ctx.attr.plugin_language
132ffe3c632Sopenharmony_ci            if not lang and plugin.basename.startswith("protoc-gen-"):
133ffe3c632Sopenharmony_ci                lang = plugin.basename[len("protoc-gen-"):]
134ffe3c632Sopenharmony_ci            if not lang:
135ffe3c632Sopenharmony_ci                fail("cannot infer the target language of plugin", "plugin_language")
136ffe3c632Sopenharmony_ci
137ffe3c632Sopenharmony_ci            outdir = "." if in_gen_dir else gen_dir
138ffe3c632Sopenharmony_ci
139ffe3c632Sopenharmony_ci            if ctx.attr.plugin_options:
140ffe3c632Sopenharmony_ci                outdir = ",".join(ctx.attr.plugin_options) + ":" + outdir
141ffe3c632Sopenharmony_ci            args += [("--plugin=protoc-gen-%s=" + path_tpl) % (lang, plugin.path)]
142ffe3c632Sopenharmony_ci            args += ["--%s_out=%s" % (lang, outdir)]
143ffe3c632Sopenharmony_ci            tools.append(plugin)
144ffe3c632Sopenharmony_ci
145ffe3c632Sopenharmony_ci        if not in_gen_dir:
146ffe3c632Sopenharmony_ci            ctx.actions.run(
147ffe3c632Sopenharmony_ci                inputs = inputs,
148ffe3c632Sopenharmony_ci                tools = tools,
149ffe3c632Sopenharmony_ci                outputs = outs,
150ffe3c632Sopenharmony_ci                arguments = args + import_flags.to_list() + [src.path],
151ffe3c632Sopenharmony_ci                executable = ctx.executable.protoc,
152ffe3c632Sopenharmony_ci                mnemonic = "ProtoCompile",
153ffe3c632Sopenharmony_ci                use_default_shell_env = True,
154ffe3c632Sopenharmony_ci            )
155ffe3c632Sopenharmony_ci        else:
156ffe3c632Sopenharmony_ci            for out in outs:
157ffe3c632Sopenharmony_ci                orig_command = " ".join(
158ffe3c632Sopenharmony_ci                    ["$(realpath %s)" % ctx.executable.protoc.path] + args +
159ffe3c632Sopenharmony_ci                    import_flags_real + ["-I.", src.basename],
160ffe3c632Sopenharmony_ci                )
161ffe3c632Sopenharmony_ci                command = ";".join([
162ffe3c632Sopenharmony_ci                    'CMD="%s"' % orig_command,
163ffe3c632Sopenharmony_ci                    "cd %s" % src.dirname,
164ffe3c632Sopenharmony_ci                    "${CMD}",
165ffe3c632Sopenharmony_ci                    "cd -",
166ffe3c632Sopenharmony_ci                ])
167ffe3c632Sopenharmony_ci                generated_out = "/".join([gen_dir, out.basename])
168ffe3c632Sopenharmony_ci                if generated_out != out.path:
169ffe3c632Sopenharmony_ci                    command += ";mv %s %s" % (generated_out, out.path)
170ffe3c632Sopenharmony_ci                ctx.actions.run_shell(
171ffe3c632Sopenharmony_ci                    inputs = inputs,
172ffe3c632Sopenharmony_ci                    outputs = [out],
173ffe3c632Sopenharmony_ci                    command = command,
174ffe3c632Sopenharmony_ci                    mnemonic = "ProtoCompile",
175ffe3c632Sopenharmony_ci                    tools = tools,
176ffe3c632Sopenharmony_ci                    use_default_shell_env = True,
177ffe3c632Sopenharmony_ci                )
178ffe3c632Sopenharmony_ci
179ffe3c632Sopenharmony_ci    return struct(
180ffe3c632Sopenharmony_ci        proto = struct(
181ffe3c632Sopenharmony_ci            srcs = srcs,
182ffe3c632Sopenharmony_ci            import_flags = import_flags,
183ffe3c632Sopenharmony_ci            deps = deps,
184ffe3c632Sopenharmony_ci        ),
185ffe3c632Sopenharmony_ci    )
186ffe3c632Sopenharmony_ci
187ffe3c632Sopenharmony_ciproto_gen = rule(
188ffe3c632Sopenharmony_ci    attrs = {
189ffe3c632Sopenharmony_ci        "srcs": attr.label_list(allow_files = True),
190ffe3c632Sopenharmony_ci        "deps": attr.label_list(providers = ["proto"]),
191ffe3c632Sopenharmony_ci        "includes": attr.string_list(),
192ffe3c632Sopenharmony_ci        "protoc": attr.label(
193ffe3c632Sopenharmony_ci            cfg = "host",
194ffe3c632Sopenharmony_ci            executable = True,
195ffe3c632Sopenharmony_ci            allow_single_file = True,
196ffe3c632Sopenharmony_ci            mandatory = True,
197ffe3c632Sopenharmony_ci        ),
198ffe3c632Sopenharmony_ci        "plugin": attr.label(
199ffe3c632Sopenharmony_ci            cfg = "host",
200ffe3c632Sopenharmony_ci            allow_files = True,
201ffe3c632Sopenharmony_ci            executable = True,
202ffe3c632Sopenharmony_ci        ),
203ffe3c632Sopenharmony_ci        "plugin_language": attr.string(),
204ffe3c632Sopenharmony_ci        "plugin_options": attr.string_list(),
205ffe3c632Sopenharmony_ci        "gen_cc": attr.bool(),
206ffe3c632Sopenharmony_ci        "gen_py": attr.bool(),
207ffe3c632Sopenharmony_ci        "outs": attr.output_list(),
208ffe3c632Sopenharmony_ci    },
209ffe3c632Sopenharmony_ci    output_to_genfiles = True,
210ffe3c632Sopenharmony_ci    implementation = _proto_gen_impl,
211ffe3c632Sopenharmony_ci)
212ffe3c632Sopenharmony_ci"""Generates codes from Protocol Buffers definitions.
213ffe3c632Sopenharmony_ci
214ffe3c632Sopenharmony_ciThis rule helps you to implement Skylark macros specific to the target
215ffe3c632Sopenharmony_cilanguage. You should prefer more specific `cc_proto_library `,
216ffe3c632Sopenharmony_ci`py_proto_library` and others unless you are adding such wrapper macros.
217ffe3c632Sopenharmony_ci
218ffe3c632Sopenharmony_ciArgs:
219ffe3c632Sopenharmony_ci  srcs: Protocol Buffers definition files (.proto) to run the protocol compiler
220ffe3c632Sopenharmony_ci    against.
221ffe3c632Sopenharmony_ci  deps: a list of dependency labels; must be other proto libraries.
222ffe3c632Sopenharmony_ci  includes: a list of include paths to .proto files.
223ffe3c632Sopenharmony_ci  protoc: the label of the protocol compiler to generate the sources.
224ffe3c632Sopenharmony_ci  plugin: the label of the protocol compiler plugin to be passed to the protocol
225ffe3c632Sopenharmony_ci    compiler.
226ffe3c632Sopenharmony_ci  plugin_language: the language of the generated sources
227ffe3c632Sopenharmony_ci  plugin_options: a list of options to be passed to the plugin
228ffe3c632Sopenharmony_ci  gen_cc: generates C++ sources in addition to the ones from the plugin.
229ffe3c632Sopenharmony_ci  gen_py: generates Python sources in addition to the ones from the plugin.
230ffe3c632Sopenharmony_ci  outs: a list of labels of the expected outputs from the protocol compiler.
231ffe3c632Sopenharmony_ci"""
232ffe3c632Sopenharmony_ci
233ffe3c632Sopenharmony_cidef _adapt_proto_library_impl(ctx):
234ffe3c632Sopenharmony_ci    deps = [dep[ProtoInfo] for dep in ctx.attr.deps]
235ffe3c632Sopenharmony_ci
236ffe3c632Sopenharmony_ci    srcs = [src for dep in deps for src in dep.direct_sources]
237ffe3c632Sopenharmony_ci    return struct(
238ffe3c632Sopenharmony_ci        proto = struct(
239ffe3c632Sopenharmony_ci            srcs = srcs,
240ffe3c632Sopenharmony_ci            import_flags = ["-I{}".format(path) for dep in deps for path in dep.transitive_proto_path.to_list()],
241ffe3c632Sopenharmony_ci            deps = srcs,
242ffe3c632Sopenharmony_ci        ),
243ffe3c632Sopenharmony_ci    )
244ffe3c632Sopenharmony_ci
245ffe3c632Sopenharmony_ciadapt_proto_library = rule(
246ffe3c632Sopenharmony_ci    implementation = _adapt_proto_library_impl,
247ffe3c632Sopenharmony_ci    attrs = {
248ffe3c632Sopenharmony_ci        "deps": attr.label_list(
249ffe3c632Sopenharmony_ci            mandatory = True,
250ffe3c632Sopenharmony_ci            providers = [ProtoInfo],
251ffe3c632Sopenharmony_ci        ),
252ffe3c632Sopenharmony_ci    },
253ffe3c632Sopenharmony_ci    doc = "Adapts `proto_library` from `@rules_proto` to be used with `{cc,py}_proto_library` from this file.",
254ffe3c632Sopenharmony_ci)
255ffe3c632Sopenharmony_ci
256ffe3c632Sopenharmony_cidef cc_proto_library(
257ffe3c632Sopenharmony_ci        name,
258ffe3c632Sopenharmony_ci        srcs = [],
259ffe3c632Sopenharmony_ci        deps = [],
260ffe3c632Sopenharmony_ci        cc_libs = [],
261ffe3c632Sopenharmony_ci        include = None,
262ffe3c632Sopenharmony_ci        protoc = "@com_google_protobuf//:protoc",
263ffe3c632Sopenharmony_ci        use_grpc_plugin = False,
264ffe3c632Sopenharmony_ci        default_runtime = "@com_google_protobuf//:protobuf",
265ffe3c632Sopenharmony_ci        **kargs):
266ffe3c632Sopenharmony_ci    """Bazel rule to create a C++ protobuf library from proto source files
267ffe3c632Sopenharmony_ci
268ffe3c632Sopenharmony_ci    NOTE: the rule is only an internal workaround to generate protos. The
269ffe3c632Sopenharmony_ci    interface may change and the rule may be removed when bazel has introduced
270ffe3c632Sopenharmony_ci    the native rule.
271ffe3c632Sopenharmony_ci
272ffe3c632Sopenharmony_ci    Args:
273ffe3c632Sopenharmony_ci      name: the name of the cc_proto_library.
274ffe3c632Sopenharmony_ci      srcs: the .proto files of the cc_proto_library.
275ffe3c632Sopenharmony_ci      deps: a list of dependency labels; must be cc_proto_library.
276ffe3c632Sopenharmony_ci      cc_libs: a list of other cc_library targets depended by the generated
277ffe3c632Sopenharmony_ci          cc_library.
278ffe3c632Sopenharmony_ci      include: a string indicating the include path of the .proto files.
279ffe3c632Sopenharmony_ci      protoc: the label of the protocol compiler to generate the sources.
280ffe3c632Sopenharmony_ci      use_grpc_plugin: a flag to indicate whether to call the grpc C++ plugin
281ffe3c632Sopenharmony_ci          when processing the proto files.
282ffe3c632Sopenharmony_ci      default_runtime: the implicitly default runtime which will be depended on by
283ffe3c632Sopenharmony_ci          the generated cc_library target.
284ffe3c632Sopenharmony_ci      **kargs: other keyword arguments that are passed to cc_library.
285ffe3c632Sopenharmony_ci    """
286ffe3c632Sopenharmony_ci
287ffe3c632Sopenharmony_ci    includes = []
288ffe3c632Sopenharmony_ci    if include != None:
289ffe3c632Sopenharmony_ci        includes = [include]
290ffe3c632Sopenharmony_ci
291ffe3c632Sopenharmony_ci    grpc_cpp_plugin = None
292ffe3c632Sopenharmony_ci    if use_grpc_plugin:
293ffe3c632Sopenharmony_ci        grpc_cpp_plugin = "//external:grpc_cpp_plugin"
294ffe3c632Sopenharmony_ci
295ffe3c632Sopenharmony_ci    gen_srcs = _CcSrcs(srcs, use_grpc_plugin)
296ffe3c632Sopenharmony_ci    gen_hdrs = _CcHdrs(srcs, use_grpc_plugin)
297ffe3c632Sopenharmony_ci    outs = gen_srcs + gen_hdrs
298ffe3c632Sopenharmony_ci
299ffe3c632Sopenharmony_ci    proto_gen(
300ffe3c632Sopenharmony_ci        name = name + "_genproto",
301ffe3c632Sopenharmony_ci        srcs = srcs,
302ffe3c632Sopenharmony_ci        deps = [s + "_genproto" for s in deps],
303ffe3c632Sopenharmony_ci        includes = includes,
304ffe3c632Sopenharmony_ci        protoc = protoc,
305ffe3c632Sopenharmony_ci        plugin = grpc_cpp_plugin,
306ffe3c632Sopenharmony_ci        plugin_language = "grpc",
307ffe3c632Sopenharmony_ci        gen_cc = 1,
308ffe3c632Sopenharmony_ci        outs = outs,
309ffe3c632Sopenharmony_ci        visibility = ["//visibility:public"],
310ffe3c632Sopenharmony_ci    )
311ffe3c632Sopenharmony_ci
312ffe3c632Sopenharmony_ci    if default_runtime and not default_runtime in cc_libs:
313ffe3c632Sopenharmony_ci        cc_libs = cc_libs + [default_runtime]
314ffe3c632Sopenharmony_ci    if use_grpc_plugin:
315ffe3c632Sopenharmony_ci        cc_libs = cc_libs + ["//external:grpc_lib"]
316ffe3c632Sopenharmony_ci    cc_library(
317ffe3c632Sopenharmony_ci        name = name,
318ffe3c632Sopenharmony_ci        srcs = gen_srcs,
319ffe3c632Sopenharmony_ci        hdrs = gen_hdrs,
320ffe3c632Sopenharmony_ci        deps = cc_libs + deps,
321ffe3c632Sopenharmony_ci        includes = includes,
322ffe3c632Sopenharmony_ci        **kargs
323ffe3c632Sopenharmony_ci    )
324ffe3c632Sopenharmony_ci
325ffe3c632Sopenharmony_cidef _internal_gen_well_known_protos_java_impl(ctx):
326ffe3c632Sopenharmony_ci    args = ctx.actions.args()
327ffe3c632Sopenharmony_ci
328ffe3c632Sopenharmony_ci    deps = [d[ProtoInfo] for d in ctx.attr.deps]
329ffe3c632Sopenharmony_ci
330ffe3c632Sopenharmony_ci    srcjar = ctx.actions.declare_file("{}.srcjar".format(ctx.attr.name))
331ffe3c632Sopenharmony_ci    args.add("--java_out", srcjar)
332ffe3c632Sopenharmony_ci
333ffe3c632Sopenharmony_ci    descriptors = depset(
334ffe3c632Sopenharmony_ci        transitive = [dep.transitive_descriptor_sets for dep in deps],
335ffe3c632Sopenharmony_ci    )
336ffe3c632Sopenharmony_ci    args.add_joined(
337ffe3c632Sopenharmony_ci        "--descriptor_set_in",
338ffe3c632Sopenharmony_ci        descriptors,
339ffe3c632Sopenharmony_ci        join_with = ctx.configuration.host_path_separator,
340ffe3c632Sopenharmony_ci    )
341ffe3c632Sopenharmony_ci
342ffe3c632Sopenharmony_ci    for dep in deps:
343ffe3c632Sopenharmony_ci        if "." == dep.proto_source_root:
344ffe3c632Sopenharmony_ci            args.add_all([src.path for src in dep.direct_sources])
345ffe3c632Sopenharmony_ci        else:
346ffe3c632Sopenharmony_ci            source_root = dep.proto_source_root
347ffe3c632Sopenharmony_ci            offset = len(source_root) + 1  # + '/'.
348ffe3c632Sopenharmony_ci            args.add_all([src.path[offset:] for src in dep.direct_sources])
349ffe3c632Sopenharmony_ci
350ffe3c632Sopenharmony_ci    ctx.actions.run(
351ffe3c632Sopenharmony_ci        executable = ctx.executable._protoc,
352ffe3c632Sopenharmony_ci        inputs = descriptors,
353ffe3c632Sopenharmony_ci        outputs = [srcjar],
354ffe3c632Sopenharmony_ci        arguments = [args],
355ffe3c632Sopenharmony_ci    )
356ffe3c632Sopenharmony_ci
357ffe3c632Sopenharmony_ci    return [
358ffe3c632Sopenharmony_ci        DefaultInfo(
359ffe3c632Sopenharmony_ci            files = depset([srcjar]),
360ffe3c632Sopenharmony_ci        ),
361ffe3c632Sopenharmony_ci    ]
362ffe3c632Sopenharmony_ci
363ffe3c632Sopenharmony_ciinternal_gen_well_known_protos_java = rule(
364ffe3c632Sopenharmony_ci    implementation = _internal_gen_well_known_protos_java_impl,
365ffe3c632Sopenharmony_ci    attrs = {
366ffe3c632Sopenharmony_ci        "deps": attr.label_list(
367ffe3c632Sopenharmony_ci            mandatory = True,
368ffe3c632Sopenharmony_ci            providers = [ProtoInfo],
369ffe3c632Sopenharmony_ci        ),
370ffe3c632Sopenharmony_ci        "_protoc": attr.label(
371ffe3c632Sopenharmony_ci            executable = True,
372ffe3c632Sopenharmony_ci            cfg = "host",
373ffe3c632Sopenharmony_ci            default = "@com_google_protobuf//:protoc",
374ffe3c632Sopenharmony_ci        ),
375ffe3c632Sopenharmony_ci    },
376ffe3c632Sopenharmony_ci)
377ffe3c632Sopenharmony_ci
378ffe3c632Sopenharmony_cidef internal_copied_filegroup(name, srcs, strip_prefix, dest, **kwargs):
379ffe3c632Sopenharmony_ci    """Macro to copy files to a different directory and then create a filegroup.
380ffe3c632Sopenharmony_ci
381ffe3c632Sopenharmony_ci    This is used by the //:protobuf_python py_proto_library target to work around
382ffe3c632Sopenharmony_ci    an issue caused by Python source files that are part of the same Python
383ffe3c632Sopenharmony_ci    package being in separate directories.
384ffe3c632Sopenharmony_ci
385ffe3c632Sopenharmony_ci    Args:
386ffe3c632Sopenharmony_ci      srcs: The source files to copy and add to the filegroup.
387ffe3c632Sopenharmony_ci      strip_prefix: Path to the root of the files to copy.
388ffe3c632Sopenharmony_ci      dest: The directory to copy the source files into.
389ffe3c632Sopenharmony_ci      **kwargs: extra arguments that will be passesd to the filegroup.
390ffe3c632Sopenharmony_ci    """
391ffe3c632Sopenharmony_ci    outs = [_RelativeOutputPath(s, strip_prefix, dest) for s in srcs]
392ffe3c632Sopenharmony_ci
393ffe3c632Sopenharmony_ci    native.genrule(
394ffe3c632Sopenharmony_ci        name = name + "_genrule",
395ffe3c632Sopenharmony_ci        srcs = srcs,
396ffe3c632Sopenharmony_ci        outs = outs,
397ffe3c632Sopenharmony_ci        cmd = " && ".join(
398ffe3c632Sopenharmony_ci            ["cp $(location %s) $(location %s)" %
399ffe3c632Sopenharmony_ci             (s, _RelativeOutputPath(s, strip_prefix, dest)) for s in srcs],
400ffe3c632Sopenharmony_ci        ),
401ffe3c632Sopenharmony_ci    )
402ffe3c632Sopenharmony_ci
403ffe3c632Sopenharmony_ci    native.filegroup(
404ffe3c632Sopenharmony_ci        name = name,
405ffe3c632Sopenharmony_ci        srcs = outs,
406ffe3c632Sopenharmony_ci        **kwargs
407ffe3c632Sopenharmony_ci    )
408ffe3c632Sopenharmony_ci
409ffe3c632Sopenharmony_cidef py_proto_library(
410ffe3c632Sopenharmony_ci        name,
411ffe3c632Sopenharmony_ci        srcs = [],
412ffe3c632Sopenharmony_ci        deps = [],
413ffe3c632Sopenharmony_ci        py_libs = [],
414ffe3c632Sopenharmony_ci        py_extra_srcs = [],
415ffe3c632Sopenharmony_ci        include = None,
416ffe3c632Sopenharmony_ci        default_runtime = "@com_google_protobuf//:protobuf_python",
417ffe3c632Sopenharmony_ci        protoc = "@com_google_protobuf//:protoc",
418ffe3c632Sopenharmony_ci        use_grpc_plugin = False,
419ffe3c632Sopenharmony_ci        **kargs):
420ffe3c632Sopenharmony_ci    """Bazel rule to create a Python protobuf library from proto source files
421ffe3c632Sopenharmony_ci
422ffe3c632Sopenharmony_ci    NOTE: the rule is only an internal workaround to generate protos. The
423ffe3c632Sopenharmony_ci    interface may change and the rule may be removed when bazel has introduced
424ffe3c632Sopenharmony_ci    the native rule.
425ffe3c632Sopenharmony_ci
426ffe3c632Sopenharmony_ci    Args:
427ffe3c632Sopenharmony_ci      name: the name of the py_proto_library.
428ffe3c632Sopenharmony_ci      srcs: the .proto files of the py_proto_library.
429ffe3c632Sopenharmony_ci      deps: a list of dependency labels; must be py_proto_library.
430ffe3c632Sopenharmony_ci      py_libs: a list of other py_library targets depended by the generated
431ffe3c632Sopenharmony_ci          py_library.
432ffe3c632Sopenharmony_ci      py_extra_srcs: extra source files that will be added to the output
433ffe3c632Sopenharmony_ci          py_library. This attribute is used for internal bootstrapping.
434ffe3c632Sopenharmony_ci      include: a string indicating the include path of the .proto files.
435ffe3c632Sopenharmony_ci      default_runtime: the implicitly default runtime which will be depended on by
436ffe3c632Sopenharmony_ci          the generated py_library target.
437ffe3c632Sopenharmony_ci      protoc: the label of the protocol compiler to generate the sources.
438ffe3c632Sopenharmony_ci      use_grpc_plugin: a flag to indicate whether to call the Python C++ plugin
439ffe3c632Sopenharmony_ci          when processing the proto files.
440ffe3c632Sopenharmony_ci      **kargs: other keyword arguments that are passed to py_library.
441ffe3c632Sopenharmony_ci
442ffe3c632Sopenharmony_ci    """
443ffe3c632Sopenharmony_ci    outs = _PyOuts(srcs, use_grpc_plugin)
444ffe3c632Sopenharmony_ci
445ffe3c632Sopenharmony_ci    includes = []
446ffe3c632Sopenharmony_ci    if include != None:
447ffe3c632Sopenharmony_ci        includes = [include]
448ffe3c632Sopenharmony_ci
449ffe3c632Sopenharmony_ci    grpc_python_plugin = None
450ffe3c632Sopenharmony_ci    if use_grpc_plugin:
451ffe3c632Sopenharmony_ci        grpc_python_plugin = "//external:grpc_python_plugin"
452ffe3c632Sopenharmony_ci        # Note: Generated grpc code depends on Python grpc module. This dependency
453ffe3c632Sopenharmony_ci        # is not explicitly listed in py_libs. Instead, host system is assumed to
454ffe3c632Sopenharmony_ci        # have grpc installed.
455ffe3c632Sopenharmony_ci
456ffe3c632Sopenharmony_ci    proto_gen(
457ffe3c632Sopenharmony_ci        name = name + "_genproto",
458ffe3c632Sopenharmony_ci        srcs = srcs,
459ffe3c632Sopenharmony_ci        deps = [s + "_genproto" for s in deps],
460ffe3c632Sopenharmony_ci        includes = includes,
461ffe3c632Sopenharmony_ci        protoc = protoc,
462ffe3c632Sopenharmony_ci        gen_py = 1,
463ffe3c632Sopenharmony_ci        outs = outs,
464ffe3c632Sopenharmony_ci        visibility = ["//visibility:public"],
465ffe3c632Sopenharmony_ci        plugin = grpc_python_plugin,
466ffe3c632Sopenharmony_ci        plugin_language = "grpc",
467ffe3c632Sopenharmony_ci    )
468ffe3c632Sopenharmony_ci
469ffe3c632Sopenharmony_ci    if default_runtime and not default_runtime in py_libs + deps:
470ffe3c632Sopenharmony_ci        py_libs = py_libs + [default_runtime]
471ffe3c632Sopenharmony_ci    py_library(
472ffe3c632Sopenharmony_ci        name = name,
473ffe3c632Sopenharmony_ci        srcs = outs + py_extra_srcs,
474ffe3c632Sopenharmony_ci        deps = py_libs + deps,
475ffe3c632Sopenharmony_ci        imports = includes,
476ffe3c632Sopenharmony_ci        **kargs
477ffe3c632Sopenharmony_ci    )
478ffe3c632Sopenharmony_ci
479ffe3c632Sopenharmony_cidef internal_protobuf_py_tests(
480ffe3c632Sopenharmony_ci        name,
481ffe3c632Sopenharmony_ci        modules = [],
482ffe3c632Sopenharmony_ci        **kargs):
483ffe3c632Sopenharmony_ci    """Bazel rules to create batch tests for protobuf internal.
484ffe3c632Sopenharmony_ci
485ffe3c632Sopenharmony_ci    Args:
486ffe3c632Sopenharmony_ci      name: the name of the rule.
487ffe3c632Sopenharmony_ci      modules: a list of modules for tests. The macro will create a py_test for
488ffe3c632Sopenharmony_ci          each of the parameter with the source "google/protobuf/%s.py"
489ffe3c632Sopenharmony_ci      kargs: extra parameters that will be passed into the py_test.
490ffe3c632Sopenharmony_ci
491ffe3c632Sopenharmony_ci    """
492ffe3c632Sopenharmony_ci    for m in modules:
493ffe3c632Sopenharmony_ci        s = "python/google/protobuf/internal/%s.py" % m
494ffe3c632Sopenharmony_ci        py_test(
495ffe3c632Sopenharmony_ci            name = "py_%s" % m,
496ffe3c632Sopenharmony_ci            srcs = [s],
497ffe3c632Sopenharmony_ci            main = s,
498ffe3c632Sopenharmony_ci            **kargs
499ffe3c632Sopenharmony_ci        )
500ffe3c632Sopenharmony_ci
501ffe3c632Sopenharmony_cidef check_protobuf_required_bazel_version():
502ffe3c632Sopenharmony_ci    """For WORKSPACE files, to check the installed version of bazel.
503ffe3c632Sopenharmony_ci
504ffe3c632Sopenharmony_ci    This ensures bazel supports our approach to proto_library() depending on a
505ffe3c632Sopenharmony_ci    copied filegroup. (Fixed in bazel 0.5.4)
506ffe3c632Sopenharmony_ci    """
507ffe3c632Sopenharmony_ci    versions.check(minimum_bazel_version = "0.5.4")
508