Roger Chen | 7492b56 | 2018-10-29 21:58:47 -0700 | [diff] [blame] | 1 | load("@bazel_skylib//lib:versions.bzl", "versions") |
Yannic Bonenberger | d2d6ff5 | 2019-08-06 21:12:06 +0200 | [diff] [blame] | 2 | load("@rules_cc//cc:defs.bzl", "cc_library") |
Yannic Bonenberger | 723a85f | 2020-02-15 13:26:56 +0100 | [diff] [blame] | 3 | load("@rules_proto//proto:defs.bzl", "ProtoInfo") |
Yannic Bonenberger | d2d6ff5 | 2019-08-06 21:12:06 +0200 | [diff] [blame] | 4 | load("@rules_python//python:defs.bzl", "py_library", "py_test") |
Jingwen Chen | b2a1908 | 2018-01-12 18:42:22 -0500 | [diff] [blame] | 5 | |
Damien Martin-Guillerez | 76547e5 | 2016-01-15 14:01:37 +0100 | [diff] [blame] | 6 | def _GetPath(ctx, path): |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 7 | if ctx.label.workspace_root: |
| 8 | return ctx.label.workspace_root + "/" + path |
| 9 | else: |
| 10 | return path |
Damien Martin-Guillerez | 76547e5 | 2016-01-15 14:01:37 +0100 | [diff] [blame] | 11 | |
Kristina Chodorow | 4e7ecde | 2017-01-25 14:10:56 -0500 | [diff] [blame] | 12 | def _IsNewExternal(ctx): |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 13 | # 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 Chodorow | 4e7ecde | 2017-01-25 14:10:56 -0500 | [diff] [blame] | 18 | |
Jisi Liu | 993fb70 | 2015-10-19 17:19:49 -0700 | [diff] [blame] | 19 | def _GenDir(ctx): |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 20 | 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 Hemmati | d1403e5 | 2018-03-16 13:23:34 -0700 | [diff] [blame] | 25 | ) |
Jisi Liu | 39362b3 | 2015-10-14 17:12:11 -0700 | [diff] [blame] | 26 | |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 27 | # 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 | |
| 31 | def _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 | |
| 40 | def _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 | |
| 46 | def _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 | |
| 52 | def _CcOuts(srcs, use_grpc_plugin = False): |
| 53 | return _CcHdrs(srcs, use_grpc_plugin) + _CcSrcs(srcs, use_grpc_plugin) |
| 54 | |
| 55 | def _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 | |
| 61 | def _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 | |
| 76 | def _proto_gen_impl(ctx): |
| 77 | """General implementation for generating protos""" |
| 78 | srcs = ctx.files.srcs |
Harvey Tuch | 7cf3f7a | 2020-01-24 13:47:15 -0500 | [diff] [blame] | 79 | deps = depset(direct=ctx.files.srcs) |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 80 | source_dir = _SourceDir(ctx) |
| 81 | gen_dir = _GenDir(ctx).rstrip("/") |
| 82 | if source_dir: |
Harvey Tuch | 7cf3f7a | 2020-01-24 13:47:15 -0500 | [diff] [blame] | 83 | import_flags = depset(direct=["-I" + source_dir, "-I" + gen_dir]) |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 84 | else: |
Harvey Tuch | 7cf3f7a | 2020-01-24 13:47:15 -0500 | [diff] [blame] | 85 | import_flags = depset(direct=["-I."]) |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 86 | |
| 87 | for dep in ctx.attr.deps: |
Harvey Tuch | e492e5a | 2020-05-26 14:27:56 -0400 | [diff] [blame] | 88 | 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 Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 96 | |
| 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 Tuch | 7cf3f7a | 2020-01-24 13:47:15 -0500 | [diff] [blame] | 112 | for f in import_flags.to_list(): |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 113 | 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 Tuch | 7cf3f7a | 2020-01-24 13:47:15 -0500 | [diff] [blame] | 127 | inputs = [src] + deps.to_list() |
Benjamin Peterson | 6153f80 | 2019-06-03 08:56:33 -0700 | [diff] [blame] | 128 | tools = [ctx.executable.protoc] |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 129 | 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 Peterson | 6153f80 | 2019-06-03 08:56:33 -0700 | [diff] [blame] | 143 | tools.append(plugin) |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 144 | |
| 145 | if not in_gen_dir: |
| 146 | ctx.actions.run( |
| 147 | inputs = inputs, |
Benjamin Peterson | 6153f80 | 2019-06-03 08:56:33 -0700 | [diff] [blame] | 148 | tools = tools, |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 149 | outputs = outs, |
Harvey Tuch | 7cf3f7a | 2020-01-24 13:47:15 -0500 | [diff] [blame] | 150 | arguments = args + import_flags.to_list() + [src.path], |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 151 | 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 Smiley | ca3ead7 | 2019-05-21 17:31:34 -0700 | [diff] [blame] | 171 | inputs = inputs, |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 172 | outputs = [out], |
| 173 | command = command, |
| 174 | mnemonic = "ProtoCompile", |
Benjamin Peterson | 6153f80 | 2019-06-03 08:56:33 -0700 | [diff] [blame] | 175 | tools = tools, |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 176 | 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 Liu | 39362b3 | 2015-10-14 17:12:11 -0700 | [diff] [blame] | 186 | |
Yuki Yugui Sonoda | 5977fb0 | 2016-06-01 16:23:15 +0900 | [diff] [blame] | 187 | proto_gen = rule( |
Jisi Liu | 39362b3 | 2015-10-14 17:12:11 -0700 | [diff] [blame] | 188 | attrs = { |
Jisi Liu | ee8131a | 2015-10-14 17:20:05 -0700 | [diff] [blame] | 189 | "srcs": attr.label_list(allow_files = True), |
| 190 | "deps": attr.label_list(providers = ["proto"]), |
Jisi Liu | 53a56be | 2015-10-20 15:18:20 -0700 | [diff] [blame] | 191 | "includes": attr.string_list(), |
Jisi Liu | ee8131a | 2015-10-14 17:20:05 -0700 | [diff] [blame] | 192 | "protoc": attr.label( |
Charles Mita | f1fe79d | 2021-05-19 20:11:13 +0200 | [diff] [blame] | 193 | cfg = "exec", |
Jisi Liu | ee8131a | 2015-10-14 17:20:05 -0700 | [diff] [blame] | 194 | executable = True, |
James Judd | d5f0dac | 2018-08-14 21:55:35 -0600 | [diff] [blame] | 195 | allow_single_file = True, |
Jisi Liu | ee8131a | 2015-10-14 17:20:05 -0700 | [diff] [blame] | 196 | mandatory = True, |
| 197 | ), |
Yuki Yugui Sonoda | 5977fb0 | 2016-06-01 16:23:15 +0900 | [diff] [blame] | 198 | "plugin": attr.label( |
Charles Mita | f1fe79d | 2021-05-19 20:11:13 +0200 | [diff] [blame] | 199 | cfg = "exec", |
Yuki Yugui Sonoda | 5977fb0 | 2016-06-01 16:23:15 +0900 | [diff] [blame] | 200 | allow_files = True, |
Manjunath Kudlur | f0966a7 | 2016-02-22 14:30:43 -0800 | [diff] [blame] | 201 | executable = True, |
Manjunath Kudlur | f0966a7 | 2016-02-22 14:30:43 -0800 | [diff] [blame] | 202 | ), |
Yuki Yugui Sonoda | 5977fb0 | 2016-06-01 16:23:15 +0900 | [diff] [blame] | 203 | "plugin_language": attr.string(), |
| 204 | "plugin_options": attr.string_list(), |
Jisi Liu | ee8131a | 2015-10-14 17:20:05 -0700 | [diff] [blame] | 205 | "gen_cc": attr.bool(), |
| 206 | "gen_py": attr.bool(), |
| 207 | "outs": attr.output_list(), |
| 208 | }, |
| 209 | output_to_genfiles = True, |
Jisi Liu | 9c7d9c0 | 2015-10-15 10:51:32 -0700 | [diff] [blame] | 210 | implementation = _proto_gen_impl, |
Jisi Liu | 39362b3 | 2015-10-14 17:12:11 -0700 | [diff] [blame] | 211 | ) |
Yuki Yugui Sonoda | 5977fb0 | 2016-06-01 16:23:15 +0900 | [diff] [blame] | 212 | """Generates codes from Protocol Buffers definitions. |
| 213 | |
| 214 | This rule helps you to implement Skylark macros specific to the target |
| 215 | language. You should prefer more specific `cc_proto_library `, |
| 216 | `py_proto_library` and others unless you are adding such wrapper macros. |
| 217 | |
| 218 | Args: |
| 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 Chodorow | 4e7ecde | 2017-01-25 14:10:56 -0500 | [diff] [blame] | 228 | gen_cc: generates C++ sources in addition to the ones from the plugin. |
Yuki Yugui Sonoda | 5977fb0 | 2016-06-01 16:23:15 +0900 | [diff] [blame] | 229 | 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 Liu | 39362b3 | 2015-10-14 17:12:11 -0700 | [diff] [blame] | 232 | |
Yannic Bonenberger | 723a85f | 2020-02-15 13:26:56 +0100 | [diff] [blame] | 233 | def _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 | |
| 245 | adapt_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 Liu | 39362b3 | 2015-10-14 17:12:11 -0700 | [diff] [blame] | 256 | def cc_proto_library( |
Jisi Liu | 125a91b | 2015-10-14 17:37:39 -0700 | [diff] [blame] | 257 | name, |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 258 | srcs = [], |
| 259 | deps = [], |
| 260 | cc_libs = [], |
| 261 | include = None, |
| 262 | protoc = "@com_google_protobuf//:protoc", |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 263 | use_grpc_plugin = False, |
| 264 | default_runtime = "@com_google_protobuf//:protobuf", |
Jisi Liu | 125a91b | 2015-10-14 17:37:39 -0700 | [diff] [blame] | 265 | **kargs): |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 266 | """Bazel rule to create a C++ protobuf library from proto source files |
Jisi Liu | 3101e73 | 2015-10-16 12:46:26 -0700 | [diff] [blame] | 267 | |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 268 | 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 Liu | d4bef7d | 2015-11-02 12:24:32 -0800 | [diff] [blame] | 271 | |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 272 | 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 Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 280 | 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 Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 285 | """ |
Jisi Liu | 39362b3 | 2015-10-14 17:12:11 -0700 | [diff] [blame] | 286 | |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 287 | includes = [] |
| 288 | if include != None: |
| 289 | includes = [include] |
Jisi Liu | 53a56be | 2015-10-20 15:18:20 -0700 | [diff] [blame] | 290 | |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 291 | 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 Sonoda | 5977fb0 | 2016-06-01 16:23:15 +0900 | [diff] [blame] | 299 | proto_gen( |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 300 | 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 Liu | 39362b3 | 2015-10-14 17:12:11 -0700 | [diff] [blame] | 310 | ) |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 311 | |
| 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 Bonenberger | bf0c69e | 2019-07-26 13:14:19 +0200 | [diff] [blame] | 316 | cc_library( |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 317 | name = name, |
| 318 | srcs = gen_srcs, |
| 319 | hdrs = gen_hdrs, |
| 320 | deps = cc_libs + deps, |
| 321 | includes = includes, |
| 322 | **kargs |
| 323 | ) |
Jisi Liu | 993fb70 | 2015-10-19 17:19:49 -0700 | [diff] [blame] | 324 | |
Yannic | f0cb9cd | 2020-02-13 22:04:14 +0100 | [diff] [blame] | 325 | def _internal_gen_well_known_protos_java_impl(ctx): |
| 326 | args = ctx.actions.args() |
Steven Parkes | ea18866 | 2016-02-25 07:53:19 -0800 | [diff] [blame] | 327 | |
Yannic | f0cb9cd | 2020-02-13 22:04:14 +0100 | [diff] [blame] | 328 | deps = [d[ProtoInfo] for d in ctx.attr.deps] |
| 329 | |
| 330 | srcjar = ctx.actions.declare_file("{}.srcjar".format(ctx.attr.name)) |
Derek Perez | bc45f92 | 2021-04-20 11:36:32 -0700 | [diff] [blame] | 331 | if ctx.attr.javalite: |
| 332 | java_out = "lite:%s" % srcjar.path |
| 333 | else: |
| 334 | java_out = srcjar |
| 335 | |
| 336 | args.add("--java_out", java_out) |
Yannic | f0cb9cd | 2020-02-13 22:04:14 +0100 | [diff] [blame] | 337 | |
| 338 | descriptors = depset( |
| 339 | transitive = [dep.transitive_descriptor_sets for dep in deps], |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 340 | ) |
Yannic | f0cb9cd | 2020-02-13 22:04:14 +0100 | [diff] [blame] | 341 | args.add_joined( |
| 342 | "--descriptor_set_in", |
| 343 | descriptors, |
| 344 | join_with = ctx.configuration.host_path_separator, |
| 345 | ) |
| 346 | |
| 347 | for dep in deps: |
| 348 | if "." == dep.proto_source_root: |
| 349 | args.add_all([src.path for src in dep.direct_sources]) |
| 350 | else: |
| 351 | source_root = dep.proto_source_root |
| 352 | offset = len(source_root) + 1 # + '/'. |
| 353 | args.add_all([src.path[offset:] for src in dep.direct_sources]) |
| 354 | |
| 355 | ctx.actions.run( |
| 356 | executable = ctx.executable._protoc, |
| 357 | inputs = descriptors, |
| 358 | outputs = [srcjar], |
| 359 | arguments = [args], |
Adam Yi | 88f3ef7 | 2020-07-29 16:49:52 +1000 | [diff] [blame] | 360 | use_default_shell_env = True, |
Yannic | f0cb9cd | 2020-02-13 22:04:14 +0100 | [diff] [blame] | 361 | ) |
| 362 | |
| 363 | return [ |
| 364 | DefaultInfo( |
| 365 | files = depset([srcjar]), |
| 366 | ), |
| 367 | ] |
| 368 | |
| 369 | internal_gen_well_known_protos_java = rule( |
| 370 | implementation = _internal_gen_well_known_protos_java_impl, |
| 371 | attrs = { |
| 372 | "deps": attr.label_list( |
| 373 | mandatory = True, |
| 374 | providers = [ProtoInfo], |
| 375 | ), |
Derek Perez | bc45f92 | 2021-04-20 11:36:32 -0700 | [diff] [blame] | 376 | "javalite": attr.bool( |
| 377 | default = False, |
| 378 | ), |
Yannic | f0cb9cd | 2020-02-13 22:04:14 +0100 | [diff] [blame] | 379 | "_protoc": attr.label( |
| 380 | executable = True, |
Charles Mita | f1fe79d | 2021-05-19 20:11:13 +0200 | [diff] [blame] | 381 | cfg = "exec", |
Yannic | f0cb9cd | 2020-02-13 22:04:14 +0100 | [diff] [blame] | 382 | default = "@com_google_protobuf//:protoc", |
| 383 | ), |
| 384 | }, |
| 385 | ) |
Steven Parkes | ea18866 | 2016-02-25 07:53:19 -0800 | [diff] [blame] | 386 | |
David Z. Chen | 02cd45c | 2016-05-20 16:49:04 -0700 | [diff] [blame] | 387 | def internal_copied_filegroup(name, srcs, strip_prefix, dest, **kwargs): |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 388 | """Macro to copy files to a different directory and then create a filegroup. |
David Z. Chen | 02cd45c | 2016-05-20 16:49:04 -0700 | [diff] [blame] | 389 | |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 390 | This is used by the //:protobuf_python py_proto_library target to work around |
| 391 | an issue caused by Python source files that are part of the same Python |
| 392 | package being in separate directories. |
David Z. Chen | 02cd45c | 2016-05-20 16:49:04 -0700 | [diff] [blame] | 393 | |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 394 | Args: |
| 395 | srcs: The source files to copy and add to the filegroup. |
| 396 | strip_prefix: Path to the root of the files to copy. |
| 397 | dest: The directory to copy the source files into. |
| 398 | **kwargs: extra arguments that will be passesd to the filegroup. |
| 399 | """ |
| 400 | outs = [_RelativeOutputPath(s, strip_prefix, dest) for s in srcs] |
David Z. Chen | 02cd45c | 2016-05-20 16:49:04 -0700 | [diff] [blame] | 401 | |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 402 | native.genrule( |
| 403 | name = name + "_genrule", |
| 404 | srcs = srcs, |
| 405 | outs = outs, |
| 406 | cmd = " && ".join( |
| 407 | ["cp $(location %s) $(location %s)" % |
| 408 | (s, _RelativeOutputPath(s, strip_prefix, dest)) for s in srcs], |
| 409 | ), |
| 410 | ) |
David Z. Chen | 02cd45c | 2016-05-20 16:49:04 -0700 | [diff] [blame] | 411 | |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 412 | native.filegroup( |
| 413 | name = name, |
| 414 | srcs = outs, |
| 415 | **kwargs |
| 416 | ) |
David Z. Chen | 02cd45c | 2016-05-20 16:49:04 -0700 | [diff] [blame] | 417 | |
Jisi Liu | 993fb70 | 2015-10-19 17:19:49 -0700 | [diff] [blame] | 418 | def py_proto_library( |
| 419 | name, |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 420 | srcs = [], |
| 421 | deps = [], |
| 422 | py_libs = [], |
| 423 | py_extra_srcs = [], |
| 424 | include = None, |
| 425 | default_runtime = "@com_google_protobuf//:protobuf_python", |
| 426 | protoc = "@com_google_protobuf//:protoc", |
| 427 | use_grpc_plugin = False, |
Jisi Liu | 993fb70 | 2015-10-19 17:19:49 -0700 | [diff] [blame] | 428 | **kargs): |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 429 | """Bazel rule to create a Python protobuf library from proto source files |
Jisi Liu | 7b948cc | 2015-10-19 17:56:27 -0700 | [diff] [blame] | 430 | |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 431 | NOTE: the rule is only an internal workaround to generate protos. The |
| 432 | interface may change and the rule may be removed when bazel has introduced |
| 433 | the native rule. |
Jisi Liu | d4bef7d | 2015-11-02 12:24:32 -0800 | [diff] [blame] | 434 | |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 435 | Args: |
| 436 | name: the name of the py_proto_library. |
| 437 | srcs: the .proto files of the py_proto_library. |
| 438 | deps: a list of dependency labels; must be py_proto_library. |
| 439 | py_libs: a list of other py_library targets depended by the generated |
| 440 | py_library. |
| 441 | py_extra_srcs: extra source files that will be added to the output |
| 442 | py_library. This attribute is used for internal bootstrapping. |
| 443 | include: a string indicating the include path of the .proto files. |
| 444 | default_runtime: the implicitly default runtime which will be depended on by |
| 445 | the generated py_library target. |
| 446 | protoc: the label of the protocol compiler to generate the sources. |
| 447 | use_grpc_plugin: a flag to indicate whether to call the Python C++ plugin |
| 448 | when processing the proto files. |
Leo | 12236c6 | 2020-05-04 11:23:44 +0900 | [diff] [blame] | 449 | **kargs: other keyword arguments that are passed to py_library. |
Jisi Liu | 7b948cc | 2015-10-19 17:56:27 -0700 | [diff] [blame] | 450 | |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 451 | """ |
| 452 | outs = _PyOuts(srcs, use_grpc_plugin) |
Jisi Liu | 53a56be | 2015-10-20 15:18:20 -0700 | [diff] [blame] | 453 | |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 454 | includes = [] |
| 455 | if include != None: |
| 456 | includes = [include] |
Jisi Liu | 53a56be | 2015-10-20 15:18:20 -0700 | [diff] [blame] | 457 | |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 458 | grpc_python_plugin = None |
| 459 | if use_grpc_plugin: |
| 460 | grpc_python_plugin = "//external:grpc_python_plugin" |
| 461 | # Note: Generated grpc code depends on Python grpc module. This dependency |
| 462 | # is not explicitly listed in py_libs. Instead, host system is assumed to |
| 463 | # have grpc installed. |
Wiktor Tomczak | 0fa31b2 | 2016-11-22 20:18:46 +0100 | [diff] [blame] | 464 | |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 465 | proto_gen( |
| 466 | name = name + "_genproto", |
| 467 | srcs = srcs, |
| 468 | deps = [s + "_genproto" for s in deps], |
| 469 | includes = includes, |
| 470 | protoc = protoc, |
| 471 | gen_py = 1, |
| 472 | outs = outs, |
| 473 | visibility = ["//visibility:public"], |
| 474 | plugin = grpc_python_plugin, |
| 475 | plugin_language = "grpc", |
| 476 | ) |
Jisi Liu | 993fb70 | 2015-10-19 17:19:49 -0700 | [diff] [blame] | 477 | |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 478 | if default_runtime and not default_runtime in py_libs + deps: |
| 479 | py_libs = py_libs + [default_runtime] |
Yannic Bonenberger | d2d6ff5 | 2019-08-06 21:12:06 +0200 | [diff] [blame] | 480 | py_library( |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 481 | name = name, |
| 482 | srcs = outs + py_extra_srcs, |
| 483 | deps = py_libs + deps, |
| 484 | imports = includes, |
| 485 | **kargs |
| 486 | ) |
Jisi Liu | 993fb70 | 2015-10-19 17:19:49 -0700 | [diff] [blame] | 487 | |
| 488 | def internal_protobuf_py_tests( |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 489 | name, |
| 490 | modules = [], |
| 491 | **kargs): |
| 492 | """Bazel rules to create batch tests for protobuf internal. |
Jisi Liu | 7b948cc | 2015-10-19 17:56:27 -0700 | [diff] [blame] | 493 | |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 494 | Args: |
| 495 | name: the name of the rule. |
| 496 | modules: a list of modules for tests. The macro will create a py_test for |
| 497 | each of the parameter with the source "google/protobuf/%s.py" |
| 498 | kargs: extra parameters that will be passed into the py_test. |
Jisi Liu | 7b948cc | 2015-10-19 17:56:27 -0700 | [diff] [blame] | 499 | |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 500 | """ |
| 501 | for m in modules: |
| 502 | s = "python/google/protobuf/internal/%s.py" % m |
Yannic Bonenberger | d2d6ff5 | 2019-08-06 21:12:06 +0200 | [diff] [blame] | 503 | py_test( |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 504 | name = "py_%s" % m, |
| 505 | srcs = [s], |
| 506 | main = s, |
| 507 | **kargs |
| 508 | ) |
Fahrzin Hemmati | 35119e3 | 2017-11-28 14:24:53 -0800 | [diff] [blame] | 509 | |
| 510 | def check_protobuf_required_bazel_version(): |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 511 | """For WORKSPACE files, to check the installed version of bazel. |
Fahrzin Hemmati | 35119e3 | 2017-11-28 14:24:53 -0800 | [diff] [blame] | 512 | |
Paul Yang | cecba29 | 2018-12-14 16:05:03 -0800 | [diff] [blame] | 513 | This ensures bazel supports our approach to proto_library() depending on a |
| 514 | copied filegroup. (Fixed in bazel 0.5.4) |
| 515 | """ |
| 516 | versions.check(minimum_bazel_version = "0.5.4") |