diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-05-10 06:51:54 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-05-10 06:51:54 +0000 |
commit | 9850fee71151e8e244e202597d6e1920ee3a71c3 (patch) | |
tree | 74393ec5dcc68491e5308c0f4d3bdc3fa1f58fcb /rules/cc/cc_library_shared.bzl | |
parent | 479e50d33ff6852449772ace5d54f9658dddf71e (diff) | |
parent | 92c1d863d4d44c61c934ddbb4392fcf3527f0639 (diff) | |
download | bazel-9850fee71151e8e244e202597d6e1920ee3a71c3.tar.gz |
Snap for 8564071 from 92c1d863d4d44c61c934ddbb4392fcf3527f0639 to mainline-conscrypt-releaseaml_con_331413000aml_con_331411000aml_con_331312000aml_con_331115000aml_con_331011010android13-mainline-conscrypt-release
Change-Id: I270f1c56b57254a0f62c75330da5ebaa3bab7fb4
Diffstat (limited to 'rules/cc/cc_library_shared.bzl')
-rw-r--r-- | rules/cc/cc_library_shared.bzl | 449 |
1 files changed, 449 insertions, 0 deletions
diff --git a/rules/cc/cc_library_shared.bzl b/rules/cc/cc_library_shared.bzl new file mode 100644 index 00000000..b4367e50 --- /dev/null +++ b/rules/cc/cc_library_shared.bzl @@ -0,0 +1,449 @@ +""" +Copyright (C) 2021 The Android Open Source Project + +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 + + http://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. +""" + +load( + ":cc_library_common.bzl", + "add_lists_defaulting_to_none", + "disable_crt_link", + "parse_sdk_version", + "system_dynamic_deps_defaults", +) +load(":cc_library_static.bzl", "cc_library_static") +load(":cc_stub_library.bzl", "CcStubInfo", "cc_stub_gen") +load(":generate_toc.bzl", "shared_library_toc", _CcTocInfo = "CcTocInfo") +load(":stl.bzl", "shared_stl_deps") +load(":stripped_cc_common.bzl", "stripped_shared_library") +load(":versioned_cc_common.bzl", "versioned_shared_library") +load("@rules_cc//examples:experimental_cc_shared_library.bzl", "cc_shared_library", _CcSharedLibraryInfo = "CcSharedLibraryInfo") +load("@rules_cc//cc:find_cc_toolchain.bzl", "find_cpp_toolchain") + +CcTocInfo = _CcTocInfo +CcSharedLibraryInfo = _CcSharedLibraryInfo + +def cc_library_shared( + name, + # Common arguments between shared_root and the shared library + features = [], + dynamic_deps = [], + implementation_dynamic_deps = [], + linkopts = [], + target_compatible_with = [], + # Ultimately _static arguments for shared_root production + srcs = [], + srcs_c = [], + srcs_as = [], + copts = [], + cppflags = [], + conlyflags = [], + asflags = [], + hdrs = [], + implementation_deps = [], + deps = [], + whole_archive_deps = [], + system_dynamic_deps = None, + export_includes = [], + export_absolute_includes = [], + export_system_includes = [], + local_includes = [], + absolute_includes = [], + rtti = False, + use_libcrt = True, # FIXME: Unused below? + stl = "", + cpp_std = "", + c_std = "", + link_crt = True, + additional_linker_inputs = None, + + # Purely _shared arguments + strip = {}, + soname = "", + + # TODO(b/202299295): Handle data attribute. + data = [], + use_version_lib = False, + stubs_symbol_file = None, + stubs_versions = [], + inject_bssl_hash = False, + sdk_version = "", + min_sdk_version = "", + **kwargs): + "Bazel macro to correspond with the cc_library_shared Soong module." + + shared_root_name = name + "_root" + unstripped_name = name + "_unstripped" + stripped_name = name + "_stripped" + toc_name = name + "_toc" + + if system_dynamic_deps == None: + system_dynamic_deps = system_dynamic_deps_defaults + + # Force crtbegin and crtend linking unless explicitly disabled (i.e. bionic + # libraries do this) + if link_crt == False: + features = disable_crt_link(features) + + if min_sdk_version: + features = features + [ + "sdk_version_" + parse_sdk_version(min_sdk_version), + "-sdk_version_default", + ] + + # The static library at the root of the shared library. + # This may be distinct from the static version of the library if e.g. + # the static-variant srcs are different than the shared-variant srcs. + cc_library_static( + name = shared_root_name, + hdrs = hdrs, + srcs = srcs, + srcs_c = srcs_c, + srcs_as = srcs_as, + copts = copts, + cppflags = cppflags, + conlyflags = conlyflags, + asflags = asflags, + export_includes = export_includes, + export_absolute_includes = export_absolute_includes, + export_system_includes = export_system_includes, + local_includes = local_includes, + absolute_includes = absolute_includes, + rtti = rtti, + stl = stl, + cpp_std = cpp_std, + c_std = c_std, + dynamic_deps = dynamic_deps, + implementation_deps = implementation_deps, + implementation_dynamic_deps = implementation_dynamic_deps, + system_dynamic_deps = system_dynamic_deps, + deps = deps + whole_archive_deps, + features = features, + use_version_lib = use_version_lib, + target_compatible_with = target_compatible_with, + ) + + stl_static, stl_shared = shared_stl_deps(stl) + + # implementation_deps and deps are to be linked into the shared library via + # --no-whole-archive. In order to do so, they need to be dependencies of + # a "root" of the cc_shared_library, but may not be roots themselves. + # Below we define stub roots (which themselves have no srcs) in order to facilitate + # this. + imp_deps_stub = name + "_implementation_deps" + deps_stub = name + "_deps" + native.cc_library( + name = imp_deps_stub, + deps = implementation_deps + stl_static, + target_compatible_with = target_compatible_with, + ) + native.cc_library( + name = deps_stub, + deps = deps, + target_compatible_with = target_compatible_with, + ) + + shared_dynamic_deps = add_lists_defaulting_to_none( + dynamic_deps, + system_dynamic_deps, + implementation_dynamic_deps, + stl_shared, + ) + + if len(soname) == 0: + soname = name + ".so" + soname_flag = "-Wl,-soname," + soname + + cc_shared_library( + name = unstripped_name, + user_link_flags = linkopts + [soname_flag], + # b/184806113: Note this is a workaround so users don't have to + # declare all transitive static deps used by this target. It'd be great + # if a shared library could declare a transitive exported static dep + # instead of needing to declare each target transitively. + static_deps = ["//:__subpackages__"] + [shared_root_name, imp_deps_stub, deps_stub], + dynamic_deps = shared_dynamic_deps, + additional_linker_inputs = additional_linker_inputs, + roots = [shared_root_name, imp_deps_stub, deps_stub] + whole_archive_deps, + features = features, + target_compatible_with = target_compatible_with, + **kwargs + ) + + hashed_name = name + "_hashed" + _bssl_hash_injection( + name = hashed_name, + src = unstripped_name, + inject_bssl_hash = inject_bssl_hash, + ) + + versioned_name = name + "_versioned" + versioned_shared_library( + name = versioned_name, + src = hashed_name, + stamp_build_number = use_version_lib, + ) + + stripped_shared_library( + name = stripped_name, + src = versioned_name, + target_compatible_with = target_compatible_with, + **strip + ) + + shared_library_toc( + name = toc_name, + src = stripped_name, + target_compatible_with = target_compatible_with, + ) + + # Emit the stub version of this library (e.g. for libraries that are + # provided by the NDK) + stub_shared_libraries = [] + if stubs_symbol_file and len(stubs_versions) > 0: + # TODO(b/193663198): This unconditionally creates stubs for every version, but + # that's not always true depending on whether this module is available + # on the host, ramdisk, vendor ramdisk. We currently don't have + # information about the image variant yet, so we'll create stub targets + # for all shared libraries with the stubs property for now. + # + # See: https://cs.android.com/android/platform/superproject/+/master:build/soong/cc/library.go;l=2316-2377;drc=3d3b35c94ed2a3432b2e5e7e969a3a788a7a80b5 + for version in stubs_versions: + stubs_library_name = "_".join([name, version, "stubs"]) + cc_stub_library_shared( + name = stubs_library_name, + stubs_symbol_file = stubs_symbol_file, + version = version, + target_compatible_with = target_compatible_with, + features = features, + ) + stub_shared_libraries.append(stubs_library_name) + + _cc_library_shared_proxy( + name = name, + shared = stripped_name, + root = shared_root_name, + table_of_contents = toc_name, + output_file = soname, + target_compatible_with = target_compatible_with, + stub_shared_libraries = stub_shared_libraries, + ) + +# cc_stub_library_shared creates a cc_library_shared target, but using stub C source files generated +# from a library's .map.txt files and ndkstubgen. The top level target returns the same +# providers as a cc_library_shared, with the addition of a CcStubInfo +# containing metadata files and versions of the stub library. +def cc_stub_library_shared(name, stubs_symbol_file, version, target_compatible_with, features): + # Call ndkstubgen to generate the stub.c source file from a .map.txt file. These + # are accessible in the CcStubInfo provider of this target. + cc_stub_gen( + name = name + "_files", + symbol_file = stubs_symbol_file, + version = version, + target_compatible_with = target_compatible_with, + ) + + # The static library at the root of the stub shared library. + cc_library_static( + name = name + "_root", + srcs_c = [name + "_files"], # compile the stub.c file + features = disable_crt_link(features) + \ + [ + # Enable the stub library compile flags + "stub_library", + # Disable all include-related features to avoid including any headers + # that may cause conflicting type errors with the symbols in the + # generated stubs source code. + # e.g. + # double acos(double); // in header + # void acos() {} // in the generated source code + # See https://cs.android.com/android/platform/superproject/+/master:build/soong/cc/library.go;l=942-946;drc=d8a72d7dc91b2122b7b10b47b80cf2f7c65f9049 + "-toolchain_include_directories", + "-includes", + "-include_paths", + ], + target_compatible_with = target_compatible_with, + stl = "none", + system_dynamic_deps = [], + ) + + # Create a .so for the stub library. This library is self contained, has + # no deps, and doesn't link against crt. + cc_shared_library( + name = name + "_so", + roots = [name + "_root"], + features = disable_crt_link(features), + target_compatible_with = target_compatible_with, + ) + + # Create a target with CcSharedLibraryInfo and CcStubInfo providers. + _cc_stub_library_shared( + name = name, + stub_target = name + "_files", + library_target = name + "_so", + ) + +def _cc_stub_library_shared_impl(ctx): + return [ + ctx.attr.library_target[DefaultInfo], + ctx.attr.library_target[CcSharedLibraryInfo], + ctx.attr.stub_target[CcStubInfo], + ] + +_cc_stub_library_shared = rule( + implementation = _cc_stub_library_shared_impl, + doc = "Top level rule to merge CcStubInfo and CcSharedLibraryInfo into a single target", + attrs = { + "stub_target": attr.label(mandatory = True), + "library_target": attr.label(mandatory = True), + }, +) + +def _swap_shared_linker_input(ctx, shared_info, new_output): + old_library_to_link = shared_info.linker_input.libraries[0] + + cc_toolchain = find_cpp_toolchain(ctx) + feature_configuration = cc_common.configure_features( + ctx = ctx, + cc_toolchain = cc_toolchain, + ) + + new_library_to_link = cc_common.create_library_to_link( + actions = ctx.actions, + dynamic_library = new_output, + feature_configuration = feature_configuration, + cc_toolchain = cc_toolchain, + ) + + new_linker_input = cc_common.create_linker_input( + owner = shared_info.linker_input.owner, + libraries = depset([new_library_to_link]), + ) + + return CcSharedLibraryInfo( + dynamic_deps = shared_info.dynamic_deps, + exports = shared_info.exports, + link_once_static_libs = shared_info.link_once_static_libs, + linker_input = new_linker_input, + preloaded_deps = shared_info.preloaded_deps, + ) + +CcStubLibrariesInfo = provider( + fields = { + "infos": "A list of dict, where each dict contains the CcStubInfo, CcSharedLibraryInfo and DefaultInfo of a version of a stub library.", + }, +) + +def _cc_library_shared_proxy_impl(ctx): + root_files = ctx.attr.root[DefaultInfo].files.to_list() + shared_files = ctx.attr.shared[DefaultInfo].files.to_list() + + if len(shared_files) != 1: + fail("Expected only one shared library file") + + shared_lib = shared_files[0] + + ctx.actions.symlink( + output = ctx.outputs.output_file, + target_file = shared_lib, + ) + + files = root_files + [ctx.outputs.output_file, ctx.files.table_of_contents[0]] + + stub_library_infos = [] + for stub_library in ctx.attr.stub_shared_libraries: + providers = { + "CcStubInfo": stub_library[CcStubInfo], + "CcSharedLibraryInfo": stub_library[CcSharedLibraryInfo], + "DefaultInfo": stub_library[DefaultInfo], + } + stub_library_infos.append(providers) + + return [ + DefaultInfo( + files = depset(direct = files), + runfiles = ctx.runfiles(files = [ctx.outputs.output_file]), + ), + _swap_shared_linker_input(ctx, ctx.attr.shared[CcSharedLibraryInfo], ctx.outputs.output_file), + ctx.attr.table_of_contents[CcTocInfo], + # Propagate only includes from the root. Do not re-propagate linker inputs. + CcInfo(compilation_context = ctx.attr.root[CcInfo].compilation_context), + CcStubLibrariesInfo(infos = stub_library_infos), + ] + +_cc_library_shared_proxy = rule( + implementation = _cc_library_shared_proxy_impl, + attrs = { + "shared": attr.label(mandatory = True, providers = [CcSharedLibraryInfo]), + "root": attr.label(mandatory = True, providers = [CcInfo]), + "output_file": attr.output(mandatory = True), + "table_of_contents": attr.label( + mandatory = True, + # TODO(b/217908237): reenable allow_single_file + # allow_single_file = True, + providers = [CcTocInfo], + ), + "stub_shared_libraries": attr.label_list(providers = [CcStubInfo, CcSharedLibraryInfo]), + }, + fragments = ["cpp"], + toolchains = ["@bazel_tools//tools/cpp:toolchain_type"], +) + +def _bssl_hash_injection_impl(ctx): + if len(ctx.files.src) != 1: + fail("Expected only one shared library file") + + hashed_file = ctx.files.src[0] + if ctx.attr.inject_bssl_hash: + hashed_file = ctx.actions.declare_file("lib" + ctx.attr.name + ".so") + args = ctx.actions.args() + args.add_all(["-sha256"]) + args.add_all(["-in-object", ctx.files.src[0]]) + args.add_all(["-o", hashed_file]) + + ctx.actions.run( + inputs = ctx.files.src, + outputs = [hashed_file], + executable = ctx.executable._bssl_inject_hash, + arguments = [args], + tools = [ctx.executable._bssl_inject_hash], + mnemonic = "BsslInjectHash", + ) + + return [ + DefaultInfo(files = depset([hashed_file])), + ctx.attr.src[CcSharedLibraryInfo], + ] + +_bssl_hash_injection = rule( + implementation = _bssl_hash_injection_impl, + attrs = { + "src": attr.label( + mandatory = True, + # TODO(b/217908237): reenable allow_single_file + # allow_single_file = True, + providers = [CcSharedLibraryInfo], + ), + "inject_bssl_hash": attr.bool( + default = False, + doc = "Whether inject BSSL hash", + ), + "_bssl_inject_hash": attr.label( + cfg = "exec", + doc = "The BSSL hash injection tool.", + executable = True, + default = "//prebuilts/build-tools:linux-x86/bin/bssl_inject_hash", + allow_single_file = True, + ), + }, +) |