blob: 88c10840753e9c2c281453b5a98c2bbcead09c09 [file]
#!/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.
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
# DO NOT EDIT. Auto-generated by tools/gen_amalgamated_python_tools
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
# This file should do the same thing when being invoked in any of these ways:
# ./trace_processor
# python trace_processor
# bash trace_processor
# cat ./trace_processor | bash
# cat ./trace_processor | python -
BASH_FALLBACK=""" "
exec python3 - "$@" <<'#'EOF
#""" # yapf: disable
# ----- Amalgamator: begin of python/perfetto/prebuilts/manifests/trace_processor_shell.py
# This file has been generated by: tools/release/roll-prebuilts v56.1
TRACE_PROCESSOR_SHELL_MANIFEST = [{
'arch':
'mac-amd64',
'file_name':
'trace_processor_shell',
'file_size':
13441096,
'url':
'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v56.1/mac-amd64/trace_processor_shell',
'sha256':
'99227035e8256d46660c21e35e097188a31465e95accf334e094d31cd709065b',
'platform':
'darwin',
'machine': ['x86_64']
}, {
'arch':
'mac-arm64',
'file_name':
'trace_processor_shell',
'file_size':
12421992,
'url':
'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v56.1/mac-arm64/trace_processor_shell',
'sha256':
'64180e40f94fa8bded24dee1ba62985c0f9fc8c89047cd3218be25084a4b06a2',
'platform':
'darwin',
'machine': ['arm64']
}, {
'arch':
'linux-amd64',
'file_name':
'trace_processor_shell',
'file_size':
13687824,
'url':
'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v56.1/linux-amd64/trace_processor_shell',
'sha256':
'becb22d3f2c51dc234627a3ffd5b066602575b50ad4eb082815156f1bc7cb65a',
'platform':
'linux',
'machine': ['x86_64']
}, {
'arch':
'linux-arm',
'file_name':
'trace_processor_shell',
'file_size':
10115224,
'url':
'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v56.1/linux-arm/trace_processor_shell',
'sha256':
'561d778f65bed8ce5c3f62043e63248d7490390a5137e4b2221893e733d43b52',
'platform':
'linux',
'machine': ['armv6l', 'armv7l', 'armv8l']
}, {
'arch':
'linux-arm64',
'file_name':
'trace_processor_shell',
'file_size':
13023160,
'url':
'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v56.1/linux-arm64/trace_processor_shell',
'sha256':
'b0b8d7bd61120bd01db7f7e5e31636f6e476170190476b34f9013c92e604509a',
'platform':
'linux',
'machine': ['aarch64']
}, {
'arch':
'android-arm',
'file_name':
'trace_processor_shell',
'file_size':
10079324,
'url':
'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v56.1/android-arm/trace_processor_shell',
'sha256':
'0a0a9c2a74282a4365d88bf681968756794e7e3dbfdb467c793b8fd4b3645e40'
}, {
'arch':
'android-arm64',
'file_name':
'trace_processor_shell',
'file_size':
12823856,
'url':
'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v56.1/android-arm64/trace_processor_shell',
'sha256':
'a1fe8eeff8d0fd98caf95927bbc983fb9062a944162c451cd84ada1ff86c381f'
}, {
'arch':
'android-x86',
'file_name':
'trace_processor_shell',
'file_size':
14498900,
'url':
'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v56.1/android-x86/trace_processor_shell',
'sha256':
'0902cc9c98f3b416ab5fcb353cfbc3d63978d77a9b1ac438b223157c278f9fec'
}, {
'arch':
'android-x64',
'file_name':
'trace_processor_shell',
'file_size':
13415352,
'url':
'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v56.1/android-x64/trace_processor_shell',
'sha256':
'36de738cf879983a75c2fc38d3e5318fb643dcf57cf6a22bf4e015af180f2c1e'
}, {
'arch':
'windows-amd64',
'file_name':
'trace_processor_shell.exe',
'file_size':
13313024,
'url':
'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/v56.1/windows-amd64/trace_processor_shell.exe',
'sha256':
'9ac8c04ca44cc22f0aa6eff2ff8d25c3a87011b48aca554e7a10f677cbbfaaa0',
'platform':
'win32',
'machine': ['amd64']
}]
# ----- Amalgamator: end of python/perfetto/prebuilts/manifests/trace_processor_shell.py
# ----- Amalgamator: begin of python/perfetto/prebuilts/perfetto_prebuilts.py
# 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.
"""
Functions to fetch pre-pinned Perfetto prebuilts.
This function is used in different places:
- Into the //tools/{trace_processor, traceconv} scripts, which are just plain
wrappers around executables.
- Into the //tools/{heap_profiler, record_android_trace} scripts, which contain
some other hand-written python code.
The manifest argument looks as follows:
TRACECONV_MANIFEST = [
{
'arch': 'mac-amd64',
'file_name': 'traceconv',
'file_size': 7087080,
'url': https://commondatastorage.googleapis.com/.../trace_to_text',
'sha256': 7d957c005b0dc130f5bd855d6cec27e060d38841b320d04840afc569f9087490',
'platform': 'darwin',
'machine': 'x86_64'
},
...
]
The intended usage is:
from perfetto.prebuilts.manifests.traceconv import TRACECONV_MANIFEST
bin_path = get_perfetto_prebuilt(TRACECONV_MANIFEST)
subprocess.call(bin_path, ...)
"""
import hashlib
import os
import platform
import random
import subprocess
import sys
def download_or_get_cached(file_name, url, sha256):
""" Downloads a prebuilt or returns a cached version
The first time this is invoked, it downloads the |url| and caches it into
~/.local/share/perfetto/prebuilts/$tool_name-$sha256. On subsequent
invocations it just runs the cached version.
The (short) SHA-256 is embedded in the cached file name so that several
versions of the same tool can coexist on the same machine. This matters when
e.g. two virtualenvs pin different Perfetto releases, or the //tools wrappers
and the Python API request different versions: without the SHA in the name
they would all map to the same path, clobber each other and trigger a
re-download on every switch.
"""
dir = os.path.join(
os.path.expanduser('~'), '.local', 'share', 'perfetto', 'prebuilts')
os.makedirs(dir, exist_ok=True)
# Embed the SHA in the file name, preserving any extension (e.g. .exe) as the
# last component since callers (and the OS, on Windows) rely on it.
root, ext = os.path.splitext(file_name)
bin_path = os.path.join(dir, '%s-%s%s' % (root, sha256[:16], ext))
# The cached file is only ever created via an atomic rename after the SHA-256
# has been verified, so if a file at this (SHA-named) path exists we can trust
# it without recomputing the hash on every invocation.
if os.path.exists(bin_path):
return bin_path
# Use a unique random file to guard against concurrent executions.
# See https://github.com/google/perfetto/issues/786 .
tmp_path = '%s.%d.tmp' % (bin_path, random.randint(0, 100000))
print('Downloading ' + url)
subprocess.check_call(['curl', '-f', '-L', '-#', '-o', tmp_path, url])
with open(tmp_path, 'rb') as fd:
actual_sha256 = hashlib.sha256(fd.read()).hexdigest()
if actual_sha256 != sha256:
raise Exception('Checksum mismatch for %s (actual: %s, expected: %s)' %
(url, actual_sha256, sha256))
os.chmod(tmp_path, 0o755)
os.replace(tmp_path, bin_path)
return bin_path
def get_perfetto_prebuilt(manifest, soft_fail=False, arch=None):
""" Downloads the prebuilt, if necessary, and returns its path on disk. """
plat = sys.platform.lower()
machine = platform.machine().lower()
manifest_entry = None
for entry in manifest:
# If the caller overrides the arch, just match that (for Android prebuilts).
if arch:
if entry.get('arch') == arch:
manifest_entry = entry
break
continue
# Otherwise guess the local machine arch.
if entry.get('platform') == plat and machine in entry.get('machine', []):
manifest_entry = entry
break
if manifest_entry is None:
if soft_fail:
return None
raise Exception(
('No prebuilts available for %s-%s\n' % (plat, machine)) +
'See https://perfetto.dev/docs/contributing/build-instructions')
# Placeholder entries (e.g. before a release has been rolled) have an empty
# URL. Treat them the same as a missing entry when soft_fail is set.
if not manifest_entry.get('url'):
if soft_fail:
return None
raise Exception('No prebuilt URL available for %s on %s-%s. '
'The prebuilt may not have been rolled yet.' %
(manifest_entry.get('file_name', '?'), plat, machine))
return download_or_get_cached(
file_name=manifest_entry['file_name'],
url=manifest_entry['url'],
sha256=manifest_entry['sha256'])
def run_perfetto_prebuilt(manifest):
bin_path = get_perfetto_prebuilt(manifest)
if sys.platform.lower() == 'win32':
sys.exit(subprocess.check_call([bin_path, *sys.argv[1:]]))
os.execv(bin_path, [bin_path] + sys.argv[1:])
# ----- Amalgamator: end of python/perfetto/prebuilts/perfetto_prebuilts.py
if __name__ == '__main__':
run_perfetto_prebuilt(TRACE_PROCESSOR_SHELL_MANIFEST)
#EOF