• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Protocol Buffers - Google's data interchange format
2# Copyright 2023 Google Inc.  All rights reserved.
3#
4# Use of this source code is governed by a BSD-style
5# license that can be found in the LICENSE file or at
6# https://developers.google.com/open-source/licenses/bsd
7"""
8Provide a rule for generating the intermediate feature set defaults used for feature resolution.
9
10See go/life-of-a-featureset for more information.
11"""
12
13load("//bazel/common:proto_info.bzl", "ProtoInfo")
14
15def _compile_edition_defaults_impl(ctx):
16    out_file = ctx.actions.declare_file(ctx.outputs.output.basename)
17    sources = []
18    paths = []
19    for src in ctx.attr.srcs:
20        sources.extend(src[ProtoInfo].transitive_sources.to_list())
21        paths.extend(src[ProtoInfo].transitive_proto_path.to_list())
22
23    args = ctx.actions.args()
24    args.add("--edition_defaults_out", out_file)
25
26    args.add("--edition_defaults_minimum", ctx.attr.minimum_edition)
27    args.add("--edition_defaults_maximum", ctx.attr.maximum_edition)
28    for p in paths:
29        args.add("--proto_path", p)
30    for source in sources:
31        args.add(source)
32    ctx.actions.run(
33        outputs = [out_file],
34        inputs = sources,
35        executable = ctx.executable.protoc or ctx.executable._protoc_minimal,
36        arguments = [args],
37        progress_message = "Generating edition defaults",
38    )
39
40compile_edition_defaults = rule(
41    attrs = {
42        "srcs": attr.label_list(
43            mandatory = True,
44            allow_rules = ["proto_library"],
45            providers = [ProtoInfo],
46        ),
47        "minimum_edition": attr.string(mandatory = True),
48        "maximum_edition": attr.string(mandatory = True),
49        "protoc": attr.label(
50            mandatory = False,
51            executable = True,
52            cfg = "exec",
53        ),
54        "_protoc_minimal": attr.label(
55            default = "//src/google/protobuf/compiler:protoc_minimal",
56            executable = True,
57            cfg = "exec",
58        ),
59    },
60    implementation = _compile_edition_defaults_impl,
61    outputs = {
62        "output": "%{name}.binpb",
63    },
64)
65
66def _embed_edition_defaults_impl(ctx):
67    if ctx.attr.encoding == "base64":
68        args = "--encoding=base64"
69    elif ctx.attr.encoding == "octal":
70        args = "--encoding=octal"
71    else:
72        fail("Unknown encoding %s" % ctx.attr.encoding)
73    ctx.actions.run_shell(
74        outputs = [ctx.outputs.output],
75        inputs = [ctx.file.defaults, ctx.file.template],
76        tools = [ctx.executable._escape],
77        command = """
78            DEFAULTS_RAW=$({escape} {args} < {defaults})
79            # Windows requires extra escaping.
80            DEFAULTS_ESCAPED=$(echo $DEFAULTS_RAW | sed 's/\\\\/\\\\\\\\/g' ||
81                echo $DEFAULTS_RAW | sed 's/\\\\\\\\/\\\\\\\\\\\\\\\\/g')
82            cp -f {template} {output}
83            # MacOS requires a backup file.
84            sed -i.bak \"s|{placeholder}|$DEFAULTS_ESCAPED|g\" {output}
85        """.format(
86            escape = ctx.executable._escape.path,
87            args = args,
88            defaults = ctx.file.defaults.path,
89            template = ctx.file.template.path,
90            output = ctx.outputs.output.path,
91            placeholder = ctx.attr.placeholder,
92        ),
93    )
94
95embed_edition_defaults = rule(
96    doc = "genrule to embed edition defaults binary data into a template file.",
97    attrs = {
98        "defaults": attr.label(
99            mandatory = True,
100            allow_single_file = True,
101            allow_rules = ["compile_edition_defaults"],
102            providers = [ProtoInfo],
103            doc = "The compile_edition_defaults rule to embed",
104        ),
105        "output": attr.output(
106            mandatory = True,
107            doc = "The name of the output file",
108        ),
109        "template": attr.label(
110            mandatory = True,
111            allow_single_file = True,
112            doc = "The template to use for generating the output file",
113        ),
114        "placeholder": attr.string(
115            mandatory = True,
116            doc = "The placeholder to replace with a serialized string in the template",
117        ),
118        "encoding": attr.string(
119            default = "octal",
120            values = ["octal", "base64"],
121            doc = "The encoding format to use for the binary data (octal or base64)",
122        ),
123        "_escape": attr.label(
124            default = "//editions:internal_defaults_escape",
125            executable = True,
126            cfg = "exec",
127        ),
128    },
129    implementation = _embed_edition_defaults_impl,
130)
131