1#!/usr/bin/env python3 2 3import argparse 4import collections 5import os 6import shutil 7import time 8 9from utils import ( 10 AOSP_DIR, COMPRESSED_SOURCE_ABI_DUMP_EXT, SOURCE_ABI_DUMP_EXT, 11 SOURCE_ABI_DUMP_EXT_END, SO_EXT, Target, copy_reference_dump, 12 find_lib_lsdumps, get_build_vars_for_product, make_libraries, make_tree, 13 read_lsdump_paths) 14 15 16PRODUCTS_DEFAULT = ['aosp_arm', 'aosp_arm64', 'aosp_x86', 'aosp_x86_64'] 17 18PREBUILTS_ABI_DUMPS_DEFAULT = os.path.join(AOSP_DIR, 'prebuilts', 'abi-dumps') 19 20SOONG_DIR = os.path.join(AOSP_DIR, 'out', 'soong', '.intermediates') 21 22 23def choose_vndk_version(version, platform_vndk_version, board_vndk_version): 24 if version is None: 25 # This logic must be in sync with the logic for reference ABI dumps 26 # directory in `build/soong/cc/library.go`. 27 version = platform_vndk_version 28 if board_vndk_version not in ('current', ''): 29 version = board_vndk_version 30 return version 31 32 33def make_libs_for_product(libs, product, variant, vndk_version, targets): 34 print('making libs for', product + '-' + variant) 35 if libs: 36 make_libraries(product, variant, vndk_version, targets, libs) 37 else: 38 make_tree(product, variant) 39 40 41def get_ref_dump_dir_stem(ref_dump_dir, category, chosen_vndk_version, 42 binder_bitness, arch): 43 return os.path.join(ref_dump_dir, category, chosen_vndk_version, 44 binder_bitness, arch) 45 46 47def find_and_remove_path(root_path, file_name=None): 48 if file_name is not None: 49 root_path = os.path.join(root_path, 'source-based', file_name) 50 51 if os.path.exists(root_path): 52 print('removing', root_path) 53 if os.path.isfile(root_path): 54 os.remove(root_path) 55 else: 56 shutil.rmtree(root_path) 57 58 59def remove_references_for_all_arches(ref_dump_dir, chosen_vndk_version, 60 binder_bitness, targets, libs): 61 for target in targets: 62 for category in ('ndk', 'platform', 'vndk'): 63 dir_to_remove = get_ref_dump_dir_stem( 64 ref_dump_dir, category, chosen_vndk_version, binder_bitness, 65 target.get_arch_str()) 66 if libs: 67 for lib in libs: 68 find_and_remove_path(dir_to_remove, 69 lib + SOURCE_ABI_DUMP_EXT) 70 find_and_remove_path(dir_to_remove, 71 lib + COMPRESSED_SOURCE_ABI_DUMP_EXT) 72 else: 73 find_and_remove_path(dir_to_remove) 74 75 76def tag_to_dir_name(tag): 77 if tag == 'NDK': 78 return 'ndk' 79 if tag == 'PLATFORM': 80 return 'platform' 81 if tag.startswith('VNDK') or tag == 'LLNDK': 82 return 'vndk' 83 raise ValueError(tag + 'is not a known tag.') 84 85 86def find_and_copy_lib_lsdumps(ref_dump_dir, chosen_vndk_version, 87 binder_bitness, target, libs, lsdump_paths, 88 compress): 89 arch_lsdump_paths = find_lib_lsdumps(lsdump_paths, libs, target) 90 91 num_created = 0 92 for tag, path in arch_lsdump_paths: 93 ref_dump_dir_stem = get_ref_dump_dir_stem( 94 ref_dump_dir, tag_to_dir_name(tag), chosen_vndk_version, 95 binder_bitness, target.get_arch_str()) 96 copy_reference_dump( 97 path, os.path.join(ref_dump_dir_stem, 'source-based'), compress) 98 num_created += 1 99 return num_created 100 101 102def create_source_abi_reference_dumps(args, chosen_vndk_version, 103 binder_bitness, lsdump_paths, targets): 104 num_libs_copied = 0 105 for target in targets: 106 assert target.primary_arch != '' 107 print(f'Creating dumps for arch: {target.arch}, ' 108 f'primary arch: {target.primary_arch}') 109 110 num_libs_copied += find_and_copy_lib_lsdumps( 111 args.ref_dump_dir, chosen_vndk_version, binder_bitness, target, 112 args.libs, lsdump_paths, args.compress) 113 return num_libs_copied 114 115 116def create_source_abi_reference_dumps_for_all_products(args): 117 """Create reference ABI dumps for all specified products.""" 118 119 num_processed = 0 120 121 for product in args.products: 122 build_vars = get_build_vars_for_product( 123 ['PLATFORM_VNDK_VERSION', 'BOARD_VNDK_VERSION', 'BINDER32BIT'], 124 product, args.build_variant) 125 126 platform_vndk_version = build_vars[0] 127 board_vndk_version = build_vars[1] 128 if build_vars[2] == 'true': 129 binder_bitness = '32' 130 else: 131 binder_bitness = '64' 132 133 chosen_vndk_version = choose_vndk_version( 134 args.version, platform_vndk_version, board_vndk_version) 135 136 targets = [t for t in (Target(True, product), Target(False, product)) 137 if t.arch] 138 # Remove reference ABI dumps specified in `args.libs` (or remove all of 139 # them if none of them are specified) so that we may build these 140 # libraries successfully. 141 remove_references_for_all_arches( 142 args.ref_dump_dir, chosen_vndk_version, binder_bitness, targets, 143 args.libs) 144 145 if not args.no_make_lib: 146 # Build all the specified libs, or build `findlsdumps` if no libs 147 # are specified. 148 make_libs_for_product(args.libs, product, args.build_variant, 149 platform_vndk_version, targets) 150 151 lsdump_paths = read_lsdump_paths(product, args.build_variant, 152 platform_vndk_version, targets, 153 build=False) 154 155 num_processed += create_source_abi_reference_dumps( 156 args, chosen_vndk_version, binder_bitness, lsdump_paths, targets) 157 158 return num_processed 159 160 161def _parse_args(): 162 """Parse the command line arguments.""" 163 164 parser = argparse.ArgumentParser() 165 parser.add_argument('--version', help='VNDK version') 166 parser.add_argument('--no-make-lib', action='store_true', 167 help='no m -j lib.vendor while creating reference') 168 parser.add_argument('--llndk', action='store_true', 169 help='the flag is deprecated and has no effect') 170 parser.add_argument('-libs', action='append', 171 help='libs to create references for') 172 parser.add_argument('-products', action='append', 173 help='products to create references for') 174 parser.add_argument('--build-variant', default='userdebug', 175 help='build variant to create references for') 176 parser.add_argument('--compress', action='store_true', 177 help='compress reference dump with gzip') 178 parser.add_argument('-ref-dump-dir', 179 help='directory to copy reference abi dumps into', 180 default=PREBUILTS_ABI_DUMPS_DEFAULT) 181 182 args = parser.parse_args() 183 184 if args.libs: 185 if any(lib_name.endswith(SOURCE_ABI_DUMP_EXT_END) or 186 lib_name.endswith(SO_EXT) for lib_name in args.libs): 187 parser.error('-libs should be followed by a base name without ' 188 'file extension.') 189 190 if args.products is None: 191 # If `args.products` is unspecified, generate reference ABI dumps for 192 # all products. 193 args.products = PRODUCTS_DEFAULT 194 195 return args 196 197 198def main(): 199 args = _parse_args() 200 201 start = time.time() 202 num_processed = create_source_abi_reference_dumps_for_all_products(args) 203 end = time.time() 204 205 print() 206 print('msg: Processed', num_processed, 'libraries in ', (end - start) / 60, 207 ' minutes') 208 209 210if __name__ == '__main__': 211 main() 212