| # Copyright 2024 The Pigweed Authors |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); you may not |
| # use this file except in compliance with the License. You may obtain a copy of |
| # the License at |
| # |
| # https://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| # License for the specific language governing permissions and limitations under |
| # the License. |
| """Rules for processing binary executables.""" |
| |
| load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "find_cpp_toolchain", "use_cpp_toolchain") |
| load("@pw_toolchain//actions:providers.bzl", "ActionNameInfo") |
| |
| def _run_action_on_executable( |
| ctx, |
| action_name, |
| action_args, |
| input, |
| output, |
| additional_outputs, |
| output_executable = False): |
| """Macro to be used in rule implementation to run an action on input executable. |
| |
| Looks up the current toolchain to find the path to the specified action.""" |
| cc_toolchain = find_cpp_toolchain(ctx) |
| |
| feature_configuration = cc_common.configure_features( |
| ctx = ctx, |
| cc_toolchain = cc_toolchain, |
| requested_features = ctx.features, |
| unsupported_features = ctx.disabled_features, |
| ) |
| tool_path = cc_common.get_tool_for_action( |
| feature_configuration = feature_configuration, |
| action_name = action_name, |
| ) |
| |
| ctx.actions.run_shell( |
| inputs = depset( |
| direct = [input], |
| transitive = [ |
| cc_toolchain.all_files, |
| ], |
| ), |
| outputs = [output], |
| command = "{tool} {args}".format( |
| tool = tool_path, |
| args = action_args, |
| ), |
| ) |
| |
| return DefaultInfo( |
| files = depset([output] + additional_outputs), |
| executable = output if output_executable else None, |
| ) |
| |
| def _pw_elf_to_bin_impl(ctx): |
| return _run_action_on_executable( |
| ctx = ctx, |
| action_name = ctx.attr._objcopy[ActionNameInfo].name, |
| action_args = "{args} {input} {output}".format( |
| args = "-Obinary", |
| input = ctx.executable.elf_input.path, |
| output = ctx.outputs.bin_out.path, |
| ), |
| input = ctx.executable.elf_input, |
| output = ctx.outputs.bin_out, |
| additional_outputs = ctx.files.elf_input, |
| output_executable = True, |
| ) |
| |
| pw_elf_to_bin = rule( |
| implementation = _pw_elf_to_bin_impl, |
| doc = """Takes in an ELF executable and uses the toolchain objcopy tool to |
| create a binary file, not containing any ELF headers. This can be used to |
| create a bare-metal bootable image. |
| """, |
| attrs = { |
| "bin_out": attr.output(mandatory = True), |
| "elf_input": attr.label(mandatory = True, executable = True, cfg = "target"), |
| "_objcopy": attr.label( |
| default = "@pw_toolchain//actions:objcopy_embed_data", |
| providers = [ActionNameInfo], |
| ), |
| }, |
| executable = True, |
| toolchains = use_cpp_toolchain(), |
| fragments = ["cpp"], |
| ) |
| |
| def _pw_elf_to_dump_impl(ctx): |
| return _run_action_on_executable( |
| ctx = ctx, |
| action_name = ctx.attr._objdump[ActionNameInfo].name, |
| action_args = "{args} {input} > {output}".format( |
| args = "-dx", |
| input = ctx.executable.elf_input.path, |
| output = ctx.outputs.dump_out.path, |
| ), |
| input = ctx.executable.elf_input, |
| output = ctx.outputs.dump_out, |
| additional_outputs = ctx.files.elf_input, |
| ) |
| |
| pw_elf_to_dump = rule( |
| implementation = _pw_elf_to_dump_impl, |
| doc = """Takes in an ELF executable and uses the toolchain objdump tool to |
| create a text file dump of the contents. |
| """, |
| attrs = { |
| "dump_out": attr.output(mandatory = True), |
| "elf_input": attr.label(mandatory = True, executable = True, cfg = "target"), |
| "_objdump": attr.label( |
| default = "@pw_toolchain//actions:objdump_embed_data", |
| providers = [ActionNameInfo], |
| ), |
| }, |
| toolchains = use_cpp_toolchain(), |
| fragments = ["cpp"], |
| ) |