#!/usr/bin/env python3 # Copyright (C) 2018 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. from __future__ import absolute_import from __future__ import division from __future__ import print_function import os import re import argparse import tempfile import subprocess import hashlib from compat import iteritems SOURCE_TARGET = [ ( 'protos/perfetto/trace_processor/trace_processor.proto', 'src/trace_processor/python/perfetto/trace_processor/trace_processor.descriptor' ), ( 'protos/perfetto/metrics/metrics.proto', 'src/trace_processor/python/perfetto/trace_processor/metrics.descriptor' ), ] ROOT_DIR = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) SCRIPT_PATH = 'tools/gen_binary_descriptors' def hash_path(path): hash = hashlib.sha1() with open(os.path.join(ROOT_DIR, path), 'rb') as f: hash.update(f.read()) return hash.hexdigest() def find_protoc(): for root, _, files in os.walk(os.path.join(ROOT_DIR, 'out')): if 'protoc' in files: return os.path.join(root, 'protoc') return None def check(source, target): assert os.path.exists(os.path.join(ROOT_DIR, target)), \ 'Output file {} does not exist and so cannot be checked'.format(target) sha1_file = target + '.sha1' assert os.path.exists(sha1_file), \ 'SHA1 file {} does not exist and so cannot be checked'.format(sha1_file) with open(sha1_file, 'rb') as f: s = f.read() hashes = re.findall(r'// SHA1\((.*)\)\n// (.*)\n', s.decode()) assert sorted([SCRIPT_PATH, source]) == sorted([key for key, _ in hashes]) for path, expected_sha1 in hashes: actual_sha1 = hash_path(os.path.join(ROOT_DIR, path)) assert actual_sha1 == expected_sha1, \ 'In {} hash given for {} did not match'.format(target, path) def generate(source, target, protoc_path): with tempfile.NamedTemporaryFile() as fdescriptor: subprocess.check_call([ protoc_path, '--include_imports', '--proto_path=.', '--proto_path=' + \ os.path.join(ROOT_DIR, "buildtools", "protobuf", "src"), '--descriptor_set_out={}'.format(fdescriptor.name), source, ], cwd=ROOT_DIR) s = fdescriptor.read() with open(target, 'wb') as out: out.write(s) sha1_path = target + '.sha1' with open(sha1_path, 'wb') as c: c.write(""" // SHA1({script_path}) // {script_hash} // SHA1({source_path}) // {source_hash} """.format( script_path=SCRIPT_PATH, script_hash=hash_path(__file__), source_path=source, source_hash=hash_path(os.path.join(source)), ).encode()) def main(): parser = argparse.ArgumentParser() parser.add_argument('--check-only', action='store_true') parser.add_argument('--protoc') args = parser.parse_args() try: for source, target in SOURCE_TARGET: if args.check_only: check(source, target) else: protoc = args.protoc or find_protoc() assert protoc, 'protoc not found specific (--protoc PROTOC_PATH)' assert os.path.exists(protoc), '{} does not exist'.format(protoc) if protoc is not args.protoc: print('Using protoc: {}'.format(protoc)) generate(source, target, protoc) except AssertionError as e: if not str(e): raise print('Error: {}'.format(e)) return 1 if __name__ == '__main__': exit(main())