1*90c8c64dSAndroid Build Coastguard Worker#!/usr/bin/env python3 2*90c8c64dSAndroid Build Coastguard Worker 3*90c8c64dSAndroid Build Coastguard Workerimport argparse 4*90c8c64dSAndroid Build Coastguard Workerimport fnmatch 5*90c8c64dSAndroid Build Coastguard Workerimport json 6*90c8c64dSAndroid Build Coastguard Workerimport os 7*90c8c64dSAndroid Build Coastguard Workerimport re 8*90c8c64dSAndroid Build Coastguard Workerimport sys 9*90c8c64dSAndroid Build Coastguard Worker 10*90c8c64dSAndroid Build Coastguard WorkerHELP_MSG = ''' 11*90c8c64dSAndroid Build Coastguard WorkerThis script analyses the usage of build-time variables which are defined in BoardConfig*.mk 12*90c8c64dSAndroid Build Coastguard Workerand used by framework modules (installed in system.img). Please 'lunch' and 'make' before 13*90c8c64dSAndroid Build Coastguard Workerrunning it. 14*90c8c64dSAndroid Build Coastguard Worker''' 15*90c8c64dSAndroid Build Coastguard Worker 16*90c8c64dSAndroid Build Coastguard WorkerTOP = os.environ.get('ANDROID_BUILD_TOP') 17*90c8c64dSAndroid Build Coastguard WorkerOUT = os.environ.get('OUT') 18*90c8c64dSAndroid Build Coastguard Worker 19*90c8c64dSAndroid Build Coastguard Workerwhite_list = [ 20*90c8c64dSAndroid Build Coastguard Worker 'TARGET_ARCH', 21*90c8c64dSAndroid Build Coastguard Worker 'TARGET_ARCH_VARIANT', 22*90c8c64dSAndroid Build Coastguard Worker 'TARGET_CPU_VARIANT', 23*90c8c64dSAndroid Build Coastguard Worker 'TARGET_CPU_ABI', 24*90c8c64dSAndroid Build Coastguard Worker 'TARGET_CPU_ABI2', 25*90c8c64dSAndroid Build Coastguard Worker 26*90c8c64dSAndroid Build Coastguard Worker 'TARGET_2ND_ARCH', 27*90c8c64dSAndroid Build Coastguard Worker 'TARGET_2ND_ARCH_VARIANT', 28*90c8c64dSAndroid Build Coastguard Worker 'TARGET_2ND_CPU_VARIANT', 29*90c8c64dSAndroid Build Coastguard Worker 'TARGET_2ND_CPU_ABI', 30*90c8c64dSAndroid Build Coastguard Worker 'TARGET_2ND_CPU_ABI2', 31*90c8c64dSAndroid Build Coastguard Worker 32*90c8c64dSAndroid Build Coastguard Worker 'TARGET_NO_BOOTLOADER', 33*90c8c64dSAndroid Build Coastguard Worker 'TARGET_NO_KERNEL', 34*90c8c64dSAndroid Build Coastguard Worker 'TARGET_NO_RADIOIMAGE', 35*90c8c64dSAndroid Build Coastguard Worker 'TARGET_NO_RECOVERY', 36*90c8c64dSAndroid Build Coastguard Worker 37*90c8c64dSAndroid Build Coastguard Worker 'TARGET_BOARD_PLATFORM', 38*90c8c64dSAndroid Build Coastguard Worker 39*90c8c64dSAndroid Build Coastguard Worker 'ARCH_ARM_HAVE_ARMV7A', 40*90c8c64dSAndroid Build Coastguard Worker 'ARCH_ARM_HAVE_NEON', 41*90c8c64dSAndroid Build Coastguard Worker 'ARCH_ARM_HAVE_VFP', 42*90c8c64dSAndroid Build Coastguard Worker 'ARCH_ARM_HAVE_VFP_D32', 43*90c8c64dSAndroid Build Coastguard Worker 44*90c8c64dSAndroid Build Coastguard Worker 'BUILD_NUMBER' 45*90c8c64dSAndroid Build Coastguard Worker] 46*90c8c64dSAndroid Build Coastguard Worker 47*90c8c64dSAndroid Build Coastguard Worker 48*90c8c64dSAndroid Build Coastguard Worker# used by find_board_configs_mks() and find_makefiles() 49*90c8c64dSAndroid Build Coastguard Workerdef find_files(folders, filter): 50*90c8c64dSAndroid Build Coastguard Worker ret = [] 51*90c8c64dSAndroid Build Coastguard Worker 52*90c8c64dSAndroid Build Coastguard Worker for folder in folders: 53*90c8c64dSAndroid Build Coastguard Worker for root, dirs, files in os.walk(os.path.join(TOP, folder), topdown=True): 54*90c8c64dSAndroid Build Coastguard Worker dirs[:] = [d for d in dirs if not d[0] == '.'] 55*90c8c64dSAndroid Build Coastguard Worker for file in files: 56*90c8c64dSAndroid Build Coastguard Worker if filter(file): 57*90c8c64dSAndroid Build Coastguard Worker ret.append(os.path.join(root, file)) 58*90c8c64dSAndroid Build Coastguard Worker 59*90c8c64dSAndroid Build Coastguard Worker return ret 60*90c8c64dSAndroid Build Coastguard Worker 61*90c8c64dSAndroid Build Coastguard Worker# find board configs (BoardConfig*.mk) 62*90c8c64dSAndroid Build Coastguard Workerdef find_board_config_mks(folders = ['build', 'device', 'vendor', 'hardware']): 63*90c8c64dSAndroid Build Coastguard Worker return find_files(folders, lambda x: 64*90c8c64dSAndroid Build Coastguard Worker fnmatch.fnmatch(x, 'BoardConfig*.mk')) 65*90c8c64dSAndroid Build Coastguard Worker 66*90c8c64dSAndroid Build Coastguard Worker# find makefiles (*.mk or Makefile) under specific folders 67*90c8c64dSAndroid Build Coastguard Workerdef find_makefiles(folders = ['system', 'frameworks', 'external']): 68*90c8c64dSAndroid Build Coastguard Worker return find_files(folders, lambda x: 69*90c8c64dSAndroid Build Coastguard Worker fnmatch.fnmatch(x, '*.mk') or fnmatch.fnmatch(x, 'Makefile')) 70*90c8c64dSAndroid Build Coastguard Worker 71*90c8c64dSAndroid Build Coastguard Worker# read module-info.json and find makefiles of modules in system image 72*90c8c64dSAndroid Build Coastguard Workerdef find_system_module_makefiles(): 73*90c8c64dSAndroid Build Coastguard Worker makefiles = [] 74*90c8c64dSAndroid Build Coastguard Worker out_system_path = os.path.join(OUT[len(TOP) + 1:], 'system') 75*90c8c64dSAndroid Build Coastguard Worker 76*90c8c64dSAndroid Build Coastguard Worker with open(os.path.join(OUT, 'module-info.json')) as module_info_json: 77*90c8c64dSAndroid Build Coastguard Worker module_info = json.load(module_info_json) 78*90c8c64dSAndroid Build Coastguard Worker for module in module_info: 79*90c8c64dSAndroid Build Coastguard Worker installs = module_info[module]['installed'] 80*90c8c64dSAndroid Build Coastguard Worker paths = module_info[module]['path'] 81*90c8c64dSAndroid Build Coastguard Worker 82*90c8c64dSAndroid Build Coastguard Worker installed_in_system = False 83*90c8c64dSAndroid Build Coastguard Worker 84*90c8c64dSAndroid Build Coastguard Worker for install in installs: 85*90c8c64dSAndroid Build Coastguard Worker if install.startswith(out_system_path): 86*90c8c64dSAndroid Build Coastguard Worker installed_in_system = True 87*90c8c64dSAndroid Build Coastguard Worker break 88*90c8c64dSAndroid Build Coastguard Worker 89*90c8c64dSAndroid Build Coastguard Worker if installed_in_system: 90*90c8c64dSAndroid Build Coastguard Worker for path in paths: 91*90c8c64dSAndroid Build Coastguard Worker makefile = os.path.join(TOP, path, 'Android.mk') 92*90c8c64dSAndroid Build Coastguard Worker makefiles.append(makefile) 93*90c8c64dSAndroid Build Coastguard Worker 94*90c8c64dSAndroid Build Coastguard Worker return makefiles 95*90c8c64dSAndroid Build Coastguard Worker 96*90c8c64dSAndroid Build Coastguard Worker# find variables defined in board_config_mks 97*90c8c64dSAndroid Build Coastguard Workerdef find_defined_variables(board_config_mks): 98*90c8c64dSAndroid Build Coastguard Worker re_def = re.compile('^[\s]*([\w\d_]*)[\s]*:=') 99*90c8c64dSAndroid Build Coastguard Worker variables = dict() 100*90c8c64dSAndroid Build Coastguard Worker 101*90c8c64dSAndroid Build Coastguard Worker for board_config_mk in board_config_mks: 102*90c8c64dSAndroid Build Coastguard Worker for line in open(board_config_mk, encoding='latin1'): 103*90c8c64dSAndroid Build Coastguard Worker mo = re_def.search(line) 104*90c8c64dSAndroid Build Coastguard Worker if mo is None: 105*90c8c64dSAndroid Build Coastguard Worker continue 106*90c8c64dSAndroid Build Coastguard Worker 107*90c8c64dSAndroid Build Coastguard Worker variable = mo.group(1) 108*90c8c64dSAndroid Build Coastguard Worker if variable in white_list: 109*90c8c64dSAndroid Build Coastguard Worker continue 110*90c8c64dSAndroid Build Coastguard Worker 111*90c8c64dSAndroid Build Coastguard Worker if variable not in variables: 112*90c8c64dSAndroid Build Coastguard Worker variables[variable] = set() 113*90c8c64dSAndroid Build Coastguard Worker 114*90c8c64dSAndroid Build Coastguard Worker variables[variable].add(board_config_mk[len(TOP) + 1:]) 115*90c8c64dSAndroid Build Coastguard Worker 116*90c8c64dSAndroid Build Coastguard Worker return variables 117*90c8c64dSAndroid Build Coastguard Worker 118*90c8c64dSAndroid Build Coastguard Worker# count variable usage in makefiles 119*90c8c64dSAndroid Build Coastguard Workerdef find_usage(variable, makefiles): 120*90c8c64dSAndroid Build Coastguard Worker re_usage = re.compile('\$\(' + variable + '\)') 121*90c8c64dSAndroid Build Coastguard Worker usage = set() 122*90c8c64dSAndroid Build Coastguard Worker 123*90c8c64dSAndroid Build Coastguard Worker for makefile in makefiles: 124*90c8c64dSAndroid Build Coastguard Worker if not os.path.isfile(makefile): 125*90c8c64dSAndroid Build Coastguard Worker # TODO: support bp 126*90c8c64dSAndroid Build Coastguard Worker continue 127*90c8c64dSAndroid Build Coastguard Worker 128*90c8c64dSAndroid Build Coastguard Worker with open(makefile, encoding='latin1') as mk_file: 129*90c8c64dSAndroid Build Coastguard Worker mk_str = mk_file.read() 130*90c8c64dSAndroid Build Coastguard Worker 131*90c8c64dSAndroid Build Coastguard Worker if re_usage.search(mk_str) is not None: 132*90c8c64dSAndroid Build Coastguard Worker usage.add(makefile[len(TOP) + 1:]) 133*90c8c64dSAndroid Build Coastguard Worker 134*90c8c64dSAndroid Build Coastguard Worker return usage 135*90c8c64dSAndroid Build Coastguard Worker 136*90c8c64dSAndroid Build Coastguard Workerdef main(): 137*90c8c64dSAndroid Build Coastguard Worker parser = argparse.ArgumentParser(description=HELP_MSG) 138*90c8c64dSAndroid Build Coastguard Worker parser.add_argument("-v", "--verbose", 139*90c8c64dSAndroid Build Coastguard Worker help="print definition and usage locations", 140*90c8c64dSAndroid Build Coastguard Worker action="store_true") 141*90c8c64dSAndroid Build Coastguard Worker args = parser.parse_args() 142*90c8c64dSAndroid Build Coastguard Worker 143*90c8c64dSAndroid Build Coastguard Worker print('TOP : ' + TOP) 144*90c8c64dSAndroid Build Coastguard Worker print('OUT : ' + OUT) 145*90c8c64dSAndroid Build Coastguard Worker print() 146*90c8c64dSAndroid Build Coastguard Worker 147*90c8c64dSAndroid Build Coastguard Worker sfe_makefiles = find_makefiles() 148*90c8c64dSAndroid Build Coastguard Worker system_module_makefiles = find_system_module_makefiles() 149*90c8c64dSAndroid Build Coastguard Worker board_config_mks = find_board_config_mks() 150*90c8c64dSAndroid Build Coastguard Worker variables = find_defined_variables(board_config_mks) 151*90c8c64dSAndroid Build Coastguard Worker 152*90c8c64dSAndroid Build Coastguard Worker if args.verbose: 153*90c8c64dSAndroid Build Coastguard Worker print('sfe_makefiles', len(sfe_makefiles)) 154*90c8c64dSAndroid Build Coastguard Worker print('system_module_makefiles', len(system_module_makefiles)) 155*90c8c64dSAndroid Build Coastguard Worker print('board_config_mks', len(board_config_mks)) 156*90c8c64dSAndroid Build Coastguard Worker print('variables', len(variables)) 157*90c8c64dSAndroid Build Coastguard Worker print() 158*90c8c64dSAndroid Build Coastguard Worker 159*90c8c64dSAndroid Build Coastguard Worker glossary = ( 160*90c8c64dSAndroid Build Coastguard Worker '*Output in CSV format\n\n' 161*90c8c64dSAndroid Build Coastguard Worker 162*90c8c64dSAndroid Build Coastguard Worker '*definition count :' 163*90c8c64dSAndroid Build Coastguard Worker ' This variable is defined in how many BoardConfig*.mk\'s\n' 164*90c8c64dSAndroid Build Coastguard Worker 165*90c8c64dSAndroid Build Coastguard Worker '*usage in SFE :' 166*90c8c64dSAndroid Build Coastguard Worker ' This variable is used by how many makefiles under system/, frameworks/ and external/ folders\n' 167*90c8c64dSAndroid Build Coastguard Worker 168*90c8c64dSAndroid Build Coastguard Worker '*usage in system image :' 169*90c8c64dSAndroid Build Coastguard Worker ' This variable is used by how many system image modules\n') 170*90c8c64dSAndroid Build Coastguard Worker 171*90c8c64dSAndroid Build Coastguard Worker csv_string = ( 172*90c8c64dSAndroid Build Coastguard Worker 'variable name,definition count,usage in SFE,usage in system image\n') 173*90c8c64dSAndroid Build Coastguard Worker 174*90c8c64dSAndroid Build Coastguard Worker for variable, locations in sorted(variables.items()): 175*90c8c64dSAndroid Build Coastguard Worker usage_in_sfe = find_usage(variable, sfe_makefiles) 176*90c8c64dSAndroid Build Coastguard Worker usage_of_system_modules = find_usage(variable, system_module_makefiles) 177*90c8c64dSAndroid Build Coastguard Worker usage = usage_in_sfe | usage_of_system_modules 178*90c8c64dSAndroid Build Coastguard Worker 179*90c8c64dSAndroid Build Coastguard Worker if len(usage) == 0: 180*90c8c64dSAndroid Build Coastguard Worker continue 181*90c8c64dSAndroid Build Coastguard Worker 182*90c8c64dSAndroid Build Coastguard Worker csv_string += ','.join([variable, 183*90c8c64dSAndroid Build Coastguard Worker str(len(locations)), 184*90c8c64dSAndroid Build Coastguard Worker str(len(usage_in_sfe)), 185*90c8c64dSAndroid Build Coastguard Worker str(len(usage_of_system_modules))]) + '\n' 186*90c8c64dSAndroid Build Coastguard Worker 187*90c8c64dSAndroid Build Coastguard Worker if args.verbose: 188*90c8c64dSAndroid Build Coastguard Worker print((variable + ' ').ljust(80, '=')) 189*90c8c64dSAndroid Build Coastguard Worker 190*90c8c64dSAndroid Build Coastguard Worker print('Defined in (' + str(len(locations)) + ') :') 191*90c8c64dSAndroid Build Coastguard Worker for location in sorted(locations): 192*90c8c64dSAndroid Build Coastguard Worker print(' ' + location) 193*90c8c64dSAndroid Build Coastguard Worker 194*90c8c64dSAndroid Build Coastguard Worker print('Used in (' + str(len(usage)) + ') :') 195*90c8c64dSAndroid Build Coastguard Worker for location in sorted(usage): 196*90c8c64dSAndroid Build Coastguard Worker print(' ' + location) 197*90c8c64dSAndroid Build Coastguard Worker 198*90c8c64dSAndroid Build Coastguard Worker print() 199*90c8c64dSAndroid Build Coastguard Worker 200*90c8c64dSAndroid Build Coastguard Worker if args.verbose: 201*90c8c64dSAndroid Build Coastguard Worker print('\n') 202*90c8c64dSAndroid Build Coastguard Worker 203*90c8c64dSAndroid Build Coastguard Worker print(glossary) 204*90c8c64dSAndroid Build Coastguard Worker print(csv_string) 205*90c8c64dSAndroid Build Coastguard Worker 206*90c8c64dSAndroid Build Coastguard Workerif __name__ == '__main__': 207*90c8c64dSAndroid Build Coastguard Worker if TOP is None: 208*90c8c64dSAndroid Build Coastguard Worker sys.exit('$ANDROID_BUILD_TOP is undefined, please lunch and make before running this script') 209*90c8c64dSAndroid Build Coastguard Worker 210*90c8c64dSAndroid Build Coastguard Worker if OUT is None: 211*90c8c64dSAndroid Build Coastguard Worker sys.exit('$OUT is undefined, please lunch and make before running this script') 212*90c8c64dSAndroid Build Coastguard Worker 213*90c8c64dSAndroid Build Coastguard Worker if not os.path.isfile(os.path.join(OUT, 'module-info.json')): 214*90c8c64dSAndroid Build Coastguard Worker sys.exit('module-info.json is missing, please lunch and make before running this script') 215*90c8c64dSAndroid Build Coastguard Worker 216*90c8c64dSAndroid Build Coastguard Worker main() 217*90c8c64dSAndroid Build Coastguard Worker 218