Ian Zerny | dcb172e | 2022-02-22 15:36:45 +0100 | [diff] [blame] | 1 | #!/usr/bin/env python3 |
Tamas Kenez | 19a3b8a | 2017-05-29 23:08:48 +0200 | [diff] [blame] | 2 | # Copyright (c) 2017, the R8 project authors. Please see the AUTHORS file |
| 3 | # for details. All rights reserved. Use of this source code is governed by a |
| 4 | # BSD-style license that can be found in the LICENSE file. |
| 5 | |
| 6 | # Take a file where each line is a tab-separated list of arguments for DX (or |
Søren Gjesse | a99636c | 2019-11-28 14:00:26 +0100 | [diff] [blame] | 7 | # D8) and create a self-contained directory with all the input files |
Tamas Kenez | 19a3b8a | 2017-05-29 23:08:48 +0200 | [diff] [blame] | 8 | # and a script which replays the same DX invocations as the original list. |
| 9 | # |
| 10 | # Usage: |
| 11 | # |
| 12 | # create_dx_replay.py <dx-args-script> <output-dir> |
| 13 | # |
| 14 | # The <dx-args-script> is a text file where each line contains tab-separated |
Søren Gjesse | a99636c | 2019-11-28 14:00:26 +0100 | [diff] [blame] | 15 | # arguments for a DX (D8) call. |
Tamas Kenez | 19a3b8a | 2017-05-29 23:08:48 +0200 | [diff] [blame] | 16 | # The script 'tools/test_android_cts.py' can log DX invocations during an AOSP |
| 17 | # build to such a file. Use 'test_android_cts.py --tool=d8 --d8log=<file> ...'. |
| 18 | |
| 19 | from __future__ import print_function |
| 20 | from os.path import join, isdir, exists, basename |
| 21 | from os import rmdir |
| 22 | from shutil import copy2 |
| 23 | import argparse |
| 24 | import os |
| 25 | import stat |
| 26 | import sys |
| 27 | |
| 28 | import utils |
| 29 | |
Christoffer Quist Adamsen | 2434a4d | 2023-10-16 11:29:03 +0200 | [diff] [blame] | 30 | IN_SUBDIR = 'in' # subdirectory for the local copy of the input files |
| 31 | OUT_SUBDIR = 'out' # subdirectory prefix for the output of DX |
Tamas Kenez | 19a3b8a | 2017-05-29 23:08:48 +0200 | [diff] [blame] | 32 | REPLAY_SCRIPT_NAME = 'replay_script.py' |
| 33 | |
Christoffer Quist Adamsen | 2434a4d | 2023-10-16 11:29:03 +0200 | [diff] [blame] | 34 | |
Tamas Kenez | 19a3b8a | 2017-05-29 23:08:48 +0200 | [diff] [blame] | 35 | # This function will be called with arguments of the original DX invocation. It |
| 36 | # copies the original input files into the local input directory and replaces |
| 37 | # the references in orig_args to the local input files. |
| 38 | # Returns the new line to be appended to the replay script. |
| 39 | def process_line(out_dir, input_counter, orig_args): |
Christoffer Quist Adamsen | 2434a4d | 2023-10-16 11:29:03 +0200 | [diff] [blame] | 40 | args = [] |
| 41 | inputs = [] |
| 42 | for arg in orig_args: |
| 43 | if arg.startswith('--output='): |
| 44 | continue # nothing to do, just skip this arg |
| 45 | if arg.startswith('--'): |
| 46 | args.append(arg) |
| 47 | else: |
| 48 | # 'arg' is the path of an input file: copy arg to local dir with |
| 49 | # a new, unique name |
| 50 | if isdir(arg): |
| 51 | raise IOError( |
| 52 | "Adding directories ('{}') to the replay script is not" |
| 53 | " implemented.".format(arg)) |
| 54 | elif not exists(arg): |
| 55 | print("The input file to DX does not exist: '{}'.".format(arg)) |
Tamas Kenez | 19a3b8a | 2017-05-29 23:08:48 +0200 | [diff] [blame] | 56 | |
Christoffer Quist Adamsen | 2434a4d | 2023-10-16 11:29:03 +0200 | [diff] [blame] | 57 | input_file = '{}_{}'.format(input_counter, basename(arg)) |
Tamas Kenez | 19a3b8a | 2017-05-29 23:08:48 +0200 | [diff] [blame] | 58 | |
Christoffer Quist Adamsen | 2434a4d | 2023-10-16 11:29:03 +0200 | [diff] [blame] | 59 | copy2(arg, join(out_dir, join(IN_SUBDIR, input_file))) |
| 60 | inputs.append(input_file) |
Tamas Kenez | 19a3b8a | 2017-05-29 23:08:48 +0200 | [diff] [blame] | 61 | |
Christoffer Quist Adamsen | 2434a4d | 2023-10-16 11:29:03 +0200 | [diff] [blame] | 62 | return 'call_dx({}, {}, {})\n'.format(input_counter, args, inputs) |
Tamas Kenez | 19a3b8a | 2017-05-29 23:08:48 +0200 | [diff] [blame] | 63 | |
| 64 | |
| 65 | def parse_arguments(): |
Christoffer Quist Adamsen | 2434a4d | 2023-10-16 11:29:03 +0200 | [diff] [blame] | 66 | parser = argparse.ArgumentParser( |
| 67 | description='Creates a self-contained directory for playing back a ' |
| 68 | ' sequence of DX calls.') |
| 69 | parser.add_argument( |
| 70 | 'dx_call_log', |
| 71 | help='File containing tab-separated arguments for a DX call on each' |
| 72 | ' line.') |
| 73 | parser.add_argument( |
| 74 | 'output_dir', |
| 75 | help='Target path the create the self-contained directory at.') |
| 76 | return parser.parse_args() |
| 77 | |
Tamas Kenez | 19a3b8a | 2017-05-29 23:08:48 +0200 | [diff] [blame] | 78 | |
| 79 | def Main(): |
Christoffer Quist Adamsen | 2434a4d | 2023-10-16 11:29:03 +0200 | [diff] [blame] | 80 | args = parse_arguments() |
Tamas Kenez | 19a3b8a | 2017-05-29 23:08:48 +0200 | [diff] [blame] | 81 | |
Christoffer Quist Adamsen | 2434a4d | 2023-10-16 11:29:03 +0200 | [diff] [blame] | 82 | if isdir(args.output_dir): |
| 83 | rmdir(args.output_dir) # make sure to write only to empty out dir |
Tamas Kenez | 19a3b8a | 2017-05-29 23:08:48 +0200 | [diff] [blame] | 84 | |
Christoffer Quist Adamsen | 2434a4d | 2023-10-16 11:29:03 +0200 | [diff] [blame] | 85 | utils.makedirs_if_needed(join(args.output_dir, IN_SUBDIR)) |
Tamas Kenez | 19a3b8a | 2017-05-29 23:08:48 +0200 | [diff] [blame] | 86 | |
Christoffer Quist Adamsen | 2434a4d | 2023-10-16 11:29:03 +0200 | [diff] [blame] | 87 | # create the first lines of the replay script |
| 88 | replay_script = \ |
| 89 | """#!/usr/bin/env python3 |
Tamas Kenez | 19a3b8a | 2017-05-29 23:08:48 +0200 | [diff] [blame] | 90 | import os |
| 91 | import shutil |
| 92 | import subprocess |
| 93 | import sys |
| 94 | |
| 95 | SCRIPT_DIR = os.path.abspath(os.path.normpath(os.path.join(__file__, '..'))) |
| 96 | IN_SUBDIR = '{}' |
| 97 | OUT_SUBDIR = '{}' |
| 98 | |
| 99 | def call_dx(input_counter, args, inputs): |
| 100 | out_dir = os.path.join(SCRIPT_DIR, OUT_SUBDIR, str(input_counter)) |
| 101 | if not os.path.isdir(out_dir): |
| 102 | os.makedirs(out_dir) |
| 103 | full_inputs = [os.path.join(SCRIPT_DIR, IN_SUBDIR, i) for i in inputs] |
| 104 | subprocess.check_call(sys.argv[1:] + args + ['--output=' + out_dir] |
| 105 | + full_inputs) |
| 106 | |
| 107 | if len(sys.argv) < 2: |
| 108 | raise IOError('Usage: create_dx_replay.py <dx-command>' |
| 109 | ' # can be multiple args') |
| 110 | abs_out_dir = os.path.join(SCRIPT_DIR, OUT_SUBDIR) |
| 111 | if os.path.isdir(abs_out_dir): |
| 112 | shutil.rmtree(abs_out_dir) |
| 113 | |
| 114 | """.format(IN_SUBDIR, OUT_SUBDIR) |
| 115 | |
Christoffer Quist Adamsen | 2434a4d | 2023-10-16 11:29:03 +0200 | [diff] [blame] | 116 | with open(args.dx_call_log) as f: |
| 117 | lines = f.read().splitlines() |
Tamas Kenez | 19a3b8a | 2017-05-29 23:08:48 +0200 | [diff] [blame] | 118 | |
Christoffer Quist Adamsen | 2434a4d | 2023-10-16 11:29:03 +0200 | [diff] [blame] | 119 | input_counter = 1 |
| 120 | for line in lines: |
| 121 | replay_script += \ |
| 122 | process_line(args.output_dir, input_counter, line.split('\t')) |
| 123 | input_counter += 1 |
Tamas Kenez | 19a3b8a | 2017-05-29 23:08:48 +0200 | [diff] [blame] | 124 | |
Christoffer Quist Adamsen | 2434a4d | 2023-10-16 11:29:03 +0200 | [diff] [blame] | 125 | script_file = join(args.output_dir, REPLAY_SCRIPT_NAME) |
| 126 | with open(script_file, 'w') as f: |
| 127 | f.write(replay_script) |
Tamas Kenez | 19a3b8a | 2017-05-29 23:08:48 +0200 | [diff] [blame] | 128 | |
Christoffer Quist Adamsen | 2434a4d | 2023-10-16 11:29:03 +0200 | [diff] [blame] | 129 | # chmod +x for script_file |
| 130 | st = os.stat(script_file) |
| 131 | os.chmod(script_file, |
| 132 | st.st_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH) |
| 133 | |
Tamas Kenez | 19a3b8a | 2017-05-29 23:08:48 +0200 | [diff] [blame] | 134 | |
| 135 | if __name__ == '__main__': |
Christoffer Quist Adamsen | 2434a4d | 2023-10-16 11:29:03 +0200 | [diff] [blame] | 136 | sys.exit(Main()) |