| #!/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:])) |