1a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov#!/usr/bin/python 2a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov# 3a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov# This tool is used to compare headers between Bionic and NDK 4a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov# script should be in development/ndk/tools for correct roots autodetection 5a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov# 6a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov 7a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynovimport sys, os, os.path 8a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynovimport subprocess 9a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynovimport argparse, textwrap 10a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov 11a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynovclass FileCollector: 12a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov """Collect headers from Bionic and sysroot 13a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov 14a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov sysincludes data format: 15a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov sysincludes -- dict with arch as key 16a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov sysincludes[arch] -- dict with includes root as key 17a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov sysincludes[arch][root] -- dict with header name as key 18a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov sysincludes[arch][root][header] -- list [last_platform, ..., first_platform] 19a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov """ 20a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov 21a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov def __init__(self, platforms_root, archs): 22a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov """Init platform roots and structures before collecting""" 23a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov self.platforms = [] 24a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov self.archs = archs 25a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov self.sysincludes = {} 26a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov for arch in self.archs: 27a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov self.sysincludes[arch] = {} 28a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov 29a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov ## scaning available platforms ## 30a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov for dirname in os.listdir(platforms_root): 31a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov path = os.path.join(platforms_root, dirname) 32a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov if os.path.isdir(path) and ('android' in dirname): 33a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov self.platforms.append(dirname) 34a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov try: 35a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov self.platforms.sort(key = lambda s: int(s.split('-')[1])) 36a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov self.root = platforms_root 37a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov except Exception: 38a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov print 'Wrong platforms list \n{0}'.format(str(self.platforms)) 39a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov 40a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov def scan_dir(self, root): 41a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov """Non-recursive file scan in directory""" 42a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov files = [] 43a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov for filename in os.listdir(root): 44a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov if os.path.isfile(os.path.join(root, filename)): 45a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov files.append(filename) 46a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov return files 47a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov 48a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov def scan_includes(self, root): 49a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov """Recursive includes scan in given root""" 50a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov includes = [] 51a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov includes_root = os.path.join(root, 'include') 52a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov if not os.path.isdir(includes_root): 53a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov return includes 54a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov 55a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov ## recursive scanning ## 56a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov includes.append(('', self.scan_dir(includes_root))) 57a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov for dirname, dirnames, filenames in os.walk(includes_root): 58a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov for subdirname in dirnames: 59a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov path = os.path.join(dirname, subdirname) 60a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov relpath = os.path.relpath(path, includes_root) 61a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov includes.append((relpath, self.scan_dir(path))) 62a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov 63a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov return includes 64a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov 65a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov def scan_archs_includes(self, root): 66a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov """Scan includes for all defined archs in given root""" 67a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov includes = {} 68a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov includes['common'] = self.scan_includes(root) 69a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov 70a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov for arch in [a for a in self.archs if a != 'common']: 71a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov arch_root = os.path.join(root, arch) 72a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov includes[arch] = self.scan_includes(arch_root) 73a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov 74a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov return includes 75a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov 76a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov def scan_platform_includes(self, platform): 77a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov """Scan all platform includes of one layer""" 78a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov platform_root = os.path.join(self.root, platform) 79a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov return self.scan_archs_includes(platform_root) 80a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov 81a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov def scan_bionic_includes(self, bionic_root): 82a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov """Scan Bionic's libc includes""" 83a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov self.bionic_root = bionic_root 84a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov self.bionic_includes = self.scan_archs_includes(bionic_root) 85a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov 86a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov def append_sysincludes(self, arch, root, headers, platform): 87a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov """Merge new platform includes layer with current sysincludes""" 88a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov if not (root in self.sysincludes[arch]): 89a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov self.sysincludes[arch][root] = {} 90a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov 91a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov for include in headers: 92a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov if include in self.sysincludes[arch][root]: 93a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov last_platform = self.sysincludes[arch][root][include][0] 94a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov if platform != last_platform: 95a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov self.sysincludes[arch][root][include].insert(0, platform) 96a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov else: 97a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov self.sysincludes[arch][root][include] = [platform] 98a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov 99a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov def update_to_platform(self, platform): 100a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov """Update sysincludes state by applying new platform layer""" 101a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov new_includes = self.scan_platform_includes(platform) 102a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov for arch in self.archs: 103a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov for pack in new_includes[arch]: 104a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov self.append_sysincludes(arch, pack[0], pack[1], platform) 105a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov 106a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov def scan_sysincludes(self, target_platform): 107a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov """Fully automated sysincludes collector upto specified platform""" 108a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov version = int(target_platform.split('-')[1]) 109a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov layers = filter(lambda s: int(s.split('-')[1]) <= version, self.platforms) 110a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov for platform in layers: 111a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov self.update_to_platform(platform) 112a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov 113a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov 114a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynovclass BionicSysincludes: 115a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov def set_roots(self): 116a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov """Automated roots initialization (AOSP oriented)""" 117a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov script_root = os.path.dirname(os.path.realpath(__file__)) 118a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov self.aosp_root = os.path.normpath(os.path.join(script_root, '../../..')) 119a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov self.platforms_root = os.path.join(self.aosp_root, 'development/ndk/platforms') 120a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov self.bionic_root = os.path.join(self.aosp_root, 'bionic/libc') 121a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov 122a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov def scan_includes(self): 123a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov """Scan all required includes""" 124a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov self.collector = FileCollector(self.platforms_root, self.archs) 125a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov ## detecting latest platform ## 126a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov self.platforms = self.collector.platforms 127a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov latest_platform = self.platforms[-1:][0] 128a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov ## scanning both includes repositories ## 129a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov self.collector.scan_sysincludes(latest_platform) 130a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov self.collector.scan_bionic_includes(self.bionic_root) 131a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov ## scan results ## 132a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov self.sysincludes = self.collector.sysincludes 133a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov self.bionic_includes = self.collector.bionic_includes 134a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov 135a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov def git_diff(self, file_origin, file_probe): 136a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov """Difference routine based on git diff""" 137a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov try: 138a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov subprocess.check_output(['git', 'diff', '--no-index', file_origin, file_probe]) 139a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov except subprocess.CalledProcessError as error: 140a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov return error.output 141a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov return None 142a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov 143a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov def match_with_bionic_includes(self): 144a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov """Compare headers between Bionic and sysroot""" 145a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov self.diffs = {} 146a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov ## for every arch ## 147a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov for arch in self.archs: 148a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov arch_root = (lambda s: s if s != 'common' else '')(arch) 149a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov ## for every includes directory ## 150a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov for pack in self.bionic_includes[arch]: 151a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov root = pack[0] 152a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov path_bionic = os.path.join(self.bionic_root, arch_root, 'include', root) 153a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov ## for every header that both in Bionic and sysroot ## 154a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov for include in pack[1]: 155a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov if include in self.sysincludes[arch][root]: 156a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov ## completing paths ## 157a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov platform = self.sysincludes[arch][root][include][0] 158a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov file_origin = os.path.join(path_bionic, include) 159a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov file_probe = os.path.join(self.platforms_root, platform, arch_root, 'include', root, include) 160a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov ## comparison by git diff ## 161a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov output = self.git_diff(file_origin, file_probe) 162a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov if output is not None: 163a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov if arch not in self.diffs: 164a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov self.diffs[arch] = {} 165a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov if root not in self.diffs[arch]: 166a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov self.diffs[arch][root] = {} 167a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov ## storing git diff ## 168a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov self.diffs[arch][root][include] = output 169a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov 170a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov def print_history(self, arch, root, header): 171a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov """Print human-readable list header updates across platforms""" 172a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov history = self.sysincludes[arch][root][header] 173a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov for platform in self.platforms: 174a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov entry = (lambda s: s.split('-')[1] if s in history else '-')(platform) 175a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov print '{0:3}'.format(entry), 176a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov print '' 177a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov 178a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov def show_and_store_results(self): 179a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov """Print summary list of headers and write diff-report to file""" 180a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov try: 181a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov diff_fd = open(self.diff_file, 'w') 182a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov for arch in self.archs: 183a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov if arch not in self.diffs: 184a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov continue 185a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov print '{0}/'.format(arch) 186a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov roots = self.diffs[arch].keys() 187a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov roots.sort() 188a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov for root in roots: 189a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov print ' {0}/'.format((lambda s: s if s != '' else '../include')(root)) 190a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov includes = self.diffs[arch][root].keys() 191a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov includes.sort() 192a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov for include in includes: 193a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov print ' {0:32}'.format(include), 194a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov self.print_history(arch, root, include) 195a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov diff = self.diffs[arch][root][include] 196a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov diff_fd.write(diff) 197a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov diff_fd.write('\n\n') 198a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov print '' 199a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov print '' 200a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov 201a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov finally: 202a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov diff_fd.close() 203a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov 204a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov def main(self): 205a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov self.set_roots() 206a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov self.scan_includes() 207a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov self.match_with_bionic_includes() 208a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov self.show_and_store_results() 209a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov 210a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynovif __name__ == '__main__': 211a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov ## configuring command line parser ## 212a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov parser = argparse.ArgumentParser(formatter_class = argparse.RawTextHelpFormatter, 213a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov description = 'Headers comparison tool between bionic and NDK platforms') 214a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov parser.epilog = textwrap.dedent(''' 215a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov output format: 216a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov {architecture}/ 217a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov {directory}/ 218a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov {header name}.h {platforms history} 219a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov 220a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov platforms history format: 221a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov number X means header has been changed in android-X 222a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov `-\' means it is the same 223a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov 224a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov diff-report format: 225a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov git diff output for all headers 226a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov use --diff option to specify filename 227a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov ''') 228a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov 229a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov parser.add_argument('--archs', metavar = 'A', nargs = '+', 230a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov default = ['common', 'arm', 'x86', 'mips'], 231a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov help = 'list of architectures\n(default: common arm x86 mips)') 232a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov parser.add_argument('--diff', metavar = 'FILE', nargs = 1, 233a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov default = ['headers-diff-bionic-vs-ndk.diff'], 234a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov help = 'diff-report filename\n(default: `bionic-vs-sysincludes_report.diff\')') 235a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov 236a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov ## parsing arguments ## 237a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov args = parser.parse_args() 238a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov 239a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov ## doing work ## 240a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov app = BionicSysincludes() 241a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov app.archs = map((lambda s: 'arch-{0}'.format(s) if s != 'common' else s), args.archs) 242a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov app.diff_file = args.diff[0] 243a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov app.main() 244a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov 245a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov print 'Headers listed above are DIFFERENT in Bionic and NDK platforms' 246a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov print 'See `{0}\' for details'.format(app.diff_file) 247a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov print 'See --help for format description.' 248a67bdae6b1de43331cec363111a858d0da069b4dGrigoriy Kraynov print '' 249