166 lines
5.5 KiB
Python
166 lines
5.5 KiB
Python
# Copyright (C) 2021 The Android Open Source Project
|
|
#
|
|
# Licensed 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("@bazel_skylib//lib:paths.bzl", "paths")
|
|
load("@bazel_skylib//lib:sets.bzl", "sets")
|
|
|
|
def _generate_and_declare_output_files(
|
|
ctx,
|
|
file_names,
|
|
type_dictionary):
|
|
ret = {}
|
|
for typ in type_dictionary:
|
|
ret[typ] = []
|
|
|
|
for name in file_names:
|
|
short_path = name.short_path
|
|
for typ, ext in type_dictionary.items():
|
|
# prefix with label.name to prevent collisions between targets
|
|
# if proto compliation becomes an aspect, can prefix with output
|
|
# information instead to allow reuse, e.g. multiple cc `lite`
|
|
# libraries containing the same proto file
|
|
out_name = paths.join(ctx.label.name, paths.replace_extension(short_path, ext))
|
|
declared = ctx.actions.declare_file(out_name)
|
|
ret[typ].append(declared)
|
|
|
|
return ret
|
|
|
|
def _generate_jar_proto_action(
|
|
proto_infos,
|
|
protoc,
|
|
ctx,
|
|
out_flags = [],
|
|
plugin_executable = None,
|
|
out_arg = None,
|
|
mnemonic = "ProtoGen"):
|
|
jar_basename = ctx.label.name + "-proto_gen"
|
|
jar_name = jar_basename + "-src.jar"
|
|
jar_file = ctx.actions.declare_file(jar_name)
|
|
|
|
_generate_proto_action(
|
|
proto_infos = proto_infos,
|
|
protoc = protoc,
|
|
ctx = ctx,
|
|
out_flags = out_flags,
|
|
plugin_executable = plugin_executable,
|
|
out_arg = out_arg,
|
|
mnemonic = mnemonic,
|
|
output_file = jar_file,
|
|
)
|
|
|
|
srcjar_name = jar_basename + ".srcjar"
|
|
srcjar_file = ctx.actions.declare_file(srcjar_name)
|
|
ctx.actions.symlink(
|
|
output = srcjar_file,
|
|
target_file = jar_file,
|
|
)
|
|
|
|
return srcjar_file
|
|
|
|
def _generate_proto_action(
|
|
proto_infos,
|
|
protoc,
|
|
ctx,
|
|
type_dictionary = None,
|
|
out_flags = [],
|
|
plugin_executable = None,
|
|
out_arg = None,
|
|
mnemonic = "ProtoGen",
|
|
output_file = None):
|
|
""" Utility function for creating proto_compiler action.
|
|
|
|
Args:
|
|
proto_infos: A list of ProtoInfo.
|
|
protoc: proto compiler executable.
|
|
ctx: context, used for declaring new files only.
|
|
type_dictionary: a dictionary of types to output extensions
|
|
out_flags: protoc output flags
|
|
plugin_executable: plugin executable file
|
|
out_arg: as appropriate, if plugin_executable and out_arg are both supplied, plugin_executable is preferred
|
|
mnemonic: (optional) a string to describe the proto compilation action
|
|
output_file: (optional) File, used to specify a specific file for protoc output (typically a JAR file)
|
|
|
|
Returns:
|
|
Dictionary with declared files grouped by type from the type_dictionary.
|
|
"""
|
|
|
|
# TODO(B/245629074): Don't build external/protobuf if it is provided in
|
|
# toolchain already.
|
|
proto_srcs = []
|
|
proto_source_root_list = sets.make()
|
|
transitive_proto_srcs_list = []
|
|
transitive_proto_path_list = sets.make()
|
|
|
|
for proto_info in proto_infos:
|
|
sets.insert(proto_source_root_list, proto_info.proto_source_root)
|
|
proto_srcs.extend(proto_info.direct_sources)
|
|
transitive_proto_srcs_list.append(proto_info.transitive_imports)
|
|
for p in proto_info.transitive_proto_path.to_list():
|
|
sets.insert(transitive_proto_path_list, p)
|
|
|
|
protoc_out_name = paths.join(ctx.bin_dir.path, ctx.label.package)
|
|
if output_file:
|
|
protoc_out_name = paths.join(protoc_out_name, output_file.basename)
|
|
out_files = {
|
|
"out": [output_file],
|
|
}
|
|
else:
|
|
protoc_out_name = paths.join(protoc_out_name, ctx.label.name)
|
|
out_files = _generate_and_declare_output_files(
|
|
ctx,
|
|
proto_srcs,
|
|
type_dictionary,
|
|
)
|
|
|
|
tools = []
|
|
args = ctx.actions.args()
|
|
if plugin_executable:
|
|
tools.append(plugin_executable)
|
|
args.add("--plugin=protoc-gen-PLUGIN=" + plugin_executable.path)
|
|
args.add("--PLUGIN_out=" + ",".join(out_flags) + ":" + protoc_out_name)
|
|
else:
|
|
args.add("{}={}:{}".format(out_arg, ",".join(out_flags), protoc_out_name))
|
|
|
|
# the order matters so we add the source roots first
|
|
args.add_all(["-I" + p for p in sets.to_list(proto_source_root_list)])
|
|
|
|
args.add_all(["-I" + p for p in sets.to_list(transitive_proto_path_list)])
|
|
args.add_all(["-I{0}={1}".format(f.short_path, f.path) for t in transitive_proto_srcs_list for f in t.to_list()])
|
|
|
|
args.add_all([f.short_path for f in proto_srcs])
|
|
|
|
inputs = depset(
|
|
direct = proto_srcs,
|
|
transitive = transitive_proto_srcs_list,
|
|
)
|
|
|
|
outputs = []
|
|
for outs in out_files.values():
|
|
outputs.extend(outs)
|
|
|
|
ctx.actions.run(
|
|
inputs = inputs,
|
|
executable = protoc,
|
|
tools = tools,
|
|
outputs = outputs,
|
|
arguments = [args],
|
|
mnemonic = mnemonic,
|
|
)
|
|
return out_files
|
|
|
|
proto_file_utils = struct(
|
|
generate_proto_action = _generate_proto_action,
|
|
generate_jar_proto_action = _generate_jar_proto_action,
|
|
)
|