blob: f08e94c4b2b58dbee0ee681e5f5a75810d35d1f4 [file]
#!/usr/bin/env python3
# Copyright (c) 2025, the R8 project authors. Please see the AUTHORS file
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.
import argparse
import os
import shutil
import sys
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
import adb
import apk_masseur
import compiledump
import utils
class AttrDict(dict):
def __getattr__(self, name):
return self.get(name, None)
def run_r8_assistant(options, temp_dir):
compiledump_args = AttrDict(
vars(
argparse.Namespace(
dump=options.dump,
compiler='assistant',
disable_assertions=options.disable_assertions,
debug_agent=options.debug_agent,
version='main',
no_build=options.no_build,
enable_missing_library_api_modeling=False,
java_opts=[],
)))
instrumented_dex = os.path.join(temp_dir, 'out.jar')
with utils.TempDir() as compiledump_temp_dir:
compile_result = compiledump.run1(compiledump_temp_dir,
compiledump_args,
['--output', instrumented_dex])
if compile_result != 0:
raise Exception('Failed to run R8 assistant')
original_app_apk = options.apk
# Create new app apk with instrumented dex.
instrumented_app_apk = os.path.join(temp_dir, "app.apk")
apk_masseur.masseur(original_app_apk,
dex=instrumented_dex,
out=instrumented_app_apk,
keystore=options.keystore)
# Sign test apk with same key as the instrumented dex apk.
original_test_apk = options.apk_test
test_apk_destination = os.path.join(temp_dir, "test.apk")
apk_masseur.masseur(original_test_apk,
out=test_apk_destination,
keystore=options.keystore)
adb.run_instrumented(options.id,
options.id_test,
options.device,
instrumented_app_apk,
test_apk_destination,
quiet=False,
enable_logging=True,
test_runner=None)
def parse_options(argv):
result = argparse.ArgumentParser(description='Run/compile dump artifacts.')
result.add_argument('--apk', help='Path to apk for app')
result.add_argument('--apk-test', help='Path to apk for androidTest')
result.add_argument('--dump', help='Path to compiler dump')
result.add_argument('--id', help='The id of the app')
result.add_argument('--id-test', help='The id of the test')
result.add_argument('--device', help='The device to run on')
result.add_argument('--debug-agent',
help='Enable Java debug agent and suspend compilation ',
default=False,
action='store_true')
result.add_argument(
'--disable-assertions',
'--disable_assertions',
'-da',
help='Disable Java assertions when running the compiler',
default=False,
action='store_true')
result.add_argument('--keystore',
help='Path to app.keystore',
default=os.path.join(utils.TOOLS_DIR, 'debug.keystore'))
result.add_argument('--no-build',
'--no_build',
help='Run without building first (only when using ToT)',
default=False,
action='store_true')
result.add_argument('--temp',
help='A directory to use for temporaries and outputs.')
return result.parse_known_args(argv)
def main(argv):
options, _ = parse_options(argv)
with utils.TempDir() as temp_dir:
if options.temp:
temp_dir = options.temp
os.makedirs(temp_dir, exist_ok=True)
run_r8_assistant(options, temp_dir)
if __name__ == '__main__':
sys.exit(main(sys.argv[1:]))