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", "additional_dynamic_deps"]: 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 hdrs = [], 99 strip_import_prefix = "", 100 srcs = None, 101 flags = None, 102 java_config = None, 103 cpp_config = None, 104 ndk_config = None, 105 stability = None, 106 versions_with_info = [], 107 unstable = False, 108 tags = [], 109 # TODO(b/261208761): Support frozen attr 110 frozen = False, 111 **kwargs): 112 """aidl_interface creates a versioned aidl_libraries and language-specific *_aidl_libraries 113 114 This macro loops over the list of required versions and searches for all 115 *.aidl source files located under the path `aidl_api/<version label/`. 116 For each version, an `aidl_library` is created with the corresponding sources. 117 For each `aidl_library`, a language-binding library *_aidl_library is created 118 based on the values passed to the `backends` argument. 119 120 Arguments: 121 name: string, base name of generated targets: <module-name>-V<version number>-<language-type> 122 deps: List[AidlGenInfo], a list of other aidl_libraries that all versions of this interface depend on 123 hdrs: List[AidlGenInfo], a list of other aidl_libraries that all versions of this interface depend on but will not link against for C++ 124 strip_import_prefix: str, a local directory to pass to the AIDL compiler to satisfy imports 125 srcs: List[file], a list of files to include in the development (unversioned) version of the aidl_interface 126 flags: List[string], a list of flags to pass to the AIDL compiler 127 java_config: Dict{"enabled": bool}, config for java backend 128 cpp_config: Dict{"enabled": bool, "min_sdk_version": string, "additional_dynamic_deps": List[Label]}, config for cpp backend 129 ndk_config: Dict{"enabled": bool, "min_sdk_version": string, "additional_dynamic_deps": List[Label]}, config for ndk backend 130 stability: string, stability promise of the interface. Currently, only supports "vintf" 131 backends: List[string], a list of the languages to generate bindings for 132 """ 133 134 # When versions_with_info is set, versions is no-op. 135 # TODO(b/244349745): Modify bp2build to skip convert versions if versions_with_info is set 136 if (len(versions_with_info) == 0 and srcs == None): 137 fail("must specify at least versions_with_info or srcs") 138 139 if len(versions_with_info) == 0: 140 if frozen == True: 141 fail("frozen cannot be set without versions_with_info attr being set") 142 elif unstable == True: 143 # https://cs.android.com/android/platform/superproject/+/master:system/tools/aidl/build/aidl_interface.go;l=872;drc=5390d9a42f5e4f99ccb3a84068f554d948cb62b9 144 fail("cannot have versions for unstable interface") 145 146 aidl_flags = ["--structured"] 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 version = version_with_info.get("version") 181 flags_for_version = aidl_flags 182 183 if version == next_version and frozen == False and flags != None: 184 flags_for_version.extend(flags) 185 186 create_aidl_binding_for_backends( 187 name = name, 188 version = version_with_info["version"], 189 deps = deps_for_version, 190 hdrs = hdrs, 191 aidl_flags = flags_for_version, 192 backend_configs = enabled_backend_configs, 193 tags = tags, 194 **kwargs 195 ) 196 197 _create_latest_version_aliases( 198 name, 199 _versioned_name(name, versions_with_info[-1]["version"]), 200 enabled_backend_configs, 201 tags = tags, 202 **kwargs 203 ) 204 else: 205 next_version = _next_version(versions_with_info, unstable) 206 207 # https://cs.android.com/android/platform/superproject/+/master:system/tools/aidl/build/aidl_interface.go;l=941;drc=5390d9a42f5e4f99ccb3a84068f554d948cb62b9 208 # Create aidl binding for next_version with srcs 209 if srcs and len(srcs) > 0: 210 create_aidl_binding_for_backends( 211 name = name, 212 version = next_version, 213 srcs = srcs, 214 strip_import_prefix = strip_import_prefix, 215 deps = deps, 216 hdrs = hdrs, 217 aidl_flags = aidl_flags, 218 backend_configs = enabled_backend_configs, 219 tags = tags, 220 **kwargs 221 ) 222 223def create_aidl_binding_for_backends( 224 name, 225 version = None, 226 srcs = None, 227 strip_import_prefix = "", 228 deps = None, 229 hdrs = None, 230 aidl_flags = [], 231 backend_configs = {}, 232 tags = [], 233 **kwargs): 234 """ 235 Create aidl_library target and corrending <backend>_aidl_library target for a given version 236 237 Arguments: 238 name: string, base name of the aidl interface 239 version: string, version of the aidl interface 240 srcs: List[Label] list of unversioned AIDL srcs 241 strip_import_prefix string, the prefix to strip the paths of the .aidl files in srcs 242 deps: List[AidlGenInfo], a list of other aidl_libraries that the version depends on 243 hdrs: List[AidlGenInfo], a list of other aidl_libraries that the version depends on but will not link against for C++ 244 the label of the targets have format <aidl-interface>-V<version_number> 245 aidl_flags: List[string], a list of flags to pass to the AIDL compiler 246 backends: List[string], a list of the languages to generate bindings for 247 """ 248 aidl_library_name = _versioned_name(name, version) 249 250 # srcs is None when create_aidl_binding_for_backends is called with a 251 # frozen version specified via versions or versions_with_info. 252 # next_version being equal to "" means this is an unstable version and 253 # we should use srcs instead 254 if version != "": 255 aidl_flags = aidl_flags + ["--version=" + version] 256 257 hash_file = None 258 259 if srcs == None: 260 if version == "": 261 fail("need srcs for unversioned interface") 262 strip_import_prefix = "aidl_api/{}/{}".format(name, version) 263 srcs = native.glob([strip_import_prefix + "/**/*.aidl"]) 264 hash_file = _hash_file(name, version) 265 266 aidl_library( 267 name = aidl_library_name, 268 deps = deps + hdrs, 269 hash_file = hash_file, 270 version = version, 271 strip_import_prefix = strip_import_prefix, 272 srcs = srcs, 273 flags = aidl_flags, 274 # The language-specific backends will set more appropriate apex_available values. 275 tags = tags + ["apex_available=//apex_available:anyapex"], 276 **kwargs 277 ) 278 279 for lang, config in backend_configs.items(): 280 # https://cs.android.com/android/platform/superproject/+/master:system/tools/aidl/build/aidl_gen_rule.go;l=207;drc=a858ae7039b876a30002a1130f24196915a859a4 281 min_sdk_version = "current" 282 if "min_sdk_version" in config: 283 min_sdk_version = config["min_sdk_version"] 284 285 if lang == JAVA: 286 #TODO(b/285574832) re-enable Java backend 287 continue 288 java_aidl_library( 289 name = aidl_library_name + "-java", 290 deps = [":" + aidl_library_name], 291 tags = tags + config.get("tags", []), 292 # TODO(b/249276008): Pass min_sdk_version to java_aidl_library 293 **(kwargs | {"target_compatible_with": ["//build/bazel_common_rules/platforms/os:android"]}) 294 ) 295 elif lang == CPP or lang == NDK: 296 dynamic_deps = [] 297 cppflags = [] 298 299 # https://cs.android.com/android/platform/superproject/+/master:system/tools/aidl/build/aidl_interface_backends.go;l=564;drc=0517d97079d4b08f909e7f35edfa33b88fcc0d0e 300 if deps != None: 301 # For each aidl_library target label versioned_name, there's an 302 # associated cc_library_shared target with label versioned_name-<cpp|ndk> 303 dynamic_deps.extend(["{}-{}".format(dep, lang) for dep in deps]) 304 305 # https://cs.android.com/android/platform/superproject/+/master:system/tools/aidl/build/aidl_interface_backends.go;l=111;drc=ef9f1352a1a8fec7bb134b1c713e13fc3ccee651 306 if lang == CPP: 307 dynamic_deps.extend([ 308 "//frameworks/native/libs/binder:libbinder", 309 "//system/core/libutils:libutils", 310 ]) 311 elif lang == NDK: 312 dynamic_deps = dynamic_deps + select({ 313 "//build/bazel/rules/apex:android-in_apex": ["//frameworks/native/libs/binder/ndk:libbinder_ndk_stub_libs_current"], 314 "//conditions:default": ["//frameworks/native/libs/binder/ndk:libbinder_ndk"], 315 }) 316 317 # https://source.corp.google.com/android/system/tools/aidl/build/aidl_interface_backends.go;l=120;rcl=18dd931bde35b502545b7a52987e2363042c151c 318 cppflags = ["-DBINDER_STABILITY_SUPPORT"] 319 320 if "additional_dynamic_deps" in config: 321 dynamic_deps += config["additional_dynamic_deps"] 322 323 if hasattr(kwargs, "tidy_checks_as_errors"): 324 fail("tidy_checks_as_errors cannot be overriden for aidl_interface cc_libraries") 325 tidy_checks_as_errors = [ 326 "*", 327 "-clang-analyzer-deadcode.DeadStores", # b/253079031 328 "-clang-analyzer-cplusplus.NewDeleteLeaks", # b/253079031 329 "-clang-analyzer-optin.performance.Padding", # b/253079031 330 ] 331 332 cc_aidl_library( 333 name = "{}-{}".format(aidl_library_name, lang), 334 make_shared = True, 335 cppflags = cppflags, 336 deps = [":" + aidl_library_name], 337 dynamic_deps = dynamic_deps, 338 lang = lang, 339 min_sdk_version = min_sdk_version, 340 tidy = "local", 341 tidy_checks_as_errors = tidy_checks_as_errors, 342 tidy_gen_header_filter = True, 343 tags = tags + config.get("tags", []), 344 **kwargs 345 ) 346