1# Copyright (C) 2022 The Android Open Source Project 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15load("//build/bazel/rules/aidl:aidl_library.bzl", "aidl_library") 16load("//build/bazel/rules/cc:cc_aidl_library.bzl", "cc_aidl_library") 17load("//build/bazel/rules/java:java_aidl_library.bzl", "java_aidl_library") 18 19JAVA = "java" 20CPP = "cpp" 21NDK = "ndk" 22#TODO(b/246803961) Add support for rust backend 23 24def _hash_file(name, version): 25 return "aidl_api/{}/{}/.hash".format(name, version) 26 27def _check_versions_with_info(versions_with_info): 28 for version_with_info in versions_with_info: 29 for dep in version_with_info.get("deps", []): 30 parts = dep.split("-V") 31 if len(parts) < 2 or not parts[-1].isdigit(): 32 fail("deps in versions_with_info must specify its version, but", dep) 33 34 versions = [] 35 36 # ensure that all versions are ints 37 for info in versions_with_info: 38 version = info["version"] 39 if version.isdigit() == False: 40 fail("version %s is not an integer".format(version)) 41 42 versions.append(int(version)) 43 44 if versions != sorted(versions): 45 fail("versions should be sorted") 46 47 for i, v in enumerate(versions): 48 if i > 0: 49 if v == versions[i - 1]: 50 fail("duplicate version found:", v) 51 if v <= 0: 52 fail("all versions should be > 0, but found version:", v) 53 54def _create_latest_version_aliases(name, last_version_name, backend_configs, **kwargs): 55 latest_name = name + "-latest" 56 native.alias( 57 name = latest_name, 58 actual = ":" + last_version_name, 59 **kwargs 60 ) 61 for lang in backend_configs.keys(): 62 language_binding_name = last_version_name + "-" + lang 63 native.alias( 64 name = latest_name + "-" + lang, 65 actual = ":" + language_binding_name, 66 **kwargs 67 ) 68 69def _versioned_name(name, version): 70 if version == "": 71 return name 72 73 return name + "-V" + version 74 75# https://cs.android.com/android/platform/superproject/+/master:system/tools/aidl/build/aidl_interface.go;l=782-799;drc=5390d9a42f5e4f99ccb3a84068f554d948cb62b9 76def _next_version(versions_with_info, unstable): 77 if unstable: 78 return "" 79 80 if versions_with_info == None or len(versions_with_info) == 0: 81 return "1" 82 83 return str(int(versions_with_info[-1]["version"]) + 1) 84 85def _is_config_enabled(config): 86 if config == None: 87 return False 88 89 for key in config: 90 if key not in ["enabled", "min_sdk_version", "tags"]: 91 fail("unknown property in aidl configuration: " + str(key)) 92 93 return config.get("enabled", False) == True 94 95def aidl_interface( 96 name, 97 deps = [], 98 strip_import_prefix = "", 99 srcs = None, 100 flags = None, 101 java_config = None, 102 cpp_config = None, 103 ndk_config = None, 104 stability = None, 105 versions_with_info = [], 106 unstable = False, 107 tags = [], 108 # TODO(b/261208761): Support frozen attr 109 frozen = False, 110 **kwargs): 111 """aidl_interface creates a versioned aidl_libraries and language-specific *_aidl_libraries 112 113 This macro loops over the list of required versions and searches for all 114 *.aidl source files located under the path `aidl_api/<version label/`. 115 For each version, an `aidl_library` is created with the corresponding sources. 116 For each `aidl_library`, a language-binding library *_aidl_library is created 117 based on the values passed to the `backends` argument. 118 119 Arguments: 120 name: string, base name of generated targets: <module-name>-V<version number>-<language-type> 121 deps: List[AidlGenInfo], a list of other aidl_libraries that all versions of this interface depend on 122 strip_import_prefix: str, a local directory to pass to the AIDL compiler to satisfy imports 123 srcs: List[file], a list of files to include in the development (unversioned) version of the aidl_interface 124 flags: List[string], a list of flags to pass to the AIDL compiler 125 java_config: Dict{"enabled": bool}, config for java backend 126 cpp_config: Dict{"enabled": bool, "min_sdk_version": string}, config for cpp backend 127 ndk_config: Dict{"enabled": bool, "min_sdk_version": string}, config for ndk backend 128 stability: string, stability promise of the interface. Currently, only supports "vintf" 129 backends: List[string], a list of the languages to generate bindings for 130 """ 131 132 # When versions_with_info is set, versions is no-op. 133 # TODO(b/244349745): Modify bp2build to skip convert versions if versions_with_info is set 134 if (len(versions_with_info) == 0 and srcs == None): 135 fail("must specify at least versions_with_info or srcs") 136 137 if len(versions_with_info) == 0: 138 if frozen == True: 139 fail("frozen cannot be set without versions_with_info attr being set") 140 elif unstable == True: 141 # https://cs.android.com/android/platform/superproject/+/master:system/tools/aidl/build/aidl_interface.go;l=872;drc=5390d9a42f5e4f99ccb3a84068f554d948cb62b9 142 fail("cannot have versions for unstable interface") 143 144 aidl_flags = ["--structured"] 145 if flags != None: 146 aidl_flags.extend(flags) 147 148 enabled_backend_configs = {} 149 if _is_config_enabled(java_config): 150 enabled_backend_configs[JAVA] = java_config 151 if _is_config_enabled(cpp_config): 152 enabled_backend_configs[CPP] = cpp_config 153 if _is_config_enabled(ndk_config): 154 enabled_backend_configs[NDK] = ndk_config 155 156 if stability != None: 157 if unstable == True: 158 fail("stability must be unset when unstable is true") 159 if stability == "vintf": 160 aidl_flags.append("--stability=" + stability) 161 162 # TODO(b/245738285): Add support for vintf stability in java backend 163 if JAVA in enabled_backend_configs: 164 enabled_backend_configs.pop(JAVA) 165 else: 166 # https://cs.android.com/android/platform/superproject/+/master:system/tools/aidl/build/aidl_interface.go;l=329;drc=e88d9a9b14eafb064a234d555a5cd96de97ca9e2 167 # only vintf is allowed currently 168 fail("stability must be unset or \"vintf\"") 169 170 # next_version will be the last specified version + 1. 171 # https://cs.android.com/android/platform/superproject/+/master:system/tools/aidl/build/aidl_interface.go;l=791?q=system%2Ftools%2Faidl%2Fbuild%2Faidl_interface.go 172 next_version = None 173 174 if len(versions_with_info) > 0: 175 _check_versions_with_info(versions_with_info) 176 next_version = _next_version(versions_with_info, False) 177 178 for version_with_info in versions_with_info: 179 deps_for_version = version_with_info.get("deps", []) 180 181 create_aidl_binding_for_backends( 182 name = name, 183 version = version_with_info["version"], 184 deps = deps_for_version, 185 aidl_flags = aidl_flags, 186 backend_configs = enabled_backend_configs, 187 tags = tags, 188 **kwargs 189 ) 190 191 _create_latest_version_aliases( 192 name, 193 _versioned_name(name, versions_with_info[-1]["version"]), 194 enabled_backend_configs, 195 tags = tags, 196 **kwargs 197 ) 198 else: 199 next_version = _next_version(versions_with_info, unstable) 200 201 # https://cs.android.com/android/platform/superproject/+/master:system/tools/aidl/build/aidl_interface.go;l=941;drc=5390d9a42f5e4f99ccb3a84068f554d948cb62b9 202 # Create aidl binding for next_version with srcs 203 if srcs and len(srcs) > 0: 204 create_aidl_binding_for_backends( 205 name = name, 206 version = next_version, 207 srcs = srcs, 208 strip_import_prefix = strip_import_prefix, 209 deps = deps, 210 aidl_flags = aidl_flags, 211 backend_configs = enabled_backend_configs, 212 tags = tags, 213 **kwargs 214 ) 215 216def create_aidl_binding_for_backends( 217 name, 218 version = None, 219 srcs = None, 220 strip_import_prefix = "", 221 deps = None, 222 aidl_flags = [], 223 backend_configs = {}, 224 tags = [], 225 **kwargs): 226 """ 227 Create aidl_library target and corrending <backend>_aidl_library target for a given version 228 229 Arguments: 230 name: string, base name of the aidl interface 231 version: string, version of the aidl interface 232 srcs: List[Label] list of unversioned AIDL srcs 233 strip_import_prefix string, the prefix to strip the paths of the .aidl files in srcs 234 deps: List[AidlGenInfo], a list of other aidl_libraries that the version depends on 235 the label of the targets have format <aidl-interface>-V<version_number> 236 aidl_flags: List[string], a list of flags to pass to the AIDL compiler 237 backends: List[string], a list of the languages to generate bindings for 238 """ 239 aidl_library_name = _versioned_name(name, version) 240 241 # srcs is None when create_aidl_binding_for_backends is called with a 242 # frozen version specified via versions or versions_with_info. 243 # next_version being equal to "" means this is an unstable version and 244 # we should use srcs instead 245 if version != "": 246 aidl_flags = aidl_flags + ["--version=" + version] 247 248 hash_file = None 249 250 if srcs == None: 251 if version == "": 252 fail("need srcs for unversioned interface") 253 strip_import_prefix = "aidl_api/{}/{}".format(name, version) 254 srcs = native.glob([strip_import_prefix + "/**/*.aidl"]) 255 hash_file = _hash_file(name, version) 256 257 aidl_library( 258 name = aidl_library_name, 259 deps = deps, 260 hash_file = hash_file, 261 version = version, 262 strip_import_prefix = strip_import_prefix, 263 srcs = srcs, 264 flags = aidl_flags, 265 # The language-specific backends will set more appropriate apex_available values. 266 tags = tags + ["apex_available=//apex_available:anyapex"], 267 **kwargs 268 ) 269 270 for lang, config in backend_configs.items(): 271 # https://cs.android.com/android/platform/superproject/+/master:system/tools/aidl/build/aidl_gen_rule.go;l=207;drc=a858ae7039b876a30002a1130f24196915a859a4 272 min_sdk_version = "current" 273 if "min_sdk_version" in config: 274 min_sdk_version = config["min_sdk_version"] 275 276 if lang == JAVA: 277 java_aidl_library( 278 name = aidl_library_name + "-java", 279 deps = [":" + aidl_library_name], 280 tags = tags + config.get("tags", []), 281 # TODO(b/249276008): Pass min_sdk_version to java_aidl_library 282 **(kwargs | {"target_compatible_with": ["//build/bazel/platforms/os:android"]}) 283 ) 284 elif lang == CPP or lang == NDK: 285 dynamic_deps = [] 286 cppflags = [] 287 288 # https://cs.android.com/android/platform/superproject/+/master:system/tools/aidl/build/aidl_interface_backends.go;l=564;drc=0517d97079d4b08f909e7f35edfa33b88fcc0d0e 289 if deps != None: 290 # For each aidl_library target label versioned_name, there's an 291 # associated cc_library_shared target with label versioned_name-<cpp|ndk> 292 dynamic_deps.extend(["{}-{}".format(dep, lang) for dep in deps]) 293 294 # https://cs.android.com/android/platform/superproject/+/master:system/tools/aidl/build/aidl_interface_backends.go;l=111;drc=ef9f1352a1a8fec7bb134b1c713e13fc3ccee651 295 if lang == CPP: 296 dynamic_deps.extend([ 297 "//frameworks/native/libs/binder:libbinder", 298 "//system/core/libutils:libutils", 299 ]) 300 elif lang == NDK: 301 dynamic_deps = dynamic_deps + select({ 302 "//build/bazel/rules/apex:android-in_apex": ["//frameworks/native/libs/binder/ndk:libbinder_ndk_stub_libs_current"], 303 "//conditions:default": ["//frameworks/native/libs/binder/ndk:libbinder_ndk"], 304 }) 305 306 # https://source.corp.google.com/android/system/tools/aidl/build/aidl_interface_backends.go;l=120;rcl=18dd931bde35b502545b7a52987e2363042c151c 307 cppflags = ["-DBINDER_STABILITY_SUPPORT"] 308 309 if hasattr(kwargs, "tidy_checks_as_errors"): 310 fail("tidy_checks_as_errors cannot be overriden for aidl_interface cc_libraries") 311 tidy_checks_as_errors = [ 312 "*", 313 "-clang-analyzer-deadcode.DeadStores", # b/253079031 314 "-clang-analyzer-cplusplus.NewDeleteLeaks", # b/253079031 315 "-clang-analyzer-optin.performance.Padding", # b/253079031 316 ] 317 318 cc_aidl_library( 319 name = "{}-{}".format(aidl_library_name, lang), 320 make_shared = True, 321 cppflags = cppflags, 322 deps = [":" + aidl_library_name], 323 dynamic_deps = dynamic_deps, 324 lang = lang, 325 min_sdk_version = min_sdk_version, 326 tidy = "local", 327 tidy_checks_as_errors = tidy_checks_as_errors, 328 tidy_gen_header_filter = True, 329 tags = tags + config.get("tags", []), 330 **kwargs 331 ) 332