1# Copyright (C) 2021 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("@bazel_skylib//lib:paths.bzl", "paths") 16load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo") 17load("@soong_injection//apex_toolchain:constants.bzl", "default_manifest_version") 18load("//build/bazel/platforms:platform_utils.bzl", "platforms") 19load("//build/bazel/product_config:product_variables_providing_rule.bzl", "ProductVariablesInfo") 20load("//build/bazel/rules:common.bzl", "get_dep_targets") 21load("//build/bazel/rules:metadata.bzl", "MetadataFileInfo") 22load("//build/bazel/rules:prebuilt_file.bzl", "PrebuiltFileInfo") 23load("//build/bazel/rules:sh_binary.bzl", "ShBinaryInfo") 24load("//build/bazel/rules:toolchain_utils.bzl", "verify_toolchain_exists") 25load("//build/bazel/rules/android:android_app_certificate.bzl", "AndroidAppCertificateInfo", "android_app_certificate_with_default_cert") 26load("//build/bazel/rules/apex:cc.bzl", "ApexCcInfo", "ApexCcMkInfo", "apex_cc_aspect") 27load("//build/bazel/rules/apex:sdk_versions.bzl", "maybe_override_min_sdk_version") 28load("//build/bazel/rules/apex:transition.bzl", "apex_transition", "shared_lib_transition_32", "shared_lib_transition_64") 29load("//build/bazel/rules/cc:clang_tidy.bzl", "collect_deps_clang_tidy_info") 30load("//build/bazel/rules/cc:stripped_cc_common.bzl", "CcUnstrippedInfo", "StrippedCcBinaryInfo") 31load("//build/bazel/rules/common:api.bzl", "api") 32load( 33 "//build/bazel/rules/license:license_aspect.bzl", 34 "RuleLicensedDependenciesInfo", 35 "license_aspect", 36 "license_map", 37 "license_map_notice_files", 38 "license_map_to_json", 39) 40load(":apex_available.bzl", "ApexAvailableInfo", "apex_available_aspect") 41load(":apex_deps_validation.bzl", "ApexDepsInfo", "apex_deps_validation_aspect", "validate_apex_deps") 42load(":apex_info.bzl", "ApexInfo", "ApexMkInfo") 43load(":apex_key.bzl", "ApexKeyInfo") 44load(":bundle.bzl", "apex_zip_files") 45 46def _create_file_mapping(ctx): 47 """Create a file mapping for the APEX filesystem image. 48 49 This returns a Dict[File, str] where the dictionary keys are paths in the 50 apex staging dir / filesystem image, and the values are the files and other 51 metadata that should be installed there. 52 53 It also returns other data structures, such as: 54 - requires: libs that this apex depend on from other apex or the platform 55 - provides: libs that this apex provide to other apex or the platform 56 - make_modules_to_install: make module names of libs that needs to be installed onto the platform in a bundled build (LOCAL_REQUIRED_MODULES) 57 - make_files_info: metadata about this apex's payload to be used for other packaging steps. 58 """ 59 60 # Dictionary mapping from paths in the apex to the files and associated metadata to be put there 61 file_mapping = {} 62 requires = {} 63 provides = {} 64 make_modules_to_install = {} 65 metadata_file_mapping = {} 66 67 # Generate a str -> str dictionary to define Make modules and variables for the 68 # packaging step in a mixed build. This is necessary as long as there are 69 # Make-derived actions that operate on bazel's outputs. If we move all Make 70 # packaging actions to Bazel, there's no need for this data flow. 71 make_files_info = {} 72 73 arch = platforms.get_target_arch(ctx.attr._platform_utils) 74 is_target_64_bit = platforms.get_target_bitness(ctx.attr._platform_utils) == 64 75 76 def add_file_mapping(install_dir, basename, bazel_file, klass, owner, arch = None, unstripped = None, metadata_file = None): 77 installed_path = paths.join(install_dir, basename) 78 if installed_path in file_mapping and file_mapping[installed_path] != bazel_file: 79 # TODO: we should figure this out and make it a failure 80 print("Warning: %s in this apex is already installed to %s, overwriting it with %s" % 81 (file_mapping[installed_path].path, installed_path, bazel_file.path)) 82 file_mapping[installed_path] = bazel_file 83 metadata_file_mapping[installed_path] = metadata_file 84 85 files_info = { 86 "built_file": bazel_file.path, 87 "class": klass, 88 "install_dir": install_dir, 89 "basename": basename, 90 "package": owner.package, 91 "make_module_name": owner.name, 92 "arch": arch, 93 } 94 if unstripped: 95 files_info["unstripped_built_file"] = unstripped.path 96 make_files_info[installed_path] = files_info 97 98 def _add_lib_files(directory, libs, arch): 99 for dep in libs: 100 apex_cc_info = dep[ApexCcInfo] 101 for lib in apex_cc_info.requires_native_libs.to_list(): 102 requires[lib] = True 103 for lib in apex_cc_info.provides_native_libs.to_list(): 104 provides[lib] = True 105 for lib_file in apex_cc_info.transitive_shared_libs.to_list(): 106 stripped = lib_file.stripped 107 unstripped = lib_file.unstripped 108 add_file_mapping( 109 directory, 110 stripped.basename, 111 stripped, 112 "nativeSharedLib", 113 stripped.owner, 114 arch = arch, 115 unstripped = unstripped, 116 metadata_file = lib_file.metadata_file, 117 ) 118 119 # For bundled builds. 120 apex_cc_mk_info = dep[ApexCcMkInfo] 121 for mk_module in apex_cc_mk_info.make_modules_to_install.to_list(): 122 make_modules_to_install[mk_module] = True 123 124 if is_target_64_bit: 125 _add_lib_files("lib64", ctx.attr.native_shared_libs_64, arch) 126 127 secondary_arch = platforms.get_target_secondary_arch(ctx.attr._platform_utils) 128 if secondary_arch: 129 _add_lib_files("lib", ctx.attr.native_shared_libs_32, secondary_arch) 130 else: 131 _add_lib_files("lib", ctx.attr.native_shared_libs_32, arch) 132 133 backing_libs = [] 134 for lib in file_mapping.values(): 135 if lib.basename not in backing_libs: 136 backing_libs.append(lib.basename) 137 backing_libs = sorted(backing_libs) 138 139 # Handle prebuilts 140 for dep in ctx.attr.prebuilts: 141 prebuilt_file_info = dep[PrebuiltFileInfo] 142 if prebuilt_file_info.filename: 143 filename = prebuilt_file_info.filename 144 else: 145 filename = dep.label.name 146 add_file_mapping( 147 prebuilt_file_info.dir, 148 filename, 149 prebuilt_file_info.src, 150 "etc", 151 dep.label, 152 arch = arch, 153 metadata_file = dep[MetadataFileInfo].metadata_file, 154 ) 155 156 # Handle binaries 157 for dep in ctx.attr.binaries: 158 if ShBinaryInfo in dep: 159 # sh_binary requires special handling on directory/filename construction. 160 sh_binary_info = dep[ShBinaryInfo] 161 if sh_binary_info: 162 directory = "bin" 163 if sh_binary_info.sub_dir: 164 directory = paths.join("bin", sh_binary_info.sub_dir) 165 166 filename = dep.label.name 167 if sh_binary_info.filename: 168 filename = sh_binary_info.filename 169 170 add_file_mapping( 171 directory, 172 filename, 173 dep[DefaultInfo].files_to_run.executable, 174 "shBinary", 175 dep.label, 176 arch = arch, 177 metadata_file = dep[MetadataFileInfo].metadata_file, 178 ) 179 elif ApexCcInfo in dep: 180 # cc_binary just takes the final executable from the runfiles. 181 add_file_mapping( 182 "bin", 183 dep.label.name, 184 dep[DefaultInfo].files_to_run.executable, 185 "nativeExecutable", 186 dep.label, 187 arch, 188 unstripped = dep[CcUnstrippedInfo].unstripped[0].files.to_list()[0], 189 metadata_file = dep[MetadataFileInfo].metadata_file, 190 ) 191 192 # Add transitive shared lib deps of apex binaries to the apex. 193 if is_target_64_bit: 194 _add_lib_files("lib64", [dep], arch) 195 else: 196 _add_lib_files("lib", [dep], arch) 197 198 return ( 199 file_mapping, 200 sorted(requires.keys(), key = lambda x: x.name), # sort on just the name of the target, not package 201 sorted(provides.keys(), key = lambda x: x.name), 202 backing_libs, 203 sorted(make_modules_to_install), 204 sorted(make_files_info.values(), key = lambda x: ":".join([x["package"], x["make_module_name"], x["arch"]])), 205 metadata_file_mapping, 206 ) 207 208def _add_so(label): 209 return label.name + ".so" 210 211def _add_apex_manifest_information( 212 ctx, 213 apex_toolchain, 214 requires_native_libs, 215 provides_native_libs): 216 apex_manifest_json = ctx.file.manifest 217 apex_manifest_full_json = ctx.actions.declare_file(ctx.attr.name + "_apex_manifest_full.json") 218 219 args = ctx.actions.args() 220 args.add(apex_manifest_json) 221 args.add_all(["-a", "requireNativeLibs"]) 222 args.add_all(requires_native_libs, map_each = _add_so) # e.g. turn "//foo/bar:baz" to "baz.so" 223 args.add_all(["-a", "provideNativeLibs"]) 224 args.add_all(provides_native_libs, map_each = _add_so) 225 226 manifest_version = ctx.attr._override_apex_manifest_default_version[BuildSettingInfo].value 227 if not manifest_version: 228 manifest_version = default_manifest_version 229 args.add_all(["-se", "version", "0", manifest_version]) 230 231 # TODO: support other optional flags like -v name and -a jniLibs 232 args.add_all(["-o", apex_manifest_full_json]) 233 234 ctx.actions.run( 235 inputs = [apex_manifest_json], 236 outputs = [apex_manifest_full_json], 237 executable = apex_toolchain.jsonmodify[DefaultInfo].files_to_run, 238 arguments = [args], 239 mnemonic = "ApexManifestModify", 240 ) 241 242 return apex_manifest_full_json 243 244# conv_apex_manifest - Convert the JSON APEX manifest to protobuf, which is needed by apexer. 245def _convert_apex_manifest_json_to_pb(ctx, apex_toolchain, apex_manifest_json): 246 apex_manifest_pb = ctx.actions.declare_file(ctx.attr.name + "_apex_manifest.pb") 247 248 ctx.actions.run( 249 outputs = [apex_manifest_pb], 250 inputs = [apex_manifest_json], 251 executable = apex_toolchain.conv_apex_manifest[DefaultInfo].files_to_run, 252 arguments = [ 253 "proto", 254 apex_manifest_json.path, 255 "-o", 256 apex_manifest_pb.path, 257 ], 258 mnemonic = "ConvApexManifest", 259 ) 260 261 return apex_manifest_pb 262 263def _generate_canned_fs_config(ctx, filepaths): 264 """Generate filesystem config. 265 266 This encodes the filemode, uid, and gid of each file in the APEX, 267 including apex_manifest.json and apex_manifest.pb. 268 NOTE: every file must have an entry. 269 """ 270 271 # Ensure all paths don't start with / and are normalized 272 filepaths = [paths.normalize(f).lstrip("/") for f in filepaths] 273 274 # Soong also sorts the config lines to be consistent with bazel 275 filepaths = sorted([f for f in filepaths if f]) 276 277 # First, collect a set of all the directories in the apex 278 apex_subdirs_set = {} 279 for f in filepaths: 280 d = paths.dirname(f) 281 if d != "": # The root dir is handled manually below 282 # Make sure all the parent dirs of the current subdir are in the set, too 283 dirs = d.split("/") 284 for i in range(1, len(dirs) + 1): 285 apex_subdirs_set["/".join(dirs[:i])] = True 286 287 config_lines = [] 288 config_lines.append("/ 1000 1000 0755") 289 config_lines.append("/apex_manifest.json 1000 1000 0644") 290 config_lines.append("/apex_manifest.pb 1000 1000 0644") 291 292 # Readonly if not executable. filepaths is already sorted. 293 config_lines += ["/" + f + " 1000 1000 0644" for f in filepaths if not f.startswith("bin/")] 294 295 # Mark all binaries as executable. filepaths is already sorted. 296 config_lines += ["/" + f + " 0 2000 0755" for f in filepaths if f.startswith("bin/")] 297 298 # All directories have the same permission. 299 config_lines += ["/" + d + " 0 2000 0755" for d in sorted(apex_subdirs_set.keys())] 300 301 output = ctx.actions.declare_file(ctx.attr.name + "_canned_fs_config.txt") 302 303 config_lines = "\n".join(config_lines) + "\n" 304 ctx.actions.write(output, config_lines) 305 306 if ctx.attr.canned_fs_config: 307 # Append the custom fs config content to the existing file 308 combined_output = ctx.actions.declare_file(ctx.attr.name + "_combined_canned_fs_config.txt") 309 ctx.actions.run_shell( 310 inputs = [ctx.file.canned_fs_config, output], 311 outputs = [combined_output], 312 mnemonic = "AppendCustomFsConfig", 313 command = "cat {i} {canned_fs_config} > {o}".format( 314 i = output.path, 315 o = combined_output.path, 316 canned_fs_config = ctx.file.canned_fs_config.path, 317 ), 318 ) 319 output = combined_output 320 321 return output 322 323# Append an entry for apex_manifest.pb to the file_contexts file for this APEX, 324# which is either from /system/sepolicy/apex/<apexname>-file_contexts (set in 325# the apex macro) or custom file_contexts attribute value of this APEX. This 326# ensures that the manifest file is correctly labeled as system_file. 327def _generate_file_contexts(ctx): 328 file_contexts = ctx.actions.declare_file(ctx.attr.name + "-file_contexts") 329 330 ctx.actions.run_shell( 331 inputs = [ctx.file.file_contexts], 332 outputs = [file_contexts], 333 mnemonic = "GenerateApexFileContexts", 334 command = "cat {i} > {o} && echo >> {o} && echo /apex_manifest\\\\.pb u:object_r:system_file:s0 >> {o} && echo / u:object_r:system_file:s0 >> {o}" 335 .format(i = ctx.file.file_contexts.path, o = file_contexts.path), 336 ) 337 338 return file_contexts 339 340# TODO(b/255592586): This can be reused by Java rules later. 341def _mark_manifest_as_test_only(ctx, apex_toolchain): 342 if ctx.file.android_manifest == None: 343 return None 344 345 android_manifest = ctx.file.android_manifest 346 dir_name = android_manifest.dirname 347 base_name = android_manifest.basename 348 android_manifest_fixed = ctx.actions.declare_file(paths.join(dir_name, "manifest_fixer", base_name)) 349 350 args = ctx.actions.args() 351 args.add("--test-only") 352 args.add(android_manifest) 353 args.add(android_manifest_fixed) 354 355 ctx.actions.run( 356 inputs = [android_manifest], 357 outputs = [android_manifest_fixed], 358 executable = apex_toolchain.manifest_fixer[DefaultInfo].files_to_run, 359 arguments = [args], 360 mnemonic = "MarkAndroidManifestTestOnly", 361 ) 362 363 return android_manifest_fixed 364 365# Generate <APEX>_backing.txt file which lists all libraries used by the APEX. 366def _generate_apex_backing_file(ctx, backing_libs): 367 backing_file = ctx.actions.declare_file(ctx.attr.name + "_backing.txt") 368 ctx.actions.write( 369 output = backing_file, 370 content = " ".join(backing_libs) + "\n", 371 ) 372 return backing_file 373 374# Generate installed-files.txt which lists all installed files by the APEX. 375def _generate_installed_files_list(ctx, file_mapping): 376 installed_files = ctx.actions.declare_file(ctx.attr.name + "-installed-files.txt") 377 command = [] 378 for device_path, bazel_file in file_mapping.items(): 379 command.append("echo $(stat -L -c %%s %s) ./%s" % (bazel_file.path, device_path)) 380 ctx.actions.run_shell( 381 inputs = file_mapping.values(), 382 outputs = [installed_files], 383 mnemonic = "GenerateApexInstalledFileList", 384 command = "(" + "; ".join(command) + ") | sort -nr > " + installed_files.path, 385 ) 386 return installed_files 387 388def _generate_notices(ctx, apex_toolchain): 389 licensees = license_map(ctx.attr.binaries + ctx.attr.prebuilts + ctx.attr.native_shared_libs_32 + ctx.attr.native_shared_libs_64) 390 licenses_file = ctx.actions.declare_file(ctx.attr.name + "_licenses.json") 391 ctx.actions.write(licenses_file, "[\n%s\n]\n" % ",\n".join(license_map_to_json(licensees))) 392 393 # Run HTML notice file generator. 394 notice_file = ctx.actions.declare_file(ctx.attr.name + "_notice_dir/NOTICE.html.gz") 395 notice_generator = apex_toolchain.notice_generator[DefaultInfo].files_to_run 396 397 args = ctx.actions.args() 398 args.add_all(["-o", notice_file, licenses_file]) 399 400 # TODO(asmundak): should we extend it with license info for self 401 # (the case when APEX itself has applicable_licenses attribute)? 402 inputs = license_map_notice_files(licensees) + [licenses_file] 403 ctx.actions.run( 404 mnemonic = "GenerateNoticeFile", 405 inputs = inputs, 406 outputs = [notice_file], 407 executable = notice_generator, 408 tools = [notice_generator], 409 arguments = [args], 410 ) 411 return notice_file 412 413def _use_api_fingerprint(ctx): 414 product_vars = ctx.attr._product_variables[ProductVariablesInfo] 415 if not product_vars.Unbundled_build: 416 return False 417 if product_vars.Always_use_prebuilt_sdks: 418 return False 419 if not ctx.attr._unbundled_build_target_sdk_with_api_fingerprint[BuildSettingInfo].value: 420 return False 421 return True 422 423# apexer - generate the APEX file. 424def _run_apexer(ctx, apex_toolchain): 425 # Inputs 426 apex_key_info = ctx.attr.key[ApexKeyInfo] 427 privkey = apex_key_info.private_key 428 pubkey = apex_key_info.public_key 429 android_jar = apex_toolchain.android_jar 430 431 file_mapping, requires_native_libs, provides_native_libs, backing_libs, make_modules_to_install, make_files_info, metadata_file_mapping = _create_file_mapping(ctx) 432 canned_fs_config = _generate_canned_fs_config(ctx, file_mapping.keys()) 433 file_contexts = _generate_file_contexts(ctx) 434 full_apex_manifest_json = _add_apex_manifest_information(ctx, apex_toolchain, requires_native_libs, provides_native_libs) 435 apex_manifest_pb = _convert_apex_manifest_json_to_pb(ctx, apex_toolchain, full_apex_manifest_json) 436 notices_file = _generate_notices(ctx, apex_toolchain) 437 api_fingerprint_file = None 438 439 file_mapping_file = ctx.actions.declare_file(ctx.attr.name + "_apex_file_mapping.json") 440 ctx.actions.write(file_mapping_file, json.encode({k: v.path for k, v in file_mapping.items()})) 441 442 # Outputs 443 apex_output_file = ctx.actions.declare_file(ctx.attr.name + ".apex.unsigned") 444 445 apexer_files = apex_toolchain.apexer[DefaultInfo].files_to_run 446 447 # Arguments 448 command = [ctx.executable._staging_dir_builder.path, file_mapping_file.path] 449 450 # NOTE: When used as inputs to another sandboxed action, this directory 451 # artifact's inner files will be made up of symlinks. Ensure that the 452 # aforementioned action handles symlinks correctly (e.g. following 453 # symlinks). 454 staging_dir = ctx.actions.declare_directory(ctx.attr.name + "_staging_dir") 455 456 command.append(staging_dir.path) 457 458 # start of apexer cmd 459 command.append(apexer_files.executable.path) 460 if ctx.attr._apexer_verbose[BuildSettingInfo].value: 461 command.append("--verbose") 462 463 command.append("--force") 464 command.append("--include_build_info") 465 command.extend(["--canned_fs_config", canned_fs_config.path]) 466 command.extend(["--manifest", apex_manifest_pb.path]) 467 command.extend(["--file_contexts", file_contexts.path]) 468 command.extend(["--key", privkey.path]) 469 command.extend(["--pubkey", pubkey.path]) 470 command.extend(["--payload_type", "image"]) 471 command.extend(["--payload_fs_type", "ext4"]) 472 command.extend(["--assets_dir", notices_file.dirname]) 473 474 # Override the package name, if it's expicitly specified 475 if ctx.attr.package_name: 476 command.extend(["--override_apk_package_name", ctx.attr.package_name]) 477 else: 478 override_package_name = _override_manifest_package_name(ctx) 479 if override_package_name: 480 command.extend(["--override_apk_package_name", override_package_name]) 481 482 if ctx.attr.logging_parent: 483 command.extend(["--logging_parent", ctx.attr.logging_parent]) 484 485 use_api_fingerprint = _use_api_fingerprint(ctx) 486 487 target_sdk_version = str(api.final_or_future(api.default_app_target_sdk())) 488 if use_api_fingerprint: 489 api_fingerprint_file = ctx.file._api_fingerprint_txt 490 sdk_version_suffix = ".$(cat {})".format(api_fingerprint_file.path) 491 target_sdk_version = ctx.attr._platform_sdk_codename[BuildSettingInfo].value + sdk_version_suffix 492 493 command.extend(["--target_sdk_version", target_sdk_version]) 494 495 # TODO(b/215339575): This is a super rudimentary way to convert "current" to a numerical number. 496 # Generalize this to API level handling logic in a separate Starlark utility, preferably using 497 # API level maps dumped from api_levels.go 498 min_sdk_version = ctx.attr.min_sdk_version 499 if min_sdk_version == "current": 500 min_sdk_version = "10000" 501 502 override_min_sdk_version = ctx.attr._apex_global_min_sdk_version_override[BuildSettingInfo].value 503 min_sdk_version = str(maybe_override_min_sdk_version(min_sdk_version, override_min_sdk_version)) 504 505 if min_sdk_version == "10000" and use_api_fingerprint: 506 min_sdk_version = ctx.attr._platform_sdk_codename[BuildSettingInfo].value + sdk_version_suffix 507 command.append(api_fingerprint_file.path) 508 command.extend(["--min_sdk_version", min_sdk_version]) 509 510 # apexer needs the list of directories containing all auxilliary tools invoked during 511 # the creation of an apex 512 avbtool_files = apex_toolchain.avbtool[DefaultInfo].files_to_run 513 e2fsdroid_files = apex_toolchain.e2fsdroid[DefaultInfo].files_to_run 514 mke2fs_files = apex_toolchain.mke2fs[DefaultInfo].files_to_run 515 resize2fs_files = apex_toolchain.resize2fs[DefaultInfo].files_to_run 516 sefcontext_compile_files = apex_toolchain.sefcontext_compile[DefaultInfo].files_to_run 517 staging_dir_builder_files = ctx.attr._staging_dir_builder[DefaultInfo].files_to_run 518 apexer_tool_paths = [ 519 apex_toolchain.aapt2.dirname, 520 apexer_files.executable.dirname, 521 avbtool_files.executable.dirname, 522 e2fsdroid_files.executable.dirname, 523 mke2fs_files.executable.dirname, 524 resize2fs_files.executable.dirname, 525 sefcontext_compile_files.executable.dirname, 526 ] 527 528 command.extend(["--apexer_tool_path", ":".join(apexer_tool_paths)]) 529 530 android_manifest = ctx.file.android_manifest 531 if android_manifest != None: 532 if ctx.attr.testonly: 533 android_manifest = _mark_manifest_as_test_only(ctx, apex_toolchain) 534 command.extend(["--android_manifest", android_manifest.path]) 535 elif ctx.attr.testonly: 536 command.append("--test_only") 537 538 command.append(staging_dir.path) 539 command.append(apex_output_file.path) 540 541 inputs = [ 542 ctx.executable._staging_dir_builder, 543 file_mapping_file, 544 canned_fs_config, 545 apex_manifest_pb, 546 file_contexts, 547 notices_file, 548 privkey, 549 pubkey, 550 android_jar, 551 ] + file_mapping.values() 552 if use_api_fingerprint: 553 inputs.append(api_fingerprint_file) 554 555 if android_manifest != None: 556 inputs.append(android_manifest) 557 558 tools = [ 559 apexer_files, 560 avbtool_files, 561 e2fsdroid_files, 562 mke2fs_files, 563 resize2fs_files, 564 sefcontext_compile_files, 565 apex_toolchain.aapt2, 566 staging_dir_builder_files, 567 ] 568 569 # This is run_shell instead of run because --target_sdk_version may 570 # use the API fingerprinting file contents using bash expansion, 571 # and only run_shell can support that by executing the whole command with 572 # /bin/bash -c. Regular run would quote the --target_sdk_version value with 573 # single quotes ('--target_sdk_version=ABC.$(cat version.txt)'), preventing 574 # bash expansion. 575 ctx.actions.run_shell( 576 inputs = inputs, 577 tools = tools, 578 outputs = [apex_output_file, staging_dir], 579 command = " ".join(command), 580 mnemonic = "Apexer", 581 ) 582 return struct( 583 unsigned_apex = apex_output_file, 584 requires_native_libs = requires_native_libs, 585 provides_native_libs = provides_native_libs, 586 backing_libs = _generate_apex_backing_file(ctx, backing_libs), 587 symbols_used_by_apex = _generate_symbols_used_by_apex(ctx, apex_toolchain, staging_dir), 588 java_symbols_used_by_apex = _generate_java_symbols_used_by_apex(ctx, apex_toolchain), 589 installed_files = _generate_installed_files_list(ctx, file_mapping), 590 make_modules_to_install = make_modules_to_install, 591 make_files_info = make_files_info, 592 file_mapping = file_mapping, 593 metadata_file_mapping = metadata_file_mapping, 594 ) 595 596def _run_signapk(ctx, unsigned_file, signed_file, private_key, public_key, mnemonic): 597 """Sign a file with signapk.""" 598 599 # Arguments 600 args = ctx.actions.args() 601 args.add_all(["-a", 4096]) 602 args.add_all(["--align-file-size"]) 603 args.add_all([public_key, private_key]) 604 args.add_all([unsigned_file, signed_file]) 605 606 ctx.actions.run( 607 inputs = [ 608 unsigned_file, 609 private_key, 610 public_key, 611 ctx.executable._signapk, 612 ], 613 outputs = [signed_file], 614 executable = ctx.executable._signapk, 615 arguments = [args], 616 mnemonic = mnemonic, 617 ) 618 619 return signed_file 620 621# See also getOverrideManifestPackageName 622# https://cs.android.com/android/platform/superproject/+/master:build/soong/apex/builder.go;l=1000;drc=241e738c7156d928e9a993b15993cb3297face45 623def _override_manifest_package_name(ctx): 624 apex_name = ctx.attr.name 625 overrides = ctx.attr._product_variables[ProductVariablesInfo].ManifestPackageNameOverrides 626 if not overrides: 627 return None 628 629 matches = [o for o in overrides if o.split(":")[0] == apex_name] 630 631 if not matches: 632 return None 633 634 if len(matches) > 1: 635 fail("unexpected multiple manifest package overrides for %s, %s" % (apex_name, matches)) 636 637 return matches[0].split(":")[1] 638 639# https://cs.android.com/android/platform/superproject/+/master:build/soong/android/config.go;drc=5ca657189aac546af0aafaba11bbc9c5d889eab3;l=1501 640# In Soong, we don't check whether the current apex is part of Unbundled_apps. 641# Hence, we might simplify the logic by just checking product_vars["Unbundled_build"] 642# TODO(b/271474456): Eventually we might default to unbundled mode in bazel-only mode 643# so that we don't need to check Unbundled_apps. 644def _compression_enabled(ctx): 645 product_vars = ctx.attr._product_variables[ProductVariablesInfo] 646 647 return product_vars.CompressedApex and len(product_vars.Unbundled_apps) == 0 648 649# Compress a file with apex_compression_tool. 650def _run_apex_compression_tool(ctx, apex_toolchain, input_file, output_file_name): 651 avbtool_files = apex_toolchain.avbtool[DefaultInfo].files_to_run 652 apex_compression_tool_files = apex_toolchain.apex_compression_tool[DefaultInfo].files_to_run 653 654 # Outputs 655 compressed_file = ctx.actions.declare_file(output_file_name) 656 657 # Arguments 658 args = ctx.actions.args() 659 args.add_all(["compress"]) 660 tool_dirs = [apex_toolchain.soong_zip.dirname, avbtool_files.executable.dirname] 661 args.add_all(["--apex_compression_tool", ":".join(tool_dirs)]) 662 args.add_all(["--input", input_file]) 663 args.add_all(["--output", compressed_file]) 664 665 ctx.actions.run( 666 inputs = [input_file], 667 tools = [ 668 avbtool_files, 669 apex_compression_tool_files, 670 apex_toolchain.soong_zip, 671 ], 672 outputs = [compressed_file], 673 executable = apex_compression_tool_files, 674 arguments = [args], 675 mnemonic = "BazelApexCompressing", 676 ) 677 return compressed_file 678 679# Generate <module>_using.txt, which contains a list of versioned NDK symbols 680# dynamically linked to by this APEX's contents. This is used for coverage 681# checks. 682def _generate_symbols_used_by_apex(ctx, apex_toolchain, staging_dir): 683 symbols_used_by_apex = ctx.actions.declare_file(ctx.attr.name + "_using.txt") 684 ctx.actions.run( 685 outputs = [symbols_used_by_apex], 686 inputs = [staging_dir], 687 tools = [ 688 apex_toolchain.readelf.files_to_run, 689 apex_toolchain.gen_ndk_usedby_apex.files_to_run, 690 ], 691 executable = apex_toolchain.gen_ndk_usedby_apex.files_to_run, 692 arguments = [ 693 staging_dir.path, 694 apex_toolchain.readelf.files_to_run.executable.path, 695 symbols_used_by_apex.path, 696 ], 697 progress_message = "Generating dynamic NDK symbol list used by the %s apex" % ctx.attr.name, 698 mnemonic = "ApexUsingNDKSymbolsForCoverage", 699 ) 700 return symbols_used_by_apex 701 702# Generate <module>_using.xml, which contains a list of java API metadata used 703# by this APEX's contents. This is used for coverage checks. 704# 705# TODO(b/257954111): Add JARs and APKs as inputs to this action when we start 706# building Java mainline modules. 707def _generate_java_symbols_used_by_apex(ctx, apex_toolchain): 708 java_symbols_used_by_apex = ctx.actions.declare_file(ctx.attr.name + "_using.xml") 709 ctx.actions.run( 710 outputs = [java_symbols_used_by_apex], 711 inputs = [], 712 tools = [ 713 apex_toolchain.dexdeps.files_to_run, 714 apex_toolchain.gen_java_usedby_apex.files_to_run, 715 ], 716 executable = apex_toolchain.gen_java_usedby_apex.files_to_run, 717 arguments = [ 718 apex_toolchain.dexdeps.files_to_run.executable.path, 719 java_symbols_used_by_apex.path, 720 ], 721 progress_message = "Generating Java symbol list used by the %s apex" % ctx.attr.name, 722 mnemonic = "ApexUsingJavaSymbolsForCoverage", 723 ) 724 return java_symbols_used_by_apex 725 726def _validate_apex_deps(ctx): 727 transitive_deps = depset( 728 transitive = [ 729 d[ApexDepsInfo].transitive_deps 730 for d in ( 731 ctx.attr.native_shared_libs_32 + 732 ctx.attr.native_shared_libs_64 + 733 ctx.attr.binaries + 734 ctx.attr.prebuilts 735 ) 736 ], 737 ) 738 validation_files = [] 739 if not ctx.attr._unsafe_disable_apex_allowed_deps_check[BuildSettingInfo].value: 740 validation_files.append(validate_apex_deps(ctx, transitive_deps, ctx.file.allowed_apex_deps_manifest)) 741 742 transitive_unvalidated_targets = [] 743 transitive_invalid_targets = [] 744 for _, attr_deps in get_dep_targets(ctx.attr, predicate = lambda target: ApexAvailableInfo in target).items(): 745 for dep in attr_deps: 746 transitive_unvalidated_targets.append(dep[ApexAvailableInfo].transitive_unvalidated_targets) 747 transitive_invalid_targets.append(dep[ApexAvailableInfo].transitive_invalid_targets) 748 749 invalid_targets = depset(transitive = transitive_invalid_targets).to_list() 750 if len(invalid_targets) > 0: 751 invalid_targets_msg = "\n ".join([ 752 "{label}; apex_available tags: {tags}".format(label = target.label, tags = list(apex_available_tags)) 753 for target, apex_available_tags in invalid_targets 754 ]) 755 msg = ("`{apex_name}` apex has transitive dependencies that do not include the apex in " + 756 "their apex_available tags:\n {invalid_targets_msg}").format( 757 apex_name = ctx.label, 758 invalid_targets_msg = invalid_targets_msg, 759 ) 760 fail(msg) 761 762 transitive_unvalidated_targets_output_file = ctx.actions.declare_file(ctx.attr.name + "_unvalidated_deps.txt") 763 ctx.actions.write( 764 transitive_unvalidated_targets_output_file, 765 "\n".join([ 766 str(label) + ": " + str(reason) 767 for label, reason in depset(transitive = transitive_unvalidated_targets).to_list() 768 ]), 769 ) 770 return transitive_deps, transitive_unvalidated_targets_output_file, validation_files 771 772def _verify_updatability(ctx): 773 # TODO(b/274732759): Add these checks as more APEXes are converted to Bazel. 774 # 775 # Keep this in sync with build/soong/apex/apex.go#checkUpdatable. 776 # 777 # - Cannot use platform APIs. 778 # - Cannot use external VNDK libs. 779 # - Does not set future_updatable. 780 781 if not ctx.attr.min_sdk_version: 782 fail("updatable APEXes must set min_sdk_version.") 783 784def _generate_sbom(ctx, file_mapping, metadata_file_mapping, apex_file): 785 apex_filename = paths.basename(apex_file.path) 786 sbom_metadata_csv = ctx.actions.declare_file(apex_filename + "-sbom-metadata.csv") 787 command = [] 788 metadata_files = [] 789 sbom_metadata_csv_columns = [ 790 "installed_file", 791 "module_path", 792 "soong_module_type", 793 "is_prebuilt_make_module", 794 "product_copy_files", 795 "kernel_module_copy_files", 796 "is_platform_generated", 797 "build_output_path", 798 "static_libraries", 799 "whole_static_libraries", 800 "is_static_lib", 801 ] 802 command.append("echo " + ",".join(sbom_metadata_csv_columns)) 803 command.append("echo %s,%s,,,,,,%s,,," % (apex_filename, ctx.label.package, apex_file.path)) 804 for installed_file, bazel_output_file in file_mapping.items(): 805 if metadata_file_mapping[installed_file]: 806 metadata_files.append(metadata_file_mapping[installed_file]) 807 command.append("echo %s,%s,,,,,,%s,,," % (installed_file, paths.dirname(bazel_output_file.short_path), bazel_output_file.path)) 808 ctx.actions.run_shell( 809 inputs = file_mapping.values(), 810 outputs = [sbom_metadata_csv], 811 mnemonic = "GenerateSBOMMetadata", 812 command = "(" + "; ".join(command) + ") > " + sbom_metadata_csv.path, 813 ) 814 815 sbom_file = ctx.actions.declare_file(apex_filename + ".spdx.json") 816 sbom_fragment_file = ctx.actions.declare_file(apex_filename + "-fragment.spdx") 817 inputs = [ 818 apex_file, 819 sbom_metadata_csv, 820 ctx.executable._generate_sbom, 821 ] 822 inputs += file_mapping.values() 823 inputs += metadata_files 824 825 product_vars = ctx.attr._product_variables[ProductVariablesInfo] 826 build_fingerprint = "%s/%s/%s:%s/%s/%s:%s/%s" % ( 827 product_vars.ProductBrand, 828 product_vars.DeviceProduct, 829 product_vars.DeviceName, 830 product_vars.Platform_version_name, 831 product_vars.BuildId, 832 "", 833 product_vars.TargetBuildVariant, 834 "_".join(product_vars.BuildVersionTags), 835 ) 836 ctx.actions.run( 837 inputs = inputs, 838 outputs = [sbom_file, sbom_fragment_file], 839 arguments = [ 840 "--output_file", 841 sbom_file.path, 842 "--metadata", 843 sbom_metadata_csv.path, 844 "--build_version", 845 build_fingerprint, 846 "--product_mfr", 847 product_vars.ProductManufacturer, 848 "--json", 849 "--unbundled_apex", 850 ], 851 mnemonic = "GenerateSBOM", 852 executable = ctx.executable._generate_sbom, 853 ) 854 return [sbom_file, sbom_fragment_file] 855 856# See the APEX section in the README on how to use this rule. 857def _apex_rule_impl(ctx): 858 verify_toolchain_exists(ctx, "//build/bazel/rules/apex:apex_toolchain_type") 859 if ctx.attr.updatable: 860 _verify_updatability(ctx) 861 862 apex_toolchain = ctx.toolchains["//build/bazel/rules/apex:apex_toolchain_type"].toolchain_info 863 864 apexer_outputs = _run_apexer(ctx, apex_toolchain) 865 unsigned_apex = apexer_outputs.unsigned_apex 866 867 apex_cert_info = ctx.attr.certificate[0][AndroidAppCertificateInfo] 868 private_key = apex_cert_info.pk8 869 public_key = apex_cert_info.pem 870 871 signed_apex = ctx.actions.declare_file(ctx.attr.name + ".apex") 872 signed_capex = None 873 874 _run_signapk(ctx, unsigned_apex, signed_apex, private_key, public_key, "BazelApexSigning") 875 876 if ctx.attr.compressible and _compression_enabled(ctx): 877 compressed_apex_output_file = _run_apex_compression_tool(ctx, apex_toolchain, signed_apex, ctx.attr.name + ".capex.unsigned") 878 signed_capex = ctx.actions.declare_file(ctx.attr.name + ".capex") 879 _run_signapk(ctx, compressed_apex_output_file, signed_capex, private_key, public_key, "BazelCompressedApexSigning") 880 881 apex_key_info = ctx.attr.key[ApexKeyInfo] 882 883 arch = platforms.get_target_arch(ctx.attr._platform_utils) 884 zip_files = apex_zip_files( 885 actions = ctx.actions, 886 name = ctx.label.name, 887 tools = struct( 888 aapt2 = apex_toolchain.aapt2, 889 zip2zip = ctx.executable._zip2zip, 890 merge_zips = ctx.executable._merge_zips, 891 soong_zip = apex_toolchain.soong_zip, 892 ), 893 apex_file = signed_apex, 894 arch = arch, 895 secondary_arch = platforms.get_target_secondary_arch(ctx.attr._platform_utils), 896 ) 897 898 transitive_apex_deps, transitive_unvalidated_targets_output_file, apex_deps_validation_files = _validate_apex_deps(ctx) 899 900 optional_output_groups = {} 901 if signed_capex: 902 optional_output_groups["signed_compressed_output"] = [signed_capex] 903 904 return [ 905 DefaultInfo(files = depset([signed_apex])), 906 ApexInfo( 907 signed_output = signed_apex, 908 signed_compressed_output = signed_capex, 909 unsigned_output = unsigned_apex, 910 requires_native_libs = apexer_outputs.requires_native_libs, 911 provides_native_libs = apexer_outputs.provides_native_libs, 912 bundle_key_info = apex_key_info, 913 container_key_info = apex_cert_info, 914 package_name = ctx.attr.package_name, 915 backing_libs = apexer_outputs.backing_libs, 916 symbols_used_by_apex = apexer_outputs.symbols_used_by_apex, 917 installed_files = apexer_outputs.installed_files, 918 java_symbols_used_by_apex = apexer_outputs.java_symbols_used_by_apex, 919 base_file = zip_files.apex_only, 920 base_with_config_zip = zip_files.apex_with_config, 921 ), 922 OutputGroupInfo( 923 coverage_files = [apexer_outputs.symbols_used_by_apex], 924 java_coverage_files = [apexer_outputs.java_symbols_used_by_apex], 925 backing_libs = depset([apexer_outputs.backing_libs]), 926 installed_files = depset([apexer_outputs.installed_files]), 927 transitive_unvalidated_targets = depset([transitive_unvalidated_targets_output_file]), 928 apex_sbom = depset(_generate_sbom(ctx, apexer_outputs.file_mapping, apexer_outputs.metadata_file_mapping, signed_apex)), 929 capex_sbom = depset(_generate_sbom(ctx, apexer_outputs.file_mapping, apexer_outputs.metadata_file_mapping, signed_capex) if signed_capex else []), 930 _validation = apex_deps_validation_files, 931 **optional_output_groups 932 ), 933 ApexDepsInfo(transitive_deps = transitive_apex_deps), 934 ApexMkInfo( 935 make_modules_to_install = apexer_outputs.make_modules_to_install, 936 files_info = apexer_outputs.make_files_info, 937 ), 938 collect_deps_clang_tidy_info(ctx), 939 ] 940 941# These are the standard aspects that should be applied on all edges that 942# contribute to an APEX's payload. 943STANDARD_PAYLOAD_ASPECTS = [ 944 license_aspect, 945 apex_available_aspect, 946 apex_deps_validation_aspect, 947] 948 949_apex = rule( 950 implementation = _apex_rule_impl, 951 attrs = { 952 # Attributes that configure the APEX container. 953 "manifest": attr.label(allow_single_file = [".json"]), 954 "android_manifest": attr.label(allow_single_file = [".xml"]), 955 "package_name": attr.string(), 956 "logging_parent": attr.string(), 957 "file_contexts": attr.label(allow_single_file = True, mandatory = True), 958 "canned_fs_config": attr.label( 959 allow_single_file = True, 960 doc = """Path to the canned fs config file for customizing file's 961uid/gid/mod/capabilities. The content of this file is appended to the 962default config, so that the custom entries are preferred. 963 964The format is /<path_or_glob> <uid> <gid> <mode> [capabilities=0x<cap>], where 965path_or_glob is a path or glob pattern for a file or set of files, uid/gid 966are numerial values of user ID and group ID, mode is octal value for the 967file mode, and cap is hexadecimal value for the capability.""", 968 ), 969 "key": attr.label(providers = [ApexKeyInfo], mandatory = True), 970 "certificate": attr.label( 971 providers = [AndroidAppCertificateInfo], 972 mandatory = True, 973 cfg = apex_transition, 974 ), 975 "min_sdk_version": attr.string( 976 default = "current", 977 doc = """The minimum SDK version that this APEX must support at minimum. This is usually set to 978the SDK version that the APEX was first introduced. 979 980When not set, defaults to "10000" (or "current").""", 981 ), 982 "updatable": attr.bool(default = True, doc = """Whether this APEX is considered updatable or not. 983 984When set to true, this will enforce additional rules for making sure that the 985APEX is truly updatable. To be updatable, min_sdk_version should be set as well."""), 986 "installable": attr.bool(default = True), 987 "compressible": attr.bool(default = False), 988 "base_apex_name": attr.string( 989 default = "", 990 doc = "The name of the base apex of this apex. For example, the AOSP variant of this apex.", 991 ), 992 993 # Attributes that contribute to the payload. 994 "native_shared_libs_32": attr.label_list( 995 providers = [ApexCcInfo, ApexCcMkInfo, RuleLicensedDependenciesInfo], 996 aspects = STANDARD_PAYLOAD_ASPECTS + [apex_cc_aspect], 997 cfg = shared_lib_transition_32, 998 doc = "The libs compiled for 32-bit", 999 ), 1000 "native_shared_libs_64": attr.label_list( 1001 providers = [ApexCcInfo, ApexCcMkInfo, RuleLicensedDependenciesInfo], 1002 aspects = STANDARD_PAYLOAD_ASPECTS + [apex_cc_aspect], 1003 cfg = shared_lib_transition_64, 1004 doc = "The libs compiled for 64-bit", 1005 ), 1006 "binaries": attr.label_list( 1007 providers = [ 1008 # The dependency must produce _all_ of the providers in _one_ of these lists. 1009 [ShBinaryInfo, RuleLicensedDependenciesInfo], # sh_binary 1010 [StrippedCcBinaryInfo, CcInfo, ApexCcInfo, ApexCcMkInfo, RuleLicensedDependenciesInfo], # cc_binary (stripped) 1011 ], 1012 cfg = apex_transition, 1013 aspects = STANDARD_PAYLOAD_ASPECTS + [apex_cc_aspect], 1014 ), 1015 "prebuilts": attr.label_list( 1016 providers = [PrebuiltFileInfo, RuleLicensedDependenciesInfo], 1017 cfg = apex_transition, 1018 aspects = STANDARD_PAYLOAD_ASPECTS, 1019 ), 1020 1021 # Required to use apex_transition. This is an acknowledgement to the risks of memory bloat when using transitions. 1022 "_allowlist_function_transition": attr.label(default = "@bazel_tools//tools/allowlists/function_transition_allowlist"), 1023 1024 # Tools that are not part of the apex_toolchain. 1025 "_staging_dir_builder": attr.label( 1026 cfg = "exec", 1027 doc = "The staging dir builder to avoid the problem where symlinks are created inside apex image.", 1028 executable = True, 1029 default = "//build/bazel/rules:staging_dir_builder", 1030 ), 1031 "_signapk": attr.label( 1032 cfg = "exec", 1033 doc = "The signapk tool.", 1034 executable = True, 1035 default = "//build/make/tools/signapk", 1036 ), 1037 "_zip2zip": attr.label( 1038 cfg = "exec", 1039 allow_single_file = True, 1040 doc = "The tool zip2zip. Used to convert apex file to the expected directory structure.", 1041 default = "//build/soong/cmd/zip2zip:zip2zip", 1042 executable = True, 1043 ), 1044 "_merge_zips": attr.label( 1045 cfg = "exec", 1046 allow_single_file = True, 1047 doc = "The tool merge_zips. Used to combine base zip and config file into a single zip for mixed build aab creation.", 1048 default = "//prebuilts/build-tools:linux-x86/bin/merge_zips", 1049 executable = True, 1050 ), 1051 "_platform_utils": attr.label( 1052 default = Label("//build/bazel/platforms:platform_utils"), 1053 ), 1054 "_generate_sbom": attr.label( 1055 cfg = "exec", 1056 doc = "SBOM generation tool", 1057 executable = True, 1058 default = "//build/make/tools/sbom:generate-sbom", 1059 ), 1060 1061 # allowed deps check 1062 "_unsafe_disable_apex_allowed_deps_check": attr.label( 1063 default = "//build/bazel/rules/apex:unsafe_disable_apex_allowed_deps_check", 1064 ), 1065 "allowed_apex_deps_manifest": attr.label( 1066 allow_single_file = True, 1067 default = "//packages/modules/common/build:allowed_deps.txt", 1068 ), 1069 1070 # Build settings. 1071 "_apexer_verbose": attr.label( 1072 default = "//build/bazel/rules/apex:apexer_verbose", 1073 doc = "If enabled, make apexer log verbosely.", 1074 ), 1075 "_override_apex_manifest_default_version": attr.label( 1076 default = "//build/bazel/rules/apex:override_apex_manifest_default_version", 1077 doc = "If specified, override 'version: 0' in apex_manifest.json with this value instead of the branch default. Non-zero versions will not be changed.", 1078 ), 1079 "_apex_global_min_sdk_version_override": attr.label( 1080 default = "//build/bazel/rules/apex:apex_global_min_sdk_version_override", 1081 doc = "If specified, override the min_sdk_version of this apex and in the transition and checks for dependencies.", 1082 ), 1083 "_product_variables": attr.label( 1084 default = "//build/bazel/product_config:product_vars", 1085 ), 1086 1087 # Api_fingerprint 1088 "_unbundled_build_target_sdk_with_api_fingerprint": attr.label( 1089 default = "//build/bazel/rules/apex:unbundled_build_target_sdk_with_api_fingerprint", 1090 ), 1091 "_platform_sdk_codename": attr.label( 1092 default = "//build/bazel/rules/apex:platform_sdk_codename", 1093 ), 1094 "_api_fingerprint_txt": attr.label( 1095 default = "//frameworks/base/api:api_fingerprint", 1096 allow_single_file = True, 1097 ), 1098 }, 1099 # The apex toolchain is not mandatory so that we don't get toolchain resolution errors even 1100 # when the apex is not compatible with the current target (via target_compatible_with). 1101 toolchains = [config_common.toolchain_type("//build/bazel/rules/apex:apex_toolchain_type", mandatory = False)], 1102 fragments = ["platform"], 1103) 1104 1105def apex( 1106 name, 1107 manifest = "apex_manifest.json", 1108 android_manifest = None, 1109 file_contexts = None, 1110 key = None, 1111 certificate = None, 1112 certificate_name = None, 1113 min_sdk_version = None, 1114 updatable = True, 1115 installable = True, 1116 compressible = False, 1117 native_shared_libs_32 = [], 1118 native_shared_libs_64 = [], 1119 binaries = [], 1120 prebuilts = [], 1121 package_name = None, 1122 logging_parent = None, 1123 canned_fs_config = None, 1124 testonly = False, 1125 # TODO(b/255400736): tests are not fully supported yet. 1126 tests = [], 1127 target_compatible_with = [], 1128 **kwargs): 1129 "Bazel macro to correspond with the APEX bundle Soong module." 1130 1131 # If file_contexts is not specified, then use the default from //system/sepolicy/apex. 1132 # https://cs.android.com/android/platform/superproject/+/master:build/soong/apex/builder.go;l=259-263;drc=b02043b84d86fe1007afef1ff012a2155172215c 1133 if file_contexts == None: 1134 file_contexts = "//system/sepolicy/apex:" + name + "-file_contexts" 1135 1136 if testonly: 1137 compressible = False 1138 elif tests: 1139 fail("Apex with tests attribute needs to be testonly.") 1140 1141 if certificate and certificate_name: 1142 fail("Cannot use both certificate_name and certificate attributes together. Use only one of them.") 1143 app_cert_name = name + "_app_certificate" 1144 if certificate_name: 1145 # use the name key in the default cert dir 1146 android_app_certificate_with_default_cert( 1147 name = app_cert_name, 1148 cert_name = certificate_name, 1149 ) 1150 certificate_label = ":" + app_cert_name 1151 elif certificate: 1152 certificate_label = certificate 1153 else: 1154 # use the default testkey 1155 android_app_certificate_with_default_cert(name = app_cert_name) 1156 certificate_label = ":" + app_cert_name 1157 1158 target_compatible_with = select({ 1159 "//build/bazel/platforms/os:android": [], 1160 "//conditions:default": ["@platforms//:incompatible"], 1161 }) + target_compatible_with 1162 1163 _apex( 1164 name = name, 1165 manifest = manifest, 1166 android_manifest = android_manifest, 1167 file_contexts = file_contexts, 1168 key = key, 1169 certificate = certificate_label, 1170 min_sdk_version = min_sdk_version, 1171 updatable = updatable, 1172 installable = installable, 1173 compressible = compressible, 1174 native_shared_libs_32 = native_shared_libs_32, 1175 native_shared_libs_64 = native_shared_libs_64, 1176 binaries = binaries, 1177 prebuilts = prebuilts, 1178 package_name = package_name, 1179 logging_parent = logging_parent, 1180 canned_fs_config = canned_fs_config, 1181 testonly = testonly, 1182 target_compatible_with = target_compatible_with, 1183 **kwargs 1184 ) 1185