daml/bazel_tools/proto.bzl

159 lines
5.2 KiB
Python
Raw Normal View History

2019-04-04 11:33:38 +03:00
# Copyright (c) 2019 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
load("//bazel_tools:pkg.bzl", "pkg_tar")
# taken from rules_proto:
# https://github.com/stackb/rules_proto/blob/f5d6eea6a4528bef3c1d3a44d486b51a214d61c2/compile.bzl#L369-L393
def get_plugin_runfiles(tool, plugin_runfiles):
2019-04-04 11:33:38 +03:00
"""Gather runfiles for a plugin.
"""
files = []
if not tool:
return files
info = tool[DefaultInfo]
if not info:
return files
if info.files:
files += info.files.to_list()
if info.default_runfiles:
runfiles = info.default_runfiles
if runfiles.files:
files += runfiles.files.to_list()
if info.data_runfiles:
runfiles = info.data_runfiles
if runfiles.files:
files += runfiles.files.to_list()
if plugin_runfiles:
for target in plugin_runfiles:
files += target.files.to_list()
2019-04-04 11:33:38 +03:00
return files
def _proto_gen_impl(ctx):
src_descs = [src.proto.direct_descriptor_set for src in ctx.attr.srcs]
dep_descs = [dep.proto.direct_descriptor_set for dep in ctx.attr.deps]
descriptors = src_descs + dep_descs
sources_out = ctx.actions.declare_directory(ctx.attr.name + "-sources")
descriptor_set_delim = "\;" if _is_windows(ctx) else ":"
args = []
args += [
"--descriptor_set_in=" + descriptor_set_delim.join([d.path for d in descriptors]),
2019-04-04 11:33:38 +03:00
]
args += [
"--{}_out={}:{}".format(ctx.attr.plugin_name, ",".join(ctx.attr.plugin_options), sources_out.path),
2019-04-04 11:33:38 +03:00
]
plugins = []
plugin_runfiles = []
if ctx.attr.plugin_name not in ["java", "python"]:
plugins = [ctx.executable.plugin_exec]
plugin_runfiles = get_plugin_runfiles(ctx.attr.plugin_exec, ctx.attr.plugin_runfiles)
2019-04-04 11:33:38 +03:00
args += [
"--plugin=protoc-gen-{}={}".format(ctx.attr.plugin_name, ctx.executable.plugin_exec.path),
2019-04-04 11:33:38 +03:00
]
inputs = []
for src in ctx.attr.srcs:
src_root = src.proto.proto_source_root
for direct_source in src.proto.direct_sources:
path = ""
2019-04-04 11:33:38 +03:00
# in some cases the paths of src_root and direct_source are only partially
# overlapping. the following for loop finds the maximum overlap of these two paths
for i in range(len(src_root) + 1):
2019-04-04 11:33:38 +03:00
if direct_source.path.startswith(src_root[-i:]):
path = direct_source.path[i:]
else:
# this noop is needed to make bazel happy
noop = ""
path = direct_source.short_path if not path else path
path = path[1:] if path.startswith("/") else path
inputs += [path]
args += inputs
ctx.actions.run_shell(
mnemonic = "ProtoGen",
outputs = [sources_out],
inputs = descriptors + [ctx.executable.protoc] + plugin_runfiles,
command = "mkdir -p " + sources_out.path + " && " + ctx.executable.protoc.path + " " + " ".join(args),
tools = plugins,
use_default_shell_env = True,
2019-04-04 11:33:38 +03:00
)
# since we only have the output directory of the protoc compilation,
# we need to find all the files below sources_out and add them to the zipper args file
zipper_args_file = ctx.actions.declare_file(ctx.label.name + ".zipper_args")
ctx.actions.run_shell(
mnemonic = "CreateZipperArgsFile",
outputs = [zipper_args_file],
inputs = [sources_out],
command = "find -L {src_path} -type f | sed -E 's#^{src_path}/(.*)$#\\1={src_path}/\\1#' | sort > {args_file}".format(
src_path = sources_out.path,
args_file = zipper_args_file.path,
2019-04-04 11:33:38 +03:00
),
progress_message = "zipper_args_file %s" % zipper_args_file.path,
use_default_shell_env = True,
2019-04-04 11:33:38 +03:00
)
# Call zipper to create srcjar
zipper_args = ctx.actions.args()
zipper_args.add("c")
zipper_args.add(ctx.outputs.out.path)
zipper_args.add("@%s" % zipper_args_file.path)
ctx.actions.run(
executable = ctx.executable._zipper,
inputs = [sources_out, zipper_args_file],
outputs = [ctx.outputs.out],
arguments = [zipper_args],
progress_message = "srcjar %s" % ctx.outputs.out.short_path,
)
proto_gen = rule(
implementation = _proto_gen_impl,
attrs = {
2019-04-04 11:33:38 +03:00
"srcs": attr.label_list(allow_files = True),
"deps": attr.label_list(providers = [ProtoInfo]),
"plugin_name": attr.string(),
"plugin_exec": attr.label(
cfg = "host",
executable = True,
2019-04-04 11:33:38 +03:00
),
"plugin_options": attr.string_list(),
"plugin_runfiles": attr.label_list(
default = [],
allow_files = True,
),
2019-04-04 11:33:38 +03:00
"protoc": attr.label(
default = Label("@com_google_protobuf//:protoc"),
cfg = "host",
allow_files = True,
executable = True,
),
"_zipper": attr.label(
default = Label("@bazel_tools//tools/zip:zipper"),
cfg = "host",
executable = True,
allow_files = True,
),
},
outputs = {
"out": "%{name}.srcjar",
2019-04-04 11:33:38 +03:00
},
output_to_genfiles = True,
2019-04-04 11:33:38 +03:00
)
def _is_windows(ctx):
return ctx.configuration.host_path_separator == ";"