esp-open-rtos/bazel/postprocess_static_library.bzl

150 lines
5.4 KiB
Python

# postprocess_static_library takes a prebuilt archive (static library) and
# filters out unnecessary objects / redefines symbols files.
# In ESP8266's case, this is because the ROM already provides their
# implementations.
load("@bazel_tools//tools/build_defs/cc:action_names.bzl", "ACTION_NAMES")
load("@bazel_tools//tools/cpp:toolchain_utils.bzl",
"find_cpp_toolchain", "use_cpp_toolchain")
def _impl(ctx):
# Find the toolchain configuration for the given platform. This is _not_
# the same way that other languages do this, as ctx.toolchains is empty
# for C/C++ (??)
cc_toolchain = find_cpp_toolchain(ctx)
# Populate the feature configuration. This is used by the various cc library
# functions to generate contexts.
feature_configuration = cc_common.configure_features(
ctx = ctx,
cc_toolchain = cc_toolchain,
requested_features = ctx.features,
unsupported_features = ctx.disabled_features
)
# We need these toolchain executables in order to process the library.
archive_tool = cc_common.get_tool_for_action(
feature_configuration = feature_configuration,
action_name = ACTION_NAMES.cpp_link_static_library,
)
objcopy_tool = cc_common.get_tool_for_action(
feature_configuration = feature_configuration,
action_name = "objcopy"
)
# Library label (target) for processing.
input_lib = ctx.file.library
# The output library will be named after the target of this rule.
output_lib = ctx.actions.declare_file(ctx.label.name + ".a")
# Bazel needs to know what files are inputs to a given action.
input_files = [input_lib]
# Construct the argument list to pass to the postprocessor script
args = ctx.actions.args()
args.add_all([
'--input', input_lib,
'--output', output_lib,
'--archive', archive_tool,
'--objcopy', objcopy_tool
])
# If removing objects from the library, create a file, write the objects
# to remove into it, and add it to the list of inputs for the action.
if len(ctx.attr.remove) > 0:
rmobjs = ctx.actions.declare_file(ctx.file.library.basename + ".remove")
ctx.actions.write(rmobjs, "\n".join(ctx.attr.remove))
input_files.append(rmobjs)
args.add_all(['--remove', rmobjs])
# Similar for redefining symbols.
if len(ctx.attr.redefine) > 0:
rdobjs = ctx.actions.declare_file(ctx.file.library.basename + ".redefine")
kv_pairs = [k + " " + v for k, v in ctx.attr.redefine.items()]
ctx.actions.write(rdobjs, "\n".join(kv_pairs) + "\n")
input_files.append(rdobjs)
args.add_all(['--redefine', rdobjs])
# TODO: Handle other ways to process a library.
# This runs the actual script to generate the processed library.
ctx.actions.run(
inputs = input_files,
outputs = [output_lib],
tools = cc_toolchain.all_files,
arguments = [args],
executable = ctx.executable.postprocessor,
)
# With the library in hand, the next step is to set up information for
# Bazel's C/C++ library to utilize the newly-created library.
library_to_link = cc_common.create_library_to_link(
actions = ctx.actions,
feature_configuration = feature_configuration,
static_library = output_lib,
)
linker_input = cc_common.create_linker_input(
libraries = depset([library_to_link]),
owner = ctx.label,
)
linking_context = cc_common.create_linking_context(
linker_inputs = depset([linker_input])
)
# Not yet complete: This part needs us to forward the library and its
# associated headers for targets to use without forwarding the original
# target's library (or you'll get a bunch of linking errors.
(compilation_context, compilation_outputs) = cc_common.compile(
actions = ctx.actions,
feature_configuration = feature_configuration,
cc_toolchain = cc_toolchain,
name = ctx.label.name,
)
# CcInfo is what is actually passed to future targets. We may need to merge
# this with the dependency's original info in order for builds to complete.
# Not sure yet.
this_cc_info = CcInfo(compilation_context = compilation_context, linking_context = linking_context)
cc_infos = [this_cc_info]
# print(this_cc_info.linking_context)
# print(ctx.attr.library[CcInfo].compilation_context)
# print(ctx.attr.library[CcInfo].linking_context)
# cc_infos.append(ctx.attr.library[CcInfo])
merged_cc_info = cc_common.merge_cc_infos(direct_cc_infos = [this_cc_info], cc_infos = cc_infos)
# print(merged_cc_info.linking_context)
return [
DefaultInfo(files = depset([output_lib])),
merged_cc_info
]
postprocess_static_library = rule(
implementation = _impl,
attrs = {
"library": attr.label(
allow_single_file = True,
),
"remove": attr.string_list(
doc = "A list of modules (objects) to remove from the library.",
),
"redefine": attr.string_dict(
doc = "A list of symbols to redefine in the library.",
),
"postprocessor": attr.label(
default = Label("//toolchain:postprocess_archive"),
executable = True,
cfg = "exec",
),
"_cc_toolchain": attr.label(
default = "@bazel_tools//tools/cpp:current_cc_toolchain",
)
},
fragments = ["cpp"],
toolchains = use_cpp_toolchain(),
)