#!/usr/bin/env python3 # Copyright (C) 2022 The Android Open Source Project # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import argparse from dataclasses import dataclass import os import re import sys from typing import Dict from typing import List from typing import Set # Allow importing of root-relative modules. ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.append(os.path.join(ROOT_DIR)) #pylint: disable=wrong-import-position from python.generators.trace_processor_table.serialize import serialize_header from python.generators.trace_processor_table.util import find_table_deps from python.generators.trace_processor_table.util import ParsedTable from python.generators.trace_processor_table.util import parse_tables_from_modules #pylint: enable=wrong-import-position # Suffix which replaces the .py extension for all input modules. OUT_HEADER_SUFFIX = '_py.h' @dataclass class Header: """Represents a Python module which will be converted to a header.""" tables: List[ParsedTable] def main(): """Main function.""" parser = argparse.ArgumentParser() parser.add_argument('--inputs', required=True, nargs='*') parser.add_argument('--gen-dir', required=True) parser.add_argument('--relative-input-dir') parser.add_argument('--import-prefix', default='') args = parser.parse_args() def get_relin_path(in_path: str): if not args.relative_input_dir: return in_path return os.path.relpath(in_path, args.relative_input_dir) def get_relout_path(in_path: str): return os.path.splitext(in_path)[0] + OUT_HEADER_SUFFIX def get_out_path(in_path: str): return os.path.join(args.gen_dir, get_relout_path(in_path)) def get_header_path(in_path: str): return os.path.join(args.import_prefix, get_relout_path(in_path)) def get_relin_path_from_module_path(module_path: str): return module_path[module_path.rfind(os.sep + 'src') + 1:] modules = [ # On Windows the path can contain '/' or os.sep, depending on how this # script is executed. So we need to replace both. os.path.splitext( get_relin_path(i).replace('/', '.').replace(os.sep, '.'))[0] for i in args.inputs ] headers: Dict[str, Header] = {} for table in parse_tables_from_modules(modules): input_path = get_relin_path_from_module_path(table.table.python_module) header = headers.get(input_path, Header([])) header.tables.append(table) headers[input_path] = header for in_path, header in headers.items(): out_path = get_out_path(in_path) relout_path = get_relout_path(in_path) # Find all headers depended on by this table. These will be #include-ed when # generating the header file below so ensure we remove ourself. header_relout_deps: Set[str] = set() for table in header.tables: header_relout_deps = header_relout_deps.union([ get_header_path(get_relin_path_from_module_path(c.python_module)) for c in find_table_deps(table.table) ]) header_relout_deps.discard(relout_path) with open(out_path, 'w', encoding='utf8') as out: ifdef_guard = re.sub(r'[^a-zA-Z0-9_-]', '_', relout_path).upper() + '_' out.write( serialize_header(ifdef_guard, header.tables, sorted(header_relout_deps))) out.write('\n') if __name__ == '__main__': sys.exit(main())