1#!/usr/bin/env python3 2# Copyright (C) 2018 The Android Open Source Project 3# 4# Licensed under the Apache License, Version 2.0 (the "License"); 5# you may not use this file except in compliance with the License. 6# You may obtain a copy of the License at 7# 8# http://www.apache.org/licenses/LICENSE-2.0 9# 10# Unless required by applicable law or agreed to in writing, software 11# distributed under the License is distributed on an "AS IS" BASIS, 12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13# See the License for the specific language governing permissions and 14# limitations under the License. 15 16from __future__ import absolute_import 17from __future__ import division 18from __future__ import print_function 19import os 20import re 21import argparse 22import tempfile 23import subprocess 24import hashlib 25from compat import iteritems 26 27SOURCE_TARGET = [ 28 ('protos/perfetto/trace_processor/trace_processor.proto', 29 'python/perfetto/trace_processor/trace_processor.descriptor' 30 ), 31 ('protos/perfetto/metrics/metrics.proto', 32 'python/perfetto/trace_processor/metrics.descriptor'), 33] 34 35ROOT_DIR = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) 36 37SCRIPT_PATH = 'tools/gen_binary_descriptors' 38 39 40def hash_path(path): 41 hash = hashlib.sha1() 42 with open(os.path.join(ROOT_DIR, path), 'rb') as f: 43 hash.update(f.read()) 44 return hash.hexdigest() 45 46 47def find_protoc(): 48 for root, _, files in os.walk(os.path.join(ROOT_DIR, 'out')): 49 if 'protoc' in files: 50 return os.path.join(root, 'protoc') 51 return None 52 53 54def check(source, target): 55 assert os.path.exists(os.path.join(ROOT_DIR, target)), \ 56 'Output file {} does not exist and so cannot be checked'.format(target) 57 58 sha1_file = target + '.sha1' 59 assert os.path.exists(sha1_file), \ 60 'SHA1 file {} does not exist and so cannot be checked'.format(sha1_file) 61 62 with open(sha1_file, 'rb') as f: 63 s = f.read() 64 65 hashes = re.findall(r'// SHA1\((.*)\)\n// (.*)\n', s.decode()) 66 assert sorted([SCRIPT_PATH, source]) == sorted([key for key, _ in hashes]) 67 for path, expected_sha1 in hashes: 68 actual_sha1 = hash_path(os.path.join(ROOT_DIR, path)) 69 assert actual_sha1 == expected_sha1, \ 70 'In {} hash given for {} did not match'.format(target, path) 71 72 73def generate(source, target, protoc_path): 74 # delete=False + manual unlink is required for Windows. Otherwise the temp 75 # file is kept locked exclusively and unaccassible until it's destroyed. 76 with tempfile.NamedTemporaryFile(delete=False) as fdescriptor: 77 subprocess.check_call([ 78 protoc_path, 79 '--include_imports', 80 '--proto_path=.', 81 '--proto_path=' + \ 82 os.path.join(ROOT_DIR, "buildtools", "protobuf", "src"), 83 '--descriptor_set_out={}'.format(fdescriptor.name), 84 source, 85 ], cwd=ROOT_DIR) 86 87 s = fdescriptor.read() 88 fdescriptor.close() 89 os.remove(fdescriptor.name) 90 with open(target, 'wb') as out: 91 out.write(s) 92 93 sha1_path = target + '.sha1' 94 with open(sha1_path, 'wb') as c: 95 c.write(""" 96// SHA1({script_path}) 97// {script_hash} 98// SHA1({source_path}) 99// {source_hash} 100 """.format( 101 script_path=SCRIPT_PATH, 102 script_hash=hash_path(__file__), 103 source_path=source, 104 source_hash=hash_path(os.path.join(source)), 105 ).encode()) 106 107 108def main(): 109 parser = argparse.ArgumentParser() 110 parser.add_argument('--check-only', action='store_true') 111 parser.add_argument('--protoc') 112 args = parser.parse_args() 113 114 try: 115 for source, target in SOURCE_TARGET: 116 if args.check_only: 117 check(source, target) 118 else: 119 protoc = args.protoc or find_protoc() 120 assert protoc, 'protoc not found specific (--protoc PROTOC_PATH)' 121 assert os.path.exists(protoc), '{} does not exist'.format(protoc) 122 if protoc is not args.protoc: 123 print('Using protoc: {}'.format(protoc)) 124 generate(source, target, protoc) 125 except AssertionError as e: 126 if not str(e): 127 raise 128 print('Error: {}'.format(e)) 129 return 1 130 131 132if __name__ == '__main__': 133 exit(main()) 134