Merge "Ensure basic blocks have unique number after split."
diff --git a/tools/d8.py b/tools/d8.py
index cb0c841..d214cf5 100755
--- a/tools/d8.py
+++ b/tools/d8.py
@@ -24,6 +24,7 @@
     cmd.append('-agentlib:hprof=cpu=samples,interval=1,depth=8')
   cmd.extend(['-jar', D8_JAR])
   cmd.extend(args)
+  utils.PrintCmd(cmd)
   subprocess.check_call(cmd)
 
 def main():
diff --git a/tools/run-r8-on-gmscore.py b/tools/run-r8-on-gmscore.py
index f4d8994..ee8b813 100755
--- a/tools/run-r8-on-gmscore.py
+++ b/tools/run-r8-on-gmscore.py
@@ -8,4 +8,5 @@
 
 if __name__ == '__main__':
   # Default compiler is R8.
-  sys.exit(run_on_app.main())
+  sys.exit(run_on_app.main(sys.argv[1:]
+      + ['--app', 'gmscore', '--compiler', 'r8']))
diff --git a/tools/run_on_app.py b/tools/run_on_app.py
index a091e1c..a207ed8 100755
--- a/tools/run_on_app.py
+++ b/tools/run_on_app.py
@@ -19,16 +19,15 @@
 
 TYPES = ['dex', 'deploy', 'proguarded']
 APPS = ['gmscore', 'youtube', 'gmail']
+COMPILERS = ['d8', 'r8']
 
-def ParseOptions():
+def ParseOptions(argv):
   result = optparse.OptionParser()
   result.add_option('--compiler',
                     help='',
-                    default='r8',
-                    choices=['d8', 'r8'])
+                    choices=COMPILERS)
   result.add_option('--app',
                     help='',
-                    default='gmscore',
                     choices=APPS)
   result.add_option('--type',
                     help='Default for R8: deploy, for D8: proguarded',
@@ -87,7 +86,7 @@
                     metavar='BENCHMARKNAME',
                     help='Print the sizes of individual dex segments as ' +
                         '\'<BENCHMARKNAME>-<segment>(CodeSize): <bytes>\'')
-  return result.parse_args()
+  return result.parse_args(argv)
 
 # Most apps have the -printmapping and -printseeds in the Proguard
 # configuration. However we don't want to write these files in these
@@ -100,9 +99,9 @@
     f.write('-printseeds ' + os.path.join(outdir, 'proguard.seeds') + "\n")
     return os.path.abspath(f.name)
 
-def main():
+def main(argv):
   app_provided_pg_conf = False;
-  (options, args) = ParseOptions()
+  (options, args) = ParseOptions(argv)
   outdir = options.out
   data = None
   if options.app == 'gmscore':
@@ -115,7 +114,11 @@
     options.version = options.version or '170604.16'
     data = gmail_data
   else:
-    raise 'Unexpected'
+    raise Exception("You need to specify '--app={}'".format('|'.join(APPS)))
+
+  if options.compiler not in COMPILERS:
+    raise Exception("You need to specify '--compiler={}'"
+        .format('|'.join(COMPILERS)))
 
   if not options.version in data.VERSIONS.keys():
     print('No version {} for application {}'
@@ -217,4 +220,4 @@
     utils.print_dexsegments(options.print_dexsegments, dex_files)
 
 if __name__ == '__main__':
-  sys.exit(main())
+  sys.exit(main(sys.argv[1:]))
diff --git a/tools/run_proguard_dx_on_app.py b/tools/run_proguard_dx_on_app.py
new file mode 100755
index 0000000..8578d1e
--- /dev/null
+++ b/tools/run_proguard_dx_on_app.py
@@ -0,0 +1,156 @@
+#!/usr/bin/env python
+# Copyright (c) 2017, 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.
+
+# Run ProGuard and the DX or CompatDX (= D8) tool on GmsCore V10.
+
+from __future__ import print_function
+from glob import glob
+from os import makedirs
+from os.path import exists, join, splitext
+from subprocess import check_call
+import argparse
+import fnmatch
+import gmscore_data
+import os
+import stat
+import sys
+import time
+
+import gmail_data
+import gmscore_data
+import proguard
+import utils
+import youtube_data
+
+APPS = ['gmscore', 'youtube']
+DX_JAR = join(utils.REPO_ROOT, 'tools', 'linux', 'dx', 'framework', 'dx.jar')
+COMPATDX_JAR = join(utils.REPO_ROOT, 'build', 'libs', 'compatdx.jar')
+
+def parse_arguments(argv):
+  parser = argparse.ArgumentParser(
+      description = 'Run ProGuard and the DX tool on GmsCore V10.')
+  parser.add_argument('--app', required = True, choices = APPS)
+  parser.add_argument('--out',
+      help = 'Output directory for the DX tool.',
+      default = os.getcwd())
+  parser.add_argument('--compatdx',
+      help = 'Use CompatDx (D8) instead of DX.',
+      default = False,
+      action = 'store_true')
+  parser.add_argument('--print-runtimeraw',
+      metavar = 'BENCHMARKNAME',
+      help = 'Print the line \'<BENCHMARKNAME>(RunTimeRaw): <elapsed>' +
+             ' ms\' at the end where <elapsed> is the elapsed time in' +
+             ' milliseconds.')
+  parser.add_argument('--print-memoryuse',
+      metavar='BENCHMARKNAME',
+      help='Print the line \'<BENCHMARKNAME>(MemoryUse):' +
+           ' <mem>\' at the end where <mem> is the peak' +
+           ' peak resident set size (VmHWM) in bytes.')
+  parser.add_argument('--print-dexsegments',
+      metavar = 'BENCHMARKNAME',
+      help = 'Print the sizes of individual dex segments as ' +
+          '\'<BENCHMARKNAME>-<segment>(CodeSize): <bytes>\'')
+  return parser.parse_args(argv)
+
+def Main(argv):
+  options = parse_arguments(argv)
+
+  outdir = options.out
+
+  if options.app == 'gmscore':
+    version = 'v10'
+    data = gmscore_data
+    base = data.V10_BASE
+  elif options.app == 'youtube':
+    version = '12.22'
+    data = youtube_data
+    base = data.V12_22_BASE
+  else:
+    raise Exception('Unexpected')
+
+
+  args = ['-forceprocessing']
+
+  if not outdir.endswith('.zip') and not outdir.endswith('.jar') \
+      and not exists(outdir):
+    makedirs(outdir)
+
+
+  values_deploy = data.VERSIONS[version]['deploy']
+  values_proguarded = data.VERSIONS[version]['proguarded']
+  assert 'pgconf' in values_deploy
+
+  for pgconf in values_deploy['pgconf']:
+    args.extend(['@' + pgconf])
+
+  # find seeds file
+  inputs = data.VERSIONS[version]['proguarded']['inputs']
+  assert len(inputs) == 1
+  basename_wo_ext = splitext(os.path.basename(inputs[0]))[0]
+  seeds_filename = basename_wo_ext + '.seeds'
+
+  seeds_files = []
+  for root, dirnames, filenames in os.walk(join(base, 'blaze-out')):
+    for filename in fnmatch.filter(filenames, seeds_filename):
+        seeds_files.append(os.path.join(root, filename))
+  assert len(seeds_files) == 1
+
+  seeds_path = seeds_files[0]
+  proguarded_jar_path = splitext(seeds_path)[0] + '.jar'
+
+  # Remove write-protection from seeds file. The seeds file is an output of
+  # ProGuard so it aborts if this is not writeable.
+  st = os.stat(seeds_path)
+  os.chmod(seeds_path,
+      st.st_mode | stat.S_IWUSR | stat.S_IWGRP | stat.S_IWOTH)
+
+  t0 = time.time()
+
+  proguard_memoryuse = None
+
+  with utils.TempDir() as temp:
+    track_memory_file = None
+    if options.print_memoryuse:
+      track_memory_file = join(temp, utils.MEMORY_USE_TMP_FILE)
+    proguard.run(args, track_memory_file = track_memory_file)
+    if options.print_memoryuse:
+      proguard_memoryuse = utils.grep_memoryuse(track_memory_file)
+
+  # run dex on the result
+  if options.compatdx:
+    jar = COMPATDX_JAR
+  else:
+    jar = DX_JAR
+
+  with utils.TempDir() as temp:
+    track_memory_file = None
+    cmd = []
+    if options.print_memoryuse:
+      track_memory_file = join(temp, utils.MEMORY_USE_TMP_FILE)
+      cmd.extend(['tools/track_memory.sh', track_memory_file])
+    cmd.extend(['java', '-jar', jar, '--multi-dex',
+        '--output=' + outdir])
+    if 'min-api' in values_proguarded:
+      cmd.append('--min-sdk-version=' + values_proguarded['min-api'])
+    cmd.extend(['--dex', proguarded_jar_path])
+    utils.PrintCmd(cmd);
+    check_call(cmd)
+    if options.print_memoryuse:
+      dx_memoryuse = utils.grep_memoryuse(track_memory_file)
+      print('{}(MemoryUse): {}'
+          .format(options.print_memoryuse,
+              max(proguard_memoryuse, dx_memoryuse)))
+
+  if options.print_runtimeraw:
+    print('{}(RunTimeRaw): {} ms'
+        .format(options.print_runtimeraw, 1000.0 * (time.time() - t0)))
+
+  if options.print_dexsegments:
+    dex_files = glob(os.path.join(outdir, '*.dex'))
+    utils.print_dexsegments(options.print_dexsegments, dex_files)
+
+if __name__ == '__main__':
+  sys.exit(Main(sys.argv[1:]))
diff --git a/tools/run_proguard_dx_on_gmscore.py b/tools/run_proguard_dx_on_gmscore.py
index 06f56f9..5a6e42a 100755
--- a/tools/run_proguard_dx_on_gmscore.py
+++ b/tools/run_proguard_dx_on_gmscore.py
@@ -5,122 +5,9 @@
 
 # Run ProGuard and the DX or CompatDX (= D8) tool on GmsCore V10.
 
-from __future__ import print_function
-from glob import glob
-from os import makedirs
-from os.path import exists, join
-from subprocess import check_call
-import argparse
-import gmscore_data
-import os
-import stat
 import sys
-import time
 
-import proguard
-import utils
-
-BLAZE_BUILD_DIR = join(gmscore_data.V10_BASE,
-    'blaze-out', 'intel-linux-android-4.8-libcxx-x86-opt', 'bin', 'java',
-    'com', 'google', 'android', 'gmscore', 'integ')
-PROGUARDED_OUTPUT = join(BLAZE_BUILD_DIR,
-    'GmsCore_prod_alldpi_release_all_locales_proguard.jar')
-GMSCORE_SEEDS_FILE = join(BLAZE_BUILD_DIR,
-    'GmsCore_prod_alldpi_release_all_locales_proguard.seeds')
-DX_JAR = join(utils.REPO_ROOT, 'tools', 'linux', 'dx', 'framework', 'dx.jar')
-COMPATDX_JAR = join(utils.REPO_ROOT, 'build', 'libs', 'compatdx.jar')
-
-def parse_arguments():
-  parser = argparse.ArgumentParser(
-      description = 'Run ProGuard and the DX tool on GmsCore V10.')
-  parser.add_argument('--out',
-      help = 'Output directory for the DX tool.',
-      default = os.getcwd())
-  parser.add_argument('--print-runtimeraw',
-      metavar = 'BENCHMARKNAME',
-      help = 'Print the line \'<BENCHMARKNAME>(RunTimeRaw): <elapsed>' +
-             ' ms\' at the end where <elapsed> is the elapsed time in' +
-             ' milliseconds.')
-  parser.add_argument('--print-memoryuse',
-      metavar='BENCHMARKNAME',
-      help='Print the line \'<BENCHMARKNAME>(MemoryUse):' +
-           ' <mem>\' at the end where <mem> is the peak' +
-           ' peak resident set size (VmHWM) in bytes.')
-  parser.add_argument('--compatdx',
-      help = 'Use CompatDx (D8) instead of DX.',
-      default = False,
-      action = 'store_true')
-  parser.add_argument('--print-dexsegments',
-      metavar = 'BENCHMARKNAME',
-      help = 'Print the sizes of individual dex segments as ' +
-          '\'<BENCHMARKNAME>-<segment>(CodeSize): <bytes>\'')
-  return parser.parse_args()
-
-def Main():
-  options = parse_arguments()
-
-  outdir = options.out
-
-  args = ['-forceprocessing']
-
-  if not outdir.endswith('.zip') and not outdir.endswith('.jar') \
-      and not exists(outdir):
-    makedirs(outdir)
-
-  version = gmscore_data.VERSIONS['v10']
-  values = version['deploy']
-  assert 'pgconf' in values
-
-  for pgconf in values['pgconf']:
-    args.extend(['@' + pgconf])
-
-  # Remove write-protection from seeds file. The seeds file is an output of
-  # ProGuard so it aborts if this is not writeable.
-  st = os.stat(GMSCORE_SEEDS_FILE)
-  os.chmod(GMSCORE_SEEDS_FILE,
-      st.st_mode | stat.S_IWUSR | stat.S_IWGRP | stat.S_IWOTH)
-
-  t0 = time.time()
-
-  proguard_memoryuse = None
-
-  with utils.TempDir() as temp:
-    track_memory_file = None
-    if options.print_memoryuse:
-      track_memory_file = join(temp, utils.MEMORY_USE_TMP_FILE)
-    proguard.run(args, track_memory_file = track_memory_file)
-    if options.print_memoryuse:
-      proguard_memoryuse = utils.grep_memoryuse(track_memory_file)
-
-  # run dex on the result
-  if options.compatdx:
-    jar = COMPATDX_JAR
-  else:
-    jar = DX_JAR
-
-  with utils.TempDir() as temp:
-    track_memory_file = None
-    cmd = []
-    if options.print_memoryuse:
-      track_memory_file = join(temp, utils.MEMORY_USE_TMP_FILE)
-      cmd.extend(['tools/track_memory.sh', track_memory_file])
-    cmd.extend(['java', '-jar', jar, '--min-sdk-version=26', '--multi-dex',
-        '--output=' + outdir, '--dex', PROGUARDED_OUTPUT]);
-    utils.PrintCmd(cmd);
-    check_call(cmd)
-    if options.print_memoryuse:
-      dx_memoryuse = utils.grep_memoryuse(track_memory_file)
-      print('{}(MemoryUse): {}'
-          .format(options.print_memoryuse,
-              max(proguard_memoryuse, dx_memoryuse)))
-
-  if options.print_runtimeraw:
-    print('{}(RunTimeRaw): {} ms'
-        .format(options.print_runtimeraw, 1000.0 * (time.time() - t0)))
-
-  if options.print_dexsegments:
-    dex_files = glob(os.path.join(outdir, '*.dex'))
-    utils.print_dexsegments(options.print_dexsegments, dex_files)
+import run_proguard_dx_on_app
 
 if __name__ == '__main__':
-  sys.exit(Main())
+  sys.exit(run_proguard_dx_on_app.Main(sys.argv[1:] + ['--app', 'gmscore']))