blob: f674a6c6da6389079c378ca0c342fd549ec3c7be [file] [log] [blame]
Jisi Liu39362b32015-10-14 17:12:11 -07001# -*- mode: python; -*- PYTHON-PREPROCESSING-REQUIRED
2
Damien Martin-Guillerez76547e52016-01-15 14:01:37 +01003def _GetPath(ctx, path):
4 if ctx.label.workspace_root:
5 return ctx.label.workspace_root + '/' + path
6 else:
7 return path
8
Jisi Liu993fb702015-10-19 17:19:49 -07009def _GenDir(ctx):
Jisi Liu53a56be2015-10-20 15:18:20 -070010 if not ctx.attr.includes:
Damien Martin-Guillerez76547e52016-01-15 14:01:37 +010011 return ctx.label.workspace_root
Jisi Liu53a56be2015-10-20 15:18:20 -070012 if not ctx.attr.includes[0]:
Damien Martin-Guillerez76547e52016-01-15 14:01:37 +010013 return _GetPath(ctx, ctx.label.package)
Jisi Liu39362b32015-10-14 17:12:11 -070014 if not ctx.label.package:
Damien Martin-Guillerez76547e52016-01-15 14:01:37 +010015 return _GetPath(ctx, ctx.attr.includes[0])
16 return _GetPath(ctx, ctx.label.package + '/' + ctx.attr.includes[0])
Jisi Liu39362b32015-10-14 17:12:11 -070017
Jisi Liu993fb702015-10-19 17:19:49 -070018def _CcOuts(srcs):
Jisi Liu39362b32015-10-14 17:12:11 -070019 return [s[:-len(".proto")] + ".pb.h" for s in srcs] + \
Jisi Liu125a91b2015-10-14 17:37:39 -070020 [s[:-len(".proto")] + ".pb.cc" for s in srcs]
Jisi Liu39362b32015-10-14 17:12:11 -070021
Jisi Liu993fb702015-10-19 17:19:49 -070022def _PyOuts(srcs):
Jisi Liu125a91b2015-10-14 17:37:39 -070023 return [s[:-len(".proto")] + "_pb2.py" for s in srcs]
Jisi Liu39362b32015-10-14 17:12:11 -070024
Jisi Liu993fb702015-10-19 17:19:49 -070025def _RelativeOutputPath(path, include):
26 if include == None:
27 return path
28
29 if not path.startswith(include):
30 fail("Include path %s isn't part of the path %s." % (include, path))
31
32 if include and include[-1] != '/':
33 include = include + '/'
34
35 path = path[len(include):]
36
37 if not path.startswith(PACKAGE_NAME):
38 fail("The package %s is not within the path %s" % (PACKAGE_NAME, path))
39
40 if not PACKAGE_NAME:
41 return path
42
43 return path[len(PACKAGE_NAME)+1:]
44
Jisi Liu9c7d9c02015-10-15 10:51:32 -070045def _proto_gen_impl(ctx):
46 """General implementation for generating protos"""
Jisi Liu39362b32015-10-14 17:12:11 -070047 srcs = ctx.files.srcs
48 deps = []
49 deps += ctx.files.srcs
Jisi Liu993fb702015-10-19 17:19:49 -070050 gen_dir = _GenDir(ctx)
Jisi Liu53a56be2015-10-20 15:18:20 -070051 if gen_dir:
52 import_flags = ["-I" + gen_dir]
53 else:
54 import_flags = ["-I."]
55
Jisi Liu39362b32015-10-14 17:12:11 -070056 for dep in ctx.attr.deps:
57 import_flags += dep.proto.import_flags
58 deps += dep.proto.deps
59
60 args = []
61 if ctx.attr.gen_cc:
62 args += ["--cpp_out=" + ctx.var["GENDIR"] + "/" + gen_dir]
63 if ctx.attr.gen_py:
64 args += ["--python_out=" + ctx.var["GENDIR"] + "/" + gen_dir]
65
66 if args:
67 ctx.action(
Jisi Liu125a91b2015-10-14 17:37:39 -070068 inputs=srcs + deps,
Jisi Liu39362b32015-10-14 17:12:11 -070069 outputs=ctx.outputs.outs,
Jisi Liu125a91b2015-10-14 17:37:39 -070070 arguments=args + import_flags + [s.path for s in srcs],
Jisi Liu9c7d9c02015-10-15 10:51:32 -070071 executable=ctx.executable.protoc,
Jisi Liu39362b32015-10-14 17:12:11 -070072 )
73
74 return struct(
75 proto=struct(
Jisi Liu125a91b2015-10-14 17:37:39 -070076 srcs=srcs,
77 import_flags=import_flags,
78 deps=deps,
79 ),
80 )
Jisi Liu39362b32015-10-14 17:12:11 -070081
Jisi Liu9c7d9c02015-10-15 10:51:32 -070082_proto_gen = rule(
Jisi Liu39362b32015-10-14 17:12:11 -070083 attrs = {
Jisi Liuee8131a2015-10-14 17:20:05 -070084 "srcs": attr.label_list(allow_files = True),
85 "deps": attr.label_list(providers = ["proto"]),
Jisi Liu53a56be2015-10-20 15:18:20 -070086 "includes": attr.string_list(),
Jisi Liuee8131a2015-10-14 17:20:05 -070087 "protoc": attr.label(
Andrew Harp38f131f2015-11-03 16:39:32 -050088 cfg = HOST_CFG,
Jisi Liuee8131a2015-10-14 17:20:05 -070089 executable = True,
90 single_file = True,
91 mandatory = True,
92 ),
93 "gen_cc": attr.bool(),
94 "gen_py": attr.bool(),
95 "outs": attr.output_list(),
96 },
97 output_to_genfiles = True,
Jisi Liu9c7d9c02015-10-15 10:51:32 -070098 implementation = _proto_gen_impl,
Jisi Liu39362b32015-10-14 17:12:11 -070099)
100
101def cc_proto_library(
Jisi Liu125a91b2015-10-14 17:37:39 -0700102 name,
103 srcs=[],
Jisi Liu125a91b2015-10-14 17:37:39 -0700104 deps=[],
Jisi Liud8701b52015-10-16 11:44:21 -0700105 cc_libs=[],
Jisi Liu6dac0822015-10-19 14:41:00 -0700106 include=None,
Jisi Liu04658a32015-10-20 15:00:13 -0700107 protoc="//google/protobuf:protoc",
Jisi Liu3101e732015-10-16 12:46:26 -0700108 internal_bootstrap_hack=False,
Jisi Liube92ffb2015-10-27 15:11:38 -0700109 default_runtime="//google/protobuf:protobuf",
Jisi Liu125a91b2015-10-14 17:37:39 -0700110 **kargs):
Jisi Liu3101e732015-10-16 12:46:26 -0700111 """Bazel rule to create a C++ protobuf library from proto source files
112
Jisi Liud4bef7d2015-11-02 12:24:32 -0800113 NOTE: the rule is only an internal workaround to generate protos. The
114 interface may change and the rule may be removed when bazel has introduced
115 the native rule.
116
Jisi Liu3101e732015-10-16 12:46:26 -0700117 Args:
118 name: the name of the cc_proto_library.
119 srcs: the .proto files of the cc_proto_library.
120 deps: a list of dependency labels; must be cc_proto_library.
121 cc_libs: a list of other cc_library targets depended by the generated
122 cc_library.
123 include: a string indicating the include path of the .proto files.
124 protoc: the label of the protocol compiler to generate the sources.
125 internal_bootstrap_hack: a flag indicate the cc_proto_library is used only
126 for bootstraping. When it is set to True, no files will be generated.
127 The rule will simply be a provider for .proto files, so that other
128 cc_proto_library can depend on it.
Jisi Liube92ffb2015-10-27 15:11:38 -0700129 default_runtime: the implicitly default runtime which will be depended on by
130 the generated cc_library target.
Jisi Liu3101e732015-10-16 12:46:26 -0700131 **kargs: other keyword arguments that are passed to cc_library.
132
133 """
Jisi Liu39362b32015-10-14 17:12:11 -0700134
Jisi Liu53a56be2015-10-20 15:18:20 -0700135 includes = []
136 if include != None:
137 includes = [include]
138
Jisi Liu39362b32015-10-14 17:12:11 -0700139 if internal_bootstrap_hack:
140 # For pre-checked-in generated files, we add the internal_bootstrap_hack
141 # which will skip the codegen action.
Jisi Liu9c7d9c02015-10-15 10:51:32 -0700142 _proto_gen(
Jisi Liu125a91b2015-10-14 17:37:39 -0700143 name=name + "_genproto",
144 srcs=srcs,
Jisi Liud8701b52015-10-16 11:44:21 -0700145 deps=[s + "_genproto" for s in deps],
Jisi Liu53a56be2015-10-20 15:18:20 -0700146 includes=includes,
Jisi Liu125a91b2015-10-14 17:37:39 -0700147 protoc=protoc,
Martin Maly8e0c9a32015-12-04 17:44:58 -0800148 visibility=["//visibility:public"],
Jisi Liu39362b32015-10-14 17:12:11 -0700149 )
150 # An empty cc_library to make rule dependency consistent.
151 native.cc_library(
Jisi Liu125a91b2015-10-14 17:37:39 -0700152 name=name,
Jisi Liud8701b52015-10-16 11:44:21 -0700153 **kargs)
Jisi Liu39362b32015-10-14 17:12:11 -0700154 return
155
Jisi Liu993fb702015-10-19 17:19:49 -0700156 outs = _CcOuts(srcs)
Jisi Liu9c7d9c02015-10-15 10:51:32 -0700157 _proto_gen(
Jisi Liu125a91b2015-10-14 17:37:39 -0700158 name=name + "_genproto",
159 srcs=srcs,
Jisi Liud8701b52015-10-16 11:44:21 -0700160 deps=[s + "_genproto" for s in deps],
Jisi Liu53a56be2015-10-20 15:18:20 -0700161 includes=includes,
Jisi Liu125a91b2015-10-14 17:37:39 -0700162 protoc=protoc,
163 gen_cc=1,
164 outs=outs,
Martin Maly8e0c9a32015-12-04 17:44:58 -0800165 visibility=["//visibility:public"],
Jisi Liu39362b32015-10-14 17:12:11 -0700166 )
167
Jisi Liube92ffb2015-10-27 15:11:38 -0700168 if default_runtime and not default_runtime in cc_libs:
169 cc_libs += [default_runtime]
Jisi Liu6dac0822015-10-19 14:41:00 -0700170
Jisi Liu39362b32015-10-14 17:12:11 -0700171 native.cc_library(
Jisi Liu125a91b2015-10-14 17:37:39 -0700172 name=name,
173 srcs=outs,
Jisi Liud8701b52015-10-16 11:44:21 -0700174 deps=cc_libs + deps,
Jisi Liu6dac0822015-10-19 14:41:00 -0700175 includes=includes,
Jisi Liud8701b52015-10-16 11:44:21 -0700176 **kargs)
Jisi Liu993fb702015-10-19 17:19:49 -0700177
178
Jisi Liubc4fd152015-10-20 16:02:58 -0700179def internal_copied_filegroup(
Jisi Liu993fb702015-10-19 17:19:49 -0700180 name,
181 srcs,
182 include,
183 **kargs):
Jisi Liu7b948cc2015-10-19 17:56:27 -0700184 """Bazel rule to fix sources file to workaround with python path issues.
185
186 Args:
Jisi Liubc4fd152015-10-20 16:02:58 -0700187 name: the name of the internal_copied_filegroup rule, which will be the
188 name of the generated filegroup.
Jisi Liu7b948cc2015-10-19 17:56:27 -0700189 srcs: the source files to be copied.
190 include: the expected import root of the source.
191 **kargs: extra arguments that will be passed into the filegroup.
192 """
Jisi Liu993fb702015-10-19 17:19:49 -0700193 outs = [_RelativeOutputPath(s, include) for s in srcs]
194
195 native.genrule(
196 name=name+"_genrule",
197 srcs=srcs,
198 outs=outs,
Jisi Liu6ddcae22015-10-21 10:48:33 -0700199 cmd=" && ".join(["cp $(location %s) $(location %s)" %
200 (s, _RelativeOutputPath(s, include))
201 for s in srcs]))
Jisi Liu993fb702015-10-19 17:19:49 -0700202
203 native.filegroup(
204 name=name,
205 srcs=outs,
206 **kargs)
207
208
209def py_proto_library(
210 name,
211 srcs=[],
212 deps=[],
213 py_libs=[],
214 py_extra_srcs=[],
215 include=None,
Jisi Liube92ffb2015-10-27 15:11:38 -0700216 default_runtime="//google/protobuf:protobuf_python",
Jisi Liu04658a32015-10-20 15:00:13 -0700217 protoc="//google/protobuf:protoc",
Jisi Liu993fb702015-10-19 17:19:49 -0700218 **kargs):
Jisi Liu7b948cc2015-10-19 17:56:27 -0700219 """Bazel rule to create a Python protobuf library from proto source files
220
Jisi Liud4bef7d2015-11-02 12:24:32 -0800221 NOTE: the rule is only an internal workaround to generate protos. The
222 interface may change and the rule may be removed when bazel has introduced
223 the native rule.
224
Jisi Liu7b948cc2015-10-19 17:56:27 -0700225 Args:
226 name: the name of the py_proto_library.
227 srcs: the .proto files of the py_proto_library.
228 deps: a list of dependency labels; must be py_proto_library.
229 py_libs: a list of other py_library targets depended by the generated
230 py_library.
231 py_extra_srcs: extra source files that will be added to the output
232 py_library. This attribute is used for internal bootstrapping.
233 include: a string indicating the include path of the .proto files.
Jisi Liube92ffb2015-10-27 15:11:38 -0700234 default_runtime: the implicitly default runtime which will be depended on by
235 the generated py_library target.
Jisi Liu7b948cc2015-10-19 17:56:27 -0700236 protoc: the label of the protocol compiler to generate the sources.
237 **kargs: other keyword arguments that are passed to cc_library.
238
239 """
Jisi Liu993fb702015-10-19 17:19:49 -0700240 outs = _PyOuts(srcs)
Jisi Liu53a56be2015-10-20 15:18:20 -0700241
242 includes = []
243 if include != None:
244 includes = [include]
245
Jisi Liu993fb702015-10-19 17:19:49 -0700246 _proto_gen(
247 name=name + "_genproto",
248 srcs=srcs,
249 deps=[s + "_genproto" for s in deps],
Jisi Liu53a56be2015-10-20 15:18:20 -0700250 includes=includes,
Jisi Liu993fb702015-10-19 17:19:49 -0700251 protoc=protoc,
252 gen_py=1,
253 outs=outs,
Martin Maly8e0c9a32015-12-04 17:44:58 -0800254 visibility=["//visibility:public"],
Jisi Liu993fb702015-10-19 17:19:49 -0700255 )
256
Jisi Liu993fb702015-10-19 17:19:49 -0700257 if include != None:
Jisi Liu7b948cc2015-10-19 17:56:27 -0700258 # Copy the output files to the desired location to make the import work.
Jisi Liubc4fd152015-10-20 16:02:58 -0700259 internal_copied_filegroup_name=name + "_internal_copied_filegroup"
260 internal_copied_filegroup(
261 name=internal_copied_filegroup_name,
Jisi Liu993fb702015-10-19 17:19:49 -0700262 srcs=outs,
263 include=include)
Jisi Liubc4fd152015-10-20 16:02:58 -0700264 outs=[internal_copied_filegroup_name]
Jisi Liu993fb702015-10-19 17:19:49 -0700265
Jisi Liube92ffb2015-10-27 15:11:38 -0700266 if default_runtime and not default_runtime in py_libs + deps:
267 py_libs += [default_runtime]
268
Jisi Liu993fb702015-10-19 17:19:49 -0700269 native.py_library(
270 name=name,
Jisi Liua33fa8e2015-10-20 15:30:44 -0700271 srcs=outs+py_extra_srcs,
272 deps=py_libs+deps,
Jisi Liu993fb702015-10-19 17:19:49 -0700273 **kargs)
274
275def internal_protobuf_py_tests(
276 name,
277 modules=[],
278 **kargs):
Jisi Liu7b948cc2015-10-19 17:56:27 -0700279 """Bazel rules to create batch tests for protobuf internal.
280
281 Args:
282 name: the name of the rule.
283 modules: a list of modules for tests. The macro will create a py_test for
284 each of the parameter with the source "google/protobuf/%s.py"
285 kargs: extra parameters that will be passed into the py_test.
286
287 """
Jisi Liu993fb702015-10-19 17:19:49 -0700288 for m in modules:
Jisi Liu7b948cc2015-10-19 17:56:27 -0700289 s = _RelativeOutputPath(
290 "python/google/protobuf/internal/%s.py" % m, "python")
Jisi Liu993fb702015-10-19 17:19:49 -0700291 native.py_test(
292 name="py_%s" % m,
Jisi Liu7b948cc2015-10-19 17:56:27 -0700293 srcs=[s],
294 main=s,
Jisi Liu993fb702015-10-19 17:19:49 -0700295 **kargs)