1*6dbdd20aSAndroid Build Coastguard Worker#!/usr/bin/env python3 2*6dbdd20aSAndroid Build Coastguard Worker# Copyright (C) 2022 The Android Open Source Project 3*6dbdd20aSAndroid Build Coastguard Worker# 4*6dbdd20aSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); 5*6dbdd20aSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 6*6dbdd20aSAndroid Build Coastguard Worker# You may obtain a copy of the License at 7*6dbdd20aSAndroid Build Coastguard Worker# 8*6dbdd20aSAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 9*6dbdd20aSAndroid Build Coastguard Worker# 10*6dbdd20aSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 11*6dbdd20aSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, 12*6dbdd20aSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*6dbdd20aSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 14*6dbdd20aSAndroid Build Coastguard Worker# limitations under the License. 15*6dbdd20aSAndroid Build Coastguard Worker 16*6dbdd20aSAndroid Build Coastguard Workerimport argparse 17*6dbdd20aSAndroid Build Coastguard Workerfrom dataclasses import dataclass 18*6dbdd20aSAndroid Build Coastguard Workerimport os 19*6dbdd20aSAndroid Build Coastguard Workerimport re 20*6dbdd20aSAndroid Build Coastguard Workerimport sys 21*6dbdd20aSAndroid Build Coastguard Workerfrom typing import Dict 22*6dbdd20aSAndroid Build Coastguard Workerfrom typing import List 23*6dbdd20aSAndroid Build Coastguard Workerfrom typing import Set 24*6dbdd20aSAndroid Build Coastguard Worker 25*6dbdd20aSAndroid Build Coastguard Worker# Allow importing of root-relative modules. 26*6dbdd20aSAndroid Build Coastguard WorkerROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 27*6dbdd20aSAndroid Build Coastguard Workersys.path.append(os.path.join(ROOT_DIR)) 28*6dbdd20aSAndroid Build Coastguard Worker 29*6dbdd20aSAndroid Build Coastguard Worker#pylint: disable=wrong-import-position 30*6dbdd20aSAndroid Build Coastguard Workerfrom python.generators.trace_processor_table.serialize import serialize_header 31*6dbdd20aSAndroid Build Coastguard Workerfrom python.generators.trace_processor_table.util import find_table_deps 32*6dbdd20aSAndroid Build Coastguard Workerfrom python.generators.trace_processor_table.util import ParsedTable 33*6dbdd20aSAndroid Build Coastguard Workerfrom python.generators.trace_processor_table.util import parse_tables_from_modules 34*6dbdd20aSAndroid Build Coastguard Worker#pylint: enable=wrong-import-position 35*6dbdd20aSAndroid Build Coastguard Worker 36*6dbdd20aSAndroid Build Coastguard Worker# Suffix which replaces the .py extension for all input modules. 37*6dbdd20aSAndroid Build Coastguard WorkerOUT_HEADER_SUFFIX = '_py.h' 38*6dbdd20aSAndroid Build Coastguard Worker 39*6dbdd20aSAndroid Build Coastguard Worker 40*6dbdd20aSAndroid Build Coastguard Worker@dataclass 41*6dbdd20aSAndroid Build Coastguard Workerclass Header: 42*6dbdd20aSAndroid Build Coastguard Worker """Represents a Python module which will be converted to a header.""" 43*6dbdd20aSAndroid Build Coastguard Worker tables: List[ParsedTable] 44*6dbdd20aSAndroid Build Coastguard Worker 45*6dbdd20aSAndroid Build Coastguard Worker 46*6dbdd20aSAndroid Build Coastguard Workerdef main(): 47*6dbdd20aSAndroid Build Coastguard Worker """Main function.""" 48*6dbdd20aSAndroid Build Coastguard Worker parser = argparse.ArgumentParser() 49*6dbdd20aSAndroid Build Coastguard Worker parser.add_argument('--inputs', required=True, nargs='*') 50*6dbdd20aSAndroid Build Coastguard Worker parser.add_argument('--gen-dir', required=True) 51*6dbdd20aSAndroid Build Coastguard Worker parser.add_argument('--relative-input-dir') 52*6dbdd20aSAndroid Build Coastguard Worker parser.add_argument('--import-prefix', default='') 53*6dbdd20aSAndroid Build Coastguard Worker args = parser.parse_args() 54*6dbdd20aSAndroid Build Coastguard Worker 55*6dbdd20aSAndroid Build Coastguard Worker def get_relin_path(in_path: str): 56*6dbdd20aSAndroid Build Coastguard Worker if not args.relative_input_dir: 57*6dbdd20aSAndroid Build Coastguard Worker return in_path 58*6dbdd20aSAndroid Build Coastguard Worker return os.path.relpath(in_path, args.relative_input_dir) 59*6dbdd20aSAndroid Build Coastguard Worker 60*6dbdd20aSAndroid Build Coastguard Worker def get_relout_path(in_path: str): 61*6dbdd20aSAndroid Build Coastguard Worker return os.path.splitext(in_path)[0] + OUT_HEADER_SUFFIX 62*6dbdd20aSAndroid Build Coastguard Worker 63*6dbdd20aSAndroid Build Coastguard Worker def get_out_path(in_path: str): 64*6dbdd20aSAndroid Build Coastguard Worker return os.path.join(args.gen_dir, get_relout_path(in_path)) 65*6dbdd20aSAndroid Build Coastguard Worker 66*6dbdd20aSAndroid Build Coastguard Worker def get_header_path(in_path: str): 67*6dbdd20aSAndroid Build Coastguard Worker return os.path.join(args.import_prefix, get_relout_path(in_path)) 68*6dbdd20aSAndroid Build Coastguard Worker 69*6dbdd20aSAndroid Build Coastguard Worker def get_relin_path_from_module_path(module_path: str): 70*6dbdd20aSAndroid Build Coastguard Worker return module_path[module_path.rfind(os.sep + 'src') + 1:] 71*6dbdd20aSAndroid Build Coastguard Worker 72*6dbdd20aSAndroid Build Coastguard Worker modules = [ 73*6dbdd20aSAndroid Build Coastguard Worker # On Windows the path can contain '/' or os.sep, depending on how this 74*6dbdd20aSAndroid Build Coastguard Worker # script is executed. So we need to replace both. 75*6dbdd20aSAndroid Build Coastguard Worker os.path.splitext( 76*6dbdd20aSAndroid Build Coastguard Worker get_relin_path(i).replace('/', '.').replace(os.sep, '.'))[0] 77*6dbdd20aSAndroid Build Coastguard Worker for i in args.inputs 78*6dbdd20aSAndroid Build Coastguard Worker ] 79*6dbdd20aSAndroid Build Coastguard Worker headers: Dict[str, Header] = {} 80*6dbdd20aSAndroid Build Coastguard Worker for table in parse_tables_from_modules(modules): 81*6dbdd20aSAndroid Build Coastguard Worker input_path = get_relin_path_from_module_path(table.table.python_module) 82*6dbdd20aSAndroid Build Coastguard Worker header = headers.get(input_path, Header([])) 83*6dbdd20aSAndroid Build Coastguard Worker header.tables.append(table) 84*6dbdd20aSAndroid Build Coastguard Worker headers[input_path] = header 85*6dbdd20aSAndroid Build Coastguard Worker 86*6dbdd20aSAndroid Build Coastguard Worker for in_path, header in headers.items(): 87*6dbdd20aSAndroid Build Coastguard Worker out_path = get_out_path(in_path) 88*6dbdd20aSAndroid Build Coastguard Worker relout_path = get_relout_path(in_path) 89*6dbdd20aSAndroid Build Coastguard Worker 90*6dbdd20aSAndroid Build Coastguard Worker # Find all headers depended on by this table. These will be #include-ed when 91*6dbdd20aSAndroid Build Coastguard Worker # generating the header file below so ensure we remove ourself. 92*6dbdd20aSAndroid Build Coastguard Worker header_relout_deps: Set[str] = set() 93*6dbdd20aSAndroid Build Coastguard Worker for table in header.tables: 94*6dbdd20aSAndroid Build Coastguard Worker header_relout_deps = header_relout_deps.union([ 95*6dbdd20aSAndroid Build Coastguard Worker get_header_path(get_relin_path_from_module_path(c.python_module)) 96*6dbdd20aSAndroid Build Coastguard Worker for c in find_table_deps(table.table) 97*6dbdd20aSAndroid Build Coastguard Worker ]) 98*6dbdd20aSAndroid Build Coastguard Worker header_relout_deps.discard(relout_path) 99*6dbdd20aSAndroid Build Coastguard Worker 100*6dbdd20aSAndroid Build Coastguard Worker with open(out_path, 'w', encoding='utf8') as out: 101*6dbdd20aSAndroid Build Coastguard Worker ifdef_guard = re.sub(r'[^a-zA-Z0-9_-]', '_', relout_path).upper() + '_' 102*6dbdd20aSAndroid Build Coastguard Worker out.write( 103*6dbdd20aSAndroid Build Coastguard Worker serialize_header(ifdef_guard, header.tables, 104*6dbdd20aSAndroid Build Coastguard Worker sorted(header_relout_deps))) 105*6dbdd20aSAndroid Build Coastguard Worker out.write('\n') 106*6dbdd20aSAndroid Build Coastguard Worker 107*6dbdd20aSAndroid Build Coastguard Worker 108*6dbdd20aSAndroid Build Coastguard Workerif __name__ == '__main__': 109*6dbdd20aSAndroid Build Coastguard Worker sys.exit(main()) 110