1*6dbdd20aSAndroid Build Coastguard Worker#!/usr/bin/env python3 2*6dbdd20aSAndroid Build Coastguard Worker# Copyright (C) 2019 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 Workerimport os 18*6dbdd20aSAndroid Build Coastguard Workerimport sys 19*6dbdd20aSAndroid Build Coastguard Worker 20*6dbdd20aSAndroid Build Coastguard Worker# Converts the SQL metrics for trace processor into a C++ header with the SQL 21*6dbdd20aSAndroid Build Coastguard Worker# as a string constant to allow trace processor to exectue the metrics. 22*6dbdd20aSAndroid Build Coastguard Worker 23*6dbdd20aSAndroid Build Coastguard WorkerREPLACEMENT_HEADER = '''/* 24*6dbdd20aSAndroid Build Coastguard Worker * Copyright (C) 2023 The Android Open Source Project 25*6dbdd20aSAndroid Build Coastguard Worker * 26*6dbdd20aSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 27*6dbdd20aSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 28*6dbdd20aSAndroid Build Coastguard Worker * You may obtain a copy of the License at 29*6dbdd20aSAndroid Build Coastguard Worker * 30*6dbdd20aSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 31*6dbdd20aSAndroid Build Coastguard Worker * 32*6dbdd20aSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 33*6dbdd20aSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 34*6dbdd20aSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 35*6dbdd20aSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 36*6dbdd20aSAndroid Build Coastguard Worker * limitations under the License. 37*6dbdd20aSAndroid Build Coastguard Worker */ 38*6dbdd20aSAndroid Build Coastguard Worker 39*6dbdd20aSAndroid Build Coastguard Worker/* 40*6dbdd20aSAndroid Build Coastguard Worker ******************************************************************************* 41*6dbdd20aSAndroid Build Coastguard Worker * AUTOGENERATED BY tools/gen_amalgamated_sql.py - DO NOT EDIT 42*6dbdd20aSAndroid Build Coastguard Worker ******************************************************************************* 43*6dbdd20aSAndroid Build Coastguard Worker */ 44*6dbdd20aSAndroid Build Coastguard Worker 45*6dbdd20aSAndroid Build Coastguard Worker #include <string.h> 46*6dbdd20aSAndroid Build Coastguard Worker''' 47*6dbdd20aSAndroid Build Coastguard Worker 48*6dbdd20aSAndroid Build Coastguard WorkerNAMESPACE_BEGIN = ''' 49*6dbdd20aSAndroid Build Coastguard Workernamespace perfetto {{ 50*6dbdd20aSAndroid Build Coastguard Workernamespace trace_processor {{ 51*6dbdd20aSAndroid Build Coastguard Workernamespace {} {{ 52*6dbdd20aSAndroid Build Coastguard Worker''' 53*6dbdd20aSAndroid Build Coastguard Worker 54*6dbdd20aSAndroid Build Coastguard WorkerNAMESPACE_END = ''' 55*6dbdd20aSAndroid Build Coastguard Worker}} // namespace {} 56*6dbdd20aSAndroid Build Coastguard Worker}} // namespace trace_processor 57*6dbdd20aSAndroid Build Coastguard Worker}} // namespace perfetto 58*6dbdd20aSAndroid Build Coastguard Worker''' 59*6dbdd20aSAndroid Build Coastguard Worker 60*6dbdd20aSAndroid Build Coastguard WorkerFILE_TO_SQL_STRUCT = ''' 61*6dbdd20aSAndroid Build Coastguard Workerstruct FileToSql { 62*6dbdd20aSAndroid Build Coastguard Worker const char* path; 63*6dbdd20aSAndroid Build Coastguard Worker const char* sql; 64*6dbdd20aSAndroid Build Coastguard Worker}; 65*6dbdd20aSAndroid Build Coastguard Worker''' 66*6dbdd20aSAndroid Build Coastguard Worker 67*6dbdd20aSAndroid Build Coastguard Worker 68*6dbdd20aSAndroid Build Coastguard Workerdef filename_to_variable(filename: str): 69*6dbdd20aSAndroid Build Coastguard Worker return "k" + "".join([ 70*6dbdd20aSAndroid Build Coastguard Worker x.capitalize() 71*6dbdd20aSAndroid Build Coastguard Worker for x in filename.replace(os.path.sep, '_').replace('-', '_').split("_") 72*6dbdd20aSAndroid Build Coastguard Worker ]) 73*6dbdd20aSAndroid Build Coastguard Worker 74*6dbdd20aSAndroid Build Coastguard Worker 75*6dbdd20aSAndroid Build Coastguard Workerdef main(): 76*6dbdd20aSAndroid Build Coastguard Worker parser = argparse.ArgumentParser() 77*6dbdd20aSAndroid Build Coastguard Worker parser.add_argument('--namespace', required=True) 78*6dbdd20aSAndroid Build Coastguard Worker parser.add_argument('--cpp-out', required=True) 79*6dbdd20aSAndroid Build Coastguard Worker parser.add_argument('--root-dir', default=None) 80*6dbdd20aSAndroid Build Coastguard Worker parser.add_argument('--input-list-file') 81*6dbdd20aSAndroid Build Coastguard Worker parser.add_argument('sql_files', nargs='*') 82*6dbdd20aSAndroid Build Coastguard Worker args = parser.parse_args() 83*6dbdd20aSAndroid Build Coastguard Worker 84*6dbdd20aSAndroid Build Coastguard Worker if args.input_list_file and args.sql_files: 85*6dbdd20aSAndroid Build Coastguard Worker print("Only one of --input-list-file and list of SQL files expected") 86*6dbdd20aSAndroid Build Coastguard Worker return 1 87*6dbdd20aSAndroid Build Coastguard Worker 88*6dbdd20aSAndroid Build Coastguard Worker sql_files = [] 89*6dbdd20aSAndroid Build Coastguard Worker if args.input_list_file: 90*6dbdd20aSAndroid Build Coastguard Worker with open(args.input_list_file, 'r') as input_list_file: 91*6dbdd20aSAndroid Build Coastguard Worker for line in input_list_file.read().splitlines(): 92*6dbdd20aSAndroid Build Coastguard Worker sql_files.append(line) 93*6dbdd20aSAndroid Build Coastguard Worker else: 94*6dbdd20aSAndroid Build Coastguard Worker sql_files = args.sql_files 95*6dbdd20aSAndroid Build Coastguard Worker 96*6dbdd20aSAndroid Build Coastguard Worker # Unfortunately we cannot always pass this in as an arg as soong does not 97*6dbdd20aSAndroid Build Coastguard Worker # provide us a way to get the path to the Perfetto source directory. This 98*6dbdd20aSAndroid Build Coastguard Worker # fails on empty path but it's a price worth paying to have to use gross hacks 99*6dbdd20aSAndroid Build Coastguard Worker # in Soong. 100*6dbdd20aSAndroid Build Coastguard Worker root_dir = args.root_dir if args.root_dir else os.path.commonpath(sql_files) 101*6dbdd20aSAndroid Build Coastguard Worker 102*6dbdd20aSAndroid Build Coastguard Worker # Extract the SQL output from each file. 103*6dbdd20aSAndroid Build Coastguard Worker sql_outputs = {} 104*6dbdd20aSAndroid Build Coastguard Worker for file_name in sql_files: 105*6dbdd20aSAndroid Build Coastguard Worker with open(file_name, 'r') as f: 106*6dbdd20aSAndroid Build Coastguard Worker relpath = os.path.relpath(file_name, root_dir) 107*6dbdd20aSAndroid Build Coastguard Worker 108*6dbdd20aSAndroid Build Coastguard Worker # We've had bugs (e.g. b/264711057) when Soong's common path logic breaks 109*6dbdd20aSAndroid Build Coastguard Worker # and ends up with a bunch of ../ prefixing the path: disallow any ../ 110*6dbdd20aSAndroid Build Coastguard Worker # as this should never be a valid in our C++ output. 111*6dbdd20aSAndroid Build Coastguard Worker assert '../' not in relpath 112*6dbdd20aSAndroid Build Coastguard Worker sql_outputs[relpath] = f.read() 113*6dbdd20aSAndroid Build Coastguard Worker 114*6dbdd20aSAndroid Build Coastguard Worker with open(args.cpp_out, 'w+') as output: 115*6dbdd20aSAndroid Build Coastguard Worker output.write(REPLACEMENT_HEADER) 116*6dbdd20aSAndroid Build Coastguard Worker output.write(NAMESPACE_BEGIN.format(args.namespace)) 117*6dbdd20aSAndroid Build Coastguard Worker 118*6dbdd20aSAndroid Build Coastguard Worker # Create the C++ variable for each SQL file. 119*6dbdd20aSAndroid Build Coastguard Worker for path, sql in sql_outputs.items(): 120*6dbdd20aSAndroid Build Coastguard Worker variable = filename_to_variable(os.path.splitext(path)[0]) 121*6dbdd20aSAndroid Build Coastguard Worker output.write('\nconst char {}[] = '.format(variable)) 122*6dbdd20aSAndroid Build Coastguard Worker # MSVC doesn't like string literals that are individually longer than 16k. 123*6dbdd20aSAndroid Build Coastguard Worker # However it's still fine "if" "we" "concatenate" "many" "of" "them". 124*6dbdd20aSAndroid Build Coastguard Worker # This code splits the sql in string literals of ~1000 chars each. 125*6dbdd20aSAndroid Build Coastguard Worker line_groups = [''] 126*6dbdd20aSAndroid Build Coastguard Worker for line in sql.split('\n'): 127*6dbdd20aSAndroid Build Coastguard Worker line_groups[-1] += line + '\n' 128*6dbdd20aSAndroid Build Coastguard Worker if len(line_groups[-1]) > 1000: 129*6dbdd20aSAndroid Build Coastguard Worker line_groups.append('') 130*6dbdd20aSAndroid Build Coastguard Worker 131*6dbdd20aSAndroid Build Coastguard Worker for line in line_groups: 132*6dbdd20aSAndroid Build Coastguard Worker output.write('R"_d3l1m1t3r_({})_d3l1m1t3r_"\n'.format(line)) 133*6dbdd20aSAndroid Build Coastguard Worker output.write(';\n') 134*6dbdd20aSAndroid Build Coastguard Worker 135*6dbdd20aSAndroid Build Coastguard Worker output.write(FILE_TO_SQL_STRUCT) 136*6dbdd20aSAndroid Build Coastguard Worker 137*6dbdd20aSAndroid Build Coastguard Worker # Create mapping of filename to variable name for each variable. 138*6dbdd20aSAndroid Build Coastguard Worker output.write("\nconst FileToSql kFileToSql[] = {") 139*6dbdd20aSAndroid Build Coastguard Worker for path in sql_outputs.keys(): 140*6dbdd20aSAndroid Build Coastguard Worker variable = filename_to_variable(os.path.splitext(path)[0]) 141*6dbdd20aSAndroid Build Coastguard Worker 142*6dbdd20aSAndroid Build Coastguard Worker # This is for Windows which has \ as a path separator. 143*6dbdd20aSAndroid Build Coastguard Worker path = path.replace("\\", "/") 144*6dbdd20aSAndroid Build Coastguard Worker output.write('\n {{"{}", {}}},\n'.format(path, variable)) 145*6dbdd20aSAndroid Build Coastguard Worker output.write("};\n") 146*6dbdd20aSAndroid Build Coastguard Worker 147*6dbdd20aSAndroid Build Coastguard Worker output.write(NAMESPACE_END.format(args.namespace)) 148*6dbdd20aSAndroid Build Coastguard Worker 149*6dbdd20aSAndroid Build Coastguard Worker return 0 150*6dbdd20aSAndroid Build Coastguard Worker 151*6dbdd20aSAndroid Build Coastguard Worker 152*6dbdd20aSAndroid Build Coastguard Workerif __name__ == '__main__': 153*6dbdd20aSAndroid Build Coastguard Worker sys.exit(main()) 154