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