# 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, )