blob: e8bc455bbe06851ac14628ba5c6f74a32a69c902 [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(
84 executable = True,
85 single_file = True,
86 mandatory = True,
87 ),
88 "gen_cc": attr.bool(),
89 "gen_py": attr.bool(),
90 "outs": attr.output_list(),
91 },
92 output_to_genfiles = True,
Jisi Liu9c7d9c02015-10-15 10:51:32 -070093 implementation = _proto_gen_impl,
Jisi Liu39362b32015-10-14 17:12:11 -070094)
95
96def cc_proto_library(
Jisi Liu125a91b2015-10-14 17:37:39 -070097 name,
98 srcs=[],
Jisi Liu125a91b2015-10-14 17:37:39 -070099 deps=[],
Jisi Liud8701b52015-10-16 11:44:21 -0700100 cc_libs=[],
Jisi Liu6dac0822015-10-19 14:41:00 -0700101 include=None,
Jisi Liu04658a32015-10-20 15:00:13 -0700102 protoc="//google/protobuf:protoc",
Jisi Liu3101e732015-10-16 12:46:26 -0700103 internal_bootstrap_hack=False,
Jisi Liube92ffb2015-10-27 15:11:38 -0700104 default_runtime="//google/protobuf:protobuf",
Jisi Liu125a91b2015-10-14 17:37:39 -0700105 **kargs):
Jisi Liu3101e732015-10-16 12:46:26 -0700106 """Bazel rule to create a C++ protobuf library from proto source files
107
108 Args:
109 name: the name of the cc_proto_library.
110 srcs: the .proto files of the cc_proto_library.
111 deps: a list of dependency labels; must be cc_proto_library.
112 cc_libs: a list of other cc_library targets depended by the generated
113 cc_library.
114 include: a string indicating the include path of the .proto files.
115 protoc: the label of the protocol compiler to generate the sources.
116 internal_bootstrap_hack: a flag indicate the cc_proto_library is used only
117 for bootstraping. When it is set to True, no files will be generated.
118 The rule will simply be a provider for .proto files, so that other
119 cc_proto_library can depend on it.
Jisi Liube92ffb2015-10-27 15:11:38 -0700120 default_runtime: the implicitly default runtime which will be depended on by
121 the generated cc_library target.
Jisi Liu3101e732015-10-16 12:46:26 -0700122 **kargs: other keyword arguments that are passed to cc_library.
123
124 """
Jisi Liu39362b32015-10-14 17:12:11 -0700125
Jisi Liu53a56be2015-10-20 15:18:20 -0700126 includes = []
127 if include != None:
128 includes = [include]
129
Jisi Liu39362b32015-10-14 17:12:11 -0700130 if internal_bootstrap_hack:
131 # For pre-checked-in generated files, we add the internal_bootstrap_hack
132 # which will skip the codegen action.
Jisi Liu9c7d9c02015-10-15 10:51:32 -0700133 _proto_gen(
Jisi Liu125a91b2015-10-14 17:37:39 -0700134 name=name + "_genproto",
135 srcs=srcs,
Jisi Liud8701b52015-10-16 11:44:21 -0700136 deps=[s + "_genproto" for s in deps],
Jisi Liu53a56be2015-10-20 15:18:20 -0700137 includes=includes,
Jisi Liu125a91b2015-10-14 17:37:39 -0700138 protoc=protoc,
Jisi Liu39362b32015-10-14 17:12:11 -0700139 )
140 # An empty cc_library to make rule dependency consistent.
141 native.cc_library(
Jisi Liu125a91b2015-10-14 17:37:39 -0700142 name=name,
Jisi Liud8701b52015-10-16 11:44:21 -0700143 **kargs)
Jisi Liu39362b32015-10-14 17:12:11 -0700144 return
145
Jisi Liu993fb702015-10-19 17:19:49 -0700146 outs = _CcOuts(srcs)
Jisi Liu9c7d9c02015-10-15 10:51:32 -0700147 _proto_gen(
Jisi Liu125a91b2015-10-14 17:37:39 -0700148 name=name + "_genproto",
149 srcs=srcs,
Jisi Liud8701b52015-10-16 11:44:21 -0700150 deps=[s + "_genproto" for s in deps],
Jisi Liu53a56be2015-10-20 15:18:20 -0700151 includes=includes,
Jisi Liu125a91b2015-10-14 17:37:39 -0700152 protoc=protoc,
153 gen_cc=1,
154 outs=outs,
Jisi Liu39362b32015-10-14 17:12:11 -0700155 )
156
Jisi Liube92ffb2015-10-27 15:11:38 -0700157 if default_runtime and not default_runtime in cc_libs:
158 cc_libs += [default_runtime]
Jisi Liu6dac0822015-10-19 14:41:00 -0700159
Jisi Liu39362b32015-10-14 17:12:11 -0700160 native.cc_library(
Jisi Liu125a91b2015-10-14 17:37:39 -0700161 name=name,
162 srcs=outs,
Jisi Liud8701b52015-10-16 11:44:21 -0700163 deps=cc_libs + deps,
Jisi Liu6dac0822015-10-19 14:41:00 -0700164 includes=includes,
Jisi Liud8701b52015-10-16 11:44:21 -0700165 **kargs)
Jisi Liu993fb702015-10-19 17:19:49 -0700166
167
Jisi Liubc4fd152015-10-20 16:02:58 -0700168def internal_copied_filegroup(
Jisi Liu993fb702015-10-19 17:19:49 -0700169 name,
170 srcs,
171 include,
172 **kargs):
Jisi Liu7b948cc2015-10-19 17:56:27 -0700173 """Bazel rule to fix sources file to workaround with python path issues.
174
175 Args:
Jisi Liubc4fd152015-10-20 16:02:58 -0700176 name: the name of the internal_copied_filegroup rule, which will be the
177 name of the generated filegroup.
Jisi Liu7b948cc2015-10-19 17:56:27 -0700178 srcs: the source files to be copied.
179 include: the expected import root of the source.
180 **kargs: extra arguments that will be passed into the filegroup.
181 """
Jisi Liu993fb702015-10-19 17:19:49 -0700182 outs = [_RelativeOutputPath(s, include) for s in srcs]
183
184 native.genrule(
185 name=name+"_genrule",
186 srcs=srcs,
187 outs=outs,
Jisi Liu6ddcae22015-10-21 10:48:33 -0700188 cmd=" && ".join(["cp $(location %s) $(location %s)" %
189 (s, _RelativeOutputPath(s, include))
190 for s in srcs]))
Jisi Liu993fb702015-10-19 17:19:49 -0700191
192 native.filegroup(
193 name=name,
194 srcs=outs,
195 **kargs)
196
197
198def py_proto_library(
199 name,
200 srcs=[],
201 deps=[],
202 py_libs=[],
203 py_extra_srcs=[],
204 include=None,
Jisi Liube92ffb2015-10-27 15:11:38 -0700205 default_runtime="//google/protobuf:protobuf_python",
Jisi Liu04658a32015-10-20 15:00:13 -0700206 protoc="//google/protobuf:protoc",
Jisi Liu993fb702015-10-19 17:19:49 -0700207 **kargs):
Jisi Liu7b948cc2015-10-19 17:56:27 -0700208 """Bazel rule to create a Python protobuf library from proto source files
209
210 Args:
211 name: the name of the py_proto_library.
212 srcs: the .proto files of the py_proto_library.
213 deps: a list of dependency labels; must be py_proto_library.
214 py_libs: a list of other py_library targets depended by the generated
215 py_library.
216 py_extra_srcs: extra source files that will be added to the output
217 py_library. This attribute is used for internal bootstrapping.
218 include: a string indicating the include path of the .proto files.
Jisi Liube92ffb2015-10-27 15:11:38 -0700219 default_runtime: the implicitly default runtime which will be depended on by
220 the generated py_library target.
Jisi Liu7b948cc2015-10-19 17:56:27 -0700221 protoc: the label of the protocol compiler to generate the sources.
222 **kargs: other keyword arguments that are passed to cc_library.
223
224 """
Jisi Liu993fb702015-10-19 17:19:49 -0700225 outs = _PyOuts(srcs)
Jisi Liu53a56be2015-10-20 15:18:20 -0700226
227 includes = []
228 if include != None:
229 includes = [include]
230
Jisi Liu993fb702015-10-19 17:19:49 -0700231 _proto_gen(
232 name=name + "_genproto",
233 srcs=srcs,
234 deps=[s + "_genproto" for s in deps],
Jisi Liu53a56be2015-10-20 15:18:20 -0700235 includes=includes,
Jisi Liu993fb702015-10-19 17:19:49 -0700236 protoc=protoc,
237 gen_py=1,
238 outs=outs,
239 )
240
Jisi Liu993fb702015-10-19 17:19:49 -0700241 if include != None:
Jisi Liu7b948cc2015-10-19 17:56:27 -0700242 # Copy the output files to the desired location to make the import work.
Jisi Liubc4fd152015-10-20 16:02:58 -0700243 internal_copied_filegroup_name=name + "_internal_copied_filegroup"
244 internal_copied_filegroup(
245 name=internal_copied_filegroup_name,
Jisi Liu993fb702015-10-19 17:19:49 -0700246 srcs=outs,
247 include=include)
Jisi Liubc4fd152015-10-20 16:02:58 -0700248 outs=[internal_copied_filegroup_name]
Jisi Liu993fb702015-10-19 17:19:49 -0700249
Jisi Liube92ffb2015-10-27 15:11:38 -0700250 if default_runtime and not default_runtime in py_libs + deps:
251 py_libs += [default_runtime]
252
Jisi Liu993fb702015-10-19 17:19:49 -0700253 native.py_library(
254 name=name,
Jisi Liua33fa8e2015-10-20 15:30:44 -0700255 srcs=outs+py_extra_srcs,
256 deps=py_libs+deps,
Jisi Liu993fb702015-10-19 17:19:49 -0700257 **kargs)
258
259def internal_protobuf_py_tests(
260 name,
261 modules=[],
262 **kargs):
Jisi Liu7b948cc2015-10-19 17:56:27 -0700263 """Bazel rules to create batch tests for protobuf internal.
264
265 Args:
266 name: the name of the rule.
267 modules: a list of modules for tests. The macro will create a py_test for
268 each of the parameter with the source "google/protobuf/%s.py"
269 kargs: extra parameters that will be passed into the py_test.
270
271 """
Jisi Liu993fb702015-10-19 17:19:49 -0700272 for m in modules:
Jisi Liu7b948cc2015-10-19 17:56:27 -0700273 s = _RelativeOutputPath(
274 "python/google/protobuf/internal/%s.py" % m, "python")
Jisi Liu993fb702015-10-19 17:19:49 -0700275 native.py_test(
276 name="py_%s" % m,
Jisi Liu7b948cc2015-10-19 17:56:27 -0700277 srcs=[s],
278 main=s,
Jisi Liu993fb702015-10-19 17:19:49 -0700279 **kargs)