1*6dbdd20aSAndroid Build Coastguard Worker#!/usr/bin/env python3 2*6dbdd20aSAndroid Build Coastguard Worker# Copyright (C) 2021 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"""Updates the python scripts in python/perfetto/prebuilts/manifests 16*6dbdd20aSAndroid Build Coastguard Worker 17*6dbdd20aSAndroid Build Coastguard WorkerThis script does the following, for each entry in MANIFESTS_TO_UPDATE: 18*6dbdd20aSAndroid Build Coastguard Worker - Downloads the artifact by the LUCI infrastructure, one for each arch. 19*6dbdd20aSAndroid Build Coastguard Worker - Computes the SHA-256 of each artifact. 20*6dbdd20aSAndroid Build Coastguard Worker - Generates a manifest with URL, SHA-256 and other details. 21*6dbdd20aSAndroid Build Coastguard Worker - Merges get_perfetto_prebuilt.py with the manifest and writes tools/xxx. 22*6dbdd20aSAndroid Build Coastguard Worker 23*6dbdd20aSAndroid Build Coastguard WorkerThis script is supposed to be run by Perfetto OWNERS after every monthly release 24*6dbdd20aSAndroid Build Coastguard Workerafter the LUCI jobs have completed. 25*6dbdd20aSAndroid Build Coastguard Worker""" 26*6dbdd20aSAndroid Build Coastguard Worker 27*6dbdd20aSAndroid Build Coastguard Workerimport argparse 28*6dbdd20aSAndroid Build Coastguard Workerimport hashlib 29*6dbdd20aSAndroid Build Coastguard Workerimport logging 30*6dbdd20aSAndroid Build Coastguard Workerimport os 31*6dbdd20aSAndroid Build Coastguard Workerimport subprocess 32*6dbdd20aSAndroid Build Coastguard Workerimport sys 33*6dbdd20aSAndroid Build Coastguard Worker 34*6dbdd20aSAndroid Build Coastguard Workerfrom concurrent.futures import ThreadPoolExecutor 35*6dbdd20aSAndroid Build Coastguard Worker 36*6dbdd20aSAndroid Build Coastguard WorkerGCS_URL = 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts' 37*6dbdd20aSAndroid Build Coastguard Worker 38*6dbdd20aSAndroid Build Coastguard WorkerROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 39*6dbdd20aSAndroid Build Coastguard WorkerMANIFESTS_DIR = os.path.join(ROOT_DIR, 'python/perfetto/prebuilts/manifests') 40*6dbdd20aSAndroid Build Coastguard Worker 41*6dbdd20aSAndroid Build Coastguard WorkerUNIX_ARCHS = [ 42*6dbdd20aSAndroid Build Coastguard Worker 'mac-amd64', 43*6dbdd20aSAndroid Build Coastguard Worker 'mac-arm64', 44*6dbdd20aSAndroid Build Coastguard Worker 'linux-amd64', 45*6dbdd20aSAndroid Build Coastguard Worker 'linux-arm', 46*6dbdd20aSAndroid Build Coastguard Worker 'linux-arm64', 47*6dbdd20aSAndroid Build Coastguard Worker 'android-arm', 48*6dbdd20aSAndroid Build Coastguard Worker 'android-arm64', 49*6dbdd20aSAndroid Build Coastguard Worker 'android-x86', 50*6dbdd20aSAndroid Build Coastguard Worker 'android-x64', 51*6dbdd20aSAndroid Build Coastguard Worker] 52*6dbdd20aSAndroid Build Coastguard WorkerALL_ARCHS = UNIX_ARCHS + ['windows-amd64'] 53*6dbdd20aSAndroid Build Coastguard Worker 54*6dbdd20aSAndroid Build Coastguard WorkerMANIFESTS_TO_UPDATE = [ 55*6dbdd20aSAndroid Build Coastguard Worker { 56*6dbdd20aSAndroid Build Coastguard Worker 'tool': 'trace_processor_shell', 57*6dbdd20aSAndroid Build Coastguard Worker 'archs': ALL_ARCHS 58*6dbdd20aSAndroid Build Coastguard Worker }, 59*6dbdd20aSAndroid Build Coastguard Worker { 60*6dbdd20aSAndroid Build Coastguard Worker 'tool': 'traceconv', 61*6dbdd20aSAndroid Build Coastguard Worker 'archs': ALL_ARCHS 62*6dbdd20aSAndroid Build Coastguard Worker }, 63*6dbdd20aSAndroid Build Coastguard Worker { 64*6dbdd20aSAndroid Build Coastguard Worker 'tool': 'tracebox', 65*6dbdd20aSAndroid Build Coastguard Worker 'archs': UNIX_ARCHS 66*6dbdd20aSAndroid Build Coastguard Worker }, 67*6dbdd20aSAndroid Build Coastguard Worker] 68*6dbdd20aSAndroid Build Coastguard Worker 69*6dbdd20aSAndroid Build Coastguard Worker# Maps a 'os-arch' string (were arch follows LUCI conventions) into 70*6dbdd20aSAndroid Build Coastguard Worker# corresponding tuples that match against python's platform / machine API 71*6dbdd20aSAndroid Build Coastguard Worker# (see get_perfetto_prebuilt.py for usage). 72*6dbdd20aSAndroid Build Coastguard WorkerARCH_TO_PYTHON = { 73*6dbdd20aSAndroid Build Coastguard Worker 'mac-amd64': { 74*6dbdd20aSAndroid Build Coastguard Worker 'platform': 'darwin', 75*6dbdd20aSAndroid Build Coastguard Worker 'machine': ['x86_64'], 76*6dbdd20aSAndroid Build Coastguard Worker }, 77*6dbdd20aSAndroid Build Coastguard Worker 'mac-arm64': { 78*6dbdd20aSAndroid Build Coastguard Worker 'platform': 'darwin', 79*6dbdd20aSAndroid Build Coastguard Worker 'machine': ['arm64'], 80*6dbdd20aSAndroid Build Coastguard Worker }, 81*6dbdd20aSAndroid Build Coastguard Worker 'windows-amd64': { 82*6dbdd20aSAndroid Build Coastguard Worker 'platform': 'win32', 83*6dbdd20aSAndroid Build Coastguard Worker 'machine': ['amd64'], 84*6dbdd20aSAndroid Build Coastguard Worker }, 85*6dbdd20aSAndroid Build Coastguard Worker 'linux-amd64': { 86*6dbdd20aSAndroid Build Coastguard Worker 'platform': 'linux', 87*6dbdd20aSAndroid Build Coastguard Worker 'machine': ['x86_64'], 88*6dbdd20aSAndroid Build Coastguard Worker }, 89*6dbdd20aSAndroid Build Coastguard Worker 'linux-arm': { 90*6dbdd20aSAndroid Build Coastguard Worker 'platform': 'linux', 91*6dbdd20aSAndroid Build Coastguard Worker 'machine': ['armv6l', 'armv7l', 'armv8l'], 92*6dbdd20aSAndroid Build Coastguard Worker }, 93*6dbdd20aSAndroid Build Coastguard Worker 'linux-arm64': { 94*6dbdd20aSAndroid Build Coastguard Worker 'platform': 'linux', 95*6dbdd20aSAndroid Build Coastguard Worker 'machine': ['aarch64'], 96*6dbdd20aSAndroid Build Coastguard Worker }, 97*6dbdd20aSAndroid Build Coastguard Worker} 98*6dbdd20aSAndroid Build Coastguard Worker 99*6dbdd20aSAndroid Build Coastguard Worker 100*6dbdd20aSAndroid Build Coastguard Workerdef make_manifest(git_revision, tool, arch): 101*6dbdd20aSAndroid Build Coastguard Worker ext = '.exe' if arch.startswith('windows') else '' 102*6dbdd20aSAndroid Build Coastguard Worker file_name = tool + ext 103*6dbdd20aSAndroid Build Coastguard Worker url = '%s/%s/%s/%s' % (GCS_URL, git_revision, arch, file_name) 104*6dbdd20aSAndroid Build Coastguard Worker logging.info('Downloading %s', url) 105*6dbdd20aSAndroid Build Coastguard Worker data = subprocess.check_output(['curl', '-fsL', '-o', '-', url]) 106*6dbdd20aSAndroid Build Coastguard Worker manifest = { 107*6dbdd20aSAndroid Build Coastguard Worker 'arch': arch, 108*6dbdd20aSAndroid Build Coastguard Worker 'file_name': file_name, 109*6dbdd20aSAndroid Build Coastguard Worker 'file_size': len(data), 110*6dbdd20aSAndroid Build Coastguard Worker 'url': url, 111*6dbdd20aSAndroid Build Coastguard Worker 'sha256': hashlib.sha256(data).hexdigest() 112*6dbdd20aSAndroid Build Coastguard Worker } 113*6dbdd20aSAndroid Build Coastguard Worker manifest.update(ARCH_TO_PYTHON.get(arch, {})) 114*6dbdd20aSAndroid Build Coastguard Worker return manifest 115*6dbdd20aSAndroid Build Coastguard Worker 116*6dbdd20aSAndroid Build Coastguard Worker 117*6dbdd20aSAndroid Build Coastguard Workerdef update_manifest(git_revision, tool_name, archs): 118*6dbdd20aSAndroid Build Coastguard Worker with ThreadPoolExecutor(max_workers=8) as executor: 119*6dbdd20aSAndroid Build Coastguard Worker manifests = list( 120*6dbdd20aSAndroid Build Coastguard Worker executor.map(lambda arch: make_manifest(git_revision, tool_name, arch), 121*6dbdd20aSAndroid Build Coastguard Worker archs)) 122*6dbdd20aSAndroid Build Coastguard Worker out_file = os.path.join(MANIFESTS_DIR, tool_name + '.py') 123*6dbdd20aSAndroid Build Coastguard Worker 124*6dbdd20aSAndroid Build Coastguard Worker content = '# This file has been generated by: {script} {git_revision}\n' 125*6dbdd20aSAndroid Build Coastguard Worker content += '{tool_uppercase}_MANIFEST = {manifests}\n' 126*6dbdd20aSAndroid Build Coastguard Worker content = content.format( 127*6dbdd20aSAndroid Build Coastguard Worker script=os.path.relpath(__file__), 128*6dbdd20aSAndroid Build Coastguard Worker tool_uppercase=tool_name.upper(), 129*6dbdd20aSAndroid Build Coastguard Worker git_revision=git_revision, 130*6dbdd20aSAndroid Build Coastguard Worker manifests=str(manifests)) 131*6dbdd20aSAndroid Build Coastguard Worker 132*6dbdd20aSAndroid Build Coastguard Worker with open(out_file + '.tmp', 'w') as f: 133*6dbdd20aSAndroid Build Coastguard Worker f.write(content) 134*6dbdd20aSAndroid Build Coastguard Worker subprocess.check_call(['yapf', '-i', out_file + '.tmp']) 135*6dbdd20aSAndroid Build Coastguard Worker os.rename(out_file + '.tmp', out_file) 136*6dbdd20aSAndroid Build Coastguard Worker os.chmod(out_file, 0o755) 137*6dbdd20aSAndroid Build Coastguard Worker 138*6dbdd20aSAndroid Build Coastguard Worker 139*6dbdd20aSAndroid Build Coastguard Workerdef main(): 140*6dbdd20aSAndroid Build Coastguard Worker usage = '%s v20.0 | 0a1b2c3d\n\n' % __file__ 141*6dbdd20aSAndroid Build Coastguard Worker usage += 'To list available revisions run\n' 142*6dbdd20aSAndroid Build Coastguard Worker usage += 'gsutil ls gs://perfetto-luci-artifacts/\n' 143*6dbdd20aSAndroid Build Coastguard Worker usage += 'or visit https://chrome-infra-packages.appspot.com/p/perfetto\n' 144*6dbdd20aSAndroid Build Coastguard Worker parser = argparse.ArgumentParser(usage=usage) 145*6dbdd20aSAndroid Build Coastguard Worker parser.add_argument('version') 146*6dbdd20aSAndroid Build Coastguard Worker args = parser.parse_args() 147*6dbdd20aSAndroid Build Coastguard Worker 148*6dbdd20aSAndroid Build Coastguard Worker git_revision = args.version 149*6dbdd20aSAndroid Build Coastguard Worker for spec in MANIFESTS_TO_UPDATE: 150*6dbdd20aSAndroid Build Coastguard Worker logging.info('Updating %s', spec['tool']) 151*6dbdd20aSAndroid Build Coastguard Worker update_manifest(git_revision, spec['tool'], spec['archs']) 152*6dbdd20aSAndroid Build Coastguard Worker 153*6dbdd20aSAndroid Build Coastguard Worker 154*6dbdd20aSAndroid Build Coastguard Workerif __name__ == '__main__': 155*6dbdd20aSAndroid Build Coastguard Worker logging.basicConfig(level=logging.INFO) 156*6dbdd20aSAndroid Build Coastguard Worker sys.exit(main()) 157