157 lines
4.5 KiB
Plaintext
157 lines
4.5 KiB
Plaintext
|
|
#!/usr/bin/env python3
|
||
|
|
# Copyright (C) 2021 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.
|
||
|
|
"""Updates the python scripts in python/perfetto/prebuilts/manifests
|
||
|
|
|
||
|
|
This script does the following, for each entry in MANIFESTS_TO_UPDATE:
|
||
|
|
- Downloads the artifact by the LUCI infrastructure, one for each arch.
|
||
|
|
- Computes the SHA-256 of each artifact.
|
||
|
|
- Generates a manifest with URL, SHA-256 and other details.
|
||
|
|
- Merges get_perfetto_prebuilt.py with the manifest and writes tools/xxx.
|
||
|
|
|
||
|
|
This script is supposed to be run by Perfetto OWNERS after every monthly release
|
||
|
|
after the LUCI jobs have completed.
|
||
|
|
"""
|
||
|
|
|
||
|
|
import argparse
|
||
|
|
import hashlib
|
||
|
|
import logging
|
||
|
|
import os
|
||
|
|
import subprocess
|
||
|
|
import sys
|
||
|
|
|
||
|
|
from concurrent.futures import ThreadPoolExecutor
|
||
|
|
|
||
|
|
GCS_URL = 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts'
|
||
|
|
|
||
|
|
ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||
|
|
MANIFESTS_DIR = os.path.join(ROOT_DIR, 'python/perfetto/prebuilts/manifests')
|
||
|
|
|
||
|
|
UNIX_ARCHS = [
|
||
|
|
'mac-amd64',
|
||
|
|
'mac-arm64',
|
||
|
|
'linux-amd64',
|
||
|
|
'linux-arm',
|
||
|
|
'linux-arm64',
|
||
|
|
'android-arm',
|
||
|
|
'android-arm64',
|
||
|
|
'android-x86',
|
||
|
|
'android-x64',
|
||
|
|
]
|
||
|
|
ALL_ARCHS = UNIX_ARCHS + ['windows-amd64']
|
||
|
|
|
||
|
|
MANIFESTS_TO_UPDATE = [
|
||
|
|
{
|
||
|
|
'tool': 'trace_processor_shell',
|
||
|
|
'archs': ALL_ARCHS
|
||
|
|
},
|
||
|
|
{
|
||
|
|
'tool': 'traceconv',
|
||
|
|
'archs': ALL_ARCHS
|
||
|
|
},
|
||
|
|
{
|
||
|
|
'tool': 'tracebox',
|
||
|
|
'archs': UNIX_ARCHS
|
||
|
|
},
|
||
|
|
]
|
||
|
|
|
||
|
|
# Maps a 'os-arch' string (were arch follows LUCI conventions) into
|
||
|
|
# corresponding tuples that match against python's platform / machine API
|
||
|
|
# (see get_perfetto_prebuilt.py for usage).
|
||
|
|
ARCH_TO_PYTHON = {
|
||
|
|
'mac-amd64': {
|
||
|
|
'platform': 'darwin',
|
||
|
|
'machine': ['x86_64'],
|
||
|
|
},
|
||
|
|
'mac-arm64': {
|
||
|
|
'platform': 'darwin',
|
||
|
|
'machine': ['arm64'],
|
||
|
|
},
|
||
|
|
'windows-amd64': {
|
||
|
|
'platform': 'win32',
|
||
|
|
'machine': ['amd64'],
|
||
|
|
},
|
||
|
|
'linux-amd64': {
|
||
|
|
'platform': 'linux',
|
||
|
|
'machine': ['x86_64'],
|
||
|
|
},
|
||
|
|
'linux-arm': {
|
||
|
|
'platform': 'linux',
|
||
|
|
'machine': ['armv6l', 'armv7l', 'armv8l'],
|
||
|
|
},
|
||
|
|
'linux-arm64': {
|
||
|
|
'platform': 'linux',
|
||
|
|
'machine': ['aarch64'],
|
||
|
|
},
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
def make_manifest(git_revision, tool, arch):
|
||
|
|
ext = '.exe' if arch.startswith('windows') else ''
|
||
|
|
file_name = tool + ext
|
||
|
|
url = '%s/%s/%s/%s' % (GCS_URL, git_revision, arch, file_name)
|
||
|
|
logging.info('Downloading %s', url)
|
||
|
|
data = subprocess.check_output(['curl', '-fsL', '-o', '-', url])
|
||
|
|
manifest = {
|
||
|
|
'arch': arch,
|
||
|
|
'file_name': file_name,
|
||
|
|
'file_size': len(data),
|
||
|
|
'url': url,
|
||
|
|
'sha256': hashlib.sha256(data).hexdigest()
|
||
|
|
}
|
||
|
|
manifest.update(ARCH_TO_PYTHON.get(arch, {}))
|
||
|
|
return manifest
|
||
|
|
|
||
|
|
|
||
|
|
def update_manifest(git_revision, tool_name, archs):
|
||
|
|
with ThreadPoolExecutor(max_workers=8) as executor:
|
||
|
|
manifests = list(
|
||
|
|
executor.map(lambda arch: make_manifest(git_revision, tool_name, arch),
|
||
|
|
archs))
|
||
|
|
out_file = os.path.join(MANIFESTS_DIR, tool_name + '.py')
|
||
|
|
|
||
|
|
content = '# This file has been generated by: {script} {git_revision}\n'
|
||
|
|
content += '{tool_uppercase}_MANIFEST = {manifests}\n'
|
||
|
|
content = content.format(
|
||
|
|
script=__file__,
|
||
|
|
tool_uppercase=tool_name.upper(),
|
||
|
|
git_revision=git_revision,
|
||
|
|
manifests=str(manifests))
|
||
|
|
|
||
|
|
with open(out_file + '.tmp', 'w') as f:
|
||
|
|
f.write(content)
|
||
|
|
subprocess.check_call(['yapf', '-i', out_file + '.tmp'])
|
||
|
|
os.rename(out_file + '.tmp', out_file)
|
||
|
|
os.chmod(out_file, 0o755)
|
||
|
|
|
||
|
|
|
||
|
|
def main():
|
||
|
|
usage = '%s v20.0 | 0a1b2c3d\n\n' % __file__
|
||
|
|
usage += 'To list available revisions run\n'
|
||
|
|
usage += 'gsutil ls gs://perfetto-luci-artifacts/\n'
|
||
|
|
usage += 'or visit https://chrome-infra-packages.appspot.com/p/perfetto\n'
|
||
|
|
parser = argparse.ArgumentParser(usage=usage)
|
||
|
|
parser.add_argument('version')
|
||
|
|
args = parser.parse_args()
|
||
|
|
|
||
|
|
git_revision = args.version
|
||
|
|
for spec in MANIFESTS_TO_UPDATE:
|
||
|
|
logging.info('Updating %s', spec['tool'])
|
||
|
|
update_manifest(git_revision, spec['tool'], spec['archs'])
|
||
|
|
|
||
|
|
|
||
|
|
if __name__ == '__main__':
|
||
|
|
logging.basicConfig(level=logging.INFO)
|
||
|
|
sys.exit(main())
|