blob: 2aa2a688861b09df1368c0c6480441d429694018 [file] [log] [blame]
"""
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", "system_dynamic_deps_defaults")
load(":cc_library_static.bzl", "cc_library_static")
load(":cc_stub_library.bzl", "cc_stub_library")
load(":generate_toc.bzl", "shared_library_toc", _CcTocInfo = "CcTocInfo")
load(":stl.bzl", "shared_stl_deps")
load(":stripped_cc_common.bzl", "stripped_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 = [],
**kwargs):
"Bazel macro to correspond with the cc_library_shared Soong module."
if use_version_lib:
libbuildversionLabel = "//build/soong/cc/libbuildversion:libbuildversion"
whole_archive_deps = whole_archive_deps + [libbuildversionLabel]
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)
# 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
)
stripped_shared_library(
name = stripped_name,
src = unstripped_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)
#
# TODO(b/207812332): This only calls ndkstubgen to generate the src now.
# Make this compile into an .so as well, and include the stub .so in a
# _cc_library_shared_proxy provider so dependents can easily determine if
# this target has stubs for a specific API version.
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(
name = stubs_library_name,
symbol_file = stubs_symbol_file,
version = version,
)
_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,
)
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,
)
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.file.table_of_contents]
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),
]
_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, allow_single_file = True, providers = [CcTocInfo]),
},
fragments = ["cpp"],
toolchains = ["@bazel_tools//tools/cpp:toolchain_type"],
)