diff options
Diffstat (limited to 'protobuf.bzl')
-rw-r--r-- | protobuf.bzl | 169 |
1 files changed, 152 insertions, 17 deletions
diff --git a/protobuf.bzl b/protobuf.bzl index b83f7f5a..2199caf1 100644 --- a/protobuf.bzl +++ b/protobuf.bzl @@ -1,28 +1,54 @@ # -*- mode: python; -*- PYTHON-PREPROCESSING-REQUIRED -def _gen_dir(ctx): - if ctx.attr.include == None: +def _GenDir(ctx): + if not ctx.attr.includes: return "" - if not ctx.attr.include: + if not ctx.attr.includes[0]: return ctx.label.package if not ctx.label.package: - return ctx.attr.include - return ctx.label.package + '/' + ctx.attr.include + return ctx.attr.includes[0] + return ctx.label.package + '/' + ctx.attr.includes[0] -def _cc_outs(srcs): +def _CcOuts(srcs): return [s[:-len(".proto")] + ".pb.h" for s in srcs] + \ [s[:-len(".proto")] + ".pb.cc" for s in srcs] -def _py_outs(srcs): +def _PyOuts(srcs): return [s[:-len(".proto")] + "_pb2.py" for s in srcs] +def _RelativeOutputPath(path, include): + if include == None: + return path + + if not path.startswith(include): + fail("Include path %s isn't part of the path %s." % (include, path)) + + if include and include[-1] != '/': + include = include + '/' + + path = path[len(include):] + + if not path.startswith(PACKAGE_NAME): + fail("The package %s is not within the path %s" % (PACKAGE_NAME, path)) + + if not PACKAGE_NAME: + return path + + return path[len(PACKAGE_NAME)+1:] + + + def _proto_gen_impl(ctx): """General implementation for generating protos""" srcs = ctx.files.srcs deps = [] deps += ctx.files.srcs - gen_dir = _gen_dir(ctx) - import_flags = ["-I" + gen_dir] + gen_dir = _GenDir(ctx) + if gen_dir: + import_flags = ["-I" + gen_dir] + else: + import_flags = ["-I."] + for dep in ctx.attr.deps: import_flags += dep.proto.import_flags deps += dep.proto.deps @@ -53,7 +79,7 @@ _proto_gen = rule( attrs = { "srcs": attr.label_list(allow_files = True), "deps": attr.label_list(providers = ["proto"]), - "include": attr.string(), + "includes": attr.string_list(), "protoc": attr.label( executable = True, single_file = True, @@ -73,7 +99,7 @@ def cc_proto_library( deps=[], cc_libs=[], include=None, - protoc=":protoc", + protoc="//google/protobuf:protoc", internal_bootstrap_hack=False, **kargs): """Bazel rule to create a C++ protobuf library from proto source files @@ -94,6 +120,10 @@ def cc_proto_library( """ + includes = [] + if include != None: + includes = [include] + if internal_bootstrap_hack: # For pre-checked-in generated files, we add the internal_bootstrap_hack # which will skip the codegen action. @@ -101,7 +131,7 @@ def cc_proto_library( name=name + "_genproto", srcs=srcs, deps=[s + "_genproto" for s in deps], - include=include, + includes=includes, protoc=protoc, ) # An empty cc_library to make rule dependency consistent. @@ -110,20 +140,17 @@ def cc_proto_library( **kargs) return - outs = _cc_outs(srcs) + outs = _CcOuts(srcs) _proto_gen( name=name + "_genproto", srcs=srcs, deps=[s + "_genproto" for s in deps], - include=include, + includes=includes, protoc=protoc, gen_cc=1, outs=outs, ) - includes = [] - if include != None: - includes = [include] native.cc_library( name=name, @@ -131,3 +158,111 @@ def cc_proto_library( deps=cc_libs + deps, includes=includes, **kargs) + + +def internal_copied_filegroup( + name, + srcs, + include, + **kargs): + """Bazel rule to fix sources file to workaround with python path issues. + + Args: + name: the name of the internal_copied_filegroup rule, which will be the + name of the generated filegroup. + srcs: the source files to be copied. + include: the expected import root of the source. + **kargs: extra arguments that will be passed into the filegroup. + """ + outs = [_RelativeOutputPath(s, include) for s in srcs] + + native.genrule( + name=name+"_genrule", + srcs=srcs, + outs=outs, + cmd=";".join(["cp $(location %s) $(location %s)" % \ + (s, _RelativeOutputPath(s, include)) \ + for s in srcs])) + + native.filegroup( + name=name, + srcs=outs, + **kargs) + + +def py_proto_library( + name, + srcs=[], + deps=[], + py_libs=[], + py_extra_srcs=[], + include=None, + protoc="//google/protobuf:protoc", + **kargs): + """Bazel rule to create a Python protobuf library from proto source files + + Args: + name: the name of the py_proto_library. + srcs: the .proto files of the py_proto_library. + deps: a list of dependency labels; must be py_proto_library. + py_libs: a list of other py_library targets depended by the generated + py_library. + py_extra_srcs: extra source files that will be added to the output + py_library. This attribute is used for internal bootstrapping. + include: a string indicating the include path of the .proto files. + protoc: the label of the protocol compiler to generate the sources. + **kargs: other keyword arguments that are passed to cc_library. + + """ + outs = _PyOuts(srcs) + + includes = [] + if include != None: + includes = [include] + + _proto_gen( + name=name + "_genproto", + srcs=srcs, + deps=[s + "_genproto" for s in deps], + includes=includes, + protoc=protoc, + gen_py=1, + outs=outs, + ) + + if include != None: + # Copy the output files to the desired location to make the import work. + internal_copied_filegroup_name=name + "_internal_copied_filegroup" + internal_copied_filegroup( + name=internal_copied_filegroup_name, + srcs=outs, + include=include) + outs=[internal_copied_filegroup_name] + + native.py_library( + name=name, + srcs=outs+py_extra_srcs, + deps=py_libs+deps, + **kargs) + +def internal_protobuf_py_tests( + name, + modules=[], + **kargs): + """Bazel rules to create batch tests for protobuf internal. + + Args: + name: the name of the rule. + modules: a list of modules for tests. The macro will create a py_test for + each of the parameter with the source "google/protobuf/%s.py" + kargs: extra parameters that will be passed into the py_test. + + """ + for m in modules: + s = _RelativeOutputPath( + "python/google/protobuf/internal/%s.py" % m, "python") + native.py_test( + name="py_%s" % m, + srcs=[s], + main=s, + **kargs) |