134 lines
4.6 KiB
Python
134 lines
4.6 KiB
Python
"""Provides a rule that outputs a monolithic static library."""
|
|
|
|
load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "find_cpp_toolchain")
|
|
|
|
TOOLS_CPP_REPO = "@bazel_tools"
|
|
|
|
def _cc_static_library_impl(ctx):
|
|
output_lib = ctx.actions.declare_file("{}.a".format(ctx.attr.name))
|
|
output_flags = ctx.actions.declare_file("{}.link".format(ctx.attr.name))
|
|
|
|
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
|
|
)
|
|
|
|
lib_sets = []
|
|
lib_inputs = []
|
|
unique_flags = {}
|
|
|
|
merged_compilation_context = cc_common.merge_compilation_contexts(
|
|
compilation_contexts = [dep[CcInfo].compilation_context for dep in ctx.attr.deps]
|
|
)
|
|
|
|
for dep in ctx.attr.deps:
|
|
if hasattr(dep[CcInfo].linking_context.linker_inputs, "to_list"):
|
|
lib_inputs.append(dep[CcInfo].linking_context.linker_inputs.to_list())
|
|
else:
|
|
lib_inputs.append(dep[CcInfo].linking_context.linker_inputs)
|
|
|
|
for lib in dep[CcInfo].linking_context.linker_inputs.to_list():
|
|
if hasattr(lib.libraries, "to_list"):
|
|
lib_sets.append(lib.libraries)
|
|
else:
|
|
lib_sets.append(depset(direct = lib.libraries))
|
|
unique_flags.update({
|
|
flag: None
|
|
for flag in lib.user_link_flags
|
|
})
|
|
|
|
libraries_to_link = depset(transitive = lib_sets)
|
|
link_flags = unique_flags.keys()
|
|
|
|
libs = []
|
|
libs.extend([lib.pic_static_library for lib in libraries_to_link.to_list() if lib.pic_static_library])
|
|
libs.extend([
|
|
lib.static_library
|
|
for lib in libraries_to_link.to_list()
|
|
if lib.static_library and not lib.pic_static_library
|
|
])
|
|
|
|
script_file = ctx.actions.declare_file("{}.mri".format(ctx.attr.name))
|
|
commands = ["create {}".format(output_lib.path)]
|
|
for lib in libs:
|
|
commands.append("addlib {}".format(lib.path))
|
|
commands.append("save")
|
|
commands.append("end")
|
|
ctx.actions.write(
|
|
output = script_file,
|
|
content = "\n".join(commands) + "\n",
|
|
)
|
|
|
|
ar_tool = cc_common.get_tool_for_action(
|
|
feature_configuration = feature_configuration,
|
|
action_name = "ar",
|
|
)
|
|
|
|
ctx.actions.run_shell(
|
|
command = "{} -M < {}".format(ar_tool, script_file.path),
|
|
inputs = [script_file] + libs + cc_toolchain.all_files.to_list(),
|
|
outputs = [output_lib],
|
|
mnemonic = "ArMerge",
|
|
progress_message = "Merging static library {}".format(output_lib.path),
|
|
)
|
|
ctx.actions.write(
|
|
output = output_flags,
|
|
content = "\n".join(link_flags) + "\n",
|
|
)
|
|
|
|
# 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,
|
|
#user_link_flags = ['fooxbar']
|
|
)
|
|
|
|
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])
|
|
)
|
|
|
|
# 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 = merged_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
|
|
]
|
|
|
|
cc_static_library = rule(
|
|
implementation = _cc_static_library_impl,
|
|
attrs = {
|
|
"deps": attr.label_list(),
|
|
"_cc_toolchain": attr.label(
|
|
default = TOOLS_CPP_REPO + "//tools/cpp:current_cc_toolchain",
|
|
),
|
|
},
|
|
toolchains = [TOOLS_CPP_REPO + "//tools/cpp:toolchain_type"],
|
|
fragments = ["cpp"],
|
|
incompatible_use_toolchain_transition = True,
|
|
)
|
|
|