blob: 31f9fe4262e91c1da3c8dbb1fe57885b6c76a37c [file] [log] [blame]
# 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"],
)