1*61046927SAndroid Build Coastguard Worker#!/usr/bin/env python3 2*61046927SAndroid Build Coastguard Worker""" 3*61046927SAndroid Build Coastguard WorkerCheck for and replace aliases with their new names from vk.xml 4*61046927SAndroid Build Coastguard Worker""" 5*61046927SAndroid Build Coastguard Worker 6*61046927SAndroid Build Coastguard Workerimport argparse 7*61046927SAndroid Build Coastguard Workerimport pathlib 8*61046927SAndroid Build Coastguard Workerimport subprocess 9*61046927SAndroid Build Coastguard Workerimport sys 10*61046927SAndroid Build Coastguard Workerimport xml.etree.ElementTree as et 11*61046927SAndroid Build Coastguard Worker 12*61046927SAndroid Build Coastguard WorkerTHIS_FILE = pathlib.Path(__file__) 13*61046927SAndroid Build Coastguard WorkerCWD = pathlib.Path.cwd() 14*61046927SAndroid Build Coastguard Worker 15*61046927SAndroid Build Coastguard WorkerVK_XML = THIS_FILE.parent / 'vk.xml' 16*61046927SAndroid Build Coastguard WorkerEXCLUDE_PATHS = [ 17*61046927SAndroid Build Coastguard Worker VK_XML.relative_to(CWD).as_posix(), 18*61046927SAndroid Build Coastguard Worker 19*61046927SAndroid Build Coastguard Worker # These files come from other repos, there's no point checking and 20*61046927SAndroid Build Coastguard Worker # fixing them here as that would be overwritten in the next sync. 21*61046927SAndroid Build Coastguard Worker 'src/amd/vulkan/radix_sort/', 22*61046927SAndroid Build Coastguard Worker 'src/virtio/venus-protocol/', 23*61046927SAndroid Build Coastguard Worker] 24*61046927SAndroid Build Coastguard Worker 25*61046927SAndroid Build Coastguard Worker 26*61046927SAndroid Build Coastguard Workerdef get_aliases(xml_file: pathlib.Path): 27*61046927SAndroid Build Coastguard Worker """ 28*61046927SAndroid Build Coastguard Worker Get all the aliases defined in vk.xml 29*61046927SAndroid Build Coastguard Worker """ 30*61046927SAndroid Build Coastguard Worker xml = et.parse(xml_file) 31*61046927SAndroid Build Coastguard Worker 32*61046927SAndroid Build Coastguard Worker for node in ([] 33*61046927SAndroid Build Coastguard Worker + xml.findall('.//enum[@alias]') 34*61046927SAndroid Build Coastguard Worker + xml.findall('.//type[@alias]') 35*61046927SAndroid Build Coastguard Worker + xml.findall('.//command[@alias]') 36*61046927SAndroid Build Coastguard Worker ): 37*61046927SAndroid Build Coastguard Worker # Some renames only apply to some APIs 38*61046927SAndroid Build Coastguard Worker if 'api' in node.attrib and 'vulkan' not in node.attrib['api'].split(','): 39*61046927SAndroid Build Coastguard Worker continue 40*61046927SAndroid Build Coastguard Worker 41*61046927SAndroid Build Coastguard Worker yield node.attrib['name'], node.attrib['alias'] 42*61046927SAndroid Build Coastguard Worker 43*61046927SAndroid Build Coastguard Worker 44*61046927SAndroid Build Coastguard Workerdef remove_prefix(string: str, prefix: str): 45*61046927SAndroid Build Coastguard Worker """ 46*61046927SAndroid Build Coastguard Worker Remove prefix if string starts with it, and return the full string 47*61046927SAndroid Build Coastguard Worker otherwise. 48*61046927SAndroid Build Coastguard Worker """ 49*61046927SAndroid Build Coastguard Worker if not string.startswith(prefix): 50*61046927SAndroid Build Coastguard Worker return string 51*61046927SAndroid Build Coastguard Worker return string[len(prefix):] 52*61046927SAndroid Build Coastguard Worker 53*61046927SAndroid Build Coastguard Worker 54*61046927SAndroid Build Coastguard Worker# Function from https://stackoverflow.com/a/312464 55*61046927SAndroid Build Coastguard Workerdef chunks(lst: list, n: int): 56*61046927SAndroid Build Coastguard Worker """ 57*61046927SAndroid Build Coastguard Worker Yield successive n-sized chunks from lst. 58*61046927SAndroid Build Coastguard Worker """ 59*61046927SAndroid Build Coastguard Worker for i in range(0, len(lst), n): 60*61046927SAndroid Build Coastguard Worker yield lst[i:i + n] 61*61046927SAndroid Build Coastguard Worker 62*61046927SAndroid Build Coastguard Worker 63*61046927SAndroid Build Coastguard Workerdef main(paths: list[str]): 64*61046927SAndroid Build Coastguard Worker """ 65*61046927SAndroid Build Coastguard Worker Entrypoint; perform the search for all the aliases and replace them. 66*61046927SAndroid Build Coastguard Worker """ 67*61046927SAndroid Build Coastguard Worker def prepare_identifier(identifier: str) -> str: 68*61046927SAndroid Build Coastguard Worker prefixes_seen = [] 69*61046927SAndroid Build Coastguard Worker for prefix in [ 70*61046927SAndroid Build Coastguard Worker # Various macros prepend these, so they will not appear in the code using them. 71*61046927SAndroid Build Coastguard Worker # List generated using this command: 72*61046927SAndroid Build Coastguard Worker # $ prefixes=$(git grep -woiE 'VK_\w+_' -- src/ ':!src/vulkan/registry/' | cut -d: -f2 | sort -u) 73*61046927SAndroid Build Coastguard Worker # $ for prefix in $prefixes; do grep -q $prefix src/vulkan/registry/vk.xml && echo "'$prefix',"; done 74*61046927SAndroid Build Coastguard Worker # (the second part eliminates prefixes used only in mesa code and not upstream) 75*61046927SAndroid Build Coastguard Worker 'VK_BLEND_FACTOR_', 76*61046927SAndroid Build Coastguard Worker 'VK_BLEND_OP_', 77*61046927SAndroid Build Coastguard Worker 'VK_BORDER_COLOR_', 78*61046927SAndroid Build Coastguard Worker 'VK_COMMAND_BUFFER_RESET_', 79*61046927SAndroid Build Coastguard Worker 'VK_COMMAND_POOL_RESET_', 80*61046927SAndroid Build Coastguard Worker 'VK_COMPARE_OP_', 81*61046927SAndroid Build Coastguard Worker 'VK_COMPONENT_SWIZZLE_', 82*61046927SAndroid Build Coastguard Worker 'VK_DESCRIPTOR_TYPE_', 83*61046927SAndroid Build Coastguard Worker 'VK_DRIVER_ID_', 84*61046927SAndroid Build Coastguard Worker 'VK_DYNAMIC_STATE_', 85*61046927SAndroid Build Coastguard Worker 'VK_FORMAT_', 86*61046927SAndroid Build Coastguard Worker 'VK_IMAGE_ASPECT_MEMORY_PLANE_', 87*61046927SAndroid Build Coastguard Worker 'VK_IMAGE_ASPECT_PLANE_', 88*61046927SAndroid Build Coastguard Worker 'VK_IMAGE_USAGE_', 89*61046927SAndroid Build Coastguard Worker 'VK_NV_', 90*61046927SAndroid Build Coastguard Worker 'VK_PERFORMANCE_COUNTER_UNIT_', 91*61046927SAndroid Build Coastguard Worker 'VK_PIPELINE_BIND_POINT_', 92*61046927SAndroid Build Coastguard Worker 'VK_SAMPLER_ADDRESS_MODE_', 93*61046927SAndroid Build Coastguard Worker 'VK_SHADER_STAGE_TESSELLATION_', 94*61046927SAndroid Build Coastguard Worker 'VK_SHADER_STAGE_', 95*61046927SAndroid Build Coastguard Worker 'VK_STENCIL_OP_', 96*61046927SAndroid Build Coastguard Worker 'VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_', 97*61046927SAndroid Build Coastguard Worker 'VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_', 98*61046927SAndroid Build Coastguard Worker 'VK_STRUCTURE_TYPE_', 99*61046927SAndroid Build Coastguard Worker 'VK_USE_PLATFORM_', 100*61046927SAndroid Build Coastguard Worker 'VK_VERSION_', 101*61046927SAndroid Build Coastguard Worker 102*61046927SAndroid Build Coastguard Worker # Many places use the identifier without the `vk` prefix 103*61046927SAndroid Build Coastguard Worker # (eg. with the driver name as a prefix instead) 104*61046927SAndroid Build Coastguard Worker 'VK_', 105*61046927SAndroid Build Coastguard Worker 'Vk', 106*61046927SAndroid Build Coastguard Worker 'vk', 107*61046927SAndroid Build Coastguard Worker ]: 108*61046927SAndroid Build Coastguard Worker # The order matters! A shorter substring will match before a longer 109*61046927SAndroid Build Coastguard Worker # one, hiding its matches. 110*61046927SAndroid Build Coastguard Worker for prefix_seen in prefixes_seen: 111*61046927SAndroid Build Coastguard Worker assert not prefix.startswith(prefix_seen), f'{prefix_seen} must come before {prefix}' 112*61046927SAndroid Build Coastguard Worker prefixes_seen.append(prefix) 113*61046927SAndroid Build Coastguard Worker 114*61046927SAndroid Build Coastguard Worker identifier = remove_prefix(identifier, prefix) 115*61046927SAndroid Build Coastguard Worker 116*61046927SAndroid Build Coastguard Worker return identifier 117*61046927SAndroid Build Coastguard Worker 118*61046927SAndroid Build Coastguard Worker aliases = {} 119*61046927SAndroid Build Coastguard Worker for old_name, alias_for in get_aliases(VK_XML): 120*61046927SAndroid Build Coastguard Worker old_name = prepare_identifier(old_name) 121*61046927SAndroid Build Coastguard Worker alias_for = prepare_identifier(alias_for) 122*61046927SAndroid Build Coastguard Worker aliases[old_name] = alias_for 123*61046927SAndroid Build Coastguard Worker 124*61046927SAndroid Build Coastguard Worker print(f'Found {len(aliases)} aliases in {VK_XML.name}') 125*61046927SAndroid Build Coastguard Worker 126*61046927SAndroid Build Coastguard Worker # Some aliases have aliases 127*61046927SAndroid Build Coastguard Worker recursion_needs_checking = True 128*61046927SAndroid Build Coastguard Worker while recursion_needs_checking: 129*61046927SAndroid Build Coastguard Worker recursion_needs_checking = False 130*61046927SAndroid Build Coastguard Worker for old, new in aliases.items(): 131*61046927SAndroid Build Coastguard Worker if new in aliases: 132*61046927SAndroid Build Coastguard Worker aliases[old] = aliases[new] 133*61046927SAndroid Build Coastguard Worker recursion_needs_checking = True 134*61046927SAndroid Build Coastguard Worker 135*61046927SAndroid Build Coastguard Worker # Doing the whole search in a single command breaks grep, so only 136*61046927SAndroid Build Coastguard Worker # look for 500 aliases at a time. Searching them one at a time would 137*61046927SAndroid Build Coastguard Worker # be extremely slow. 138*61046927SAndroid Build Coastguard Worker files_with_aliases = set() 139*61046927SAndroid Build Coastguard Worker for aliases_chunk in chunks([*aliases], 500): 140*61046927SAndroid Build Coastguard Worker grep_cmd = [ 141*61046927SAndroid Build Coastguard Worker 'git', 142*61046927SAndroid Build Coastguard Worker 'grep', 143*61046927SAndroid Build Coastguard Worker '-rlP', 144*61046927SAndroid Build Coastguard Worker '|'.join(aliases_chunk), 145*61046927SAndroid Build Coastguard Worker ] + paths 146*61046927SAndroid Build Coastguard Worker search_output = subprocess.run( 147*61046927SAndroid Build Coastguard Worker grep_cmd, 148*61046927SAndroid Build Coastguard Worker check=False, 149*61046927SAndroid Build Coastguard Worker stdout=subprocess.PIPE, 150*61046927SAndroid Build Coastguard Worker stderr=subprocess.DEVNULL, 151*61046927SAndroid Build Coastguard Worker ).stdout.decode() 152*61046927SAndroid Build Coastguard Worker files_with_aliases.update(search_output.splitlines()) 153*61046927SAndroid Build Coastguard Worker 154*61046927SAndroid Build Coastguard Worker 155*61046927SAndroid Build Coastguard Worker def file_matches_path(file: str, path: str) -> bool: 156*61046927SAndroid Build Coastguard Worker # if path is a folder; match any file within 157*61046927SAndroid Build Coastguard Worker if path.endswith('/') and file.startswith(path): 158*61046927SAndroid Build Coastguard Worker return True 159*61046927SAndroid Build Coastguard Worker return file == path 160*61046927SAndroid Build Coastguard Worker 161*61046927SAndroid Build Coastguard Worker for excluded_path in EXCLUDE_PATHS: 162*61046927SAndroid Build Coastguard Worker files_with_aliases = { 163*61046927SAndroid Build Coastguard Worker file for file in files_with_aliases 164*61046927SAndroid Build Coastguard Worker if not file_matches_path(file, excluded_path) 165*61046927SAndroid Build Coastguard Worker } 166*61046927SAndroid Build Coastguard Worker 167*61046927SAndroid Build Coastguard Worker if not files_with_aliases: 168*61046927SAndroid Build Coastguard Worker print('No alias found in any file.') 169*61046927SAndroid Build Coastguard Worker sys.exit(0) 170*61046927SAndroid Build Coastguard Worker 171*61046927SAndroid Build Coastguard Worker print(f'{len(files_with_aliases)} files contain aliases:') 172*61046927SAndroid Build Coastguard Worker print('\n'.join(f'- {file}' for file in sorted(files_with_aliases))) 173*61046927SAndroid Build Coastguard Worker 174*61046927SAndroid Build Coastguard Worker command = [ 175*61046927SAndroid Build Coastguard Worker 'sed', 176*61046927SAndroid Build Coastguard Worker '-i', 177*61046927SAndroid Build Coastguard Worker ";".join([f's/{old}/{new}/g' for old, new in aliases.items()]), 178*61046927SAndroid Build Coastguard Worker ] 179*61046927SAndroid Build Coastguard Worker command += files_with_aliases 180*61046927SAndroid Build Coastguard Worker subprocess.check_call(command, stderr=subprocess.DEVNULL) 181*61046927SAndroid Build Coastguard Worker print('All aliases have been replaced') 182*61046927SAndroid Build Coastguard Worker 183*61046927SAndroid Build Coastguard Worker 184*61046927SAndroid Build Coastguard Workerif __name__ == '__main__': 185*61046927SAndroid Build Coastguard Worker parser = argparse.ArgumentParser() 186*61046927SAndroid Build Coastguard Worker parser.add_argument('paths', 187*61046927SAndroid Build Coastguard Worker nargs=argparse.ZERO_OR_MORE, 188*61046927SAndroid Build Coastguard Worker default=['src/'], 189*61046927SAndroid Build Coastguard Worker help='Limit script to these paths (default: `src/`)') 190*61046927SAndroid Build Coastguard Worker args = parser.parse_args() 191*61046927SAndroid Build Coastguard Worker main(**vars(args)) 192