blob: 38532b18efb9664e6e083d261b28e4e1bac1358c [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("//build/bazel/rules/cc:cc_library_shared.bzl", "CcStubLibrariesInfo")
load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo")
ApexCcInfo = provider(
"Info needed to use CC targets in APEXes",
fields = {
"transitive_shared_libs": "File references to transitive .so libs produced by the CC targets and should be included in the APEX.",
},
)
# Return True if this target provides stubs that is equal to, or below, the
# APEX's min_sdk_level.
#
# These stable ABI libraries are intentionally omitted from APEXes as they are
# provided from another APEX or the platform. By omitting them from APEXes, we
# ensure that there are no multiple copies of such libraries on a device.
def has_cc_stubs(target, ctx):
if ctx.rule.kind != "_cc_library_shared_proxy":
# only _cc_library_shared_proxy contains merged CcStubLibrariesInfo providers
# (a provider aggregating CcStubInfo and CcSharedLibraryInfo)
return False
if len(target[CcStubLibrariesInfo].infos) == 0:
# Not all shared library targets have stubs
return False
# Minimum SDK version supported by the APEX that transitively depends on
# this target.
min_sdk_version = ctx.attr._min_sdk_version[BuildSettingInfo].value
apex_name = ctx.attr._apex_name[BuildSettingInfo].value
available_versions = []
# Check that the shared library has stubs built for (at least) the
# min_sdk_version of the APEX
for stub_info in target[CcStubLibrariesInfo].infos:
stub_version = stub_info["CcStubInfo"].version
available_versions.append(stub_version)
if stub_version <= min_sdk_version:
return True
fail("cannot find a stub lib version for min_sdk_level %s (%s apex)\navailable versions: %s (%s)"
% (min_sdk_version, apex_name, available_versions, target.label))
# Check if this target is specified as a direct dependency of the APEX,
# as opposed to a transitive dependency, as the transitivity impacts
# the files that go into an APEX.
def is_apex_direct_dep(target, ctx):
apex_direct_deps = ctx.attr._apex_direct_deps[BuildSettingInfo].value
return str(target.label) in apex_direct_deps
def _apex_cc_aspect_impl(target, ctx):
# Whether this dep is a direct dep of an APEX or makes a difference in dependency
# traversal, and aggregation of libs that are required from the platform/other APEXes,
# and libs that this APEX will provide to others.
is_direct_dep = is_apex_direct_dep(target, ctx)
if has_cc_stubs(target, ctx):
if is_direct_dep:
# TODO(b/215500321): Mark these libraries as "stub-providing" exports
# of this APEX, which the system and other APEXes can depend on,
# and propagate this list.
pass
else:
# If this is not a direct dep, and stubs are available, don't propagate
# the libraries.
#
# TODO(b/215500321): In a bundled build, ensure that these libraries are
# available on the system either via the system partition, or another APEX
# and propagate this list.
return [ApexCcInfo(transitive_shared_libs = depset())]
shared_object_files = []
# Transitive deps containing shared libraries to be propagated the apex.
transitive_deps = []
# Exclude the stripped and unstripped so files
if ctx.rule.kind == "_cc_library_shared_proxy":
for output_file in target[DefaultInfo].files.to_list():
if output_file.extension == "so":
shared_object_files.append(output_file)
if hasattr(ctx.rule.attr, "shared"):
transitive_deps.append(ctx.rule.attr.shared)
elif ctx.rule.kind == "cc_shared_library" and hasattr(ctx.rule.attr, "dynamic_deps"):
# Propagate along the dynamic_deps edge
for dep in ctx.rule.attr.dynamic_deps:
transitive_deps.append(dep)
elif ctx.rule.kind == "_bssl_hash_injection" and hasattr(ctx.rule.attr, "src"):
# Propagate along the src edge
transitive_deps.append(ctx.rule.attr.src)
elif ctx.rule.kind == "stripped_shared_library" and hasattr(ctx.rule.attr, "src"):
# Propagate along the src edge
transitive_deps.append(ctx.rule.attr.src)
return [
ApexCcInfo(
# TODO: Rely on a split transition across arches to happen earlier
transitive_shared_libs = depset(
shared_object_files,
transitive = [dep[ApexCcInfo].transitive_shared_libs for dep in transitive_deps],
)
),
]
# This aspect is intended to be applied on a apex.native_shared_libs attribute
apex_cc_aspect = aspect(
implementation = _apex_cc_aspect_impl,
attrs = {
"_min_sdk_version": attr.label(default = "//build/bazel/rules/apex:min_sdk_version"),
"_apex_name": attr.label(default = "//build/bazel/rules/apex:apex_name"),
"_apex_direct_deps": attr.label(default = "//build/bazel/rules/apex:apex_direct_deps"),
},
attr_aspects = ["dynamic_deps", "shared", "src"],
# TODO: Have this aspect also propagate along attributes of native_shared_libs?
)