roll_prebuilt: update scripts
This change runs tools/roll_prebuilt and also introduces
some matching changes required to make use of it in
tools/{heap_profile, record_android_trace}
Bug: 177349647
Change-Id: Ia5b569086d66896ff09f23680235547ed2ee181a
diff --git a/tools/get_perfetto_prebuilt.py b/tools/get_perfetto_prebuilt.py
index 28e9806..99f3459 100644
--- a/tools/get_perfetto_prebuilt.py
+++ b/tools/get_perfetto_prebuilt.py
@@ -106,7 +106,7 @@
break
# Otherwise guess the local machine arch.
if entry.get('tool') == tool_name and entry.get(
- 'platform') == plat and entry.get('machine') == machine:
+ 'platform') == plat and machine in entry.get('machine', []):
manifest_entry = entry
break
if manifest_entry is None:
diff --git a/tools/heap_profile b/tools/heap_profile
index 6a931cf..09bd96c 100755
--- a/tools/heap_profile
+++ b/tools/heap_profile
@@ -29,15 +29,6 @@
import tempfile
import time
import uuid
-import platform
-
-
-TRACE_TO_TEXT_SHAS = {
- 'linux': '150d8e65b8173c317642abfc44f3861832fbcd4e',
- 'mac': '818143f3283559a89c311e7e506d0099d1f6408c',
-}
-TRACE_TO_TEXT_PATH = tempfile.gettempdir()
-TRACE_TO_TEXT_BASE_URL = ('https://storage.googleapis.com/perfetto/')
NULL = open(os.devnull)
NOOUT = {
@@ -47,37 +38,6 @@
UUID = str(uuid.uuid4())[-6:]
-def check_hash(file_name, sha_value):
- file_hash = hashlib.sha1()
- with open(file_name, 'rb') as fd:
- while True:
- chunk = fd.read(4096)
- if not chunk:
- break
- file_hash.update(chunk)
- return file_hash.hexdigest() == sha_value
-
-
-def load_trace_to_text(os_name):
- sha_value = TRACE_TO_TEXT_SHAS[os_name]
- file_name = 'trace_to_text-' + os_name + '-' + sha_value
- local_file = os.path.join(TRACE_TO_TEXT_PATH, file_name)
-
- if os.path.exists(local_file):
- if not check_hash(local_file, sha_value):
- os.remove(local_file)
- else:
- return local_file
-
- url = TRACE_TO_TEXT_BASE_URL + file_name
- subprocess.check_call(['curl', '-L', '-#', '-o', local_file, url])
- if not check_hash(local_file, sha_value):
- os.remove(local_file)
- raise ValueError("Invalid signature.")
- os.chmod(local_file, 0o755)
- return local_file
-
-
PACKAGES_LIST_CFG = '''data_sources {
config {
name: "android.packages_list"
@@ -120,6 +80,7 @@
IS_INTERRUPTED = False
+
def sigint_handler(sig, frame):
global IS_INTERRUPTED
IS_INTERRUPTED = True
@@ -128,44 +89,52 @@
def print_no_profile_error():
print("No profiles generated", file=sys.stderr)
print(
- "If this is unexpected, check "
- "https://perfetto.dev/docs/data-sources/native-heap-profiler#troubleshooting.",
- file=sys.stderr)
+ "If this is unexpected, check "
+ "https://perfetto.dev/docs/data-sources/native-heap-profiler#troubleshooting.",
+ file=sys.stderr)
+
def known_issues_url(number):
return ('https://perfetto.dev/docs/data-sources/native-heap-profiler'
'#known-issues-android{}'.format(number))
+
KNOWN_ISSUES = {
- '10': known_issues_url(10),
- 'Q': known_issues_url(10),
- '11': known_issues_url(11),
- 'R': known_issues_url(11),
+ '10': known_issues_url(10),
+ 'Q': known_issues_url(10),
+ '11': known_issues_url(11),
+ 'R': known_issues_url(11),
}
+
def maybe_known_issues():
release_or_codename = subprocess.check_output(
- ['adb', 'shell', 'getprop', 'ro.build.version.release_or_codename']
- ).decode('utf-8').strip()
+ ['adb', 'shell', 'getprop',
+ 'ro.build.version.release_or_codename']).decode('utf-8').strip()
return KNOWN_ISSUES.get(release_or_codename, None)
+
SDK = {
'R': 30,
}
+
def release_or_newer(release):
- sdk = int(subprocess.check_output(
- ['adb', 'shell', 'getprop', 'ro.system.build.version.sdk']
- ).decode('utf-8').strip())
+ sdk = int(
+ subprocess.check_output(
+ ['adb', 'shell', 'getprop',
+ 'ro.system.build.version.sdk']).decode('utf-8').strip())
if sdk >= SDK[release]:
return True
codename = subprocess.check_output(
- ['adb', 'shell', 'getprop', 'ro.build.version.codename']
- ).decode('utf-8').strip()
+ ['adb', 'shell', 'getprop',
+ 'ro.build.version.codename']).decode('utf-8').strip()
return codename == release
+
ORDER = ['-n', '-p', '-i', '-o']
+
def arg_order(action):
result = len(ORDER)
for opt in action.option_strings:
@@ -173,16 +142,18 @@
result = min(ORDER.index(opt), result)
return result, action.option_strings[0].strip('-')
+
def print_options(parser):
for action in sorted(parser._actions, key=arg_order):
if action.help is argparse.SUPPRESS:
continue
opts = ', '.join('`' + x + '`' for x in action.option_strings)
- metavar = '' if action.metavar is None else ' _' + action.metavar + '_'
+ metavar = '' if action.metavar is None else ' _' + action.metavar + '_'
print('{}{}'.format(opts, metavar))
print(': {}'.format(action.help))
print()
+
def main(argv):
parser = argparse.ArgumentParser()
parser.add_argument(
@@ -229,14 +200,12 @@
parser.add_argument(
"--all-heaps",
action="store_true",
- help="Collect allocations from all heaps registered by target."
- )
+ help="Collect allocations from all heaps registered by target.")
parser.add_argument(
"--no-android-tree-symbolization",
action="store_true",
help="Do not symbolize using currently lunched target in the "
- "Android tree."
- )
+ "Android tree.")
parser.add_argument(
"--disable-selinux",
action="store_true",
@@ -314,10 +283,7 @@
metavar="DIRECTORY",
default=None)
parser.add_argument(
- "--print-options",
- action="store_true",
- help=argparse.SUPPRESS
- )
+ "--print-options", action="store_true", help=argparse.SUPPRESS)
args = parser.parse_args()
if args.print_options:
@@ -352,8 +318,8 @@
target_cfg += CFG_INDENT + "block_client: true\n"
if args.block_client_timeout:
target_cfg += (
- CFG_INDENT + "block_client_timeout_us: %s\n" % args.block_client_timeout
- )
+ CFG_INDENT +
+ "block_client_timeout_us: %s\n" % args.block_client_timeout)
if args.no_startup:
target_cfg += CFG_INDENT + "no_startup: true\n"
if args.no_running:
@@ -401,25 +367,9 @@
# Do this AFTER print_config so we do not download trace_to_text only to
# print out the config.
- has_trace_to_text = True
if trace_to_text_binary is None:
- os_name = None
- if sys.platform.startswith('linux'):
- os_name = 'linux'
- elif sys.platform.startswith('darwin'):
- os_name = 'mac'
- elif sys.platform.startswith('win32'):
- has_trace_to_text = False
- else:
- print("Invalid platform: {}".format(sys.platform), file=sys.stderr)
- return 1
-
- arch = platform.machine()
- if arch not in ['x86_64', 'amd64']:
- has_trace_to_text = False
-
- if has_trace_to_text:
- trace_to_text_binary = load_trace_to_text(os_name)
+ trace_to_text_binary = get_perfetto_prebuilt(
+ 'trace_to_text', soft_fail=True)
known_issues = maybe_known_issues()
if known_issues:
@@ -432,8 +382,8 @@
if uuid_trace:
profile_device_path = '/data/misc/perfetto-traces/profile-' + UUID
else:
- user = subprocess.check_output(
- ['adb', 'shell', 'whoami']).decode('utf-8').strip()
+ user = subprocess.check_output(['adb', 'shell',
+ 'whoami']).decode('utf-8').strip()
profile_device_path = '/data/misc/perfetto-traces/profile-' + user
perfetto_cmd = ('CFG=\'{cfg}\'; echo ${{CFG}} | '
@@ -461,18 +411,17 @@
os.mkdir(profile_target)
if not os.path.isdir(profile_target):
- print("Output directory {} not found".format(profile_target),
- file=sys.stderr)
+ print(
+ "Output directory {} not found".format(profile_target), file=sys.stderr)
return 1
if os.listdir(profile_target):
- print("Output directory {} not empty".format(profile_target),
- file=sys.stderr)
+ print(
+ "Output directory {} not empty".format(profile_target), file=sys.stderr)
return 1
perfetto_pid = subprocess.check_output(
- ['adb', 'exec-out',
- perfetto_cmd.format(cfg=cfg)]).strip()
+ ['adb', 'exec-out', perfetto_cmd.format(cfg=cfg)]).strip()
try:
perfetto_pid = int(perfetto_pid.strip())
except ValueError:
@@ -503,8 +452,8 @@
time.sleep(1)
subprocess.check_call(
['adb', 'pull', '/data/local/tmp/heapprofd_profile', profile_target])
- print(
- "Pulled simpleperf profile to " + profile_target + "/heapprofd_profile")
+ print("Pulled simpleperf profile to " + profile_target +
+ "/heapprofd_profile")
# Wait for perfetto cmd to return.
while exists:
@@ -513,15 +462,17 @@
time.sleep(1)
profile_host_path = os.path.join(profile_target, 'raw-trace')
- subprocess.check_call(
- ['adb', 'pull', profile_device_path, profile_host_path], stdout=NULL)
+ subprocess.check_call(['adb', 'pull', profile_device_path, profile_host_path],
+ stdout=NULL)
if uuid_trace:
- subprocess.check_call(
- ['adb', 'shell', 'rm', profile_device_path], stdout=NULL)
+ subprocess.check_call(['adb', 'shell', 'rm', profile_device_path],
+ stdout=NULL)
- if not has_trace_to_text:
+ if trace_to_text_binary is None:
print('Wrote profile to {}'.format(profile_host_path))
- print('This file can be opened using the Perfetto UI, https://ui.perfetto.dev')
+ print(
+ 'This file can be opened using the Perfetto UI, https://ui.perfetto.dev'
+ )
return 0
binary_path = os.getenv('PERFETTO_BINARY_PATH')
@@ -544,29 +495,32 @@
with open(os.path.join(profile_target, 'symbols'), 'w') as fd:
ret = subprocess.call([
trace_to_text_binary, 'symbolize',
- os.path.join(profile_target, 'raw-trace')],
- env=dict(os.environ, PERFETTO_BINARY_PATH=binary_path),
- stdout=fd)
+ os.path.join(profile_target, 'raw-trace')
+ ],
+ env=dict(
+ os.environ, PERFETTO_BINARY_PATH=binary_path),
+ stdout=fd)
if ret == 0:
concat_files.append(os.path.join(profile_target, 'symbols'))
else:
- print("Failed to symbolize. Continuing without symbols.",
- file=sys.stderr)
+ print("Failed to symbolize. Continuing without symbols.", file=sys.stderr)
proguard_map = os.getenv('PERFETTO_PROGUARD_MAP')
if proguard_map is not None:
with open(os.path.join(profile_target, 'deobfuscation-packets'), 'w') as fd:
ret = subprocess.call([
trace_to_text_binary, 'deobfuscate',
- os.path.join(profile_target, 'raw-trace')],
- env=dict(os.environ, PERFETTO_PROGUARD_MAP=proguard_map),
- stdout=fd)
+ os.path.join(profile_target, 'raw-trace')
+ ],
+ env=dict(
+ os.environ, PERFETTO_PROGUARD_MAP=proguard_map),
+ stdout=fd)
if ret == 0:
- concat_files.append(
- os.path.join(profile_target, 'deobfuscation-packets'))
+ concat_files.append(os.path.join(profile_target, 'deobfuscation-packets'))
else:
- print("Failed to deobfuscate. Continuing without deobfuscated.",
- file=sys.stderr)
+ print(
+ "Failed to deobfuscate. Continuing without deobfuscated.",
+ file=sys.stderr)
if len(concat_files) > 1:
with open(os.path.join(profile_target, 'symbolized-trace'), 'wb') as out:
@@ -598,20 +552,19 @@
shutil.copy(os.path.join(profile_path, profile_file), profile_target)
subprocess.check_call(
- ['gzip'] +
- [os.path.join(profile_target, x) for x in profile_files])
+ ['gzip'] + [os.path.join(profile_target, x) for x in profile_files])
symlink_path = None
if args.output is None:
symlink_path = os.path.join(
- os.path.dirname(profile_target), "heap_profile-latest")
+ os.path.dirname(profile_target), "heap_profile-latest")
if os.path.lexists(symlink_path):
os.unlink(symlink_path)
os.symlink(profile_target, symlink_path)
if symlink_path is not None:
- print("Wrote profiles to {} (symlink {})".format(
- profile_target, symlink_path))
+ print("Wrote profiles to {} (symlink {})".format(profile_target,
+ symlink_path))
else:
print("Wrote profiles to {}".format(profile_target))
@@ -619,5 +572,131 @@
"upload them.")
+# BEGIN_SECTION_GENERATED_BY(roll-prebuilts)
+# Revision: 45571639857aa59be41f77a2d774f6577d03c86c
+PERFETTO_PREBUILT_MANIFEST = [{
+ 'tool':
+ 'trace_to_text',
+ 'arch':
+ 'mac-amd64',
+ 'file_name':
+ 'trace_to_text',
+ 'file_size':
+ 7087056,
+ 'url':
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/45571639857aa59be41f77a2d774f6577d03c86c/mac-amd64/trace_to_text',
+ 'sha256':
+ 'beaf8151ed0994f970e4e6d4da10b6681ac48a74f29133f4bea6f3d3294c1009',
+ 'platform':
+ 'darwin',
+ 'machine': ['x86_64']
+}, {
+ 'tool':
+ 'trace_to_text',
+ 'arch':
+ 'windows-amd64',
+ 'file_name':
+ 'trace_to_text.exe',
+ 'file_size':
+ 6702080,
+ 'url':
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/45571639857aa59be41f77a2d774f6577d03c86c/windows-amd64/trace_to_text.exe',
+ 'sha256':
+ '58a1b1e1bb69465002ccf9611d13a029943257d41311a6603d45ba1ebfcfa077',
+ 'platform':
+ 'win32',
+ 'machine': ['amd64']
+}, {
+ 'tool':
+ 'trace_to_text',
+ 'arch':
+ 'linux-amd64',
+ 'file_name':
+ 'trace_to_text',
+ 'file_size':
+ 7435576,
+ 'url':
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/45571639857aa59be41f77a2d774f6577d03c86c/linux-amd64/trace_to_text',
+ 'sha256':
+ '6c19500bfa983cfbf49fe0ef55284285ba674b43d1d2273f19249fa5b3dd9f84',
+ 'platform':
+ 'linux',
+ 'machine': ['x86_64']
+}]
+
+
+# DO NOT EDIT. If you wish to make edits to this code, you need to change only
+# //tools/get_perfetto_prebuilt.py and run /tools/roll-prebuilts to regenerate
+# all the others scripts this is embedded into.
+def get_perfetto_prebuilt(tool_name, soft_fail=False, arch=None):
+ """ Downloads the prebuilt, if necessary, and returns its path on disk. """
+
+ # The first time this is invoked, it downloads the |url| and caches it into
+ # ~/.perfetto/prebuilts/$tool_name. On subsequent invocations it just runs the
+ # cached version.
+ def download_or_get_cached(file_name, url, sha256):
+ import os, hashlib, subprocess
+ dir = os.path.join(
+ os.path.expanduser('~'), '.local', 'share', 'perfetto', 'prebuilts')
+ os.makedirs(dir, exist_ok=True)
+ bin_path = os.path.join(dir, file_name)
+ sha256_path = os.path.join(dir, file_name + '.sha256')
+ needs_download = True
+
+ # Avoid recomputing the SHA-256 on each invocation. The SHA-256 of the last
+ # download is cached into file_name.sha256, just check if that matches.
+ if os.path.exists(bin_path) and os.path.exists(sha256_path):
+ with open(sha256_path, 'rb') as f:
+ digest = f.read().decode()
+ if digest == sha256:
+ needs_download = False
+
+ if needs_download:
+ # Either the filed doesn't exist or the SHA256 doesn't match.
+ tmp_path = bin_path + '.tmp'
+ 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.rename(tmp_path, bin_path)
+ with open(sha256_path, 'w') as f:
+ f.write(sha256)
+ return bin_path
+ # --- end of download_or_get_cached() ---
+
+ # --- get_perfetto_prebuilt() function starts here. ---
+ import os, platform, sys
+ plat = sys.platform.lower()
+ machine = platform.machine().lower()
+ manifest_entry = None
+ for entry in PERFETTO_PREBUILT_MANIFEST:
+ # If the caller overrides the arch, just match that (for Android prebuilts).
+ if arch and entry.get('arch') == arch:
+ manifest_entry = entry
+ break
+ # Otherwise guess the local machine arch.
+ if entry.get('tool') == tool_name and 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')
+
+ return download_or_get_cached(
+ file_name=manifest_entry['file_name'],
+ url=manifest_entry['url'],
+ sha256=manifest_entry['sha256'])
+
+
+# END_SECTION_GENERATED_BY(roll-prebuilts)
+
if __name__ == '__main__':
sys.exit(main(sys.argv))
diff --git a/tools/record_android_trace b/tools/record_android_trace
index b59b8bb..c079c1a 100755
--- a/tools/record_android_trace
+++ b/tools/record_android_trace
@@ -33,16 +33,6 @@
# PATH. It's fine if it doesn't exist so this script can be copied elsewhere.
HERMETIC_ADB_PATH = ROOT_DIR + '/buildtools/android_sdk/platform-tools/adb'
-# For downloading and sideloading tracebox on older devices, or when the
-# --sideload argument is passed.
-TRACEBOX_BASE_URL = 'https://storage.googleapis.com/perfetto/'
-TRACEBOX_SHA1S = {
- 'android-arm': '6e9dfee326468fc6858c6d95e00be110efd187a3', # v15.0.248
- 'android-arm64': 'ca2d4a02511f73dac32a2ae49964f3e5cd59d252', # v15.0.248
- 'android-x86': '3fdbc9246412e460d0a373140c114cff858b9b7c', # v15.0.248
- 'android-x64': 'be85f6f4a2d014d425246b85941c137c28d158cc', # v15.0.248
-}
-
# Translates the Android ro.product.cpu.abi into the GN's target_cpu.
ABI_TO_ARCH = {
'armeabi-v7a': 'arm',
@@ -207,7 +197,9 @@
sys.exit(1)
shell_user = lines[2]
if api_level < 29 or args.sideload: # 29: Android Q.
- tracebox_bin = args.sideload_path or download_tracebox_if_needed(arch)
+ tracebox_bin = args.sideload_path
+ if tracebox_bin is None:
+ tracebox_bin = get_perfetto_prebuilt('tracebox', arch='android-' + arch)
perfetto_cmd = '/data/local/tmp/tracebox'
exit_code = adb('push', '--sync', tracebox_bin, perfetto_cmd).wait()
exit_code |= adb('shell', 'chmod 755 ' + perfetto_cmd).wait()
@@ -370,26 +362,135 @@
return file_hash == sha_value
-def download_tracebox_if_needed(arch):
- sha_value = TRACEBOX_SHA1S.get('android-' + arch)
- if sha_value is None:
- prt('Unsupported architecture ' + arch)
- sys.exit(1)
- file_name = 'tracebox-android-' + arch + '-' + sha_value
- local_file = os.path.join(tempfile.gettempdir(), file_name)
- if os.path.exists(local_file):
- if not check_hash(local_file, sha_value):
- os.remove(local_file)
- else:
- return local_file
- url = TRACEBOX_BASE_URL + file_name
- prt('Downloading %s' % url)
- subprocess.check_call(['curl', '-L', '-#', '-o', local_file, url])
- if not check_hash(local_file, sha_value):
- os.remove(local_file)
- raise ValueError('Invalid SHA1 for %s' % local_file)
- return local_file
+# BEGIN_SECTION_GENERATED_BY(roll-prebuilts)
+# Revision: 45571639857aa59be41f77a2d774f6577d03c86c
+PERFETTO_PREBUILT_MANIFEST = [{
+ 'tool':
+ 'tracebox',
+ 'arch':
+ 'android-arm',
+ 'file_name':
+ 'tracebox',
+ 'file_size':
+ 1021824,
+ 'url':
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/45571639857aa59be41f77a2d774f6577d03c86c/android-arm/tracebox',
+ 'sha256':
+ 'b6b05fdc623462b010ac7720557d7fb0c3313d620cdbe9830a41f2e6d22042a0'
+}, {
+ 'tool':
+ 'tracebox',
+ 'arch':
+ 'android-arm64',
+ 'file_name':
+ 'tracebox',
+ 'file_size':
+ 1559112,
+ 'url':
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/45571639857aa59be41f77a2d774f6577d03c86c/android-arm64/tracebox',
+ 'sha256':
+ '62cb645e979510c59a599af2d5feb265572197ddd6740aa329e3345d6ed4f813'
+}, {
+ 'tool':
+ 'tracebox',
+ 'arch':
+ 'android-x86',
+ 'file_name':
+ 'tracebox',
+ 'file_size':
+ 1587028,
+ 'url':
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/45571639857aa59be41f77a2d774f6577d03c86c/android-x86/tracebox',
+ 'sha256':
+ '01d7111c0c9f4da18f5308358e24227b1b8e732fc5787969cd07543916d5ac00'
+}, {
+ 'tool':
+ 'tracebox',
+ 'arch':
+ 'android-x64',
+ 'file_name':
+ 'tracebox',
+ 'file_size':
+ 1829448,
+ 'url':
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/45571639857aa59be41f77a2d774f6577d03c86c/android-x64/tracebox',
+ 'sha256':
+ '2eea577e7b001ab6193265dfd2f0a7aeab46bb22ed21a7da0d0c5f80639bd7af'
+}]
+# DO NOT EDIT. If you wish to make edits to this code, you need to change only
+# //tools/get_perfetto_prebuilt.py and run /tools/roll-prebuilts to regenerate
+# all the others scripts this is embedded into.
+def get_perfetto_prebuilt(tool_name, soft_fail=False, arch=None):
+ """ Downloads the prebuilt, if necessary, and returns its path on disk. """
+
+ # The first time this is invoked, it downloads the |url| and caches it into
+ # ~/.perfetto/prebuilts/$tool_name. On subsequent invocations it just runs the
+ # cached version.
+ def download_or_get_cached(file_name, url, sha256):
+ import os, hashlib, subprocess
+ dir = os.path.join(
+ os.path.expanduser('~'), '.local', 'share', 'perfetto', 'prebuilts')
+ os.makedirs(dir, exist_ok=True)
+ bin_path = os.path.join(dir, file_name)
+ sha256_path = os.path.join(dir, file_name + '.sha256')
+ needs_download = True
+
+ # Avoid recomputing the SHA-256 on each invocation. The SHA-256 of the last
+ # download is cached into file_name.sha256, just check if that matches.
+ if os.path.exists(bin_path) and os.path.exists(sha256_path):
+ with open(sha256_path, 'rb') as f:
+ digest = f.read().decode()
+ if digest == sha256:
+ needs_download = False
+
+ if needs_download:
+ # Either the filed doesn't exist or the SHA256 doesn't match.
+ tmp_path = bin_path + '.tmp'
+ 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.rename(tmp_path, bin_path)
+ with open(sha256_path, 'w') as f:
+ f.write(sha256)
+ return bin_path
+ # --- end of download_or_get_cached() ---
+
+ # --- get_perfetto_prebuilt() function starts here. ---
+ import os, platform, sys
+ plat = sys.platform.lower()
+ machine = platform.machine().lower()
+ manifest_entry = None
+ for entry in PERFETTO_PREBUILT_MANIFEST:
+ # If the caller overrides the arch, just match that (for Android prebuilts).
+ if arch and entry.get('arch') == arch:
+ manifest_entry = entry
+ break
+ # Otherwise guess the local machine arch.
+ if entry.get('tool') == tool_name and 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')
+
+ return download_or_get_cached(
+ file_name=manifest_entry['file_name'],
+ url=manifest_entry['url'],
+ sha256=manifest_entry['sha256'])
+
+
+# END_SECTION_GENERATED_BY(roll-prebuilts)
+
if __name__ == '__main__':
sys.exit(main())
diff --git a/tools/roll-prebuilts b/tools/roll-prebuilts
index 5cd3aee..4a68508 100755
--- a/tools/roll-prebuilts
+++ b/tools/roll-prebuilts
@@ -41,9 +41,14 @@
SCRIPTS_TO_UPDATE = [
{
- 'script': 'trace_processor',
- 'tool': 'trace_processor_shell',
- 'archs': ['mac-amd64', 'linux-amd64', 'windows-amd64']
+ 'script':
+ 'trace_processor',
+ 'tool':
+ 'trace_processor_shell',
+ 'archs': [
+ 'mac-amd64', 'windows-amd64', 'linux-amd64', 'linux-arm',
+ 'linux-arm64'
+ ]
},
{
'script': 'traceconv',
@@ -51,14 +56,19 @@
'archs': ['mac-amd64', 'linux-amd64', 'windows-amd64']
},
{
- 'script': 'tracebox',
- 'tool': 'tracebox',
- 'archs': ['mac-amd64', 'linux-amd64']
+ 'script':
+ 'tracebox',
+ 'tool':
+ 'tracebox',
+ 'archs': [
+ 'mac-amd64', 'linux-amd64', 'linux-amd64', 'linux-arm',
+ 'linux-arm64'
+ ]
},
{
'script': 'heap_profile',
'tool': 'trace_to_text',
- 'archs': ['mac-amd64', 'linux-amd64', 'windows-amd64']
+ 'archs': ['mac-amd64', 'windows-amd64', 'linux-amd64']
},
{
'script': 'record_android_trace',
@@ -67,20 +77,29 @@
},
]
-# Maps a 'os-arch' string into corresponding tuples that match against
-# python's platform / machine API (see get_perfetto_prebuilt.py).
+# 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'
- },
- 'linux-amd64': {
- 'platform': 'linux',
- 'machine': 'x86_64'
+ 'machine': ['x86_64'],
},
'windows-amd64': {
'platform': 'win32',
- 'machine': 'amd64'
+ 'machine': ['amd64'],
+ },
+ 'linux-amd64': {
+ 'platform': 'linux',
+ 'machine': ['x86_64'],
+ },
+ 'linux-arm': {
+ 'platform': 'linux',
+ 'machine': ['armv6l', 'armv7l', 'armv8l'],
+ },
+ 'linux-arm64': {
+ 'platform': 'linux',
+ 'machine': ['aarch64'],
},
}
diff --git a/tools/trace_processor b/tools/trace_processor
index f680cff..0a3a00e 100755
--- a/tools/trace_processor
+++ b/tools/trace_processor
@@ -24,73 +24,169 @@
exec python3 - "$@" <<'#'EOF
#"""
-import hashlib
-import os
-import sys
-import tempfile
-import subprocess
-import platform
+TOOL_NAME = 'trace_processor_shell'
-TRACE_PROCESSOR_SHELL_SHAS = {
- 'linux': '6dcb207dabcf5dc0d88aee8b3ae6abe2380e3e8d',
- 'mac': '8196240f76ee9472e39e538afa1bc76bdfce292a',
-}
-TRACE_PROCESSOR_SHELL_PATH = tempfile.gettempdir()
-TRACE_PROCESSOR_SHELL_BASE_URL = ('https://storage.googleapis.com/perfetto/')
+# BEGIN_SECTION_GENERATED_BY(roll-prebuilts)
+# Revision: 45571639857aa59be41f77a2d774f6577d03c86c
+PERFETTO_PREBUILT_MANIFEST = [{
+ 'tool':
+ 'trace_processor_shell',
+ 'arch':
+ 'mac-amd64',
+ 'file_name':
+ 'trace_processor_shell',
+ 'file_size':
+ 7022312,
+ 'url':
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/45571639857aa59be41f77a2d774f6577d03c86c/mac-amd64/trace_processor_shell',
+ 'sha256':
+ '1981f80067ea95d1da9431b816de592b6b64eac5bd73519e0f5f6e263935078b',
+ 'platform':
+ 'darwin',
+ 'machine': ['x86_64']
+}, {
+ 'tool':
+ 'trace_processor_shell',
+ 'arch':
+ 'windows-amd64',
+ 'file_name':
+ 'trace_processor_shell.exe',
+ 'file_size':
+ 6663680,
+ 'url':
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/45571639857aa59be41f77a2d774f6577d03c86c/windows-amd64/trace_processor_shell.exe',
+ 'sha256':
+ '5e03b5c3cbdc5fc58690bfd0cce310ee9f6fe786eca9edced23ee7b37d2dffff',
+ 'platform':
+ 'win32',
+ 'machine': ['amd64']
+}, {
+ 'tool':
+ 'trace_processor_shell',
+ 'arch':
+ 'linux-amd64',
+ 'file_name':
+ 'trace_processor_shell',
+ 'file_size':
+ 7378592,
+ 'url':
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/45571639857aa59be41f77a2d774f6577d03c86c/linux-amd64/trace_processor_shell',
+ 'sha256':
+ 'bfb8f8258be397edf0a9757847fe3c0ccfc0985fa379f694cdc26b885960f34b',
+ 'platform':
+ 'linux',
+ 'machine': ['x86_64']
+}, {
+ 'tool':
+ 'trace_processor_shell',
+ 'arch':
+ 'linux-arm',
+ 'file_name':
+ 'trace_processor_shell',
+ 'file_size':
+ 4635352,
+ 'url':
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/45571639857aa59be41f77a2d774f6577d03c86c/linux-arm/trace_processor_shell',
+ 'sha256':
+ '55b5cf7d9363ee3996fc991830b4d253a20c015b9bddbd9c929557721e16b16b',
+ 'platform':
+ 'linux',
+ 'machine': ['armv6l', 'armv7l', 'armv8l']
+}, {
+ 'tool':
+ 'trace_processor_shell',
+ 'arch':
+ 'linux-arm64',
+ 'file_name':
+ 'trace_processor_shell',
+ 'file_size':
+ 6165664,
+ 'url':
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/45571639857aa59be41f77a2d774f6577d03c86c/linux-arm64/trace_processor_shell',
+ 'sha256':
+ '6e1fc84dc5d238d48563d2f5f58509ce2a0e61ad0ac4f75af26e541eff1cd648',
+ 'platform':
+ 'linux',
+ 'machine': ['aarch64']
+}]
-def DownloadURL(url, out_file):
- subprocess.check_call(['curl', '-L', '-#', '-o', out_file, url])
+# DO NOT EDIT. If you wish to make edits to this code, you need to change only
+# //tools/get_perfetto_prebuilt.py and run /tools/roll-prebuilts to regenerate
+# all the others scripts this is embedded into.
+def get_perfetto_prebuilt(tool_name, soft_fail=False, arch=None):
+ """ Downloads the prebuilt, if necessary, and returns its path on disk. """
+
+ # The first time this is invoked, it downloads the |url| and caches it into
+ # ~/.perfetto/prebuilts/$tool_name. On subsequent invocations it just runs the
+ # cached version.
+ def download_or_get_cached(file_name, url, sha256):
+ import os, hashlib, subprocess
+ dir = os.path.join(
+ os.path.expanduser('~'), '.local', 'share', 'perfetto', 'prebuilts')
+ os.makedirs(dir, exist_ok=True)
+ bin_path = os.path.join(dir, file_name)
+ sha256_path = os.path.join(dir, file_name + '.sha256')
+ needs_download = True
+
+ # Avoid recomputing the SHA-256 on each invocation. The SHA-256 of the last
+ # download is cached into file_name.sha256, just check if that matches.
+ if os.path.exists(bin_path) and os.path.exists(sha256_path):
+ with open(sha256_path, 'rb') as f:
+ digest = f.read().decode()
+ if digest == sha256:
+ needs_download = False
+
+ if needs_download:
+ # Either the filed doesn't exist or the SHA256 doesn't match.
+ tmp_path = bin_path + '.tmp'
+ 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.rename(tmp_path, bin_path)
+ with open(sha256_path, 'w') as f:
+ f.write(sha256)
+ return bin_path
+ # --- end of download_or_get_cached() ---
+
+ # --- get_perfetto_prebuilt() function starts here. ---
+ import os, platform, sys
+ plat = sys.platform.lower()
+ machine = platform.machine().lower()
+ manifest_entry = None
+ for entry in PERFETTO_PREBUILT_MANIFEST:
+ # If the caller overrides the arch, just match that (for Android prebuilts).
+ if arch and entry.get('arch') == arch:
+ manifest_entry = entry
+ break
+ # Otherwise guess the local machine arch.
+ if entry.get('tool') == tool_name and 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')
+
+ return download_or_get_cached(
+ file_name=manifest_entry['file_name'],
+ url=manifest_entry['url'],
+ sha256=manifest_entry['sha256'])
-def check_hash(file_name, sha_value):
- with open(file_name, 'rb') as fd:
- file_hash = hashlib.sha1(fd.read()).hexdigest()
- return file_hash == sha_value
-
-
-def load_trace_processor_shell(platform):
- sha_value = TRACE_PROCESSOR_SHELL_SHAS[platform]
- file_name = 'trace_processor_shell-' + platform + '-' + sha_value
- local_file = os.path.join(TRACE_PROCESSOR_SHELL_PATH, file_name)
-
- if os.path.exists(local_file):
- if not check_hash(local_file, sha_value):
- os.remove(local_file)
- else:
- return local_file
-
- url = TRACE_PROCESSOR_SHELL_BASE_URL + file_name
- DownloadURL(url, local_file)
- if not check_hash(local_file, sha_value):
- os.remove(local_file)
- raise ValueError("Invalid signature.")
- os.chmod(local_file, 0o755)
- return local_file
-
-
-def main(argv):
- os_name = None
- if sys.platform.startswith('linux'):
- os_name = 'linux'
- elif sys.platform.startswith('darwin'):
- os_name = 'mac'
- else:
- print("Invalid platform: {}".format(sys.platform))
- return 1
-
- arch = platform.machine()
- if arch not in ['x86_64', 'amd64']:
- print("Prebuilts are only available for x86_64 (found '{}' instead).".format(arch))
- print("Follow https://perfetto.dev/docs/contributing/build-instructions to build locally.")
- return 1
-
- trace_processor_shell_binary = load_trace_processor_shell(os_name)
- os.execv(trace_processor_shell_binary,
- [trace_processor_shell_binary] + argv[1:])
-
+# END_SECTION_GENERATED_BY(roll-prebuilts)
if __name__ == '__main__':
- sys.exit(main(sys.argv))
+ import sys, os
+ bin_path = get_perfetto_prebuilt(TOOL_NAME)
+ os.execv(bin_path, [bin_path] + sys.argv[1:])
#EOF
diff --git a/tools/tracebox b/tools/tracebox
new file mode 100755
index 0000000..5183f2c
--- /dev/null
+++ b/tools/tracebox
@@ -0,0 +1,192 @@
+#!/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.
+
+# This file should do the same thing when being invoked in any of these ways:
+# ./tracebox
+# python tracebox
+# bash tracebox
+# cat ./tracebox | bash
+# cat ./tracebox | python -
+
+BASH_FALLBACK = """ "
+exec python3 - "$@" <<'#'EOF
+#"""
+
+TOOL_NAME = 'tracebox'
+
+# BEGIN_SECTION_GENERATED_BY(roll-prebuilts)
+# Revision: 45571639857aa59be41f77a2d774f6577d03c86c
+PERFETTO_PREBUILT_MANIFEST = [{
+ 'tool':
+ 'tracebox',
+ 'arch':
+ 'mac-amd64',
+ 'file_name':
+ 'tracebox',
+ 'file_size':
+ 1315792,
+ 'url':
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/45571639857aa59be41f77a2d774f6577d03c86c/mac-amd64/tracebox',
+ 'sha256':
+ '5ccbdf4548ab6d80f728b028ad88e7e9c95c02a06691212a396356449036487a',
+ 'platform':
+ 'darwin',
+ 'machine': ['x86_64']
+}, {
+ 'tool':
+ 'tracebox',
+ 'arch':
+ 'linux-amd64',
+ 'file_name':
+ 'tracebox',
+ 'file_size':
+ 1750688,
+ 'url':
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/45571639857aa59be41f77a2d774f6577d03c86c/linux-amd64/tracebox',
+ 'sha256':
+ '9e304cebb0bb09b47ff1e1c42b0d8ad6c9e499a12565de6b66961f9431109a02',
+ 'platform':
+ 'linux',
+ 'machine': ['x86_64']
+}, {
+ 'tool':
+ 'tracebox',
+ 'arch':
+ 'linux-amd64',
+ 'file_name':
+ 'tracebox',
+ 'file_size':
+ 1750688,
+ 'url':
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/45571639857aa59be41f77a2d774f6577d03c86c/linux-amd64/tracebox',
+ 'sha256':
+ '9e304cebb0bb09b47ff1e1c42b0d8ad6c9e499a12565de6b66961f9431109a02',
+ 'platform':
+ 'linux',
+ 'machine': ['x86_64']
+}, {
+ 'tool':
+ 'tracebox',
+ 'arch':
+ 'linux-arm',
+ 'file_name':
+ 'tracebox',
+ 'file_size':
+ 990096,
+ 'url':
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/45571639857aa59be41f77a2d774f6577d03c86c/linux-arm/tracebox',
+ 'sha256':
+ '259d676d90d3a3cd37af61ded9a7956f1dfe8370bff1c9f62bfced202731c231',
+ 'platform':
+ 'linux',
+ 'machine': ['armv6l', 'armv7l', 'armv8l']
+}, {
+ 'tool':
+ 'tracebox',
+ 'arch':
+ 'linux-arm64',
+ 'file_name':
+ 'tracebox',
+ 'file_size':
+ 1493456,
+ 'url':
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/45571639857aa59be41f77a2d774f6577d03c86c/linux-arm64/tracebox',
+ 'sha256':
+ '23c9d3f732c678f4002577f4f415703e221b092a90fc83e2bea3d69dd4061257',
+ 'platform':
+ 'linux',
+ 'machine': ['aarch64']
+}]
+
+
+# DO NOT EDIT. If you wish to make edits to this code, you need to change only
+# //tools/get_perfetto_prebuilt.py and run /tools/roll-prebuilts to regenerate
+# all the others scripts this is embedded into.
+def get_perfetto_prebuilt(tool_name, soft_fail=False, arch=None):
+ """ Downloads the prebuilt, if necessary, and returns its path on disk. """
+
+ # The first time this is invoked, it downloads the |url| and caches it into
+ # ~/.perfetto/prebuilts/$tool_name. On subsequent invocations it just runs the
+ # cached version.
+ def download_or_get_cached(file_name, url, sha256):
+ import os, hashlib, subprocess
+ dir = os.path.join(
+ os.path.expanduser('~'), '.local', 'share', 'perfetto', 'prebuilts')
+ os.makedirs(dir, exist_ok=True)
+ bin_path = os.path.join(dir, file_name)
+ sha256_path = os.path.join(dir, file_name + '.sha256')
+ needs_download = True
+
+ # Avoid recomputing the SHA-256 on each invocation. The SHA-256 of the last
+ # download is cached into file_name.sha256, just check if that matches.
+ if os.path.exists(bin_path) and os.path.exists(sha256_path):
+ with open(sha256_path, 'rb') as f:
+ digest = f.read().decode()
+ if digest == sha256:
+ needs_download = False
+
+ if needs_download:
+ # Either the filed doesn't exist or the SHA256 doesn't match.
+ tmp_path = bin_path + '.tmp'
+ 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.rename(tmp_path, bin_path)
+ with open(sha256_path, 'w') as f:
+ f.write(sha256)
+ return bin_path
+ # --- end of download_or_get_cached() ---
+
+ # --- get_perfetto_prebuilt() function starts here. ---
+ import os, platform, sys
+ plat = sys.platform.lower()
+ machine = platform.machine().lower()
+ manifest_entry = None
+ for entry in PERFETTO_PREBUILT_MANIFEST:
+ # If the caller overrides the arch, just match that (for Android prebuilts).
+ if arch and entry.get('arch') == arch:
+ manifest_entry = entry
+ break
+ # Otherwise guess the local machine arch.
+ if entry.get('tool') == tool_name and 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')
+
+ return download_or_get_cached(
+ file_name=manifest_entry['file_name'],
+ url=manifest_entry['url'],
+ sha256=manifest_entry['sha256'])
+
+
+# END_SECTION_GENERATED_BY(roll-prebuilts)
+
+if __name__ == '__main__':
+ import sys, os
+ bin_path = get_perfetto_prebuilt(TOOL_NAME)
+ os.execv(bin_path, [bin_path] + sys.argv[1:])
+
+#EOF
diff --git a/tools/traceconv b/tools/traceconv
index f0648aa..19d7194 100755
--- a/tools/traceconv
+++ b/tools/traceconv
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (C) 2019 The Android Open Source Project
+# 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.
@@ -24,73 +24,137 @@
exec python3 - "$@" <<'#'EOF
#"""
-import hashlib
-import os
-import sys
-import subprocess
-import tempfile
-import platform
+TOOL_NAME = 'trace_to_text'
+
+# BEGIN_SECTION_GENERATED_BY(roll-prebuilts)
+# Revision: 45571639857aa59be41f77a2d774f6577d03c86c
+PERFETTO_PREBUILT_MANIFEST = [{
+ 'tool':
+ 'trace_to_text',
+ 'arch':
+ 'mac-amd64',
+ 'file_name':
+ 'trace_to_text',
+ 'file_size':
+ 7087056,
+ 'url':
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/45571639857aa59be41f77a2d774f6577d03c86c/mac-amd64/trace_to_text',
+ 'sha256':
+ 'beaf8151ed0994f970e4e6d4da10b6681ac48a74f29133f4bea6f3d3294c1009',
+ 'platform':
+ 'darwin',
+ 'machine': ['x86_64']
+}, {
+ 'tool':
+ 'trace_to_text',
+ 'arch':
+ 'linux-amd64',
+ 'file_name':
+ 'trace_to_text',
+ 'file_size':
+ 7435576,
+ 'url':
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/45571639857aa59be41f77a2d774f6577d03c86c/linux-amd64/trace_to_text',
+ 'sha256':
+ '6c19500bfa983cfbf49fe0ef55284285ba674b43d1d2273f19249fa5b3dd9f84',
+ 'platform':
+ 'linux',
+ 'machine': ['x86_64']
+}, {
+ 'tool':
+ 'trace_to_text',
+ 'arch':
+ 'windows-amd64',
+ 'file_name':
+ 'trace_to_text.exe',
+ 'file_size':
+ 6702080,
+ 'url':
+ 'https://commondatastorage.googleapis.com/perfetto-luci-artifacts/45571639857aa59be41f77a2d774f6577d03c86c/windows-amd64/trace_to_text.exe',
+ 'sha256':
+ '58a1b1e1bb69465002ccf9611d13a029943257d41311a6603d45ba1ebfcfa077',
+ 'platform':
+ 'win32',
+ 'machine': ['amd64']
+}]
-TRACE_TO_TEXT_SHAS = {
- 'linux': '150d8e65b8173c317642abfc44f3861832fbcd4e',
- 'mac': '818143f3283559a89c311e7e506d0099d1f6408c',
-}
-TRACE_TO_TEXT_PATH = tempfile.gettempdir()
-TRACE_TO_TEXT_BASE_URL = ('https://storage.googleapis.com/perfetto/')
+# DO NOT EDIT. If you wish to make edits to this code, you need to change only
+# //tools/get_perfetto_prebuilt.py and run /tools/roll-prebuilts to regenerate
+# all the others scripts this is embedded into.
+def get_perfetto_prebuilt(tool_name, soft_fail=False, arch=None):
+ """ Downloads the prebuilt, if necessary, and returns its path on disk. """
+
+ # The first time this is invoked, it downloads the |url| and caches it into
+ # ~/.perfetto/prebuilts/$tool_name. On subsequent invocations it just runs the
+ # cached version.
+ def download_or_get_cached(file_name, url, sha256):
+ import os, hashlib, subprocess
+ dir = os.path.join(
+ os.path.expanduser('~'), '.local', 'share', 'perfetto', 'prebuilts')
+ os.makedirs(dir, exist_ok=True)
+ bin_path = os.path.join(dir, file_name)
+ sha256_path = os.path.join(dir, file_name + '.sha256')
+ needs_download = True
+
+ # Avoid recomputing the SHA-256 on each invocation. The SHA-256 of the last
+ # download is cached into file_name.sha256, just check if that matches.
+ if os.path.exists(bin_path) and os.path.exists(sha256_path):
+ with open(sha256_path, 'rb') as f:
+ digest = f.read().decode()
+ if digest == sha256:
+ needs_download = False
+
+ if needs_download:
+ # Either the filed doesn't exist or the SHA256 doesn't match.
+ tmp_path = bin_path + '.tmp'
+ 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.rename(tmp_path, bin_path)
+ with open(sha256_path, 'w') as f:
+ f.write(sha256)
+ return bin_path
+ # --- end of download_or_get_cached() ---
+
+ # --- get_perfetto_prebuilt() function starts here. ---
+ import os, platform, sys
+ plat = sys.platform.lower()
+ machine = platform.machine().lower()
+ manifest_entry = None
+ for entry in PERFETTO_PREBUILT_MANIFEST:
+ # If the caller overrides the arch, just match that (for Android prebuilts).
+ if arch and entry.get('arch') == arch:
+ manifest_entry = entry
+ break
+ # Otherwise guess the local machine arch.
+ if entry.get('tool') == tool_name and 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')
+
+ return download_or_get_cached(
+ file_name=manifest_entry['file_name'],
+ url=manifest_entry['url'],
+ sha256=manifest_entry['sha256'])
-def DownloadURL(url, out_file):
- subprocess.check_call(['curl', '-L', '-#', '-o', out_file, url])
-
-
-def check_hash(file_name, sha_value):
- with open(file_name, 'rb') as fd:
- file_hash = hashlib.sha1(fd.read()).hexdigest()
- return file_hash == sha_value
-
-
-def load_trace_to_text(platform):
- sha_value = TRACE_TO_TEXT_SHAS[platform]
- file_name = 'trace_to_text-' + platform + '-' + sha_value
- local_file = os.path.join(TRACE_TO_TEXT_PATH, file_name)
-
- if os.path.exists(local_file):
- if not check_hash(local_file, sha_value):
- os.remove(local_file)
- else:
- return local_file
-
- url = TRACE_TO_TEXT_BASE_URL + file_name
- DownloadURL(url, local_file)
- if not check_hash(local_file, sha_value):
- os.remove(local_file)
- raise ValueError("Invalid signature.")
- os.chmod(local_file, 0o755)
- return local_file
-
-
-def main(argv):
- os_name = None
- if sys.platform.startswith('linux'):
- os_name = 'linux'
- elif sys.platform.startswith('darwin'):
- os_name = 'mac'
- else:
- print("Invalid platform: {}".format(sys.platform))
- return 1
-
- arch = platform.machine()
- if arch not in ['x86_64', 'amd64']:
- print("Prebuilts are only available for x86_64 (found '{}' instead).".format(arch))
- print("Follow https://perfetto.dev/docs/contributing/build-instructions to build locally.")
- return 1
-
- trace_to_text_binary = load_trace_to_text(os_name)
- os.execv(trace_to_text_binary, [trace_to_text_binary] + argv[1:])
-
+# END_SECTION_GENERATED_BY(roll-prebuilts)
if __name__ == '__main__':
- sys.exit(main(sys.argv))
+ import sys, os
+ bin_path = get_perfetto_prebuilt(TOOL_NAME)
+ os.execv(bin_path, [bin_path] + sys.argv[1:])
#EOF