github.com/johnnyeven/libtools@v0.0.0-20191126065708-61829c1adf46/third_party/systemlibs/protobuf.bzl (about) 1 def _GetPath(ctx, path): 2 if ctx.label.workspace_root: 3 return ctx.label.workspace_root + "/" + path 4 else: 5 return path 6 7 def _IsNewExternal(ctx): 8 # Bazel 0.4.4 and older have genfiles paths that look like: 9 # bazel-out/local-fastbuild/genfiles/external/repo/foo 10 # After the exec root rearrangement, they look like: 11 # ../repo/bazel-out/local-fastbuild/genfiles/foo 12 return ctx.label.workspace_root.startswith("../") 13 14 def _GenDir(ctx): 15 if _IsNewExternal(ctx): 16 # We are using the fact that Bazel 0.4.4+ provides repository-relative paths 17 # for ctx.genfiles_dir. 18 return ctx.genfiles_dir.path + ( 19 "/" + ctx.attr.includes[0] if ctx.attr.includes and ctx.attr.includes[0] else "" 20 ) 21 22 # This means that we're either in the old version OR the new version in the local repo. 23 # Either way, appending the source path to the genfiles dir works. 24 return ctx.var["GENDIR"] + "/" + _SourceDir(ctx) 25 26 def _SourceDir(ctx): 27 if not ctx.attr.includes: 28 return ctx.label.workspace_root 29 if not ctx.attr.includes[0]: 30 return _GetPath(ctx, ctx.label.package) 31 if not ctx.label.package: 32 return _GetPath(ctx, ctx.attr.includes[0]) 33 return _GetPath(ctx, ctx.label.package + "/" + ctx.attr.includes[0]) 34 35 def _CcHdrs(srcs, use_grpc_plugin = False): 36 ret = [s[:-len(".proto")] + ".pb.h" for s in srcs] 37 if use_grpc_plugin: 38 ret += [s[:-len(".proto")] + ".grpc.pb.h" for s in srcs] 39 return ret 40 41 def _CcSrcs(srcs, use_grpc_plugin = False): 42 ret = [s[:-len(".proto")] + ".pb.cc" for s in srcs] 43 if use_grpc_plugin: 44 ret += [s[:-len(".proto")] + ".grpc.pb.cc" for s in srcs] 45 return ret 46 47 def _CcOuts(srcs, use_grpc_plugin = False): 48 return _CcHdrs(srcs, use_grpc_plugin) + _CcSrcs(srcs, use_grpc_plugin) 49 50 def _PyOuts(srcs, use_grpc_plugin = False): 51 ret = [s[:-len(".proto")] + "_pb2.py" for s in srcs] 52 if use_grpc_plugin: 53 ret += [s[:-len(".proto")] + "_pb2_grpc.py" for s in srcs] 54 return ret 55 56 def _RelativeOutputPath(path, include, dest = ""): 57 if include == None: 58 return path 59 60 if not path.startswith(include): 61 fail("Include path %s isn't part of the path %s." % (include, path)) 62 63 if include and include[-1] != "/": 64 include = include + "/" 65 if dest and dest[-1] != "/": 66 dest = dest + "/" 67 68 path = path[len(include):] 69 return dest + path 70 71 def _proto_gen_impl(ctx): 72 """General implementation for generating protos""" 73 srcs = ctx.files.srcs 74 deps = [] 75 deps += ctx.files.srcs 76 source_dir = _SourceDir(ctx) 77 gen_dir = _GenDir(ctx) 78 if source_dir: 79 import_flags = ["-I" + source_dir, "-I" + gen_dir] 80 else: 81 import_flags = ["-I."] 82 83 for dep in ctx.attr.deps: 84 import_flags += dep.proto.import_flags 85 deps += dep.proto.deps 86 87 args = [] 88 if ctx.attr.gen_cc: 89 args += ["--cpp_out=" + gen_dir] 90 if ctx.attr.gen_py: 91 args += ["--python_out=" + gen_dir] 92 93 inputs = srcs + deps 94 if ctx.executable.plugin: 95 plugin = ctx.executable.plugin 96 lang = ctx.attr.plugin_language 97 if not lang and plugin.basename.startswith("protoc-gen-"): 98 lang = plugin.basename[len("protoc-gen-"):] 99 if not lang: 100 fail("cannot infer the target language of plugin", "plugin_language") 101 102 outdir = gen_dir 103 if ctx.attr.plugin_options: 104 outdir = ",".join(ctx.attr.plugin_options) + ":" + outdir 105 args += ["--plugin=protoc-gen-%s=%s" % (lang, plugin.path)] 106 args += ["--%s_out=%s" % (lang, outdir)] 107 inputs += [plugin] 108 109 if args: 110 ctx.actions.run( 111 inputs = inputs, 112 outputs = ctx.outputs.outs, 113 arguments = args + import_flags + [s.path for s in srcs], 114 executable = ctx.executable.protoc, 115 mnemonic = "ProtoCompile", 116 use_default_shell_env = True, 117 ) 118 119 return struct( 120 proto = struct( 121 srcs = srcs, 122 import_flags = import_flags, 123 deps = deps, 124 ), 125 ) 126 127 proto_gen = rule( 128 attrs = { 129 "srcs": attr.label_list(allow_files = True), 130 "deps": attr.label_list(providers = ["proto"]), 131 "includes": attr.string_list(), 132 "protoc": attr.label( 133 cfg = "host", 134 executable = True, 135 allow_single_file = True, 136 mandatory = True, 137 ), 138 "plugin": attr.label( 139 cfg = "host", 140 allow_files = True, 141 executable = True, 142 ), 143 "plugin_language": attr.string(), 144 "plugin_options": attr.string_list(), 145 "gen_cc": attr.bool(), 146 "gen_py": attr.bool(), 147 "outs": attr.output_list(), 148 }, 149 output_to_genfiles = True, 150 implementation = _proto_gen_impl, 151 ) 152 """Generates codes from Protocol Buffers definitions. 153 154 This rule helps you to implement Skylark macros specific to the target 155 language. You should prefer more specific `cc_proto_library `, 156 `py_proto_library` and others unless you are adding such wrapper macros. 157 158 Args: 159 srcs: Protocol Buffers definition files (.proto) to run the protocol compiler 160 against. 161 deps: a list of dependency labels; must be other proto libraries. 162 includes: a list of include paths to .proto files. 163 protoc: the label of the protocol compiler to generate the sources. 164 plugin: the label of the protocol compiler plugin to be passed to the protocol 165 compiler. 166 plugin_language: the language of the generated sources 167 plugin_options: a list of options to be passed to the plugin 168 gen_cc: generates C++ sources in addition to the ones from the plugin. 169 gen_py: generates Python sources in addition to the ones from the plugin. 170 outs: a list of labels of the expected outputs from the protocol compiler. 171 """ 172 173 def cc_proto_library( 174 name, 175 srcs = [], 176 deps = [], 177 cc_libs = [], 178 include = None, 179 protoc = "@com_google_protobuf//:protoc", 180 internal_bootstrap_hack = False, 181 use_grpc_plugin = False, 182 default_runtime = "@com_google_protobuf//:protobuf", 183 **kargs): 184 """Bazel rule to create a C++ protobuf library from proto source files 185 186 NOTE: the rule is only an internal workaround to generate protos. The 187 interface may change and the rule may be removed when bazel has introduced 188 the native rule. 189 190 Args: 191 name: the name of the cc_proto_library. 192 srcs: the .proto files of the cc_proto_library. 193 deps: a list of dependency labels; must be cc_proto_library. 194 cc_libs: a list of other cc_library targets depended by the generated 195 cc_library. 196 include: a string indicating the include path of the .proto files. 197 protoc: the label of the protocol compiler to generate the sources. 198 internal_bootstrap_hack: a flag indicate the cc_proto_library is used only 199 for bootstraping. When it is set to True, no files will be generated. 200 The rule will simply be a provider for .proto files, so that other 201 cc_proto_library can depend on it. 202 use_grpc_plugin: a flag to indicate whether to call the grpc C++ plugin 203 when processing the proto files. 204 default_runtime: the implicitly default runtime which will be depended on by 205 the generated cc_library target. 206 **kargs: other keyword arguments that are passed to cc_library. 207 208 """ 209 210 includes = [] 211 if include != None: 212 includes = [include] 213 214 if internal_bootstrap_hack: 215 # For pre-checked-in generated files, we add the internal_bootstrap_hack 216 # which will skip the codegen action. 217 proto_gen( 218 name = name + "_genproto", 219 srcs = srcs, 220 deps = [s + "_genproto" for s in deps], 221 includes = includes, 222 protoc = protoc, 223 visibility = ["//visibility:public"], 224 ) 225 226 # An empty cc_library to make rule dependency consistent. 227 native.cc_library( 228 name = name, 229 **kargs 230 ) 231 return 232 233 grpc_cpp_plugin = None 234 if use_grpc_plugin: 235 grpc_cpp_plugin = "//external:grpc_cpp_plugin" 236 237 gen_srcs = _CcSrcs(srcs, use_grpc_plugin) 238 gen_hdrs = _CcHdrs(srcs, use_grpc_plugin) 239 outs = gen_srcs + gen_hdrs 240 241 proto_gen( 242 name = name + "_genproto", 243 srcs = srcs, 244 deps = [s + "_genproto" for s in deps], 245 includes = includes, 246 protoc = protoc, 247 plugin = grpc_cpp_plugin, 248 plugin_language = "grpc", 249 gen_cc = 1, 250 outs = outs, 251 visibility = ["//visibility:public"], 252 ) 253 254 if default_runtime and not default_runtime in cc_libs: 255 cc_libs = cc_libs + [default_runtime] 256 if use_grpc_plugin: 257 cc_libs = cc_libs + ["//external:grpc_lib"] 258 259 native.cc_library( 260 name = name, 261 srcs = gen_srcs, 262 hdrs = gen_hdrs, 263 deps = cc_libs + deps, 264 includes = includes, 265 **kargs 266 ) 267 268 def internal_gen_well_known_protos_java(srcs): 269 """Bazel rule to generate the gen_well_known_protos_java genrule 270 271 Args: 272 srcs: the well known protos 273 """ 274 root = Label("%s//protobuf_java" % (REPOSITORY_NAME)).workspace_root 275 pkg = PACKAGE_NAME + "/" if PACKAGE_NAME else "" 276 if root == "": 277 include = " -I%ssrc " % pkg 278 else: 279 include = " -I%s/%ssrc " % (root, pkg) 280 native.genrule( 281 name = "gen_well_known_protos_java", 282 srcs = srcs, 283 outs = [ 284 "wellknown.srcjar", 285 ], 286 cmd = "$(location :protoc) --java_out=$(@D)/wellknown.jar" + 287 " %s $(SRCS) " % include + 288 " && mv $(@D)/wellknown.jar $(@D)/wellknown.srcjar", 289 tools = [":protoc"], 290 ) 291 292 def internal_copied_filegroup(name, srcs, strip_prefix, dest, **kwargs): 293 """Macro to copy files to a different directory and then create a filegroup. 294 295 This is used by the //:protobuf_python py_proto_library target to work around 296 an issue caused by Python source files that are part of the same Python 297 package being in separate directories. 298 299 Args: 300 srcs: The source files to copy and add to the filegroup. 301 strip_prefix: Path to the root of the files to copy. 302 dest: The directory to copy the source files into. 303 **kwargs: extra arguments that will be passesd to the filegroup. 304 """ 305 outs = [_RelativeOutputPath(s, strip_prefix, dest) for s in srcs] 306 307 native.genrule( 308 name = name + "_genrule", 309 srcs = srcs, 310 outs = outs, 311 cmd = " && ".join( 312 ["cp $(location %s) $(location %s)" % 313 (s, _RelativeOutputPath(s, strip_prefix, dest)) for s in srcs], 314 ), 315 ) 316 317 native.filegroup( 318 name = name, 319 srcs = outs, 320 **kwargs 321 ) 322 323 def py_proto_library( 324 name, 325 srcs = [], 326 deps = [], 327 py_libs = [], 328 py_extra_srcs = [], 329 include = None, 330 default_runtime = "@com_google_protobuf//:protobuf_python", 331 protoc = "@com_google_protobuf//:protoc", 332 use_grpc_plugin = False, 333 **kargs): 334 """Bazel rule to create a Python protobuf library from proto source files 335 336 NOTE: the rule is only an internal workaround to generate protos. The 337 interface may change and the rule may be removed when bazel has introduced 338 the native rule. 339 340 Args: 341 name: the name of the py_proto_library. 342 srcs: the .proto files of the py_proto_library. 343 deps: a list of dependency labels; must be py_proto_library. 344 py_libs: a list of other py_library targets depended by the generated 345 py_library. 346 py_extra_srcs: extra source files that will be added to the output 347 py_library. This attribute is used for internal bootstrapping. 348 include: a string indicating the include path of the .proto files. 349 default_runtime: the implicitly default runtime which will be depended on by 350 the generated py_library target. 351 protoc: the label of the protocol compiler to generate the sources. 352 use_grpc_plugin: a flag to indicate whether to call the Python C++ plugin 353 when processing the proto files. 354 **kargs: other keyword arguments that are passed to cc_library. 355 356 """ 357 outs = _PyOuts(srcs, use_grpc_plugin) 358 359 includes = [] 360 if include != None: 361 includes = [include] 362 363 grpc_python_plugin = None 364 if use_grpc_plugin: 365 grpc_python_plugin = "//external:grpc_python_plugin" 366 # Note: Generated grpc code depends on Python grpc module. This dependency 367 # is not explicitly listed in py_libs. Instead, host system is assumed to 368 # have grpc installed. 369 370 proto_gen( 371 name = name + "_genproto", 372 srcs = srcs, 373 deps = [s + "_genproto" for s in deps], 374 includes = includes, 375 protoc = protoc, 376 gen_py = 1, 377 outs = outs, 378 visibility = ["//visibility:public"], 379 plugin = grpc_python_plugin, 380 plugin_language = "grpc", 381 ) 382 383 if default_runtime and not default_runtime in py_libs + deps: 384 py_libs = py_libs + [default_runtime] 385 386 native.py_library( 387 name = name, 388 srcs = outs + py_extra_srcs, 389 deps = py_libs + deps, 390 imports = includes, 391 **kargs 392 ) 393 394 def internal_protobuf_py_tests( 395 name, 396 modules = [], 397 **kargs): 398 """Bazel rules to create batch tests for protobuf internal. 399 400 Args: 401 name: the name of the rule. 402 modules: a list of modules for tests. The macro will create a py_test for 403 each of the parameter with the source "google/protobuf/%s.py" 404 kargs: extra parameters that will be passed into the py_test. 405 406 """ 407 for m in modules: 408 s = "python/google/protobuf/internal/%s.py" % m 409 native.py_test( 410 name = "py_%s" % m, 411 srcs = [s], 412 main = s, 413 **kargs 414 ) 415 416 def check_protobuf_required_bazel_version(): 417 """For WORKSPACE files, to check the installed version of bazel. 418 419 This ensures bazel supports our approach to proto_library() depending on a 420 copied filegroup. (Fixed in bazel 0.5.4) 421 """ 422 expected = apple_common.dotted_version("0.5.4") 423 current = apple_common.dotted_version(native.bazel_version) 424 if current.compare_to(expected) < 0: 425 fail("Bazel must be newer than 0.5.4")