xref: /aosp_15_r20/build/bazel/rules/apex/apex_available.bzl (revision 7594170e27e0732bc44b93d1440d87a54b6ffe7c)
1*7594170eSAndroid Build Coastguard Worker# Copyright (C) 2022 The Android Open Source Project
2*7594170eSAndroid Build Coastguard Worker#
3*7594170eSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License");
4*7594170eSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License.
5*7594170eSAndroid Build Coastguard Worker# You may obtain a copy of the License at
6*7594170eSAndroid Build Coastguard Worker#
7*7594170eSAndroid Build Coastguard Worker#     http://www.apache.org/licenses/LICENSE-2.0
8*7594170eSAndroid Build Coastguard Worker#
9*7594170eSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software
10*7594170eSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS,
11*7594170eSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*7594170eSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and
13*7594170eSAndroid Build Coastguard Worker# limitations under the License.
14*7594170eSAndroid Build Coastguard Worker
15*7594170eSAndroid Build Coastguard Workerload("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo")
16*7594170eSAndroid Build Coastguard Workerload("@soong_injection//apex_toolchain:constants.bzl", "apex_available_baseline")
17*7594170eSAndroid Build Coastguard Workerload("//build/bazel/rules:common.bzl", "get_dep_targets", "strip_bp2build_label_suffix")
18*7594170eSAndroid Build Coastguard Workerload("//build/bazel/rules:prebuilt_file.bzl", "PrebuiltFileInfo")
19*7594170eSAndroid Build Coastguard Workerload("//build/bazel/rules/apex:cc.bzl", "CC_ATTR_ASPECTS")
20*7594170eSAndroid Build Coastguard Workerload("//build/bazel/rules/cc:cc_library_static.bzl", "CcStaticLibraryInfo")
21*7594170eSAndroid Build Coastguard Workerload("//build/bazel/rules/cc:cc_stub_library.bzl", "CcStubLibrarySharedInfo")
22*7594170eSAndroid Build Coastguard Worker
23*7594170eSAndroid Build Coastguard WorkerApexAvailableInfo = provider(
24*7594170eSAndroid Build Coastguard Worker    "ApexAvailableInfo collects APEX availability metadata.",
25*7594170eSAndroid Build Coastguard Worker    fields = {
26*7594170eSAndroid Build Coastguard Worker        "apex_available_names": "names of APEXs that this target is available to",
27*7594170eSAndroid Build Coastguard Worker        "platform_available": "whether this target is available for the platform",
28*7594170eSAndroid Build Coastguard Worker        "transitive_invalid_targets": "list of targets that had an invalid apex_available attribute",
29*7594170eSAndroid Build Coastguard Worker        "transitive_unvalidated_targets": "list of targets that were skipped in the apex_available_validation function",
30*7594170eSAndroid Build Coastguard Worker    },
31*7594170eSAndroid Build Coastguard Worker)
32*7594170eSAndroid Build Coastguard Worker
33*7594170eSAndroid Build Coastguard Worker# Validates if a target is made available as a transitive dependency of an APEX. The return
34*7594170eSAndroid Build Coastguard Worker# value is tri-state: True, False, string. Strings are used when a target is _not checked_
35*7594170eSAndroid Build Coastguard Worker# and the string itself contains the reason.
36*7594170eSAndroid Build Coastguard Workerdef _validate_apex_available(target, ctx, *, apex_available_tags, apex_name, base_apex_name):
37*7594170eSAndroid Build Coastguard Worker    # testonly apexes aren't checked.
38*7594170eSAndroid Build Coastguard Worker    if ctx.attr.testonly:
39*7594170eSAndroid Build Coastguard Worker        return "testonly"
40*7594170eSAndroid Build Coastguard Worker
41*7594170eSAndroid Build Coastguard Worker    # Macro-internal manual targets aren't checked.
42*7594170eSAndroid Build Coastguard Worker    if "manual" in ctx.rule.attr.tags and "apex_available_checked_manual_for_testing" not in ctx.rule.attr.tags:
43*7594170eSAndroid Build Coastguard Worker        return "manual"
44*7594170eSAndroid Build Coastguard Worker
45*7594170eSAndroid Build Coastguard Worker    # prebuilt_file targets don't specify apex_available, and aren't checked.
46*7594170eSAndroid Build Coastguard Worker    if PrebuiltFileInfo in target:
47*7594170eSAndroid Build Coastguard Worker        return "prebuilt"
48*7594170eSAndroid Build Coastguard Worker
49*7594170eSAndroid Build Coastguard Worker    # stubs are APIs, and don't specify apex_available, and aren't checked.
50*7594170eSAndroid Build Coastguard Worker    if CcStubLibrarySharedInfo in target:
51*7594170eSAndroid Build Coastguard Worker        return "stubs"
52*7594170eSAndroid Build Coastguard Worker
53*7594170eSAndroid Build Coastguard Worker    if "//apex_available:anyapex" in apex_available_tags:
54*7594170eSAndroid Build Coastguard Worker        return "//apex_available:anyapex"
55*7594170eSAndroid Build Coastguard Worker
56*7594170eSAndroid Build Coastguard Worker    # https://cs.android.com/android/platform/superproject/+/master:build/soong/apex/apex.go;l=2910;drc=862c0d68fff500d7fe59bc2fcfc9c7d75596e5b5
57*7594170eSAndroid Build Coastguard Worker    # Bp2build-generated cc_library_static target from stubs-providing lib
58*7594170eSAndroid Build Coastguard Worker    # doesn't have apex_available tag.
59*7594170eSAndroid Build Coastguard Worker    # If its shared variant is directly in the apex, skip validation
60*7594170eSAndroid Build Coastguard Worker    # Otherwise, it will be invalidated.
61*7594170eSAndroid Build Coastguard Worker    direct_deps = ctx.attr._direct_deps[BuildSettingInfo].value
62*7594170eSAndroid Build Coastguard Worker    if CcStaticLibraryInfo in target and str(target.label).removesuffix("_bp2build_cc_library_static") in direct_deps:
63*7594170eSAndroid Build Coastguard Worker        return "has shared variant directly included"
64*7594170eSAndroid Build Coastguard Worker
65*7594170eSAndroid Build Coastguard Worker    if base_apex_name in apex_available_tags or apex_name in apex_available_tags:
66*7594170eSAndroid Build Coastguard Worker        return True
67*7594170eSAndroid Build Coastguard Worker
68*7594170eSAndroid Build Coastguard Worker    target_name = strip_bp2build_label_suffix(target.label.name)
69*7594170eSAndroid Build Coastguard Worker    baselines = [
70*7594170eSAndroid Build Coastguard Worker        apex_available_baseline.get(base_apex_name, []),
71*7594170eSAndroid Build Coastguard Worker        apex_available_baseline.get(apex_name, []),
72*7594170eSAndroid Build Coastguard Worker        apex_available_baseline.get("//apex_available:anyapex", []),
73*7594170eSAndroid Build Coastguard Worker    ]
74*7594170eSAndroid Build Coastguard Worker    if any([target_name in b for b in baselines]):
75*7594170eSAndroid Build Coastguard Worker        return True
76*7594170eSAndroid Build Coastguard Worker
77*7594170eSAndroid Build Coastguard Worker    return False
78*7594170eSAndroid Build Coastguard Worker
79*7594170eSAndroid Build Coastguard Worker_IGNORED_ATTRS = [
80*7594170eSAndroid Build Coastguard Worker    "certificate",
81*7594170eSAndroid Build Coastguard Worker    "key",
82*7594170eSAndroid Build Coastguard Worker    "android_manifest",
83*7594170eSAndroid Build Coastguard Worker    "applicable_licenses",
84*7594170eSAndroid Build Coastguard Worker    "androidmk_static_deps",
85*7594170eSAndroid Build Coastguard Worker    "androidmk_whole_archive_deps",
86*7594170eSAndroid Build Coastguard Worker    "androidmk_dynamic_deps",
87*7594170eSAndroid Build Coastguard Worker    "androidmk_deps",
88*7594170eSAndroid Build Coastguard Worker]
89*7594170eSAndroid Build Coastguard Worker
90*7594170eSAndroid Build Coastguard Workerdef _apex_available_aspect_impl(target, ctx):
91*7594170eSAndroid Build Coastguard Worker    apex_available_tags = [
92*7594170eSAndroid Build Coastguard Worker        t.removeprefix("apex_available=")
93*7594170eSAndroid Build Coastguard Worker        for t in ctx.rule.attr.tags
94*7594170eSAndroid Build Coastguard Worker        if t.startswith("apex_available=")
95*7594170eSAndroid Build Coastguard Worker    ]
96*7594170eSAndroid Build Coastguard Worker    platform_available = (
97*7594170eSAndroid Build Coastguard Worker        "//apex_available:platform" in apex_available_tags or
98*7594170eSAndroid Build Coastguard Worker        len(apex_available_tags) == 0
99*7594170eSAndroid Build Coastguard Worker    )
100*7594170eSAndroid Build Coastguard Worker    apex_name = ctx.attr._apex_name[BuildSettingInfo].value
101*7594170eSAndroid Build Coastguard Worker
102*7594170eSAndroid Build Coastguard Worker    dep_targets = get_dep_targets(
103*7594170eSAndroid Build Coastguard Worker        ctx.rule.attr,
104*7594170eSAndroid Build Coastguard Worker        predicate = lambda target: ApexAvailableInfo in target,
105*7594170eSAndroid Build Coastguard Worker    )
106*7594170eSAndroid Build Coastguard Worker    transitive_unvalidated_targets = []
107*7594170eSAndroid Build Coastguard Worker    transitive_invalid_targets = []
108*7594170eSAndroid Build Coastguard Worker    for attr, attr_targets in dep_targets.items():
109*7594170eSAndroid Build Coastguard Worker        for t in attr_targets:
110*7594170eSAndroid Build Coastguard Worker            info = t[ApexAvailableInfo]
111*7594170eSAndroid Build Coastguard Worker            transitive_unvalidated_targets.append(info.transitive_unvalidated_targets)
112*7594170eSAndroid Build Coastguard Worker            if attr in CC_ATTR_ASPECTS:
113*7594170eSAndroid Build Coastguard Worker                transitive_invalid_targets.append(info.transitive_invalid_targets)
114*7594170eSAndroid Build Coastguard Worker            if attr not in _IGNORED_ATTRS:
115*7594170eSAndroid Build Coastguard Worker                if info.platform_available != None:
116*7594170eSAndroid Build Coastguard Worker                    platform_available = platform_available and info.platform_available
117*7594170eSAndroid Build Coastguard Worker
118*7594170eSAndroid Build Coastguard Worker    if "manual" in ctx.rule.attr.tags and "apex_available_checked_manual_for_testing" not in ctx.rule.attr.tags:
119*7594170eSAndroid Build Coastguard Worker        platform_available = None
120*7594170eSAndroid Build Coastguard Worker
121*7594170eSAndroid Build Coastguard Worker    if CcStubLibrarySharedInfo in target:
122*7594170eSAndroid Build Coastguard Worker        # stub libraries libraries are always available to platform
123*7594170eSAndroid Build Coastguard Worker        # https://cs.android.com/android/platform/superproject/+/master:build/soong/cc/cc.go;l=3670;drc=89ff729d1d65fb0ce2945ec6b8c4777a9d78dcab
124*7594170eSAndroid Build Coastguard Worker        platform_available = True
125*7594170eSAndroid Build Coastguard Worker
126*7594170eSAndroid Build Coastguard Worker    skipped_reason = _validate_apex_available(
127*7594170eSAndroid Build Coastguard Worker        target,
128*7594170eSAndroid Build Coastguard Worker        ctx,
129*7594170eSAndroid Build Coastguard Worker        apex_available_tags = apex_available_tags,
130*7594170eSAndroid Build Coastguard Worker        apex_name = apex_name,
131*7594170eSAndroid Build Coastguard Worker        base_apex_name = ctx.attr._base_apex_name[BuildSettingInfo].value,
132*7594170eSAndroid Build Coastguard Worker    )
133*7594170eSAndroid Build Coastguard Worker
134*7594170eSAndroid Build Coastguard Worker    return [
135*7594170eSAndroid Build Coastguard Worker        ApexAvailableInfo(
136*7594170eSAndroid Build Coastguard Worker            platform_available = platform_available,
137*7594170eSAndroid Build Coastguard Worker            apex_available_names = apex_available_tags,
138*7594170eSAndroid Build Coastguard Worker            transitive_unvalidated_targets = depset(
139*7594170eSAndroid Build Coastguard Worker                direct = [(ctx.label, skipped_reason)] if type(skipped_reason) == type("") else None,
140*7594170eSAndroid Build Coastguard Worker                transitive = transitive_unvalidated_targets,
141*7594170eSAndroid Build Coastguard Worker            ),
142*7594170eSAndroid Build Coastguard Worker            transitive_invalid_targets = depset(
143*7594170eSAndroid Build Coastguard Worker                direct = [(target, tuple(apex_available_tags))] if skipped_reason == False else None,
144*7594170eSAndroid Build Coastguard Worker                transitive = transitive_invalid_targets,
145*7594170eSAndroid Build Coastguard Worker            ),
146*7594170eSAndroid Build Coastguard Worker        ),
147*7594170eSAndroid Build Coastguard Worker    ]
148*7594170eSAndroid Build Coastguard Worker
149*7594170eSAndroid Build Coastguard Workerapex_available_aspect = aspect(
150*7594170eSAndroid Build Coastguard Worker    implementation = _apex_available_aspect_impl,
151*7594170eSAndroid Build Coastguard Worker    provides = [ApexAvailableInfo],
152*7594170eSAndroid Build Coastguard Worker    apply_to_generating_rules = True,
153*7594170eSAndroid Build Coastguard Worker    attr_aspects = ["*"],
154*7594170eSAndroid Build Coastguard Worker    attrs = {
155*7594170eSAndroid Build Coastguard Worker        "testonly": attr.bool(default = False),  # propagated from the apex
156*7594170eSAndroid Build Coastguard Worker        "_apex_name": attr.label(default = "//build/bazel/rules/apex:apex_name"),
157*7594170eSAndroid Build Coastguard Worker        "_base_apex_name": attr.label(default = "//build/bazel/rules/apex:base_apex_name"),
158*7594170eSAndroid Build Coastguard Worker        "_direct_deps": attr.label(default = "//build/bazel/rules/apex:apex_direct_deps"),
159*7594170eSAndroid Build Coastguard Worker    },
160*7594170eSAndroid Build Coastguard Worker)
161