1*90c8c64dSAndroid Build Coastguard Worker#!/usr/bin/env python3 2*90c8c64dSAndroid Build Coastguard Worker 3*90c8c64dSAndroid Build Coastguard Workerimport collections 4*90c8c64dSAndroid Build Coastguard Workerimport os 5*90c8c64dSAndroid Build Coastguard Workerimport re 6*90c8c64dSAndroid Build Coastguard Workerimport shutil 7*90c8c64dSAndroid Build Coastguard Workerimport subprocess 8*90c8c64dSAndroid Build Coastguard Workerimport sys 9*90c8c64dSAndroid Build Coastguard Workerimport tempfile 10*90c8c64dSAndroid Build Coastguard Workerimport collections 11*90c8c64dSAndroid Build Coastguard Worker 12*90c8c64dSAndroid Build Coastguard Worker 13*90c8c64dSAndroid Build Coastguard WorkerSCRIPT_DIR = os.path.abspath(os.path.dirname(__file__)) 14*90c8c64dSAndroid Build Coastguard Worker 15*90c8c64dSAndroid Build Coastguard Workertry: 16*90c8c64dSAndroid Build Coastguard Worker AOSP_DIR = os.environ['ANDROID_BUILD_TOP'] 17*90c8c64dSAndroid Build Coastguard Workerexcept KeyError: 18*90c8c64dSAndroid Build Coastguard Worker print('error: ANDROID_BUILD_TOP environment variable is not set.', 19*90c8c64dSAndroid Build Coastguard Worker file=sys.stderr) 20*90c8c64dSAndroid Build Coastguard Worker sys.exit(1) 21*90c8c64dSAndroid Build Coastguard Worker 22*90c8c64dSAndroid Build Coastguard WorkerBUILTIN_HEADERS_DIR = ( 23*90c8c64dSAndroid Build Coastguard Worker os.path.join(AOSP_DIR, 'bionic', 'libc', 'include'), 24*90c8c64dSAndroid Build Coastguard Worker os.path.join(AOSP_DIR, 'external', 'libcxx', 'include'), 25*90c8c64dSAndroid Build Coastguard Worker os.path.join(AOSP_DIR, 'prebuilts', 'clang-tools', 'linux-x86', 26*90c8c64dSAndroid Build Coastguard Worker 'clang-headers'), 27*90c8c64dSAndroid Build Coastguard Worker) 28*90c8c64dSAndroid Build Coastguard Worker 29*90c8c64dSAndroid Build Coastguard WorkerSO_EXT = '.so' 30*90c8c64dSAndroid Build Coastguard WorkerSOURCE_ABI_DUMP_EXT_END = '.lsdump' 31*90c8c64dSAndroid Build Coastguard WorkerSOURCE_ABI_DUMP_EXT = SO_EXT + SOURCE_ABI_DUMP_EXT_END 32*90c8c64dSAndroid Build Coastguard WorkerKNOWN_ABI_DUMP_EXTS = { 33*90c8c64dSAndroid Build Coastguard Worker SOURCE_ABI_DUMP_EXT, 34*90c8c64dSAndroid Build Coastguard Worker SO_EXT + '.apex' + SOURCE_ABI_DUMP_EXT_END, 35*90c8c64dSAndroid Build Coastguard Worker SO_EXT + '.llndk' + SOURCE_ABI_DUMP_EXT_END, 36*90c8c64dSAndroid Build Coastguard Worker} 37*90c8c64dSAndroid Build Coastguard Worker 38*90c8c64dSAndroid Build Coastguard WorkerDEFAULT_CPPFLAGS = ['-x', 'c++', '-std=c++11'] 39*90c8c64dSAndroid Build Coastguard WorkerDEFAULT_CFLAGS = ['-std=gnu99'] 40*90c8c64dSAndroid Build Coastguard WorkerDEFAULT_HEADER_FLAGS = ["-dump-function-declarations"] 41*90c8c64dSAndroid Build Coastguard WorkerDEFAULT_FORMAT = 'ProtobufTextFormat' 42*90c8c64dSAndroid Build Coastguard Worker 43*90c8c64dSAndroid Build Coastguard WorkerBuildTarget = collections.namedtuple( 44*90c8c64dSAndroid Build Coastguard Worker 'BuildTarget', ['product', 'release', 'variant']) 45*90c8c64dSAndroid Build Coastguard Worker 46*90c8c64dSAndroid Build Coastguard Worker 47*90c8c64dSAndroid Build Coastguard Workerclass Arch(object): 48*90c8c64dSAndroid Build Coastguard Worker """A CPU architecture of a build target.""" 49*90c8c64dSAndroid Build Coastguard Worker def __init__(self, is_2nd, build_target): 50*90c8c64dSAndroid Build Coastguard Worker extra = '_2ND' if is_2nd else '' 51*90c8c64dSAndroid Build Coastguard Worker build_vars_to_fetch = ['TARGET_ARCH', 52*90c8c64dSAndroid Build Coastguard Worker 'TARGET{}_ARCH'.format(extra), 53*90c8c64dSAndroid Build Coastguard Worker 'TARGET{}_ARCH_VARIANT'.format(extra), 54*90c8c64dSAndroid Build Coastguard Worker 'TARGET{}_CPU_VARIANT'.format(extra)] 55*90c8c64dSAndroid Build Coastguard Worker build_vars = get_build_vars(build_vars_to_fetch, build_target) 56*90c8c64dSAndroid Build Coastguard Worker self.primary_arch = build_vars[0] 57*90c8c64dSAndroid Build Coastguard Worker assert self.primary_arch != '' 58*90c8c64dSAndroid Build Coastguard Worker self.arch = build_vars[1] 59*90c8c64dSAndroid Build Coastguard Worker self.arch_variant = build_vars[2] 60*90c8c64dSAndroid Build Coastguard Worker self.cpu_variant = build_vars[3] 61*90c8c64dSAndroid Build Coastguard Worker 62*90c8c64dSAndroid Build Coastguard Worker def get_arch_str(self): 63*90c8c64dSAndroid Build Coastguard Worker """Return a string that represents the architecture and the primary 64*90c8c64dSAndroid Build Coastguard Worker architecture. 65*90c8c64dSAndroid Build Coastguard Worker """ 66*90c8c64dSAndroid Build Coastguard Worker if not self.arch or self.arch == self.primary_arch: 67*90c8c64dSAndroid Build Coastguard Worker return self.primary_arch 68*90c8c64dSAndroid Build Coastguard Worker return self.arch + '_' + self.primary_arch 69*90c8c64dSAndroid Build Coastguard Worker 70*90c8c64dSAndroid Build Coastguard Worker def get_arch_cpu_str(self): 71*90c8c64dSAndroid Build Coastguard Worker """Return a string that represents the architecture, the architecture 72*90c8c64dSAndroid Build Coastguard Worker variant, and the CPU variant. 73*90c8c64dSAndroid Build Coastguard Worker 74*90c8c64dSAndroid Build Coastguard Worker If TARGET_ARCH == TARGET_ARCH_VARIANT, soong makes targetArchVariant 75*90c8c64dSAndroid Build Coastguard Worker empty. This is the case for aosp_x86_64. 76*90c8c64dSAndroid Build Coastguard Worker """ 77*90c8c64dSAndroid Build Coastguard Worker if not self.arch_variant or self.arch_variant == self.arch: 78*90c8c64dSAndroid Build Coastguard Worker arch_variant = '' 79*90c8c64dSAndroid Build Coastguard Worker else: 80*90c8c64dSAndroid Build Coastguard Worker arch_variant = '_' + self.arch_variant 81*90c8c64dSAndroid Build Coastguard Worker 82*90c8c64dSAndroid Build Coastguard Worker if not self.cpu_variant or self.cpu_variant == 'generic': 83*90c8c64dSAndroid Build Coastguard Worker cpu_variant = '' 84*90c8c64dSAndroid Build Coastguard Worker else: 85*90c8c64dSAndroid Build Coastguard Worker cpu_variant = '_' + self.cpu_variant 86*90c8c64dSAndroid Build Coastguard Worker 87*90c8c64dSAndroid Build Coastguard Worker return self.arch + arch_variant + cpu_variant 88*90c8c64dSAndroid Build Coastguard Worker 89*90c8c64dSAndroid Build Coastguard Worker 90*90c8c64dSAndroid Build Coastguard Workerdef _strip_dump_name_ext(filename): 91*90c8c64dSAndroid Build Coastguard Worker """Remove .so*.lsdump from a file name.""" 92*90c8c64dSAndroid Build Coastguard Worker for ext in KNOWN_ABI_DUMP_EXTS: 93*90c8c64dSAndroid Build Coastguard Worker if filename.endswith(ext) and len(filename) > len(ext): 94*90c8c64dSAndroid Build Coastguard Worker return filename[:-len(ext)] 95*90c8c64dSAndroid Build Coastguard Worker raise ValueError(f'{filename} has an unknown file name extension.') 96*90c8c64dSAndroid Build Coastguard Worker 97*90c8c64dSAndroid Build Coastguard Worker 98*90c8c64dSAndroid Build Coastguard Workerdef _validate_dump_content(dump_path): 99*90c8c64dSAndroid Build Coastguard Worker """Make sure that the dump contains relative source paths.""" 100*90c8c64dSAndroid Build Coastguard Worker with open(dump_path, 'r') as f: 101*90c8c64dSAndroid Build Coastguard Worker for line_number, line in enumerate(f, 1): 102*90c8c64dSAndroid Build Coastguard Worker start = 0 103*90c8c64dSAndroid Build Coastguard Worker while True: 104*90c8c64dSAndroid Build Coastguard Worker start = line.find(AOSP_DIR, start) 105*90c8c64dSAndroid Build Coastguard Worker if start < 0: 106*90c8c64dSAndroid Build Coastguard Worker break 107*90c8c64dSAndroid Build Coastguard Worker # The substring is not preceded by a common path character. 108*90c8c64dSAndroid Build Coastguard Worker if start == 0 or not (line[start - 1].isalnum() or 109*90c8c64dSAndroid Build Coastguard Worker line[start - 1] in '.-_/'): 110*90c8c64dSAndroid Build Coastguard Worker raise ValueError(f'{dump_path} contains absolute path to ' 111*90c8c64dSAndroid Build Coastguard Worker f'$ANDROID_BUILD_TOP at line ' 112*90c8c64dSAndroid Build Coastguard Worker f'{line_number}:\n{line}') 113*90c8c64dSAndroid Build Coastguard Worker start += len(AOSP_DIR) 114*90c8c64dSAndroid Build Coastguard Worker 115*90c8c64dSAndroid Build Coastguard Worker 116*90c8c64dSAndroid Build Coastguard Workerdef copy_reference_dump(lib_path, reference_dump_dir): 117*90c8c64dSAndroid Build Coastguard Worker _validate_dump_content(lib_path) 118*90c8c64dSAndroid Build Coastguard Worker ref_dump_name = (_strip_dump_name_ext(os.path.basename(lib_path)) + 119*90c8c64dSAndroid Build Coastguard Worker SOURCE_ABI_DUMP_EXT) 120*90c8c64dSAndroid Build Coastguard Worker ref_dump_path = os.path.join(reference_dump_dir, ref_dump_name) 121*90c8c64dSAndroid Build Coastguard Worker os.makedirs(reference_dump_dir, exist_ok=True) 122*90c8c64dSAndroid Build Coastguard Worker shutil.copyfile(lib_path, ref_dump_path) 123*90c8c64dSAndroid Build Coastguard Worker print(f'Created abi dump at {ref_dump_path}') 124*90c8c64dSAndroid Build Coastguard Worker return ref_dump_path 125*90c8c64dSAndroid Build Coastguard Worker 126*90c8c64dSAndroid Build Coastguard Worker 127*90c8c64dSAndroid Build Coastguard Workerdef run_header_abi_dumper(input_path, output_path, cflags=tuple(), 128*90c8c64dSAndroid Build Coastguard Worker export_include_dirs=tuple(), flags=tuple()): 129*90c8c64dSAndroid Build Coastguard Worker """Run header-abi-dumper to dump ABI from `input_path` and the output is 130*90c8c64dSAndroid Build Coastguard Worker written to `output_path`.""" 131*90c8c64dSAndroid Build Coastguard Worker input_ext = os.path.splitext(input_path)[1] 132*90c8c64dSAndroid Build Coastguard Worker cmd = ['header-abi-dumper', '-o', output_path, input_path] 133*90c8c64dSAndroid Build Coastguard Worker for dir in export_include_dirs: 134*90c8c64dSAndroid Build Coastguard Worker cmd += ['-I', dir] 135*90c8c64dSAndroid Build Coastguard Worker cmd += flags 136*90c8c64dSAndroid Build Coastguard Worker if '-output-format' not in flags: 137*90c8c64dSAndroid Build Coastguard Worker cmd += ['-output-format', DEFAULT_FORMAT] 138*90c8c64dSAndroid Build Coastguard Worker if input_ext == ".h": 139*90c8c64dSAndroid Build Coastguard Worker cmd += DEFAULT_HEADER_FLAGS 140*90c8c64dSAndroid Build Coastguard Worker cmd += ['--'] 141*90c8c64dSAndroid Build Coastguard Worker cmd += cflags 142*90c8c64dSAndroid Build Coastguard Worker if input_ext in ('.cpp', '.cc', '.h'): 143*90c8c64dSAndroid Build Coastguard Worker cmd += DEFAULT_CPPFLAGS 144*90c8c64dSAndroid Build Coastguard Worker else: 145*90c8c64dSAndroid Build Coastguard Worker cmd += DEFAULT_CFLAGS 146*90c8c64dSAndroid Build Coastguard Worker 147*90c8c64dSAndroid Build Coastguard Worker for dir in BUILTIN_HEADERS_DIR: 148*90c8c64dSAndroid Build Coastguard Worker cmd += ['-isystem', dir] 149*90c8c64dSAndroid Build Coastguard Worker # The export include dirs imply local include dirs. 150*90c8c64dSAndroid Build Coastguard Worker for dir in export_include_dirs: 151*90c8c64dSAndroid Build Coastguard Worker cmd += ['-I', dir] 152*90c8c64dSAndroid Build Coastguard Worker subprocess.check_call(cmd, cwd=AOSP_DIR) 153*90c8c64dSAndroid Build Coastguard Worker _validate_dump_content(output_path) 154*90c8c64dSAndroid Build Coastguard Worker 155*90c8c64dSAndroid Build Coastguard Worker 156*90c8c64dSAndroid Build Coastguard Workerdef run_header_abi_linker(inputs, output_path, version_script, api, arch_str, 157*90c8c64dSAndroid Build Coastguard Worker flags=tuple()): 158*90c8c64dSAndroid Build Coastguard Worker """Link inputs, taking version_script into account""" 159*90c8c64dSAndroid Build Coastguard Worker cmd = ['header-abi-linker', '-o', output_path, '-v', version_script, 160*90c8c64dSAndroid Build Coastguard Worker '-api', api, '-arch', arch_str] 161*90c8c64dSAndroid Build Coastguard Worker cmd += flags 162*90c8c64dSAndroid Build Coastguard Worker if '-input-format' not in flags: 163*90c8c64dSAndroid Build Coastguard Worker cmd += ['-input-format', DEFAULT_FORMAT] 164*90c8c64dSAndroid Build Coastguard Worker if '-output-format' not in flags: 165*90c8c64dSAndroid Build Coastguard Worker cmd += ['-output-format', DEFAULT_FORMAT] 166*90c8c64dSAndroid Build Coastguard Worker cmd += inputs 167*90c8c64dSAndroid Build Coastguard Worker subprocess.check_call(cmd, cwd=AOSP_DIR) 168*90c8c64dSAndroid Build Coastguard Worker _validate_dump_content(output_path) 169*90c8c64dSAndroid Build Coastguard Worker 170*90c8c64dSAndroid Build Coastguard Worker 171*90c8c64dSAndroid Build Coastguard Workerdef make_targets(build_target, args): 172*90c8c64dSAndroid Build Coastguard Worker make_cmd = ['build/soong/soong_ui.bash', '--make-mode', '-j', 173*90c8c64dSAndroid Build Coastguard Worker 'TARGET_PRODUCT=' + build_target.product, 174*90c8c64dSAndroid Build Coastguard Worker 'TARGET_BUILD_VARIANT=' + build_target.variant] 175*90c8c64dSAndroid Build Coastguard Worker if build_target.release: 176*90c8c64dSAndroid Build Coastguard Worker make_cmd.append('TARGET_RELEASE=' + build_target.release) 177*90c8c64dSAndroid Build Coastguard Worker make_cmd += args 178*90c8c64dSAndroid Build Coastguard Worker subprocess.check_call(make_cmd, cwd=AOSP_DIR) 179*90c8c64dSAndroid Build Coastguard Worker 180*90c8c64dSAndroid Build Coastguard Worker 181*90c8c64dSAndroid Build Coastguard Workerdef make_libraries(build_target, arches, libs, lsdump_filter): 182*90c8c64dSAndroid Build Coastguard Worker """Build lsdump files for specific libs.""" 183*90c8c64dSAndroid Build Coastguard Worker lsdump_paths = read_lsdump_paths(build_target, arches, lsdump_filter, 184*90c8c64dSAndroid Build Coastguard Worker build=True) 185*90c8c64dSAndroid Build Coastguard Worker make_target_paths = [] 186*90c8c64dSAndroid Build Coastguard Worker for name in libs: 187*90c8c64dSAndroid Build Coastguard Worker if not (name in lsdump_paths and lsdump_paths[name]): 188*90c8c64dSAndroid Build Coastguard Worker raise KeyError('Cannot find lsdump for %s.' % name) 189*90c8c64dSAndroid Build Coastguard Worker for tag_path_dict in lsdump_paths[name].values(): 190*90c8c64dSAndroid Build Coastguard Worker make_target_paths.extend(tag_path_dict.values()) 191*90c8c64dSAndroid Build Coastguard Worker make_targets(build_target, make_target_paths) 192*90c8c64dSAndroid Build Coastguard Worker 193*90c8c64dSAndroid Build Coastguard Worker 194*90c8c64dSAndroid Build Coastguard Workerdef get_lsdump_paths_file_path(build_target): 195*90c8c64dSAndroid Build Coastguard Worker """Get the path to lsdump_paths.txt.""" 196*90c8c64dSAndroid Build Coastguard Worker product_out = get_build_vars(['PRODUCT_OUT'], build_target)[0] 197*90c8c64dSAndroid Build Coastguard Worker return os.path.join(product_out, 'lsdump_paths.txt') 198*90c8c64dSAndroid Build Coastguard Worker 199*90c8c64dSAndroid Build Coastguard Worker 200*90c8c64dSAndroid Build Coastguard Workerdef _get_module_variant_sort_key(suffix): 201*90c8c64dSAndroid Build Coastguard Worker for variant in suffix.split('_'): 202*90c8c64dSAndroid Build Coastguard Worker match = re.match(r'apex(\d+)$', variant) 203*90c8c64dSAndroid Build Coastguard Worker if match: 204*90c8c64dSAndroid Build Coastguard Worker return (int(match.group(1)), suffix) 205*90c8c64dSAndroid Build Coastguard Worker return (-1, suffix) 206*90c8c64dSAndroid Build Coastguard Worker 207*90c8c64dSAndroid Build Coastguard Worker 208*90c8c64dSAndroid Build Coastguard Workerdef _get_module_variant_dir_name(tag, arch_cpu_str): 209*90c8c64dSAndroid Build Coastguard Worker """Return the module variant directory name. 210*90c8c64dSAndroid Build Coastguard Worker 211*90c8c64dSAndroid Build Coastguard Worker For example, android_x86_shared, android_vendor.R_arm_armv7-a-neon_shared. 212*90c8c64dSAndroid Build Coastguard Worker """ 213*90c8c64dSAndroid Build Coastguard Worker if tag in ('LLNDK', 'NDK', 'PLATFORM', 'APEX'): 214*90c8c64dSAndroid Build Coastguard Worker return f'android_{arch_cpu_str}_shared' 215*90c8c64dSAndroid Build Coastguard Worker if tag == 'VENDOR': 216*90c8c64dSAndroid Build Coastguard Worker return f'android_vendor_{arch_cpu_str}_shared' 217*90c8c64dSAndroid Build Coastguard Worker if tag == 'PRODUCT': 218*90c8c64dSAndroid Build Coastguard Worker return f'android_product_{arch_cpu_str}_shared' 219*90c8c64dSAndroid Build Coastguard Worker raise ValueError(tag + ' is not a known tag.') 220*90c8c64dSAndroid Build Coastguard Worker 221*90c8c64dSAndroid Build Coastguard Worker 222*90c8c64dSAndroid Build Coastguard Workerdef _read_lsdump_paths(lsdump_paths_file_path, arches, lsdump_filter): 223*90c8c64dSAndroid Build Coastguard Worker """Read lsdump paths from lsdump_paths.txt for each libname and variant. 224*90c8c64dSAndroid Build Coastguard Worker 225*90c8c64dSAndroid Build Coastguard Worker This function returns a dictionary, {lib_name: {arch_cpu: {tag: path}}}. 226*90c8c64dSAndroid Build Coastguard Worker For example, 227*90c8c64dSAndroid Build Coastguard Worker { 228*90c8c64dSAndroid Build Coastguard Worker "libc": { 229*90c8c64dSAndroid Build Coastguard Worker "x86_x86_64": { 230*90c8c64dSAndroid Build Coastguard Worker "NDK": "path/to/libc.so.lsdump" 231*90c8c64dSAndroid Build Coastguard Worker } 232*90c8c64dSAndroid Build Coastguard Worker } 233*90c8c64dSAndroid Build Coastguard Worker } 234*90c8c64dSAndroid Build Coastguard Worker """ 235*90c8c64dSAndroid Build Coastguard Worker lsdump_paths = collections.defaultdict( 236*90c8c64dSAndroid Build Coastguard Worker lambda: collections.defaultdict(dict)) 237*90c8c64dSAndroid Build Coastguard Worker suffixes = collections.defaultdict( 238*90c8c64dSAndroid Build Coastguard Worker lambda: collections.defaultdict(dict)) 239*90c8c64dSAndroid Build Coastguard Worker 240*90c8c64dSAndroid Build Coastguard Worker with open(lsdump_paths_file_path, 'r') as lsdump_paths_file: 241*90c8c64dSAndroid Build Coastguard Worker for line in lsdump_paths_file: 242*90c8c64dSAndroid Build Coastguard Worker if not line.strip(): 243*90c8c64dSAndroid Build Coastguard Worker continue 244*90c8c64dSAndroid Build Coastguard Worker tag, path = (x.strip() for x in line.split(':', 1)) 245*90c8c64dSAndroid Build Coastguard Worker dir_path, filename = os.path.split(path) 246*90c8c64dSAndroid Build Coastguard Worker libname = _strip_dump_name_ext(filename) 247*90c8c64dSAndroid Build Coastguard Worker if not lsdump_filter(tag, libname): 248*90c8c64dSAndroid Build Coastguard Worker continue 249*90c8c64dSAndroid Build Coastguard Worker # dir_path may contain soong config hash. 250*90c8c64dSAndroid Build Coastguard Worker # For example, the following dir_paths are valid. 251*90c8c64dSAndroid Build Coastguard Worker # android_x86_x86_64_shared/012abc/libc.so.lsdump 252*90c8c64dSAndroid Build Coastguard Worker # android_x86_x86_64_shared/libc.so.lsdump 253*90c8c64dSAndroid Build Coastguard Worker dirnames = [] 254*90c8c64dSAndroid Build Coastguard Worker dir_path, dirname = os.path.split(dir_path) 255*90c8c64dSAndroid Build Coastguard Worker dirnames.append(dirname) 256*90c8c64dSAndroid Build Coastguard Worker dirname = os.path.basename(dir_path) 257*90c8c64dSAndroid Build Coastguard Worker dirnames.append(dirname) 258*90c8c64dSAndroid Build Coastguard Worker for arch in arches: 259*90c8c64dSAndroid Build Coastguard Worker arch_cpu = arch.get_arch_cpu_str() 260*90c8c64dSAndroid Build Coastguard Worker prefix = _get_module_variant_dir_name(tag, arch_cpu) 261*90c8c64dSAndroid Build Coastguard Worker variant = next((d for d in dirnames if d.startswith(prefix)), 262*90c8c64dSAndroid Build Coastguard Worker None) 263*90c8c64dSAndroid Build Coastguard Worker if not variant: 264*90c8c64dSAndroid Build Coastguard Worker continue 265*90c8c64dSAndroid Build Coastguard Worker new_suffix = variant[len(prefix):] 266*90c8c64dSAndroid Build Coastguard Worker old_suffix = suffixes[libname][arch_cpu].get(tag) 267*90c8c64dSAndroid Build Coastguard Worker if (not old_suffix or 268*90c8c64dSAndroid Build Coastguard Worker _get_module_variant_sort_key(new_suffix) > 269*90c8c64dSAndroid Build Coastguard Worker _get_module_variant_sort_key(old_suffix)): 270*90c8c64dSAndroid Build Coastguard Worker lsdump_paths[libname][arch_cpu][tag] = path 271*90c8c64dSAndroid Build Coastguard Worker suffixes[libname][arch_cpu][tag] = new_suffix 272*90c8c64dSAndroid Build Coastguard Worker return lsdump_paths 273*90c8c64dSAndroid Build Coastguard Worker 274*90c8c64dSAndroid Build Coastguard Worker 275*90c8c64dSAndroid Build Coastguard Workerdef read_lsdump_paths(build_target, arches, lsdump_filter, build): 276*90c8c64dSAndroid Build Coastguard Worker """Build lsdump_paths.txt and read the paths.""" 277*90c8c64dSAndroid Build Coastguard Worker lsdump_paths_file_path = get_lsdump_paths_file_path(build_target) 278*90c8c64dSAndroid Build Coastguard Worker lsdump_paths_file_abspath = os.path.join(AOSP_DIR, lsdump_paths_file_path) 279*90c8c64dSAndroid Build Coastguard Worker if build: 280*90c8c64dSAndroid Build Coastguard Worker if os.path.lexists(lsdump_paths_file_abspath): 281*90c8c64dSAndroid Build Coastguard Worker os.unlink(lsdump_paths_file_abspath) 282*90c8c64dSAndroid Build Coastguard Worker make_targets(build_target, [lsdump_paths_file_path]) 283*90c8c64dSAndroid Build Coastguard Worker return _read_lsdump_paths(lsdump_paths_file_abspath, arches, lsdump_filter) 284*90c8c64dSAndroid Build Coastguard Worker 285*90c8c64dSAndroid Build Coastguard Worker 286*90c8c64dSAndroid Build Coastguard Workerdef find_lib_lsdumps(lsdump_paths, libs, arch): 287*90c8c64dSAndroid Build Coastguard Worker """Find the lsdump corresponding to libs for the given architecture. 288*90c8c64dSAndroid Build Coastguard Worker 289*90c8c64dSAndroid Build Coastguard Worker This function returns a list of (tag, absolute_path). 290*90c8c64dSAndroid Build Coastguard Worker For example, 291*90c8c64dSAndroid Build Coastguard Worker [ 292*90c8c64dSAndroid Build Coastguard Worker ( 293*90c8c64dSAndroid Build Coastguard Worker "NDK", 294*90c8c64dSAndroid Build Coastguard Worker "/path/to/libc.so.lsdump" 295*90c8c64dSAndroid Build Coastguard Worker ) 296*90c8c64dSAndroid Build Coastguard Worker ] 297*90c8c64dSAndroid Build Coastguard Worker """ 298*90c8c64dSAndroid Build Coastguard Worker arch_cpu = arch.get_arch_cpu_str() 299*90c8c64dSAndroid Build Coastguard Worker result = [] 300*90c8c64dSAndroid Build Coastguard Worker if libs: 301*90c8c64dSAndroid Build Coastguard Worker for lib_name in libs: 302*90c8c64dSAndroid Build Coastguard Worker if not (lib_name in lsdump_paths and 303*90c8c64dSAndroid Build Coastguard Worker arch_cpu in lsdump_paths[lib_name]): 304*90c8c64dSAndroid Build Coastguard Worker raise KeyError('Cannot find lsdump for %s, %s.' % 305*90c8c64dSAndroid Build Coastguard Worker (lib_name, arch_cpu)) 306*90c8c64dSAndroid Build Coastguard Worker result.extend(lsdump_paths[lib_name][arch_cpu].items()) 307*90c8c64dSAndroid Build Coastguard Worker else: 308*90c8c64dSAndroid Build Coastguard Worker for arch_tag_path_dict in lsdump_paths.values(): 309*90c8c64dSAndroid Build Coastguard Worker result.extend(arch_tag_path_dict[arch_cpu].items()) 310*90c8c64dSAndroid Build Coastguard Worker return [(tag, os.path.join(AOSP_DIR, path)) for tag, path in result] 311*90c8c64dSAndroid Build Coastguard Worker 312*90c8c64dSAndroid Build Coastguard Worker 313*90c8c64dSAndroid Build Coastguard Workerdef run_abi_diff(old_dump_path, new_dump_path, output_path, arch_str, lib_name, 314*90c8c64dSAndroid Build Coastguard Worker flags): 315*90c8c64dSAndroid Build Coastguard Worker abi_diff_cmd = ['header-abi-diff', '-new', new_dump_path, '-old', 316*90c8c64dSAndroid Build Coastguard Worker old_dump_path, '-arch', arch_str, '-lib', lib_name, 317*90c8c64dSAndroid Build Coastguard Worker '-o', output_path] 318*90c8c64dSAndroid Build Coastguard Worker abi_diff_cmd += flags 319*90c8c64dSAndroid Build Coastguard Worker if '-input-format-old' not in flags: 320*90c8c64dSAndroid Build Coastguard Worker abi_diff_cmd += ['-input-format-old', DEFAULT_FORMAT] 321*90c8c64dSAndroid Build Coastguard Worker if '-input-format-new' not in flags: 322*90c8c64dSAndroid Build Coastguard Worker abi_diff_cmd += ['-input-format-new', DEFAULT_FORMAT] 323*90c8c64dSAndroid Build Coastguard Worker return subprocess.run(abi_diff_cmd).returncode 324*90c8c64dSAndroid Build Coastguard Worker 325*90c8c64dSAndroid Build Coastguard Worker 326*90c8c64dSAndroid Build Coastguard Workerdef run_and_read_abi_diff(old_dump_path, new_dump_path, arch_str, lib_name, 327*90c8c64dSAndroid Build Coastguard Worker flags=tuple()): 328*90c8c64dSAndroid Build Coastguard Worker with tempfile.TemporaryDirectory() as tmp: 329*90c8c64dSAndroid Build Coastguard Worker output_name = os.path.join(tmp, lib_name) + '.abidiff' 330*90c8c64dSAndroid Build Coastguard Worker result = run_abi_diff(old_dump_path, new_dump_path, output_name, 331*90c8c64dSAndroid Build Coastguard Worker arch_str, lib_name, flags) 332*90c8c64dSAndroid Build Coastguard Worker with open(output_name, 'r') as output_file: 333*90c8c64dSAndroid Build Coastguard Worker return result, output_file.read() 334*90c8c64dSAndroid Build Coastguard Worker 335*90c8c64dSAndroid Build Coastguard Worker 336*90c8c64dSAndroid Build Coastguard Workerdef get_build_vars(names, build_target): 337*90c8c64dSAndroid Build Coastguard Worker """ Get build system variable for the launched target.""" 338*90c8c64dSAndroid Build Coastguard Worker env = os.environ.copy() 339*90c8c64dSAndroid Build Coastguard Worker env['TARGET_PRODUCT'] = build_target.product 340*90c8c64dSAndroid Build Coastguard Worker env['TARGET_BUILD_VARIANT'] = build_target.variant 341*90c8c64dSAndroid Build Coastguard Worker if build_target.release: 342*90c8c64dSAndroid Build Coastguard Worker env['TARGET_RELEASE'] = build_target.release 343*90c8c64dSAndroid Build Coastguard Worker cmd = [ 344*90c8c64dSAndroid Build Coastguard Worker os.path.join('build', 'soong', 'soong_ui.bash'), 345*90c8c64dSAndroid Build Coastguard Worker '--dumpvars-mode', '-vars', ' '.join(names), 346*90c8c64dSAndroid Build Coastguard Worker ] 347*90c8c64dSAndroid Build Coastguard Worker 348*90c8c64dSAndroid Build Coastguard Worker proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, 349*90c8c64dSAndroid Build Coastguard Worker stderr=subprocess.PIPE, cwd=AOSP_DIR, env=env) 350*90c8c64dSAndroid Build Coastguard Worker out, err = proc.communicate() 351*90c8c64dSAndroid Build Coastguard Worker 352*90c8c64dSAndroid Build Coastguard Worker if proc.returncode != 0: 353*90c8c64dSAndroid Build Coastguard Worker print("error: %s" % err.decode('utf-8'), file=sys.stderr) 354*90c8c64dSAndroid Build Coastguard Worker return None 355*90c8c64dSAndroid Build Coastguard Worker 356*90c8c64dSAndroid Build Coastguard Worker build_vars = out.decode('utf-8').strip().splitlines() 357*90c8c64dSAndroid Build Coastguard Worker 358*90c8c64dSAndroid Build Coastguard Worker build_vars_list = [] 359*90c8c64dSAndroid Build Coastguard Worker for build_var in build_vars: 360*90c8c64dSAndroid Build Coastguard Worker value = build_var.partition('=')[2] 361*90c8c64dSAndroid Build Coastguard Worker build_vars_list.append(value.replace('\'', '')) 362*90c8c64dSAndroid Build Coastguard Worker return build_vars_list 363