# 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(), )