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('') 116 output.append('%s {' % target_type) 117 for (key, value) in values.items(): 118 write_blueprint_key_value(output, key, value) 119 output.append('}') 120 121 122def gn_target_to_blueprint_target(target, target_info): 123 if 'output_name' in target_info: 124 return target_info['output_name'] 125 126 # Split the gn target name (in the form of //gn_file_path:target_name) into gn_file_path and 127 # target_name 128 match = re.match(r"^//([a-zA-Z0-9\-\+_/]*):([a-zA-Z0-9\-\+_.]+)$", target) 129 assert match is not None 130 131 gn_file_path = match.group(1) 132 target_name = match.group(2) 133 assert len(target_name) > 0 134 135 # Clean up the gn file path to be a valid blueprint target name. 136 gn_file_path = gn_file_path.replace("/", "_").replace(".", "_").replace("-", "_") 137 138 # Generate a blueprint target name by merging the gn path and target so each target is unique. 139 # Prepend the 'angle' prefix to all targets in the root path (empty gn_file_path). 140 # Skip this step if the target name already starts with 'angle' to avoid target names such as 'angle_angle_common'. 141 root_prefix = "angle" 142 if len(gn_file_path) == 0 and not target_name.startswith(root_prefix): 143 gn_file_path = root_prefix 144 145 # Avoid names such as _angle_common if the gn_file_path is empty. 146 if len(gn_file_path) > 0: 147 gn_file_path += "_" 148 149 return gn_file_path + target_name 150 151 152def remap_gn_path(path): 153 # TODO: pass the gn gen folder as an arg so it is future proof. b/150457277 154 remap_folders = [ 155 ('out/Android/gen/angle/', ''), 156 ('out/Android/gen/', ''), 157 ] 158 159 remapped_path = path 160 for (remap_source, remap_dest) in remap_folders: 161 remapped_path = remapped_path.replace(remap_source, remap_dest) 162 163 return remapped_path 164 165 166def gn_path_to_blueprint_path(source): 167 # gn uses '//' to indicate the root directory, blueprint uses the .bp file's location 168 return remap_gn_path(re.sub(r'^//?', '', source)) 169 170 171def gn_paths_to_blueprint_paths(paths): 172 rebased_paths = [] 173 for path in paths: 174 rebased_paths.append(gn_path_to_blueprint_path(path)) 175 return rebased_paths 176 177 178def gn_sources_to_blueprint_sources(sources): 179 # Blueprints only list source files in the sources list. Headers are only referenced though 180 # include paths. 181 file_extension_allowlist = [ 182 '.c', 183 '.cc', 184 '.cpp', 185 ] 186 187 rebased_sources = [] 188 for source in sources: 189 if os.path.splitext(source)[1] in file_extension_allowlist: 190 rebased_sources.append(gn_path_to_blueprint_path(source)) 191 return rebased_sources 192 193 194target_blockist = [ 195 '//build/config:shared_library_deps', 196 '//third_party/vulkan-validation-layers/src:vulkan_clean_old_validation_layer_objects', 197 '//third_party/zlib:zlib', 198 '//third_party/zlib/google:compression_utils_portable', 199] 200 201third_party_target_allowlist = [ 202 '//third_party/abseil-cpp', 203 '//third_party/glslang/src', 204 '//third_party/spirv-cross/src', 205 '//third_party/spirv-headers/src', 206 '//third_party/spirv-tools/src', 207 '//third_party/vulkan-headers/src', 208 '//third_party/vulkan-loader/src', 209 '//third_party/vulkan-tools/src', 210 '//third_party/vulkan-utility-libraries/src', 211 '//third_party/vulkan-validation-layers/src', 212 '//third_party/vulkan_memory_allocator', 213] 214 215include_blocklist = [ 216 '//buildtools/third_party/libc++/', 217 '//third_party/libc++/src/', 218 '//out/Android/gen/third_party/glslang/src/include/', 219 '//third_party/zlib/', 220 '//third_party/zlib/google/', 221] 222 223 224@functools.lru_cache(maxsize=None) # .cache() is py3.9 http://b/246559064#comment8 225def gn_deps_to_blueprint_deps(abi, target, build_info): 226 target_info = build_info[abi][target] 227 static_libs = [] 228 shared_libs = [] 229 defaults = [] 230 generated_headers = [] 231 header_libs = [] 232 if 'deps' not in target_info: 233 return static_libs, defaults 234 235 for dep in target_info['deps']: 236 if dep not in target_blockist and (not dep.startswith('//third_party') or any( 237 dep.startswith(substring) for substring in third_party_target_allowlist)): 238 dep_info = build_info[abi][dep] 239 blueprint_dep_name = gn_target_to_blueprint_target(dep, dep_info) 240 241 # Depending on the dep type, blueprints reference it differently. 242 gn_dep_type = dep_info['type'] 243 if gn_dep_type == 'static_library': 244 static_libs.append(blueprint_dep_name) 245 elif gn_dep_type == 'shared_library': 246 shared_libs.append(blueprint_dep_name) 247 elif gn_dep_type == 'source_set' or gn_dep_type == 'group': 248 defaults.append(blueprint_dep_name) 249 elif gn_dep_type == 'action': 250 generated_headers.append(blueprint_dep_name) 251 252 # Blueprints do not chain linking of static libraries. 253 (child_static_libs, _, _, child_generated_headers, 254 _) = gn_deps_to_blueprint_deps(abi, dep, build_info) 255 256 # Each target needs to link all child static library dependencies. 257 static_libs += child_static_libs 258 259 # Each blueprint target runs genrules in a different output directory unlike GN. If a 260 # target depends on another's genrule, it wont find the outputs. Propogate generated 261 # headers up the dependency stack. 262 generated_headers += child_generated_headers 263 elif dep == '//third_party/zlib/google:compression_utils_portable': 264 # Replace zlib by Android's zlib, compression_utils_portable is the root dependency 265 shared_libs.append('libz') 266 static_libs.extend(['zlib_google_compression_utils_portable', 'cpufeatures']) 267 268 return static_libs, shared_libs, defaults, generated_headers, header_libs 269 270 271def gn_libs_to_blueprint_shared_libraries(target_info): 272 lib_blockist = [ 273 'android_support', 274 'unwind', 275 ] 276 277 result = [] 278 if 'libs' in target_info: 279 for lib in target_info['libs']: 280 if lib not in lib_blockist: 281 android_lib = lib if '@' in lib else 'lib' + lib 282 result.append(android_lib) 283 return result 284 285 286def gn_include_dirs_to_blueprint_include_dirs(target_info): 287 result = [] 288 if 'include_dirs' in target_info: 289 for include_dir in target_info['include_dirs']: 290 if len(include_dir) > 0 and include_dir not in include_blocklist: 291 result.append(gn_path_to_blueprint_path(include_dir)) 292 return result 293 294 295def escape_quotes(string): 296 return string.replace("\"", "\\\"").replace("\'", "\\\'") 297 298 299def gn_cflags_to_blueprint_cflags(target_info): 300 result = [] 301 302 # regexs of allowlisted cflags 303 cflag_allowlist = [ 304 r'^-Wno-.*$', # forward cflags that disable warnings 305 r'^-fvisibility.*$', # forward visibility (https://gcc.gnu.org/wiki/Visibility) flags for better perf on x86 306 r'-mpclmul' # forward "-mpclmul" (used by zlib) 307 ] 308 309 for cflag_type in ['cflags', 'cflags_c', 'cflags_cc']: 310 if cflag_type in target_info: 311 for cflag in target_info[cflag_type]: 312 for allowlisted_cflag in cflag_allowlist: 313 if re.search(allowlisted_cflag, cflag): 314 result.append(cflag) 315 316 if 'defines' in target_info: 317 for define in target_info['defines']: 318 # Don't emit ANGLE's CPU-bits define here, it will be part of the arch-specific 319 # information later 320 result.append('-D%s' % escape_quotes(define)) 321 322 return result 323 324 325blueprint_library_target_types = { 326 "static_library": "cc_library_static", 327 "shared_library": "cc_library_shared", 328 "source_set": "cc_defaults", 329 "group": "cc_defaults", 330} 331 332 333def merge_bps(bps_for_abis): 334 common_bp = {} 335 for abi in ABI_TARGETS: 336 for key, values in bps_for_abis[abi].items(): 337 if not isinstance(values, list): 338 # Assume everything that's not a list is common to all ABIs 339 common_bp[key] = values 340 continue 341 342 # Find list values that are common to all ABIs 343 values_in_all_abis = set.intersection( 344 *[set(bps_for_abis[abi2].get(key, [])) for abi2 in ABI_TARGETS]) 345 346 for value in values: 347 if value in values_in_all_abis or key == 'defaults': # arch-specific defaults are not supported 348 common_bp.setdefault(key, []) 349 common_bp[key].append(value) 350 else: 351 common_bp.setdefault('arch', {abi3: {} for abi3 in ABI_TARGETS}) 352 abi_specific = common_bp['arch'][abi] 353 abi_specific.setdefault(key, []) 354 abi_specific[key].append(value) 355 356 return common_bp 357 358 359def library_target_to_blueprint(target, build_info): 360 bps_for_abis = {} 361 blueprint_type = "" 362 for abi in ABI_TARGETS: 363 if target not in build_info[abi].keys(): 364 bps_for_abis[abi] = {} 365 continue 366 367 target_info = build_info[abi][target] 368 369 blueprint_type = blueprint_library_target_types[target_info['type']] 370 371 bp = {'name': gn_target_to_blueprint_target(target, target_info)} 372 373 if 'sources' in target_info: 374 bp['srcs'] = gn_sources_to_blueprint_sources(target_info['sources']) 375 376 (bp['static_libs'], bp['shared_libs'], bp['defaults'], bp['generated_headers'], 377 bp['header_libs']) = gn_deps_to_blueprint_deps(abi, target, build_info) 378 bp['shared_libs'] += gn_libs_to_blueprint_shared_libraries(target_info) 379 380 bp['local_include_dirs'] = gn_include_dirs_to_blueprint_include_dirs(target_info) 381 382 bp['cflags'] = gn_cflags_to_blueprint_cflags(target_info) 383 384 bp['defaults'].append('angle_common_library_cflags') 385 386 bp['sdk_version'] = MIN_SDK_VERSION 387 bp['stl'] = STL 388 if target in ROOT_TARGETS: 389 bp['defaults'].append('angle_vendor_cc_defaults') 390 bps_for_abis[abi] = bp 391 392 common_bp = merge_bps(bps_for_abis) 393 394 return blueprint_type, common_bp 395 396 397def gn_action_args_to_blueprint_args(blueprint_inputs, blueprint_outputs, args): 398 # TODO: pass the gn gen folder as an arg so we know how to get from the gen path to the root 399 # path. b/150457277 400 remap_folders = [ 401 # Specific special-cases first, since the other will strip the prefixes. 402 ('gen/third_party/glslang/src/include/glslang/build_info.h', 'glslang/build_info.h'), 403 ('third_party/glslang/src', 'external/angle/third_party/glslang/src'), 404 ('../../', ''), 405 ('gen/', ''), 406 ] 407 408 result_args = [] 409 for arg in args: 410 # Attempt to find if this arg is a path to one of the inputs. If it is, use the blueprint 411 # $(location <path>) argument instead so the path gets remapped properly to the location 412 # that the script is run from 413 remapped_path_arg = arg 414 for (remap_source, remap_dest) in remap_folders: 415 remapped_path_arg = remapped_path_arg.replace(remap_source, remap_dest) 416 417 if remapped_path_arg in blueprint_inputs or remapped_path_arg in blueprint_outputs: 418 result_args.append('$(location %s)' % remapped_path_arg) 419 elif os.path.basename(remapped_path_arg) in blueprint_outputs: 420 result_args.append('$(location %s)' % os.path.basename(remapped_path_arg)) 421 else: 422 result_args.append(remapped_path_arg) 423 424 return result_args 425 426 427blueprint_gen_types = { 428 "action": "cc_genrule", 429} 430 431 432inputs_blocklist = [ 433 '//.git/HEAD', 434] 435 436outputs_remap = { 437 'build_info.h': 'glslang/build_info.h', 438} 439 440 441def is_input_in_tool_files(tool_files, input): 442 return input in tool_files 443 444 445# special handling the {{response_file_name}} args in GN: 446# see https://gn.googlesource.com/gn/+/main/docs/reference.md#var_response_file_contents 447# in GN, if we use response_file_contents, the GN build system will automatically 448# write contents specified in response_file_contents arg into a temporary file 449# identified by {{response_file_name}}. However, Android blueprint does not have 450# the matching machanism. Android blueprint does automatically generate the 451# temporary file and does not recognize '{{response_file_name}}'. 452# To solve the problem: 453# 1) replace the '{{response_file_name}}' in command argument with the new 454# temporary file name. 455# 2) write the content specified in 'response_file_contents' to the new temporary 456# file 457# This function completes step 1) above. It checks if there are 458# '{{response_file_name}}' used in the command arguments. If there are, 459# the function replaces the '{{response_file_name}}' with the new temp file 460# named 'gn_response_file', and returns the new temp file to indicate 461# we need to complete step 2) 462def handle_gn_build_arg_response_file_name(command_arg_list): 463 new_temp_file_name = None 464 updated_args = command_arg_list[:] 465 for index, arg in enumerate(updated_args): 466 if arg == '{{response_file_name}}': 467 new_temp_file_name = '$(genDir)/gn_response_file' 468 updated_args[index] = new_temp_file_name 469 return new_temp_file_name, updated_args 470 471 472def action_target_to_blueprint(abi, target, build_info): 473 target_info = build_info[abi][target] 474 blueprint_type = blueprint_gen_types[target_info['type']] 475 476 bp = {'name': gn_target_to_blueprint_target(target, target_info)} 477 478 # Blueprints use only one 'srcs', merge all gn inputs into one list. 479 gn_inputs = [] 480 if 'inputs' in target_info: 481 for input in target_info['inputs']: 482 if input not in inputs_blocklist: 483 gn_inputs.append(input) 484 if 'sources' in target_info: 485 gn_inputs += target_info['sources'] 486 # Filter out the 'script' entry since Android.bp doesn't like the duplicate entries 487 if 'script' in target_info: 488 gn_inputs = [ 489 input for input in gn_inputs 490 if not is_input_in_tool_files(target_info['script'], input) 491 ] 492 493 bp_srcs = gn_paths_to_blueprint_paths(gn_inputs) 494 495 bp['srcs'] = bp_srcs 496 497 # genrules generate the output right into the 'root' directory. Strip any path before the 498 # file name. 499 bp_outputs = [] 500 for gn_output in target_info['outputs']: 501 output = os.path.basename(gn_output) 502 if output in outputs_remap.keys(): 503 output = outputs_remap[output] 504 bp_outputs.append(output) 505 506 bp['out'] = bp_outputs 507 508 bp['tool_files'] = [gn_path_to_blueprint_path(target_info['script'])] 509 510 new_temporary_gn_response_file, updated_args = handle_gn_build_arg_response_file_name( 511 target_info['args']) 512 513 if new_temporary_gn_response_file: 514 # add the command 'echo $(in) > $(genDir)/gn_response_file' to 515 # write $response_file_contents into the new_temporary_gn_response_file. 516 cmd = ['echo $(in) >', new_temporary_gn_response_file, '&&', '$(location)' 517 ] + gn_action_args_to_blueprint_args(bp_srcs, bp_outputs, updated_args) 518 else: 519 cmd = ['$(location)'] + gn_action_args_to_blueprint_args(bp_srcs, bp_outputs, 520 target_info['args']) 521 522 bp['cmd'] = ' '.join(cmd) 523 524 bp['sdk_version'] = MIN_SDK_VERSION 525 526 return blueprint_type, bp 527 528 529def gn_target_to_blueprint(target, build_info): 530 for abi in ABI_TARGETS: 531 gn_type = build_info[abi][target]['type'] 532 if gn_type in blueprint_library_target_types: 533 return library_target_to_blueprint(target, build_info) 534 elif gn_type in blueprint_gen_types: 535 return action_target_to_blueprint(abi, target, build_info) 536 else: 537 # Target is not used by this ABI 538 continue 539 540 541@functools.lru_cache(maxsize=None) 542def get_gn_target_dependencies(abi, target, build_info): 543 result = collections.OrderedDict() 544 result[target] = 1 545 546 for dep in build_info[abi][target]['deps']: 547 if dep in target_blockist: 548 # Blocklisted dep 549 continue 550 if dep not in build_info[abi]: 551 # No info for this dep, skip it 552 continue 553 554 # Recurse 555 result.update(get_gn_target_dependencies(abi, dep, build_info)) 556 557 return result 558 559 560def get_angle_in_vendor_flag_config(): 561 blueprint_results = [] 562 563 blueprint_results.append(('soong_config_module_type', { 564 'name': 'angle_config_cc_defaults', 565 'module_type': 'cc_defaults', 566 'config_namespace': 'angle', 567 'bool_variables': ['angle_in_vendor',], 568 'properties': [ 569 'target.android.relative_install_path', 570 'vendor', 571 ], 572 })) 573 574 blueprint_results.append(('soong_config_bool_variable', { 575 'name': 'angle_in_vendor', 576 })) 577 578 blueprint_results.append(( 579 'angle_config_cc_defaults', 580 { 581 'name': 'angle_vendor_cc_defaults', 582 'vendor': False, 583 'target': { 584 'android': { 585 # Android EGL loader can not load from /system/egl/${LIB} 586 # path and hence don't set the relative path so that ANGLE 587 # libraries get built into /system/${LIB} 588 'relative_install_path': '', 589 }, 590 }, 591 'soong_config_variables': { 592 'angle_in_vendor': { 593 'vendor': True, 594 'target': { 595 'android': { 596 'relative_install_path': 'egl', 597 }, 598 }, 599 }, 600 }, 601 })) 602 603 return blueprint_results 604 605 606def main(): 607 parser = argparse.ArgumentParser( 608 description='Generate Android blueprints from gn descriptions.') 609 610 for abi in ABI_TARGETS: 611 parser.add_argument( 612 '--gn_json_' + gn_abi(abi), 613 help=gn_abi(abi) + 614 ' gn desc file in json format. Generated with \'gn desc <out_dir> --format=json "*"\'.', 615 required=True) 616 parser.add_argument('--output', help='output file (e.g. Android.bp)') 617 args = vars(parser.parse_args()) 618 619 infos = {} 620 for abi in ABI_TARGETS: 621 with open(args['gn_json_' + gn_abi(abi)], 'r') as f: 622 infos[abi] = json.load(f) 623 624 build_info = BuildInfo(infos) 625 targets_to_write = collections.OrderedDict() 626 for abi in ABI_TARGETS: 627 for root_target in ROOT_TARGETS: 628 targets_to_write.update(get_gn_target_dependencies(abi, root_target, build_info)) 629 630 blueprint_targets = [] 631 632 blueprint_targets.extend(get_angle_in_vendor_flag_config()) 633 634 blueprint_targets.append(( 635 'cc_defaults', 636 { 637 'name': 638 'angle_common_library_cflags', 639 'cpp_std': 640 'gnu++17', # TODO(b/330910097): std::popcount missing from external/libcxx 641 'cflags': [ 642 # Chrome and Android use different versions of Clang which support differnt warning options. 643 # Ignore errors about unrecognized warning flags. 644 '-Wno-unknown-warning-option', 645 '-O2', 646 # Override AOSP build flags to match ANGLE's CQ testing and reduce binary size 647 '-fno-unwind-tables', 648 # Disable stack protector to reduce cpu overhead. 649 '-fno-stack-protector', 650 ], 651 })) 652 653 generated_targets = [] 654 for target in reversed(targets_to_write.keys()): 655 generated_targets.append(gn_target_to_blueprint(target, build_info)) 656 657 # Move cflags that are repeated in each target to cc_defaults 658 all_cflags = [set(bp['cflags']) for _, bp in generated_targets if 'cflags' in bp] 659 all_target_cflags = set.intersection(*all_cflags) 660 661 for _, bp in generated_targets: 662 if 'cflags' in bp: 663 bp['cflags'] = list(set(bp['cflags']) - all_target_cflags) 664 bp['defaults'].append('angle_common_auto_cflags') 665 666 blueprint_targets.append(('cc_defaults', { 667 'name': 'angle_common_auto_cflags', 668 'cflags': list(all_target_cflags), 669 })) 670 blueprint_targets.extend(generated_targets) 671 672 # Add license build rules 673 blueprint_targets.append(('package', { 674 'default_applicable_licenses': ['external_angle_license'], 675 })) 676 blueprint_targets.append(('license', { 677 'name': 678 'external_angle_license', 679 'visibility': [':__subpackages__'], 680 'license_kinds': [ 681 'SPDX-license-identifier-Apache-2.0', 682 'SPDX-license-identifier-BSD', 683 'SPDX-license-identifier-GPL', 684 'SPDX-license-identifier-GPL-2.0', 685 'SPDX-license-identifier-GPL-3.0', 686 'SPDX-license-identifier-LGPL', 687 'SPDX-license-identifier-MIT', 688 'SPDX-license-identifier-Zlib', 689 'legacy_unencumbered', 690 ], 691 'license_text': [ 692 'LICENSE', 693 'src/common/third_party/xxhash/LICENSE', 694 'src/libANGLE/renderer/vulkan/shaders/src/third_party/ffx_spd/LICENSE', 695 'src/tests/test_utils/third_party/LICENSE', 696 'src/third_party/libXNVCtrl/LICENSE', 697 'src/third_party/volk/LICENSE.md', 698 'third_party/abseil-cpp/LICENSE', 699 'third_party/android_system_sdk/LICENSE', 700 'third_party/bazel/LICENSE', 701 'third_party/colorama/LICENSE', 702 'third_party/proguard/LICENSE', 703 'third_party/r8/LICENSE', 704 'third_party/turbine/LICENSE', 705 'third_party/glslang/LICENSE', 706 'third_party/glslang/src/LICENSE.txt', 707 'third_party/spirv-headers/LICENSE', 708 'third_party/spirv-headers/src/LICENSE', 709 'third_party/spirv-tools/LICENSE', 710 'third_party/spirv-tools/src/LICENSE', 711 'third_party/spirv-tools/src/utils/vscode/src/lsp/LICENSE', 712 'third_party/vulkan-headers/LICENSE.txt', 713 'third_party/vulkan-headers/src/LICENSE.md', 714 'third_party/vulkan_memory_allocator/LICENSE.txt', 715 'tools/flex-bison/third_party/m4sugar/LICENSE', 716 'tools/flex-bison/third_party/skeletons/LICENSE', 717 'util/windows/third_party/StackWalker/LICENSE', 718 ], 719 })) 720 721 # Add APKs with all of the root libraries and permissions xml 722 blueprint_targets.append(( 723 'filegroup', 724 { 725 'name': 726 'ANGLE_srcs', 727 # We only need EmptyMainActivity.java since we just need to be able to reply to the intent 728 # android.app.action.ANGLE_FOR_ANDROID to indicate ANGLE is present on the device. 729 # However, the internal branch currently uses these files with patches in that branch. 730 'srcs': [ 731 'src/android_system_settings/src/com/android/angle/MainActivity.java', 732 'src/android_system_settings/src/com/android/angle/common/AngleRuleHelper.java', 733 'src/android_system_settings/src/com/android/angle/common/GlobalSettings.java', 734 'src/android_system_settings/src/com/android/angle/common/MainFragment.java', 735 'src/android_system_settings/src/com/android/angle/common/Receiver.java', 736 'src/android_system_settings/src/com/android/angle/common/SearchProvider.java', 737 ], 738 })) 739 740 blueprint_targets.append(('prebuilt_etc', { 741 'name': 'android.software.angle.xml', 742 'src': 'android/android.software.angle.xml', 743 'product_specific': True, 744 'sub_dir': 'permissions', 745 })) 746 747 blueprint_targets.append(( 748 'java_defaults', 749 { 750 'name': 'ANGLE_java_defaults', 751 'sdk_version': 'system_current', 752 'target_sdk_version': TARGET_SDK_VERSION, 753 'min_sdk_version': MIN_SDK_VERSION, 754 'compile_multilib': 'both', 755 'use_embedded_native_libs': True, 756 'jni_libs': [ 757 # hack: assume ABI_ARM 758 gn_target_to_blueprint_target(target, build_info[ABI_ARM][target]) 759 for target in ROOT_TARGETS 760 ], 761 'aaptflags': [ 762 '-0 .json', # Don't compress *.json files 763 "--extra-packages com.android.angle.common", 764 ], 765 'srcs': [':ANGLE_srcs'], 766 'privileged': True, 767 'product_specific': True, 768 'owner': 'google', 769 'required': ['android.software.angle.xml'], 770 })) 771 772 blueprint_targets.append(('android_library', { 773 'name': 'ANGLE_library', 774 'sdk_version': 'system_current', 775 'target_sdk_version': TARGET_SDK_VERSION, 776 'min_sdk_version': MIN_SDK_VERSION, 777 'resource_dirs': ['src/android_system_settings/res',], 778 'asset_dirs': ['src/android_system_settings/assets',], 779 'aaptflags': ['-0 .json',], 780 'manifest': 'src/android_system_settings/src/com/android/angle/AndroidManifest.xml', 781 'static_libs': ['androidx.preference_preference',], 782 })) 783 784 blueprint_targets.append(('android_app', { 785 'name': 'ANGLE', 786 'defaults': ['ANGLE_java_defaults'], 787 'manifest': 'src/android_system_settings/src/com/android/angle/AndroidManifest.xml', 788 'static_libs': ['ANGLE_library'], 789 'optimize': { 790 'enabled': True, 791 'shrink': True, 792 'proguard_compatibility': False, 793 }, 794 'asset_dirs': ['src/android_system_settings/assets',], 795 })) 796 797 blueprint_targets.append(( 798 'java_defaults', 799 { 800 'name': 'ANGLE_java_settings_defaults', 801 'sdk_version': 'system_current', 802 'target_sdk_version': TARGET_SDK_VERSION, 803 'min_sdk_version': MIN_SDK_VERSION, 804 'compile_multilib': 'both', 805 'use_embedded_native_libs': True, 806 'aaptflags': [ 807 '-0 .json', # Don't compress *.json files 808 "--extra-packages com.android.angle.common", 809 ], 810 'srcs': [':ANGLE_srcs'], 811 'privileged': True, 812 'product_specific': True, 813 'owner': 'google', 814 'required': ['android.software.angle.xml'], 815 })) 816 817 blueprint_targets.append(('android_app', { 818 'name': 'ANGLE_settings', 819 'defaults': ['ANGLE_java_settings_defaults'], 820 'manifest': 'src/android_system_settings/src/com/android/angle/AndroidManifest.xml', 821 'static_libs': ['ANGLE_library'], 822 'optimize': { 823 'enabled': True, 824 'shrink': True, 825 'proguard_compatibility': False, 826 }, 827 'asset_dirs': ['src/android_system_settings/assets',], 828 })) 829 830 output = [ 831 """// GENERATED FILE - DO NOT EDIT. 832// Generated by %s 833// 834// Copyright 2020 The ANGLE Project Authors. All rights reserved. 835// Use of this source code is governed by a BSD-style license that can be 836// found in the LICENSE file. 837//""" % sys.argv[0] 838 ] 839 for (blueprint_type, blueprint_data) in blueprint_targets: 840 write_blueprint(output, blueprint_type, blueprint_data) 841 842 with open(args['output'], 'w') as f: 843 f.write('\n'.join(output) + '\n') 844 845 846if __name__ == '__main__': 847 sys.exit(main()) 848