• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2025 The Pigweed Authors
2#
3# Licensed under the Apache License, Version 2.0 (the "License"); you may not
4# use this file except in compliance with the License. You may obtain a copy of
5# the License at
6#
7#     https://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations under
13# the License.
14"""Internal implementation of size report tables."""
15
16PwSizeBinaryInfo = provider(
17    "Metadata about a binary compiled for a size report",
18    fields = {
19        "binary": "[File] Path to the compiled binary",
20        "bloaty_config": "[File] Bloaty configuration file for the target's platform",
21    },
22)
23
24PwBloatInfo = provider(
25    "Information about a pw_bloat size report",
26    fields = {
27        "fragment": "[File] Path to compiled RST fragment",
28    },
29)
30
31def _pw_bloat_report_impl(ctx):
32    rst_output = ctx.actions.declare_file(ctx.label.name)
33    script_input = ctx.actions.declare_file(ctx.label.name + "_binaries.json")
34
35    if ctx.file.bloaty_config != None:
36        bloaty_config = ctx.file.bloaty_config
37    else:
38        bloaty_config = ctx.attr.target[PwSizeBinaryInfo].bloaty_config
39
40    json_metadata = {
41        "binaries": [
42            {
43                "bloaty_config": bloaty_config.path,
44                "label": ctx.attr.label,
45                "target": ctx.executable.target.path,
46            },
47        ],
48        "out_dir": rst_output.dirname,
49        "target_name": ctx.label.name,
50    }
51
52    action_inputs = [
53        ctx.executable.target,
54        bloaty_config,
55        script_input,
56    ]
57
58    args = ctx.actions.args()
59    args.add("--target-json={}".format(script_input.path))
60    args.add("--generate-rst-fragment")
61
62    if ctx.executable.base != None:
63        json_metadata["binaries"][0]["base"] = ctx.executable.base.path
64        action_inputs.append(ctx.executable.base)
65    else:
66        args.add("--single-report")
67
68    if ctx.attr.source_filter != None:
69        json_metadata["binaries"][0]["source_filter"] = ctx.attr.source_filter
70
71    ctx.actions.write(script_input, json.encode(json_metadata))
72
73    ctx.actions.run(
74        inputs = depset(direct = action_inputs),
75        progress_message = "Generating RST size report for " + ctx.label.name,
76        executable = ctx.executable._bloat_script,
77        arguments = [args],
78        outputs = [rst_output],
79    )
80
81    return [
82        DefaultInfo(files = depset([rst_output])),
83        PwBloatInfo(fragment = rst_output),
84    ]
85
86pw_bloat_report = rule(
87    implementation = _pw_bloat_report_impl,
88    attrs = {
89        "base": attr.label(
90            executable = True,
91            cfg = "target",
92            doc = "Optional base binary for a size diff report",
93        ),
94        "bloaty_config": attr.label(
95            allow_single_file = True,
96            doc = "Bloaty configuration file to use for the size report, overriding the platform default",
97        ),
98        "label": attr.string(doc = "Title for the size report"),
99        "source_filter": attr.string(doc = "Regex with which to filter symbols"),
100        "target": attr.label(
101            mandatory = True,
102            executable = True,
103            cfg = "target",
104            doc = "Binary on which to run the size report",
105            providers = [PwSizeBinaryInfo],
106        ),
107        "_bloat_script": attr.label(
108            default = Label("//pw_bloat/py:bloat_build"),
109            executable = True,
110            cfg = "exec",
111        ),
112    },
113)
114
115def pw_size_table_impl(ctx):
116    """Implementation of the pw_size_table rule.
117
118    Args:
119      ctx: Rule execution context.
120
121    Returns:
122      DefaultInfo provider with the output RST file.
123    """
124    table_output = ctx.actions.declare_file(ctx.label.name)
125
126    input_fragments = []
127
128    for report in ctx.attr.reports:
129        input_fragments.append(report[PwBloatInfo].fragment)
130
131    args = ctx.actions.args()
132    args.add("--collect-fragments-to={}".format(table_output.path))
133
134    for fragment in input_fragments:
135        args.add(fragment.path)
136
137    ctx.actions.run(
138        inputs = depset(direct = input_fragments),
139        progress_message = "Generating RST report table for " + ctx.label.name,
140        executable = ctx.executable._bloat_script,
141        arguments = [args],
142        outputs = [table_output],
143    )
144
145    return DefaultInfo(files = depset([table_output]))
146