blob: 6fd3cae509bde8744b38a121c2d9456e2c9c570a [file] [log] [blame]
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
load("pex_rules", "pex_library")
standard_proto_path = "heron/proto"
def _genproto_impl(ctx):
proto_src_deps = [src.proto_src for src in ctx.attr.deps]
inputs, outputs, arguments = [ctx.file.src] + proto_src_deps, [], ["--proto_path=."]
for src in proto_src_deps:
if src.path.startswith(standard_proto_path):
arguments += ["--proto_path=" + standard_proto_path]
break
if ctx.attr.gen_cc:
outputs += [ctx.outputs.cc_hdr, ctx.outputs.cc_src]
arguments += ["--cpp_out=" + ctx.configuration.genfiles_dir.path]
if ctx.attr.gen_java:
if ctx.outputs.java_src.path.endswith(".srcjar"):
srcjar = ctx.new_file(ctx.outputs.java_src.basename[:-6] + "jar")
else:
srcjar = ctx.outputs.java_src
outputs += [srcjar]
arguments += ["--java_out=" + srcjar.path]
if ctx.attr.gen_py:
outputs += [ctx.outputs.py_src]
arguments += ["--python_out=" + ctx.configuration.genfiles_dir.path]
ctx.action(
mnemonic = "GenProto",
inputs = inputs,
outputs = outputs,
arguments = arguments + [ctx.file.src.path],
executable = ctx.executable._protoc)
# This is required because protoc only understands .jar extensions, but Bazel
# requires source JAR files end in .srcjar.
if ctx.attr.gen_java and srcjar != ctx.outputs.java_src:
ctx.action(
mnemonic = "FixProtoSrcJar",
inputs = [srcjar],
outputs = [ctx.outputs.java_src],
arguments = [srcjar.path, ctx.outputs.java_src.path],
command = "cp $1 $2")
# Fixup the resulting outputs to keep the source-only .jar out of the result.
outputs += [ctx.outputs.java_src]
outputs = [e for e in outputs if e != srcjar]
return struct(files=set(outputs),
proto_src=ctx.file.src)
_genproto_attrs = {
"src": attr.label(
allow_files = FileType([".proto"]),
single_file = True,
),
"deps": attr.label_list(
allow_files = False,
providers = ["proto_src"],
),
"_protoc": attr.label(
default = Label("//third_party/protobuf:protoc"),
executable = True,
),
"gen_cc": attr.bool(),
"gen_java": attr.bool(),
"gen_py": attr.bool(),
}
def _genproto_outputs(attrs):
outputs = {}
if attrs.gen_cc:
outputs += {
"cc_hdr": "%{src}.pb.h",
"cc_src": "%{src}.pb.cc"
}
if attrs.gen_java:
outputs += {
"java_src": "%{src}.srcjar",
}
if attrs.gen_py:
outputs += {
"py_src": "%{src}_pb2.py"
}
return outputs
genproto = rule(
_genproto_impl,
attrs = _genproto_attrs,
output_to_genfiles = True,
outputs = _genproto_outputs,
)
def proto_library(name, src=None, deps=[], visibility=None,
gen_java=False, gen_cc=False, gen_py=False):
if not src:
if name.endswith("_proto"):
src = name[:-6] + ".proto"
else:
src = name + ".proto"
proto_pkg = genproto(name=name,
src=src,
deps=deps,
gen_java=gen_java,
gen_cc=gen_cc,
gen_py=gen_py)
# TODO(shahms): These should probably not be separate libraries, but
# allowing upstream *_library and *_binary targets to depend on the
# proto_library() directly is a challenge. We'd also need a different
# workaround for the non-generated any.pb.{h,cc} from the upstream protocol
# buffer library.
if gen_java:
java_deps = ["@com_google_protobuf//:protobuf_java"]
for dep in deps:
java_deps += [dep + "_java"]
native.java_library(
name = name + "_java",
srcs = [proto_pkg.label()],
deps = java_deps,
visibility = visibility,
)
if gen_cc:
cc_deps = ["//third_party/protobuf:protobuf-cxx"]
for dep in deps:
cc_deps += [dep + "_cc"]
native.cc_library(
name = name + "_cc",
visibility = visibility,
hdrs = [proto_pkg.label()],
srcs = [proto_pkg.label()],
defines = ["GOOGLE_PROTOBUF_NO_RTTI"],
deps = cc_deps,
)
if gen_py:
py_deps = []
for dep in deps:
py_deps += [dep + "_py"]
pex_library(
name = name + "_py",
visibility = visibility,
srcs = [proto_pkg.label()],
deps = py_deps,
)