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