blob: bf748db664b971e933b8ae1cb3dbf0109d47caf8 [file] [log] [blame]
Jisi Liu39362b32015-10-14 17:12:11 -07001# -*- mode: python; -*- PYTHON-PREPROCESSING-REQUIRED
2
Jisi Liu993fb702015-10-19 17:19:49 -07003def _GenDir(ctx):
Jisi Liu53a56be2015-10-20 15:18:20 -07004 if not ctx.attr.includes:
Jisi Liu6dac0822015-10-19 14:41:00 -07005 return ""
Jisi Liu53a56be2015-10-20 15:18:20 -07006 if not ctx.attr.includes[0]:
Jisi Liu39362b32015-10-14 17:12:11 -07007 return ctx.label.package
8 if not ctx.label.package:
Jisi Liu53a56be2015-10-20 15:18:20 -07009 return ctx.attr.includes[0]
10 return ctx.label.package + '/' + ctx.attr.includes[0]
Jisi Liu39362b32015-10-14 17:12:11 -070011
Jisi Liu993fb702015-10-19 17:19:49 -070012def _CcOuts(srcs):
Jisi Liu39362b32015-10-14 17:12:11 -070013 return [s[:-len(".proto")] + ".pb.h" for s in srcs] + \
Jisi Liu125a91b2015-10-14 17:37:39 -070014 [s[:-len(".proto")] + ".pb.cc" for s in srcs]
Jisi Liu39362b32015-10-14 17:12:11 -070015
Jisi Liu993fb702015-10-19 17:19:49 -070016def _PyOuts(srcs):
Jisi Liu125a91b2015-10-14 17:37:39 -070017 return [s[:-len(".proto")] + "_pb2.py" for s in srcs]
Jisi Liu39362b32015-10-14 17:12:11 -070018
Jisi Liu993fb702015-10-19 17:19:49 -070019def _RelativeOutputPath(path, include):
20 if include == None:
21 return path
22
23 if not path.startswith(include):
24 fail("Include path %s isn't part of the path %s." % (include, path))
25
26 if include and include[-1] != '/':
27 include = include + '/'
28
29 path = path[len(include):]
30
31 if not path.startswith(PACKAGE_NAME):
32 fail("The package %s is not within the path %s" % (PACKAGE_NAME, path))
33
34 if not PACKAGE_NAME:
35 return path
36
37 return path[len(PACKAGE_NAME)+1:]
38
39
40
Jisi Liu9c7d9c02015-10-15 10:51:32 -070041def _proto_gen_impl(ctx):
42 """General implementation for generating protos"""
Jisi Liu39362b32015-10-14 17:12:11 -070043 srcs = ctx.files.srcs
44 deps = []
45 deps += ctx.files.srcs
Jisi Liu993fb702015-10-19 17:19:49 -070046 gen_dir = _GenDir(ctx)
Jisi Liu53a56be2015-10-20 15:18:20 -070047 if gen_dir:
48 import_flags = ["-I" + gen_dir]
49 else:
50 import_flags = ["-I."]
51
Jisi Liu39362b32015-10-14 17:12:11 -070052 for dep in ctx.attr.deps:
53 import_flags += dep.proto.import_flags
54 deps += dep.proto.deps
55
56 args = []
57 if ctx.attr.gen_cc:
58 args += ["--cpp_out=" + ctx.var["GENDIR"] + "/" + gen_dir]
59 if ctx.attr.gen_py:
60 args += ["--python_out=" + ctx.var["GENDIR"] + "/" + gen_dir]
61
62 if args:
63 ctx.action(
Jisi Liu125a91b2015-10-14 17:37:39 -070064 inputs=srcs + deps,
Jisi Liu39362b32015-10-14 17:12:11 -070065 outputs=ctx.outputs.outs,
Jisi Liu125a91b2015-10-14 17:37:39 -070066 arguments=args + import_flags + [s.path for s in srcs],
Jisi Liu9c7d9c02015-10-15 10:51:32 -070067 executable=ctx.executable.protoc,
Jisi Liu39362b32015-10-14 17:12:11 -070068 )
69
70 return struct(
71 proto=struct(
Jisi Liu125a91b2015-10-14 17:37:39 -070072 srcs=srcs,
73 import_flags=import_flags,
74 deps=deps,
75 ),
76 )
Jisi Liu39362b32015-10-14 17:12:11 -070077
Jisi Liu9c7d9c02015-10-15 10:51:32 -070078_proto_gen = rule(
Jisi Liu39362b32015-10-14 17:12:11 -070079 attrs = {
Jisi Liuee8131a2015-10-14 17:20:05 -070080 "srcs": attr.label_list(allow_files = True),
81 "deps": attr.label_list(providers = ["proto"]),
Jisi Liu53a56be2015-10-20 15:18:20 -070082 "includes": attr.string_list(),
Jisi Liuee8131a2015-10-14 17:20:05 -070083 "protoc": attr.label(
Andrew Harp38f131f2015-11-03 16:39:32 -050084 cfg = HOST_CFG,
Jisi Liuee8131a2015-10-14 17:20:05 -070085 executable = True,
86 single_file = True,
87 mandatory = True,
88 ),
89 "gen_cc": attr.bool(),
90 "gen_py": attr.bool(),
91 "outs": attr.output_list(),
92 },
93 output_to_genfiles = True,
Jisi Liu9c7d9c02015-10-15 10:51:32 -070094 implementation = _proto_gen_impl,
Jisi Liu39362b32015-10-14 17:12:11 -070095)
96
97def cc_proto_library(
Jisi Liu125a91b2015-10-14 17:37:39 -070098 name,
99 srcs=[],
Jisi Liu125a91b2015-10-14 17:37:39 -0700100 deps=[],
Jisi Liud8701b52015-10-16 11:44:21 -0700101 cc_libs=[],
Jisi Liu6dac0822015-10-19 14:41:00 -0700102 include=None,
Jisi Liu04658a32015-10-20 15:00:13 -0700103 protoc="//google/protobuf:protoc",
Jisi Liu3101e732015-10-16 12:46:26 -0700104 internal_bootstrap_hack=False,
Jisi Liube92ffb2015-10-27 15:11:38 -0700105 default_runtime="//google/protobuf:protobuf",
Jisi Liu125a91b2015-10-14 17:37:39 -0700106 **kargs):
Jisi Liu3101e732015-10-16 12:46:26 -0700107 """Bazel rule to create a C++ protobuf library from proto source files
108
Jisi Liud4bef7d2015-11-02 12:24:32 -0800109 NOTE: the rule is only an internal workaround to generate protos. The
110 interface may change and the rule may be removed when bazel has introduced
111 the native rule.
112
Jisi Liu3101e732015-10-16 12:46:26 -0700113 Args:
114 name: the name of the cc_proto_library.
115 srcs: the .proto files of the cc_proto_library.
116 deps: a list of dependency labels; must be cc_proto_library.
117 cc_libs: a list of other cc_library targets depended by the generated
118 cc_library.
119 include: a string indicating the include path of the .proto files.
120 protoc: the label of the protocol compiler to generate the sources.
121 internal_bootstrap_hack: a flag indicate the cc_proto_library is used only
122 for bootstraping. When it is set to True, no files will be generated.
123 The rule will simply be a provider for .proto files, so that other
124 cc_proto_library can depend on it.
Jisi Liube92ffb2015-10-27 15:11:38 -0700125 default_runtime: the implicitly default runtime which will be depended on by
126 the generated cc_library target.
Jisi Liu3101e732015-10-16 12:46:26 -0700127 **kargs: other keyword arguments that are passed to cc_library.
128
129 """
Jisi Liu39362b32015-10-14 17:12:11 -0700130
Jisi Liu53a56be2015-10-20 15:18:20 -0700131 includes = []
132 if include != None:
133 includes = [include]
134
Jisi Liu39362b32015-10-14 17:12:11 -0700135 if internal_bootstrap_hack:
136 # For pre-checked-in generated files, we add the internal_bootstrap_hack
137 # which will skip the codegen action.
Jisi Liu9c7d9c02015-10-15 10:51:32 -0700138 _proto_gen(
Jisi Liu125a91b2015-10-14 17:37:39 -0700139 name=name + "_genproto",
140 srcs=srcs,
Jisi Liud8701b52015-10-16 11:44:21 -0700141 deps=[s + "_genproto" for s in deps],
Jisi Liu53a56be2015-10-20 15:18:20 -0700142 includes=includes,
Jisi Liu125a91b2015-10-14 17:37:39 -0700143 protoc=protoc,
Martin Maly8e0c9a32015-12-04 17:44:58 -0800144 visibility=["//visibility:public"],
Jisi Liu39362b32015-10-14 17:12:11 -0700145 )
146 # An empty cc_library to make rule dependency consistent.
147 native.cc_library(
Jisi Liu125a91b2015-10-14 17:37:39 -0700148 name=name,
Jisi Liud8701b52015-10-16 11:44:21 -0700149 **kargs)
Jisi Liu39362b32015-10-14 17:12:11 -0700150 return
151
Jisi Liu993fb702015-10-19 17:19:49 -0700152 outs = _CcOuts(srcs)
Jisi Liu9c7d9c02015-10-15 10:51:32 -0700153 _proto_gen(
Jisi Liu125a91b2015-10-14 17:37:39 -0700154 name=name + "_genproto",
155 srcs=srcs,
Jisi Liud8701b52015-10-16 11:44:21 -0700156 deps=[s + "_genproto" for s in deps],
Jisi Liu53a56be2015-10-20 15:18:20 -0700157 includes=includes,
Jisi Liu125a91b2015-10-14 17:37:39 -0700158 protoc=protoc,
159 gen_cc=1,
160 outs=outs,
Martin Maly8e0c9a32015-12-04 17:44:58 -0800161 visibility=["//visibility:public"],
Jisi Liu39362b32015-10-14 17:12:11 -0700162 )
163
Jisi Liube92ffb2015-10-27 15:11:38 -0700164 if default_runtime and not default_runtime in cc_libs:
165 cc_libs += [default_runtime]
Jisi Liu6dac0822015-10-19 14:41:00 -0700166
Jisi Liu39362b32015-10-14 17:12:11 -0700167 native.cc_library(
Jisi Liu125a91b2015-10-14 17:37:39 -0700168 name=name,
169 srcs=outs,
Jisi Liud8701b52015-10-16 11:44:21 -0700170 deps=cc_libs + deps,
Jisi Liu6dac0822015-10-19 14:41:00 -0700171 includes=includes,
Jisi Liud8701b52015-10-16 11:44:21 -0700172 **kargs)
Jisi Liu993fb702015-10-19 17:19:49 -0700173
174
Jisi Liubc4fd152015-10-20 16:02:58 -0700175def internal_copied_filegroup(
Jisi Liu993fb702015-10-19 17:19:49 -0700176 name,
177 srcs,
178 include,
179 **kargs):
Jisi Liu7b948cc2015-10-19 17:56:27 -0700180 """Bazel rule to fix sources file to workaround with python path issues.
181
182 Args:
Jisi Liubc4fd152015-10-20 16:02:58 -0700183 name: the name of the internal_copied_filegroup rule, which will be the
184 name of the generated filegroup.
Jisi Liu7b948cc2015-10-19 17:56:27 -0700185 srcs: the source files to be copied.
186 include: the expected import root of the source.
187 **kargs: extra arguments that will be passed into the filegroup.
188 """
Jisi Liu993fb702015-10-19 17:19:49 -0700189 outs = [_RelativeOutputPath(s, include) for s in srcs]
190
191 native.genrule(
192 name=name+"_genrule",
193 srcs=srcs,
194 outs=outs,
Jisi Liu6ddcae22015-10-21 10:48:33 -0700195 cmd=" && ".join(["cp $(location %s) $(location %s)" %
196 (s, _RelativeOutputPath(s, include))
197 for s in srcs]))
Jisi Liu993fb702015-10-19 17:19:49 -0700198
199 native.filegroup(
200 name=name,
201 srcs=outs,
202 **kargs)
203
204
205def py_proto_library(
206 name,
207 srcs=[],
208 deps=[],
209 py_libs=[],
210 py_extra_srcs=[],
211 include=None,
Jisi Liube92ffb2015-10-27 15:11:38 -0700212 default_runtime="//google/protobuf:protobuf_python",
Jisi Liu04658a32015-10-20 15:00:13 -0700213 protoc="//google/protobuf:protoc",
Jisi Liu993fb702015-10-19 17:19:49 -0700214 **kargs):
Jisi Liu7b948cc2015-10-19 17:56:27 -0700215 """Bazel rule to create a Python protobuf library from proto source files
216
Jisi Liud4bef7d2015-11-02 12:24:32 -0800217 NOTE: the rule is only an internal workaround to generate protos. The
218 interface may change and the rule may be removed when bazel has introduced
219 the native rule.
220
Jisi Liu7b948cc2015-10-19 17:56:27 -0700221 Args:
222 name: the name of the py_proto_library.
223 srcs: the .proto files of the py_proto_library.
224 deps: a list of dependency labels; must be py_proto_library.
225 py_libs: a list of other py_library targets depended by the generated
226 py_library.
227 py_extra_srcs: extra source files that will be added to the output
228 py_library. This attribute is used for internal bootstrapping.
229 include: a string indicating the include path of the .proto files.
Jisi Liube92ffb2015-10-27 15:11:38 -0700230 default_runtime: the implicitly default runtime which will be depended on by
231 the generated py_library target.
Jisi Liu7b948cc2015-10-19 17:56:27 -0700232 protoc: the label of the protocol compiler to generate the sources.
233 **kargs: other keyword arguments that are passed to cc_library.
234
235 """
Jisi Liu993fb702015-10-19 17:19:49 -0700236 outs = _PyOuts(srcs)
Jisi Liu53a56be2015-10-20 15:18:20 -0700237
238 includes = []
239 if include != None:
240 includes = [include]
241
Jisi Liu993fb702015-10-19 17:19:49 -0700242 _proto_gen(
243 name=name + "_genproto",
244 srcs=srcs,
245 deps=[s + "_genproto" for s in deps],
Jisi Liu53a56be2015-10-20 15:18:20 -0700246 includes=includes,
Jisi Liu993fb702015-10-19 17:19:49 -0700247 protoc=protoc,
248 gen_py=1,
249 outs=outs,
Martin Maly8e0c9a32015-12-04 17:44:58 -0800250 visibility=["//visibility:public"],
Jisi Liu993fb702015-10-19 17:19:49 -0700251 )
252
Jisi Liu993fb702015-10-19 17:19:49 -0700253 if include != None:
Jisi Liu7b948cc2015-10-19 17:56:27 -0700254 # Copy the output files to the desired location to make the import work.
Jisi Liubc4fd152015-10-20 16:02:58 -0700255 internal_copied_filegroup_name=name + "_internal_copied_filegroup"
256 internal_copied_filegroup(
257 name=internal_copied_filegroup_name,
Jisi Liu993fb702015-10-19 17:19:49 -0700258 srcs=outs,
259 include=include)
Jisi Liubc4fd152015-10-20 16:02:58 -0700260 outs=[internal_copied_filegroup_name]
Jisi Liu993fb702015-10-19 17:19:49 -0700261
Jisi Liube92ffb2015-10-27 15:11:38 -0700262 if default_runtime and not default_runtime in py_libs + deps:
263 py_libs += [default_runtime]
264
Jisi Liu993fb702015-10-19 17:19:49 -0700265 native.py_library(
266 name=name,
Jisi Liua33fa8e2015-10-20 15:30:44 -0700267 srcs=outs+py_extra_srcs,
268 deps=py_libs+deps,
Jisi Liu993fb702015-10-19 17:19:49 -0700269 **kargs)
270
271def internal_protobuf_py_tests(
272 name,
273 modules=[],
274 **kargs):
Jisi Liu7b948cc2015-10-19 17:56:27 -0700275 """Bazel rules to create batch tests for protobuf internal.
276
277 Args:
278 name: the name of the rule.
279 modules: a list of modules for tests. The macro will create a py_test for
280 each of the parameter with the source "google/protobuf/%s.py"
281 kargs: extra parameters that will be passed into the py_test.
282
283 """
Jisi Liu993fb702015-10-19 17:19:49 -0700284 for m in modules:
Jisi Liu7b948cc2015-10-19 17:56:27 -0700285 s = _RelativeOutputPath(
286 "python/google/protobuf/internal/%s.py" % m, "python")
Jisi Liu993fb702015-10-19 17:19:49 -0700287 native.py_test(
288 name="py_%s" % m,
Jisi Liu7b948cc2015-10-19 17:56:27 -0700289 srcs=[s],
290 main=s,
Jisi Liu993fb702015-10-19 17:19:49 -0700291 **kargs)