protobuf/editions/defaults.bzl

130 lines
4.4 KiB
Python

# Protocol Buffers - Google's data interchange format
# Copyright 2023 Google Inc. All rights reserved.
#
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file or at
# https://developers.google.com/open-source/licenses/bsd
"""
Provide a rule for generating the intermediate feature set defaults used for feature resolution.
See go/life-of-a-featureset for more information.
"""
def _compile_edition_defaults_impl(ctx):
out_file = ctx.actions.declare_file(ctx.outputs.output.basename)
sources = []
paths = []
for src in ctx.attr.srcs:
sources.extend(src[ProtoInfo].transitive_sources.to_list())
paths.extend(src[ProtoInfo].transitive_proto_path.to_list())
args = ctx.actions.args()
args.add("--edition_defaults_out", out_file)
args.add("--edition_defaults_minimum", ctx.attr.minimum_edition)
args.add("--edition_defaults_maximum", ctx.attr.maximum_edition)
for p in paths:
args.add("--proto_path", p)
for source in sources:
args.add(source)
ctx.actions.run(
outputs = [out_file],
inputs = sources,
executable = ctx.executable.protoc or ctx.executable._protoc_minimal,
arguments = [args],
progress_message = "Generating edition defaults",
)
compile_edition_defaults = rule(
attrs = {
"srcs": attr.label_list(
mandatory = True,
allow_rules = ["proto_library"],
providers = [ProtoInfo],
),
"minimum_edition": attr.string(mandatory = True),
"maximum_edition": attr.string(mandatory = True),
"protoc": attr.label(
mandatory = False,
executable = True,
cfg = "exec",
),
"_protoc_minimal": attr.label(
default = "//src/google/protobuf/compiler:protoc_minimal",
executable = True,
cfg = "exec",
),
},
implementation = _compile_edition_defaults_impl,
outputs = {
"output": "%{name}.binpb",
},
)
def _embed_edition_defaults_impl(ctx):
if ctx.attr.encoding == "base64":
args = "--encoding=base64"
elif ctx.attr.encoding == "octal":
args = "--encoding=octal"
else:
fail("Unknown encoding %s" % ctx.attr.encoding)
ctx.actions.run_shell(
outputs = [ctx.outputs.output],
inputs = [ctx.file.defaults, ctx.file.template],
tools = [ctx.executable._escape],
command = """
DEFAULTS_RAW=$({escape} {args} < {defaults})
# Windows requires extra escaping.
DEFAULTS_ESCAPED=$(echo $DEFAULTS_RAW | sed 's/\\\\/\\\\\\\\/g' ||
echo $DEFAULTS_RAW | sed 's/\\\\\\\\/\\\\\\\\\\\\\\\\/g')
cp -f {template} {output}
# MacOS requires a backup file.
sed -i.bak \"s|{placeholder}|$DEFAULTS_ESCAPED|g\" {output}
""".format(
escape = ctx.executable._escape.path,
args = args,
defaults = ctx.file.defaults.path,
template = ctx.file.template.path,
output = ctx.outputs.output.path,
placeholder = ctx.attr.placeholder,
),
)
embed_edition_defaults = rule(
doc = "genrule to embed edition defaults binary data into a template file.",
attrs = {
"defaults": attr.label(
mandatory = True,
allow_single_file = True,
allow_rules = ["compile_edition_defaults"],
providers = [ProtoInfo],
doc = "The compile_edition_defaults rule to embed",
),
"output": attr.output(
mandatory = True,
doc = "The name of the output file",
),
"template": attr.label(
mandatory = True,
allow_single_file = True,
doc = "The template to use for generating the output file",
),
"placeholder": attr.string(
mandatory = True,
doc = "The placeholder to replace with a serialized string in the template",
),
"encoding": attr.string(
default = "octal",
values = ["octal", "base64"],
doc = "The encoding format to use for the binary data (octal or base64)",
),
"_escape": attr.label(
default = "//editions:internal_defaults_escape",
executable = True,
cfg = "exec",
),
},
implementation = _embed_edition_defaults_impl,
)