1# Copyright The ANGLE Project Authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4# 5# Generates an Android.bp file from the json output of 4 'gn desc' commands. 6# Invoked during Skia rolls by roll_aosp.sh. For local testing, see: 7# scripts/roll_aosp.sh --genAndroidBp 8 9import json 10import sys 11import re 12import os 13import argparse 14import functools 15import collections 16 17ROOT_TARGETS = [ 18 "//:libGLESv2", 19 "//:libGLESv1_CM", 20 "//:libEGL", 21] 22 23MIN_SDK_VERSION = '28' 24TARGET_SDK_VERSION = '33' 25STL = 'libc++_static' 26 27ABI_ARM = 'arm' 28ABI_ARM64 = 'arm64' 29ABI_X86 = 'x86' 30ABI_X64 = 'x86_64' 31 32ABI_TARGETS = [ABI_ARM, ABI_ARM64, ABI_X86, ABI_X64] 33 34 35def gn_abi(abi): 36 # gn uses x64, rather than x86_64 37 return 'x64' if abi == ABI_X64 else abi 38 39 40# Makes dict cache-able "by reference" (assumed not to be mutated) 41class BuildInfo(dict): 42 43 def __hash__(self): 44 return 0 45 46 def __eq__(self, other): 47 return self is other 48 49 50def tabs(indent): 51 return ' ' * (indent * 4) 52 53 54def has_child_values(value): 55 # Elements of the blueprint can be pruned if they are empty lists or dictionaries of empty 56 # lists 57 if isinstance(value, list): 58 return len(value) > 0 59 if isinstance(value, dict): 60 for (item, item_value) in value.items(): 61 if has_child_values(item_value): 62 return True 63 return False 64 65 # This is a value leaf node 66 return True 67 68 69def write_blueprint_key_value(output, name, value, indent=1): 70 if not has_child_values(value): 71 return 72 73 if isinstance(value, set) or isinstance(value, list): 74 value = list(sorted(set(value))) 75 76 if isinstance(value, list): 77 output.append(tabs(indent) + '%s: [' % name) 78 for item in value: 79 output.append(tabs(indent + 1) + '"%s",' % item) 80 output.append(tabs(indent) + '],') 81 return 82 if isinstance(value, dict): 83 if not value: 84 return 85 output.append(tabs(indent) + '%s: {' % name) 86 for (item, item_value) in value.items(): 87 write_blueprint_key_value(output, item, item_value, indent + 1) 88 output.append(tabs(indent) + '},') 89 return 90 if isinstance(value, bool): 91 output.append(tabs(indent) + '%s: %s,' % (name, 'true' if value else 'false')) 92 return 93 output.append(tabs(indent) + '%s: "%s",' % (name, value)) 94 95 96def write_blueprint(output, target_type, values): 97 if target_type == 'license': 98 comment = """ 99// Added automatically by a large-scale-change that took the approach of 100// 'apply every license found to every target'. While this makes sure we respect 101// every license restriction, it may not be entirely correct. 102// 103// e.g. GPL in an MIT project might only apply to the contrib/ directory. 104// 105// Please consider splitting the single license below into multiple licenses, 106// taking care not to lose any license_kind information, and overriding the 107// default license using the 'licenses: [...]' property on targets as needed. 108// 109// For unused files, consider creating a 'fileGroup' with "//visibility:private" 110// to attach the license to, and including a comment whether the files may be 111// used in the current project. 112// See: http://go/android-license-faq""" 113 output.append(comment) 114 115 output.append('%s {' % target_type) 116 for (key, value) in values.items(): 117 write_blueprint_key_value(output, key, value) 118 output.append('}') 119 120 121def gn_target_to_blueprint_target(target, target_info): 122 if 'output_name' in target_info: 123 return target_info['output_name'] 124 125 # Split the gn target name (in the form of //gn_file_path:target_name) into gn_file_path and 126 # target_name 127 match = re.match(r"^//([a-zA-Z0-9\-\+_/]*):([a-zA-Z0-9\-\+_.]+)$", target) 128 assert match is not None 129 130 gn_file_path = match.group(1) 131 target_name = match.group(2) 132 assert len(target_name) > 0 133 134 # Clean up the gn file path to be a valid blueprint target name. 135 gn_file_path = gn_file_path.replace("/", "_").replace(".", "_").replace("-", "_") 136 137 # Generate a blueprint target name by merging the gn path and target so each target is unique. 138 # Prepend the 'angle' prefix to all targets in the root path (empty gn_file_path). 139 # Skip this step if the target name already starts with 'angle' to avoid target names such as 'angle_angle_common'. 140 root_prefix = "angle" 141 if len(gn_file_path) == 0 and not target_name.startswith(root_prefix): 142 gn_file_path = root_prefix 143 144 # Avoid names such as _angle_common if the gn_file_path is empty. 145 if len(gn_file_path) > 0: 146 gn_file_path += "_" 147 148 return gn_file_path + target_name 149 150 151def remap_gn_path(path): 152 # TODO: pass the gn gen folder as an arg so it is future proof. b/150457277 153 remap_folders = [ 154 ('out/Android/gen/angle/', ''), 155 ('out/Android/gen/', ''), 156 ] 157 158 remapped_path = path 159 for (remap_source, remap_dest) in remap_folders: 160 remapped_path = remapped_path.replace(remap_source, remap_dest) 161 162 return remapped_path 163 164 165def gn_path_to_blueprint_path(source): 166 # gn uses '//' to indicate the root directory, blueprint uses the .bp file's location 167 return remap_gn_path(re.sub(r'^//?', '', source)) 168 169 170def gn_paths_to_blueprint_paths(paths): 171 rebased_paths = [] 172 for path in paths: 173 rebased_paths.append(gn_path_to_blueprint_path(path)) 174 return rebased_paths 175 176 177def gn_sources_to_blueprint_sources(sources): 178 # Blueprints only list source files in the sources list. Headers are only referenced though 179 # include paths. 180 file_extension_allowlist = [ 181 '.c', 182 '.cc', 183 '.cpp', 184 ] 185 186 rebased_sources = [] 187 for source in sources: 188 if os.path.splitext(source)[1] in file_extension_allowlist: 189 rebased_sources.append(gn_path_to_blueprint_path(source)) 190 return rebased_sources 191 192 193target_blockist = [ 194 '//build/config:shared_library_deps', 195 '//third_party/vulkan-validation-layers/src:vulkan_clean_old_validation_layer_objects', 196 '//third_party/zlib:zlib', 197 '//third_party/zlib/google:compression_utils_portable', 198] 199 200third_party_target_allowlist = [ 201 '//third_party/abseil-cpp', 202 '//third_party/vulkan-deps', 203 '//third_party/vulkan_memory_allocator', 204] 205 206include_blocklist = [ 207 '//buildtools/third_party/libc++/', 208 '//third_party/libc++/src/', 209 '//out/Android/gen/third_party/vulkan-deps/glslang/src/include/', 210 '//third_party/zlib/', 211 '//third_party/zlib/google/', 212] 213 214 215@functools.lru_cache(maxsize=None) # .cache() is py3.9 http://b/246559064#comment8 216def gn_deps_to_blueprint_deps(abi, target, build_info): 217 target_info = build_info[abi][target] 218 static_libs = [] 219 shared_libs = [] 220 defaults = [] 221 generated_headers = [] 222 header_libs = [] 223 if 'deps' not in target_info: 224 return static_libs, defaults 225 226 for dep in target_info['deps']: 227 if dep not in target_blockist and (not dep.startswith('//third_party') or any( 228 dep.startswith(substring) for substring in third_party_target_allowlist)): 229 dep_info = build_info[abi][dep] 230 blueprint_dep_name = gn_target_to_blueprint_target(dep, dep_info) 231 232 # Depending on the dep type, blueprints reference it differently. 233 gn_dep_type = dep_info['type'] 234 if gn_dep_type == 'static_library': 235 static_libs.append(blueprint_dep_name) 236 elif gn_dep_type == 'shared_library': 237 shared_libs.append(blueprint_dep_name) 238 elif gn_dep_type == 'source_set' or gn_dep_type == 'group': 239 defaults.append(blueprint_dep_name) 240 elif gn_dep_type == 'action': 241 generated_headers.append(blueprint_dep_name) 242 243 # Blueprints do not chain linking of static libraries. 244 (child_static_libs, _, _, child_generated_headers, 245 _) = gn_deps_to_blueprint_deps(abi, dep, build_info) 246 247 # Each target needs to link all child static library dependencies. 248 static_libs += child_static_libs 249 250 # Each blueprint target runs genrules in a different output directory unlike GN. If a 251 # target depends on another's genrule, it wont find the outputs. Propogate generated 252 # headers up the dependency stack. 253 generated_headers += child_generated_headers 254 elif dep == '//third_party/zlib/google:compression_utils_portable': 255 # Replace zlib by Android's zlib, compression_utils_portable is the root dependency 256 static_libs.extend( 257 ['zlib_google_compression_utils_portable', 'libz_static', 'cpufeatures']) 258 259 return static_libs, shared_libs, defaults, generated_headers, header_libs 260 261 262def gn_libs_to_blueprint_shared_libraries(target_info): 263 lib_blockist = [ 264 'android_support', 265 'unwind', 266 ] 267 268 result = [] 269 if 'libs' in target_info: 270 for lib in target_info['libs']: 271 if lib not in lib_blockist: 272 android_lib = lib if '@' in lib else 'lib' + lib 273 result.append(android_lib) 274 return result 275 276 277def gn_include_dirs_to_blueprint_include_dirs(target_info): 278 result = [] 279 if 'include_dirs' in target_info: 280 for include_dir in target_info['include_dirs']: 281 if len(include_dir) > 0 and include_dir not in include_blocklist: 282 result.append(gn_path_to_blueprint_path(include_dir)) 283 return result 284 285 286def escape_quotes(string): 287 return string.replace("\"", "\\\"").replace("\'", "\\\'") 288 289 290def gn_cflags_to_blueprint_cflags(target_info): 291 result = [] 292 293 # regexs of allowlisted cflags 294 cflag_allowlist = [ 295 r'^-Wno-.*$', # forward cflags that disable warnings 296 r'-mpclmul' # forward "-mpclmul" (used by zlib) 297 ] 298 299 for cflag_type in ['cflags', 'cflags_c', 'cflags_cc']: 300 if cflag_type in target_info: 301 for cflag in target_info[cflag_type]: 302 for allowlisted_cflag in cflag_allowlist: 303 if re.search(allowlisted_cflag, cflag): 304 result.append(cflag) 305 306 if 'defines' in target_info: 307 for define in target_info['defines']: 308 # Don't emit ANGLE's CPU-bits define here, it will be part of the arch-specific 309 # information later 310 result.append('-D%s' % escape_quotes(define)) 311 312 return result 313 314 315blueprint_library_target_types = { 316 "static_library": "cc_library_static", 317 "shared_library": "cc_library_shared", 318 "source_set": "cc_defaults", 319 "group": "cc_defaults", 320} 321 322 323def merge_bps(bps_for_abis): 324 common_bp = {} 325 for abi in ABI_TARGETS: 326 for key, values in bps_for_abis[abi].items(): 327 if not isinstance(values, list): 328 # Assume everything that's not a list is common to all ABIs 329 common_bp[key] = values 330 continue 331 332 # Find list values that are common to all ABIs 333 values_in_all_abis = set.intersection( 334 *[set(bps_for_abis[abi2].get(key, [])) for abi2 in ABI_TARGETS]) 335 336 for value in values: 337 if value in values_in_all_abis or key == 'defaults': # arch-specific defaults are not supported 338 common_bp.setdefault(key, []) 339 common_bp[key].append(value) 340 else: 341 common_bp.setdefault('arch', {abi3: {} for abi3 in ABI_TARGETS}) 342 abi_specific = common_bp['arch'][abi] 343 abi_specific.setdefault(key, []) 344 abi_specific[key].append(value) 345 346 return common_bp 347 348 349def library_target_to_blueprint(target, build_info): 350 bps_for_abis = {} 351 blueprint_type = "" 352 for abi in ABI_TARGETS: 353 if target not in build_info[abi].keys(): 354 bps_for_abis[abi] = {} 355 continue 356 357 target_info = build_info[abi][target] 358 359 blueprint_type = blueprint_library_target_types[target_info['type']] 360 361 bp = {'name': gn_target_to_blueprint_target(target, target_info)} 362 363 if 'sources' in target_info: 364 bp['srcs'] = gn_sources_to_blueprint_sources(target_info['sources']) 365 366 (bp['static_libs'], bp['shared_libs'], bp['defaults'], bp['generated_headers'], 367 bp['header_libs']) = gn_deps_to_blueprint_deps(abi, target, build_info) 368 bp['shared_libs'] += gn_libs_to_blueprint_shared_libraries(target_info) 369 370 bp['local_include_dirs'] = gn_include_dirs_to_blueprint_include_dirs(target_info) 371 372 bp['cflags'] = gn_cflags_to_blueprint_cflags(target_info) 373 374 bp['defaults'].append('angle_common_library_cflags') 375 376 bp['sdk_version'] = MIN_SDK_VERSION 377 bp['stl'] = STL 378 if target in ROOT_TARGETS: 379 bp['vendor'] = True 380 bp['target'] = {'android': {'relative_install_path': 'egl'}} 381 bps_for_abis[abi] = bp 382 383 common_bp = merge_bps(bps_for_abis) 384 385 return blueprint_type, common_bp 386 387 388def gn_action_args_to_blueprint_args(blueprint_inputs, blueprint_outputs, args): 389 # TODO: pass the gn gen folder as an arg so we know how to get from the gen path to the root 390 # path. b/150457277 391 remap_folders = [ 392 # Specific special-cases first, since the other will strip the prefixes. 393 ('gen/third_party/vulkan-deps/glslang/src/include/glslang/build_info.h', 394 'glslang/build_info.h'), 395 ('third_party/vulkan-deps/glslang/src', 396 'external/angle/third_party/vulkan-deps/glslang/src'), 397 ('../../', ''), 398 ('gen/', ''), 399 ] 400 401 result_args = [] 402 for arg in args: 403 # Attempt to find if this arg is a path to one of the inputs. If it is, use the blueprint 404 # $(location <path>) argument instead so the path gets remapped properly to the location 405 # that the script is run from 406 remapped_path_arg = arg 407 for (remap_source, remap_dest) in remap_folders: 408 remapped_path_arg = remapped_path_arg.replace(remap_source, remap_dest) 409 410 if remapped_path_arg in blueprint_inputs or remapped_path_arg in blueprint_outputs: 411 result_args.append('$(location %s)' % remapped_path_arg) 412 elif os.path.basename(remapped_path_arg) in blueprint_outputs: 413 result_args.append('$(location %s)' % os.path.basename(remapped_path_arg)) 414 else: 415 result_args.append(remapped_path_arg) 416 417 return result_args 418 419 420blueprint_gen_types = { 421 "action": "cc_genrule", 422} 423 424 425inputs_blocklist = [ 426 '//.git/HEAD', 427] 428 429outputs_remap = { 430 'build_info.h': 'glslang/build_info.h', 431} 432 433 434def is_input_in_tool_files(tool_files, input): 435 return input in tool_files 436 437 438# special handling the {{response_file_name}} args in GN: 439# see https://gn.googlesource.com/gn/+/main/docs/reference.md#var_response_file_contents 440# in GN, if we use response_file_contents, the GN build system will automatically 441# write contents specified in response_file_contents arg into a temporary file 442# identified by {{response_file_name}}. However, Android blueprint does not have 443# the matching machanism. Android blueprint does automatically generate the 444# temporary file and does not recognize '{{response_file_name}}'. 445# To solve the problem: 446# 1) replace the '{{response_file_name}}' in command argument with the new 447# temporary file name. 448# 2) write the content specified in 'response_file_contents' to the new temporary 449# file 450# This function completes step 1) above. It checks if there are 451# '{{response_file_name}}' used in the command arguments. If there are, 452# the function replaces the '{{response_file_name}}' with the new temp file 453# named 'gn_response_file', and returns the new temp file to indicate 454# we need to complete step 2) 455def handle_gn_build_arg_response_file_name(command_arg_list): 456 new_temp_file_name = None 457 updated_args = command_arg_list[:] 458 for index, arg in enumerate(updated_args): 459 if arg == '{{response_file_name}}': 460 new_temp_file_name = '$(genDir)/gn_response_file' 461 updated_args[index] = new_temp_file_name 462 return new_temp_file_name, updated_args 463 464 465def action_target_to_blueprint(abi, target, build_info): 466 target_info = build_info[abi][target] 467 blueprint_type = blueprint_gen_types[target_info['type']] 468 469 bp = {'name': gn_target_to_blueprint_target(target, target_info)} 470 471 # Blueprints use only one 'srcs', merge all gn inputs into one list. 472 gn_inputs = [] 473 if 'inputs' in target_info: 474 for input in target_info['inputs']: 475 if input not in inputs_blocklist: 476 gn_inputs.append(input) 477 if 'sources' in target_info: 478 gn_inputs += target_info['sources'] 479 # Filter out the 'script' entry since Android.bp doesn't like the duplicate entries 480 if 'script' in target_info: 481 gn_inputs = [ 482 input for input in gn_inputs 483 if not is_input_in_tool_files(target_info['script'], input) 484 ] 485 486 bp_srcs = gn_paths_to_blueprint_paths(gn_inputs) 487 488 bp['srcs'] = bp_srcs 489 490 # genrules generate the output right into the 'root' directory. Strip any path before the 491 # file name. 492 bp_outputs = [] 493 for gn_output in target_info['outputs']: 494 output = os.path.basename(gn_output) 495 if output in outputs_remap.keys(): 496 output = outputs_remap[output] 497 bp_outputs.append(output) 498 499 bp['out'] = bp_outputs 500 501 bp['tool_files'] = [gn_path_to_blueprint_path(target_info['script'])] 502 503 new_temporary_gn_response_file, updated_args = handle_gn_build_arg_response_file_name( 504 target_info['args']) 505 506 if new_temporary_gn_response_file: 507 # add the command 'echo $(in) > $(genDir)/gn_response_file' to 508 # write $response_file_contents into the new_temporary_gn_response_file. 509 cmd = ['echo $(in) >', new_temporary_gn_response_file, '&&', '$(location)' 510 ] + gn_action_args_to_blueprint_args(bp_srcs, bp_outputs, updated_args) 511 else: 512 cmd = ['$(location)'] + gn_action_args_to_blueprint_args(bp_srcs, bp_outputs, 513 target_info['args']) 514 515 bp['cmd'] = ' '.join(cmd) 516 517 bp['sdk_version'] = MIN_SDK_VERSION 518 519 return blueprint_type, bp 520 521 522def gn_target_to_blueprint(target, build_info): 523 for abi in ABI_TARGETS: 524 gn_type = build_info[abi][target]['type'] 525 if gn_type in blueprint_library_target_types: 526 return library_target_to_blueprint(target, build_info) 527 elif gn_type in blueprint_gen_types: 528 return action_target_to_blueprint(abi, target, build_info) 529 else: 530 # Target is not used by this ABI 531 continue 532 533 534@functools.lru_cache(maxsize=None) 535def get_gn_target_dependencies(abi, target, build_info): 536 result = collections.OrderedDict() 537 result[target] = 1 538 539 for dep in build_info[abi][target]['deps']: 540 if dep in target_blockist: 541 # Blocklisted dep 542 continue 543 if dep not in build_info[abi]: 544 # No info for this dep, skip it 545 continue 546 547 # Recurse 548 result.update(get_gn_target_dependencies(abi, dep, build_info)) 549 550 return result 551 552 553def main(): 554 parser = argparse.ArgumentParser( 555 description='Generate Android blueprints from gn descriptions.') 556 557 for abi in ABI_TARGETS: 558 parser.add_argument( 559 '--gn_json_' + gn_abi(abi), 560 help=gn_abi(abi) + 561 ' gn desc file in json format. Generated with \'gn desc <out_dir> --format=json "*"\'.', 562 required=True) 563 args = vars(parser.parse_args()) 564 565 infos = {} 566 for abi in ABI_TARGETS: 567 with open(args['gn_json_' + gn_abi(abi)], 'r') as f: 568 infos[abi] = json.load(f) 569 570 build_info = BuildInfo(infos) 571 targets_to_write = collections.OrderedDict() 572 for abi in ABI_TARGETS: 573 for root_target in ROOT_TARGETS: 574 targets_to_write.update(get_gn_target_dependencies(abi, root_target, build_info)) 575 576 blueprint_targets = [] 577 578 blueprint_targets.append(( 579 'cc_defaults', 580 { 581 'name': 582 'angle_common_library_cflags', 583 'cflags': [ 584 # Chrome and Android use different versions of Clang which support differnt warning options. 585 # Ignore errors about unrecognized warning flags. 586 '-Wno-unknown-warning-option', 587 '-Os', 588 # Override AOSP build flags to match ANGLE's CQ testing and reduce binary size 589 '-fno-unwind-tables', 590 ], 591 })) 592 593 for target in reversed(targets_to_write.keys()): 594 blueprint_targets.append(gn_target_to_blueprint(target, build_info)) 595 596 # Add license build rules 597 blueprint_targets.append(('package', { 598 'default_applicable_licenses': ['external_angle_license'], 599 })) 600 blueprint_targets.append(('license', { 601 'name': 602 'external_angle_license', 603 'visibility': [':__subpackages__'], 604 'license_kinds': [ 605 'SPDX-license-identifier-Apache-2.0', 606 'SPDX-license-identifier-BSD', 607 'SPDX-license-identifier-GPL', 608 'SPDX-license-identifier-GPL-2.0', 609 'SPDX-license-identifier-GPL-3.0', 610 'SPDX-license-identifier-LGPL', 611 'SPDX-license-identifier-MIT', 612 'SPDX-license-identifier-Zlib', 613 'legacy_unencumbered', 614 ], 615 'license_text': [ 616 'LICENSE', 617 'src/common/third_party/xxhash/LICENSE', 618 'src/libANGLE/renderer/vulkan/shaders/src/third_party/ffx_spd/LICENSE', 619 'src/tests/test_utils/third_party/LICENSE', 620 'src/third_party/libXNVCtrl/LICENSE', 621 'src/third_party/volk/LICENSE.md', 622 'third_party/abseil-cpp/LICENSE', 623 'third_party/android_system_sdk/LICENSE', 624 'third_party/bazel/LICENSE', 625 'third_party/colorama/LICENSE', 626 'third_party/proguard/LICENSE', 627 'third_party/r8/LICENSE', 628 'third_party/turbine/LICENSE', 629 'third_party/vulkan-deps/glslang/LICENSE', 630 'third_party/vulkan-deps/glslang/src/LICENSE.txt', 631 'third_party/vulkan-deps/LICENSE', 632 'third_party/vulkan-deps/spirv-headers/LICENSE', 633 'third_party/vulkan-deps/spirv-headers/src/LICENSE', 634 'third_party/vulkan-deps/spirv-tools/LICENSE', 635 'third_party/vulkan-deps/spirv-tools/src/LICENSE', 636 'third_party/vulkan-deps/spirv-tools/src/utils/vscode/src/lsp/LICENSE', 637 'third_party/vulkan-deps/vulkan-headers/LICENSE.txt', 638 'third_party/vulkan-deps/vulkan-headers/src/LICENSE.md', 639 'third_party/vulkan_memory_allocator/LICENSE.txt', 640 'tools/flex-bison/third_party/m4sugar/LICENSE', 641 'tools/flex-bison/third_party/skeletons/LICENSE', 642 'util/windows/third_party/StackWalker/LICENSE', 643 ], 644 })) 645 646 # Add APKs with all of the root libraries and permissions xml 647 blueprint_targets.append(( 648 'filegroup', 649 { 650 'name': 651 'ANGLE_srcs', 652 # We only need EmptyMainActivity.java since we just need to be able to reply to the intent 653 # android.app.action.ANGLE_FOR_ANDROID to indicate ANGLE is present on the device. 654 # However, the internal branch currently uses these files with patches in that branch. 655 'srcs': [ 656 'src/android_system_settings/src/com/android/angle/MainActivity.java', 657 'src/android_system_settings/src/com/android/angle/common/GlobalSettings.java', 658 'src/android_system_settings/src/com/android/angle/common/MainFragment.java', 659 'src/android_system_settings/src/com/android/angle/common/Receiver.java', 660 'src/android_system_settings/src/com/android/angle/common/SearchProvider.java', 661 ], 662 })) 663 664 blueprint_targets.append(('prebuilt_etc', { 665 'name': 'android.software.angle.xml', 666 'src': 'android/android.software.angle.xml', 667 'product_specific': True, 668 'sub_dir': 'permissions', 669 })) 670 671 blueprint_targets.append(( 672 'java_defaults', 673 { 674 'name': 'ANGLE_java_defaults', 675 'sdk_version': 'system_current', 676 'target_sdk_version': TARGET_SDK_VERSION, 677 'min_sdk_version': MIN_SDK_VERSION, 678 'compile_multilib': 'both', 679 'use_embedded_native_libs': True, 680 'jni_libs': [ 681 # hack: assume ABI_ARM 682 gn_target_to_blueprint_target(target, build_info[ABI_ARM][target]) 683 for target in ROOT_TARGETS 684 ], 685 'aaptflags': [ 686 '-0 .json', # Don't compress *.json files 687 "--extra-packages com.android.angle.common", 688 ], 689 'srcs': [':ANGLE_srcs'], 690 'privileged': True, 691 'product_specific': True, 692 'owner': 'google', 693 'required': ['android.software.angle.xml'], 694 })) 695 696 blueprint_targets.append(('android_library', { 697 'name': 'ANGLE_library', 698 'sdk_version': 'system_current', 699 'target_sdk_version': TARGET_SDK_VERSION, 700 'min_sdk_version': MIN_SDK_VERSION, 701 'resource_dirs': ['src/android_system_settings/res',], 702 'asset_dirs': ['src/android_system_settings/assets',], 703 'aaptflags': ['-0 .json',], 704 'manifest': 'src/android_system_settings/src/com/android/angle/AndroidManifest.xml', 705 'static_libs': ['androidx.preference_preference',], 706 })) 707 708 blueprint_targets.append(('android_app', { 709 'name': 'ANGLE', 710 'defaults': ['ANGLE_java_defaults'], 711 'manifest': 'src/android_system_settings/src/com/android/angle/AndroidManifest.xml', 712 'static_libs': ['ANGLE_library'], 713 'optimize': { 714 'enabled': True, 715 'shrink': True, 716 'proguard_compatibility': False, 717 }, 718 'asset_dirs': ['src/android_system_settings/assets',], 719 })) 720 721 output = [ 722 """// GENERATED FILE - DO NOT EDIT. 723// Generated by %s 724// 725// Copyright 2020 The ANGLE Project Authors. All rights reserved. 726// Use of this source code is governed by a BSD-style license that can be 727// found in the LICENSE file. 728// 729""" % sys.argv[0] 730 ] 731 for (blueprint_type, blueprint_data) in blueprint_targets: 732 write_blueprint(output, blueprint_type, blueprint_data) 733 734 print('\n'.join(output)) 735 736 737if __name__ == '__main__': 738 sys.exit(main()) 739