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