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