blob: 3b525815cb175f0020448fb6d8fbc343505b87d6 [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 Liu125a91b2015-10-14 17:37:39 -0700104 **kargs):
Jisi Liu3101e732015-10-16 12:46:26 -0700105 """Bazel rule to create a C++ protobuf library from proto source files
106
107 Args:
108 name: the name of the cc_proto_library.
109 srcs: the .proto files of the cc_proto_library.
110 deps: a list of dependency labels; must be cc_proto_library.
111 cc_libs: a list of other cc_library targets depended by the generated
112 cc_library.
113 include: a string indicating the include path of the .proto files.
114 protoc: the label of the protocol compiler to generate the sources.
115 internal_bootstrap_hack: a flag indicate the cc_proto_library is used only
116 for bootstraping. When it is set to True, no files will be generated.
117 The rule will simply be a provider for .proto files, so that other
118 cc_proto_library can depend on it.
119 **kargs: other keyword arguments that are passed to cc_library.
120
121 """
Jisi Liu39362b32015-10-14 17:12:11 -0700122
Jisi Liu53a56be2015-10-20 15:18:20 -0700123 includes = []
124 if include != None:
125 includes = [include]
126
Jisi Liu39362b32015-10-14 17:12:11 -0700127 if internal_bootstrap_hack:
128 # For pre-checked-in generated files, we add the internal_bootstrap_hack
129 # which will skip the codegen action.
Jisi Liu9c7d9c02015-10-15 10:51:32 -0700130 _proto_gen(
Jisi Liu125a91b2015-10-14 17:37:39 -0700131 name=name + "_genproto",
132 srcs=srcs,
Jisi Liud8701b52015-10-16 11:44:21 -0700133 deps=[s + "_genproto" for s in deps],
Jisi Liu53a56be2015-10-20 15:18:20 -0700134 includes=includes,
Jisi Liu125a91b2015-10-14 17:37:39 -0700135 protoc=protoc,
Jisi Liu39362b32015-10-14 17:12:11 -0700136 )
137 # An empty cc_library to make rule dependency consistent.
138 native.cc_library(
Jisi Liu125a91b2015-10-14 17:37:39 -0700139 name=name,
Jisi Liud8701b52015-10-16 11:44:21 -0700140 **kargs)
Jisi Liu39362b32015-10-14 17:12:11 -0700141 return
142
Jisi Liu993fb702015-10-19 17:19:49 -0700143 outs = _CcOuts(srcs)
Jisi Liu9c7d9c02015-10-15 10:51:32 -0700144 _proto_gen(
Jisi Liu125a91b2015-10-14 17:37:39 -0700145 name=name + "_genproto",
146 srcs=srcs,
Jisi Liud8701b52015-10-16 11:44:21 -0700147 deps=[s + "_genproto" for s in deps],
Jisi Liu53a56be2015-10-20 15:18:20 -0700148 includes=includes,
Jisi Liu125a91b2015-10-14 17:37:39 -0700149 protoc=protoc,
150 gen_cc=1,
151 outs=outs,
Jisi Liu39362b32015-10-14 17:12:11 -0700152 )
153
Jisi Liu6dac0822015-10-19 14:41:00 -0700154
Jisi Liu39362b32015-10-14 17:12:11 -0700155 native.cc_library(
Jisi Liu125a91b2015-10-14 17:37:39 -0700156 name=name,
157 srcs=outs,
Jisi Liud8701b52015-10-16 11:44:21 -0700158 deps=cc_libs + deps,
Jisi Liu6dac0822015-10-19 14:41:00 -0700159 includes=includes,
Jisi Liud8701b52015-10-16 11:44:21 -0700160 **kargs)
Jisi Liu993fb702015-10-19 17:19:49 -0700161
162
163def copied_srcs(
164 name,
165 srcs,
166 include,
167 **kargs):
Jisi Liu7b948cc2015-10-19 17:56:27 -0700168 """Bazel rule to fix sources file to workaround with python path issues.
169
170 Args:
171 name: the name of the copied_srcs rule, which will be the name of the
172 generated filegroup.
173 srcs: the source files to be copied.
174 include: the expected import root of the source.
175 **kargs: extra arguments that will be passed into the filegroup.
176 """
Jisi Liu993fb702015-10-19 17:19:49 -0700177 outs = [_RelativeOutputPath(s, include) for s in srcs]
178
179 native.genrule(
180 name=name+"_genrule",
181 srcs=srcs,
182 outs=outs,
183 cmd=";".join(["cp $(location %s) $(location %s)" % \
184 (s, _RelativeOutputPath(s, include)) \
185 for s in srcs]))
186
187 native.filegroup(
188 name=name,
189 srcs=outs,
190 **kargs)
191
192
193def py_proto_library(
194 name,
195 srcs=[],
196 deps=[],
197 py_libs=[],
198 py_extra_srcs=[],
199 include=None,
Jisi Liu04658a32015-10-20 15:00:13 -0700200 protoc="//google/protobuf:protoc",
Jisi Liu993fb702015-10-19 17:19:49 -0700201 **kargs):
Jisi Liu7b948cc2015-10-19 17:56:27 -0700202 """Bazel rule to create a Python protobuf library from proto source files
203
204 Args:
205 name: the name of the py_proto_library.
206 srcs: the .proto files of the py_proto_library.
207 deps: a list of dependency labels; must be py_proto_library.
208 py_libs: a list of other py_library targets depended by the generated
209 py_library.
210 py_extra_srcs: extra source files that will be added to the output
211 py_library. This attribute is used for internal bootstrapping.
212 include: a string indicating the include path of the .proto files.
213 protoc: the label of the protocol compiler to generate the sources.
214 **kargs: other keyword arguments that are passed to cc_library.
215
216 """
Jisi Liu993fb702015-10-19 17:19:49 -0700217 outs = _PyOuts(srcs)
Jisi Liu53a56be2015-10-20 15:18:20 -0700218
219 includes = []
220 if include != None:
221 includes = [include]
222
Jisi Liu993fb702015-10-19 17:19:49 -0700223 _proto_gen(
224 name=name + "_genproto",
225 srcs=srcs,
226 deps=[s + "_genproto" for s in deps],
Jisi Liu53a56be2015-10-20 15:18:20 -0700227 includes=includes,
Jisi Liu993fb702015-10-19 17:19:49 -0700228 protoc=protoc,
229 gen_py=1,
230 outs=outs,
231 )
232
Jisi Liu993fb702015-10-19 17:19:49 -0700233 if include != None:
Jisi Liu7b948cc2015-10-19 17:56:27 -0700234 # Copy the output files to the desired location to make the import work.
235 copied_srcs_name=name + "_copied_srcs"
Jisi Liu993fb702015-10-19 17:19:49 -0700236 copied_srcs(
237 name=copied_srcs_name,
238 srcs=outs,
239 include=include)
Jisi Liua33fa8e2015-10-20 15:30:44 -0700240 outs=[copied_srcs_name]
Jisi Liu993fb702015-10-19 17:19:49 -0700241
242 native.py_library(
243 name=name,
Jisi Liua33fa8e2015-10-20 15:30:44 -0700244 srcs=outs+py_extra_srcs,
245 deps=py_libs+deps,
Jisi Liu993fb702015-10-19 17:19:49 -0700246 **kargs)
247
248def internal_protobuf_py_tests(
249 name,
250 modules=[],
251 **kargs):
Jisi Liu7b948cc2015-10-19 17:56:27 -0700252 """Bazel rules to create batch tests for protobuf internal.
253
254 Args:
255 name: the name of the rule.
256 modules: a list of modules for tests. The macro will create a py_test for
257 each of the parameter with the source "google/protobuf/%s.py"
258 kargs: extra parameters that will be passed into the py_test.
259
260 """
Jisi Liu993fb702015-10-19 17:19:49 -0700261 for m in modules:
Jisi Liu7b948cc2015-10-19 17:56:27 -0700262 s = _RelativeOutputPath(
263 "python/google/protobuf/internal/%s.py" % m, "python")
Jisi Liu993fb702015-10-19 17:19:49 -0700264 native.py_test(
265 name="py_%s" % m,
Jisi Liu7b948cc2015-10-19 17:56:27 -0700266 srcs=[s],
267 main=s,
Jisi Liu993fb702015-10-19 17:19:49 -0700268 **kargs)