Example #1
0
def Main():
    utils.check_java_version()
    args = parse_arguments()
    output_dir = args.output
    if args.golem:
        golem.link_third_party()
    with utils.TempDir() as temp_dir:

        if not output_dir:
            output_dir = temp_dir

        xmx = None
        if args.tool == 'dx':
            tool_file = DX_JAR
            tool_args = [
                '--dex', '--output=' + output_dir, '--multi-dex',
                '--min-sdk-version=' + MIN_SDK_VERSION
            ]
            xmx = '-Xmx1600m'
        else:
            tool_file = utils.D8_JAR
            tool_args = ['--output', output_dir, '--min-api', MIN_SDK_VERSION]
            if args.tool == 'd8-release':
                tool_args.append('--release')
            xmx = '-Xmx600m'

        cmd = []

        track_memory_file = None
        if args.print_memoryuse:
            track_memory_file = os.path.join(output_dir,
                                             utils.MEMORY_USE_TMP_FILE)
            cmd.extend(['tools/track_memory.sh', track_memory_file])

        if tool_file.endswith('.jar'):
            assert xmx is not None
            cmd.extend(['java', xmx, '-jar'])

        cmd.extend([tool_file] + tool_args + [FRAMEWORK_JAR])

        utils.PrintCmd(cmd)

        t0 = time.time()
        subprocess.check_call(cmd)
        dt = time.time() - t0

        if args.print_memoryuse:
            print('{}-Total(MemoryUse): {}'.format(
                args.name, utils.grep_memoryuse(track_memory_file)))

        dex_files = [f for f in glob(os.path.join(output_dir, '*.dex'))]
        code_size = 0
        for dex_file in dex_files:
            code_size += os.path.getsize(dex_file)

        print('{}-Total(RunTimeRaw): {} ms'.format(args.name, 1000.0 * dt))

        print('{}-Total(CodeSize): {}'.format(args.name, code_size))

        utils.print_dexsegments(args.name, dex_files)
def Main():
    (options, args) = parse_options()
    if options.golem:
        golem.link_third_party()
    with utils.TempDir() as temp:
        dex_path = os.path.join(temp, "classes.jar")
        proguard_conf = os.path.join(temp, 'proguard.conf')
        with open(proguard_conf, 'w') as f:
            f.write(PROGUARD_CONF)
        benchmark_jar = get_jar_for_benchmark(options.benchmark)
        r8_args = [
            '--lib',
            utils.get_android_jar(26),  # Only works with api 26
            '--output',
            dex_path,
            '--pg-conf',
            proguard_conf,
            '--min-api',
            str(options.api),
            benchmark_jar
        ]
        toolhelper.run('r8', r8_args, build=not options.golem)
        if options.use_device:
            result = run_art_device(dex_path)
        else:
            result = run_art(dex_path)
        print('Kotlin_{}(RunTimeRaw): {} ms'.format(options.benchmark, result))
Example #3
0
def Main():
    args = parse_arguments()
    if args.golem:
        golem.link_third_party()
    utils.check_java_version()

    with utils.TempDir() as temp_dir:
        cmd_prefix = []
        output_dir = args.output if args.output else temp_dir
        temp_dir = os.path.join(args.output,
                                'tmp') if args.output else temp_dir

        track_memory_file = None
        if args.print_memoryuse:
            track_memory_file = os.path.join(output_dir,
                                             utils.MEMORY_USE_TMP_FILE)
            cmd_prefix.extend(['tools/track_memory.sh', track_memory_file])

        name = 'CompileHelloExample'

        tool = args.tool
        output_mode = args.output_mode
        lib = None
        if output_mode == 'dex':
            name += 'Dex'
            lib = utils.get_android_jar(28)
        else:
            lib = utils.RT_JAR

        extra = []
        if args.large:
            name += 'Large'
            extra = EXTRA_INPUTS

        if args.noopt:
            name += 'NoOpt'

        cmds = Compile(
            tool,
            output_mode,
            lib,
            extra,
            output_dir,
            args.noopt,
            temp_dir,
        )

        t0 = time.time()
        for cmd in cmds:
            fullcmd = cmd_prefix + cmd
            utils.PrintCmd(fullcmd)
            subprocess.check_output(fullcmd)
        dt = time.time() - t0

        if args.print_memoryuse:
            print('{}(MemoryUse): {}'.format(
                name, utils.grep_memoryuse(track_memory_file)))

        print('{}(RunTimeRaw): {} ms'.format(name, 1000.0 * dt))
def Main():
    args = parse_arguments()
    if args.golem:
        # Ensure that we don't have a running daemon
        exitcode = subprocess.call(['pkill', 'java'])
        assert exitcode == 0 or exitcode == 1
        golem.link_third_party()

    if args.tool == 'd8':
        tool = Benchmark.Tools.D8
        desugarMode = Benchmark.DesugarMode.D8_DESUGARING
    else:
        tool = Benchmark.Tools.DX
        desugarMode = Benchmark.DesugarMode.DESUGAR_TOOL

    buildTimeBenchmarks = [
        Benchmark('AntennaPod', os.path.join('antenna-pod', 'AntennaPod'),
                  ':app', [':app:assembleDebug'], ['clean']),
        Benchmark(
            'Maps', 'gradle-java-1.6', ':maps',
            [':maps:assembleDebug', '--settings-file', 'settings.gradle.maps'],
            ['clean']),
        Benchmark('Music2', 'gradle-java-1.6', ':music2Old', [
            ':music2Old:assembleDebug', '--settings-file',
            'settings.gradle.music2Old'
        ], ['clean']),
        Benchmark('Velvet', 'gradle-java-1.6', ':velvet', [
            ':velvet:assembleDebug', '--settings-file',
            'settings.gradle.velvet'
        ], ['clean']),
        Benchmark('SantaTracker', 'santa-tracker', ':santa-tracker',
                  [':santa-tracker:assembleDebug'], ['clean']),

        # disabled for now, apparently because of b/74227571
        # Benchmark('Tachiyomi',
        #           'tachiyomi',
        #           ':app',
        #           ['assembleStandardDebug'],
        #           ['clean']),
        Benchmark('WordPress', 'wordpress', ':WordPress',
                  ['assembleVanillaDebug'], ['clean']),
    ]
    if not args.skip_download and not args.golem:
        EnsurePresence(
            os.path.join('third_party', 'benchmarks', 'android-sdk'),
            'android SDK')
        EnsurePresence(os.path.join('third_party', 'gradle-plugin'),
                       'Android Gradle plugin')
    toRun = buildTimeBenchmarks
    if args.benchmark:
        toRun = [b for b in toRun if b.displayName == args.benchmark]
        if len(toRun) != 1:
            raise AssertionError("Unknown benchmark: " + args.benchmark)
    for benchmark in toRun:
        if not args.skip_download:
            benchmark.EnsurePresence()
        benchmark.Clean()
        stdOut = benchmark.Build(tool, desugarMode)
        PrintBuildTimeForGolem(benchmark, stdOut)
Example #5
0
        '--lib',
        utils.RT_JAR,
        '--min-api',
        '10000',
        '--no-desugaring',
    ],
                                 debug=False,
                                 build=False)
    if return_code != 0:
        sys.exit(return_code)


if __name__ == '__main__':
    options = parse_arguments(sys.argv[1:])
    if options.golem:
        golem.link_third_party()
    with utils.TempDir() as temp:
        memory_file = os.path.join(temp, 'memory.dump')
        r8_output = os.path.join(temp, 'r8.zip')
        d8_r8_output = os.path.join(temp, 'd8r8.zip')
        d8_pg_output = os.path.join(temp, 'd8pg.zip')

        return_code = minify_tool.minify_tool(input_jar=PINNED_R8_JAR,
                                              output_jar=r8_output,
                                              debug=False,
                                              build=False,
                                              track_memory_file=memory_file,
                                              benchmark_name="BootstrapR8")
        if return_code != 0:
            sys.exit(return_code)
Example #6
0
def main(argv):
  (options, args) = ParseOptions(argv)

  if options.bot:
    utils.DownloadFromGoogleCloudStorage(utils.OPENSOURCE_APPS_SHA_FILE)
    utils.DownloadFromGoogleCloudStorage(utils.ANDROID_SDK + '.tar.gz.sha1',
                                         bucket='r8-deps-internal',
                                         auth=True)
    if os.path.exists(WORKING_DIR):
      shutil.rmtree(WORKING_DIR)
    shutil.copytree(utils.OPENSOURCE_APPS_FOLDER, WORKING_DIR)
    os.environ[utils.ANDROID_HOME_ENVIROMENT_NAME] = os.path.join(
        utils.ANDROID_SDK)
    os.environ[utils.ANDROID_TOOLS_VERSION_ENVIRONMENT_NAME] = '28.0.3'
    # TODO(b/141081520): Set to True once fixed.
    options.no_logging = False
    # TODO(b/141081520): Remove logging filter once fixed.
    options.app_logging_filter = ['sqldelight']
    options.shrinker = ['r8', 'r8-full']
    print(options.shrinker)

  if options.golem:
    golem.link_third_party()
    if os.path.exists(WORKING_DIR):
      shutil.rmtree(WORKING_DIR)
    shutil.copytree(utils.OPENSOURCE_APPS_FOLDER, WORKING_DIR)
    os.environ[utils.ANDROID_HOME_ENVIROMENT_NAME] = os.path.join(
        utils.ANDROID_SDK)
    os.environ[utils.ANDROID_TOOLS_VERSION_ENVIRONMENT_NAME] = '28.0.3'
    options.disable_assertions = True
    options.ignore_versions = True
    options.no_build = True
    options.r8_compilation_steps = 1
    options.quiet = True
    options.gradle_pre_runs = 2
    options.use_daemon = True
    options.no_logging = True

  if not os.path.exists(WORKING_DIR):
    os.makedirs(WORKING_DIR)

  if options.download_only:
    clone_repositories(options.quiet)
    return

  with utils.TempDir() as temp_dir:
    if not (options.no_build or options.golem):
      gradle.RunGradle(['r8', '-Pno_internal'])
      build_r8lib = False
      for shrinker in options.shrinker:
        if IsMinifiedR8(shrinker):
          build_r8lib = True
      if build_r8lib:
        gradle.RunGradle(['r8lib', '-Pno_internal'])

    if options.hash:
      # Download r8-<hash>.jar from
      # https://storage.googleapis.com/r8-releases/raw/.
      target = 'r8-{}.jar'.format(options.hash)
      update_prebuilds_in_android.download_hash(
          temp_dir, 'com/android/tools/r8/' + options.hash, target)
      as_utils.MoveFile(
          os.path.join(temp_dir, target), os.path.join(temp_dir, 'r8lib.jar'),
          quiet=options.quiet)
    elif options.version:
      # Download r8-<version>.jar from
      # https://storage.googleapis.com/r8-releases/raw/.
      target = 'r8-{}.jar'.format(options.version)
      update_prebuilds_in_android.download_version(
          temp_dir, 'com/android/tools/r8/' + options.version, target)
      as_utils.MoveFile(
          os.path.join(temp_dir, target), os.path.join(temp_dir, 'r8lib.jar'),
          quiet=options.quiet)
    else:
      # Make a copy of r8.jar and r8lib.jar such that they stay the same for
      # the entire execution of this script.
      if 'r8-nolib' in options.shrinker or 'r8-nolib-full' in options.shrinker:
        assert os.path.isfile(utils.R8_JAR), 'Cannot build without r8.jar'
        shutil.copyfile(utils.R8_JAR, os.path.join(temp_dir, 'r8.jar'))
      if 'r8' in options.shrinker or 'r8-full' in options.shrinker:
        assert os.path.isfile(utils.R8LIB_JAR), 'Cannot build without r8lib.jar'
        shutil.copyfile(utils.R8LIB_JAR, os.path.join(temp_dir, 'r8lib.jar'))

    result_per_shrinker_per_app = []
    # If we are running on golem we kill all java processes after the run
    # to ensure no hanging gradle daemons.
    with EnsureNoGradleAlive(options.golem):
      for (app, repo) in options.apps:
        if app.skip:
          continue
        result_per_shrinker_per_app.append(
            (app, GetResultsForApp(app, repo, options, temp_dir)))
    return LogResultsForApps(result_per_shrinker_per_app, options)
Example #7
0
def run_with_options(options, args, extra_args=None):
    if extra_args is None:
        extra_args = []
    app_provided_pg_conf = False
    # todo(121018500): remove when memory is under control
    if not any('-Xmx' in arg for arg in extra_args):
        extra_args.append('-Xmx8G')
    if options.golem:
        golem.link_third_party()
        options.out = os.getcwd()
    if not options.ignore_java_version:
        utils.check_java_version()

    outdir = options.out
    data = None
    if options.app == 'gmscore':
        options.version = options.version or 'v9'
        data = gmscore_data
    elif options.app == 'nest':
        options.version = options.version or '20180926'
        data = nest_data
    elif options.app == 'youtube':
        options.version = options.version or '12.22'
        data = youtube_data
    elif options.app == 'chrome':
        options.version = options.version or '180917'
        data = chrome_data
    elif options.app == 'gmail':
        options.version = options.version or '170604.16'
        data = gmail_data
    else:
        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 options.compiler_build not in COMPILER_BUILDS:
        raise Exception("You need to specify '--compiler-build={}'".format(
            '|'.join(COMPILER_BUILDS)))

    if not options.version in data.VERSIONS.keys():
        print('No version {} for application {}'.format(
            options.version, options.app))
        print('Valid versions are {}'.format(data.VERSIONS.keys()))
        return 1

    version = data.VERSIONS[options.version]

    if not options.type:
        options.type = 'deploy' if options.compiler == 'r8' \
            else 'proguarded'

    if options.type not in version:
        print('No type {} for version {}'.format(options.type,
                                                 options.version))
        print('Valid types are {}'.format(version.keys()))
        return 1
    values = version[options.type]
    inputs = None
    # For R8 'deploy' the JAR is located using the Proguard configuration
    # -injars option. For chrome and nest we don't have the injars in the
    # proguard files.
    if 'inputs' in values and (options.compiler != 'r8'
                               or options.type != 'deploy' or options.app
                               == 'chrome' or options.app == 'nest'):
        inputs = values['inputs']

    args.extend(['--output', outdir])
    if 'min-api' in values:
        args.extend(['--min-api', values['min-api']])

    if 'main-dex-list' in values:
        args.extend(['--main-dex-list', values['main-dex-list']])

    if options.compiler == 'r8':
        if 'pgconf' in values and not options.k:
            sanitized_lib_path = os.path.join(os.path.abspath(outdir),
                                              'sanitized_lib.jar')
            sanitized_pgconf_path = os.path.join(os.path.abspath(outdir),
                                                 'sanitized.config')
            SanitizeLibraries(sanitized_lib_path, sanitized_pgconf_path,
                              values['pgconf'])
            args.extend(['--pg-conf', sanitized_pgconf_path])
            app_provided_pg_conf = True
        if options.k:
            args.extend(['--pg-conf', options.k])
        if 'maindexrules' in values:
            for rules in values['maindexrules']:
                args.extend(['--main-dex-rules', rules])
        if 'allow-type-errors' in values:
            extra_args.append('-Dcom.android.tools.r8.allowTypeErrors=1')
        if 'proto-shrinking' in values:
            extra_args.append(
                '-Dcom.android.tools.r8.generatedExtensionRegistryShrinking=1')

    if not options.no_libraries and 'libraries' in values:
        for lib in values['libraries']:
            args.extend(['--lib', lib])

    if not outdir.endswith('.zip') and not outdir.endswith('.jar') \
        and not os.path.exists(outdir):
        os.makedirs(outdir)

    # Additional flags for the compiler from the configuration file.
    if 'flags' in values:
        args.extend(values['flags'].split(' '))
    if options.compiler == 'r8':
        if 'r8-flags' in values:
            args.extend(values['r8-flags'].split(' '))

    # Additional flags for the compiler from the command line.
    if options.compiler_flags:
        args.extend(options.compiler_flags.split(' '))
    if options.r8_flags:
        args.extend(options.r8_flags.split(' '))

    if inputs:
        args.extend(inputs)

    t0 = time.time()
    if options.dump_args_file:
        with open(options.dump_args_file, 'w') as args_file:
            args_file.writelines([arg + os.linesep for arg in args])
    else:
        with utils.TempDir() as temp:
            if options.print_memoryuse and not options.track_memory_to_file:
                options.track_memory_to_file = os.path.join(
                    temp, utils.MEMORY_USE_TMP_FILE)
            if options.compiler == 'r8' and app_provided_pg_conf:
                # Ensure that output of -printmapping and -printseeds go to the output
                # location and not where the app Proguard configuration places them.
                if outdir.endswith('.zip') or outdir.endswith('.jar'):
                    pg_outdir = os.path.dirname(outdir)
                else:
                    pg_outdir = outdir
                additional_pg_conf = GenerateAdditionalProguardConfiguration(
                    temp, os.path.abspath(pg_outdir))
                args.extend(['--pg-conf', additional_pg_conf])
            build = not options.no_build and not options.golem
            stderr_path = os.path.join(temp, 'stderr')
            with open(stderr_path, 'w') as stderr:
                if options.compiler_build == 'full':
                    tool = options.compiler
                else:
                    assert (options.compiler_build == 'lib')
                    tool = 'r8lib-' + options.compiler
                exit_code = toolhelper.run(
                    tool,
                    args,
                    build=build,
                    debug=not options.no_debug,
                    profile=options.profile,
                    track_memory_file=options.track_memory_to_file,
                    extra_args=extra_args,
                    stderr=stderr,
                    timeout=options.timeout)
            if exit_code != 0:
                with open(stderr_path) as stderr:
                    stderr_text = stderr.read()
                    print(stderr_text)
                    if 'java.lang.OutOfMemoryError' in stderr_text:
                        print('Failure was OOM')
                        return OOM_EXIT_CODE
                    return exit_code

            if options.print_memoryuse:
                print('{}(MemoryUse): {}'.format(
                    options.print_memoryuse,
                    utils.grep_memoryuse(options.track_memory_to_file)))

    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)
    return 0
Example #8
0
def Main(argv):
  utils.check_java_version()
  options = parse_arguments(argv)
  if options.golem:
    golem.link_third_party()
  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,
        stdout=open(os.devnull, 'w'))
    if options.print_memoryuse:
      proguard_memoryuse = utils.grep_memoryuse(track_memory_file)

  # run dex on the result
  if options.compatdx:
    jar = utils.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)
Example #9
0
def main(argv):
    (options, args) = ParseOptions(argv)

    if options.golem:
        golem.link_third_party()
        if os.path.exists(WORKING_DIR):
            shutil.rmtree(WORKING_DIR)
        shutil.copytree(utils.OPENSOURCE_APPS_FOLDER, WORKING_DIR)
        os.environ[utils.ANDROID_HOME_ENVIROMENT_NAME] = os.path.join(
            utils.ANDROID_SDK)
        os.environ[utils.ANDROID_TOOLS_VERSION_ENVIRONMENT_NAME] = '28.0.3'
        options.disable_assertions = True
        options.ignore_versions = True
        options.no_build = True
        options.r8_compilation_steps = 1
        options.quiet = True
        options.gradle_pre_runs = 2
        options.use_daemon = True

    if not os.path.exists(WORKING_DIR):
        os.makedirs(WORKING_DIR)

    if options.download_only:
        clone_repositories(options.quiet)
        return

    with utils.TempDir() as temp_dir:
        if not (options.no_build or options.golem):
            gradle.RunGradle(['r8', 'r8lib'])

        if options.version:
            # Download r8-<version>.jar from
            # http://storage.googleapis.com/r8-releases/raw/.
            target = 'r8-{}.jar'.format(options.version)
            update_prebuilds_in_android.download_version(
                temp_dir, 'com/android/tools/r8/' + options.version, target)
            as_utils.MoveFile(os.path.join(temp_dir, target),
                              os.path.join(temp_dir, 'r8lib.jar'),
                              quiet=options.quiet)
        else:
            # Make a copy of r8.jar and r8lib.jar such that they stay the same for
            # the entire execution of this script.
            if 'r8-nolib' in options.shrinker or 'r8-nolib-full' in options.shrinker:
                assert os.path.isfile(
                    utils.R8_JAR), 'Cannot build without r8.jar'
                shutil.copyfile(utils.R8_JAR, os.path.join(temp_dir, 'r8.jar'))
            if 'r8' in options.shrinker or 'r8-full' in options.shrinker:
                assert os.path.isfile(
                    utils.R8LIB_JAR), 'Cannot build without r8lib.jar'
                shutil.copyfile(utils.R8LIB_JAR,
                                os.path.join(temp_dir, 'r8lib.jar'))

        result_per_shrinker_per_app = []

        for (app, repo) in options.apps:
            if app.skip:
                continue
            result_per_shrinker_per_app.append(
                (app, GetResultsForApp(app, repo, options, temp_dir)))

        LogResultsForApps(result_per_shrinker_per_app, options)
Example #10
0
def run_with_options(options, args, extra_args=None, stdout=None, quiet=False):
    if extra_args is None:
        extra_args = []
    app_provided_pg_conf = False
    # todo(121018500): remove when memory is under control
    if not any('-Xmx' in arg for arg in extra_args):
        if options.max_memory:
            extra_args.append('-Xmx%sM' % options.max_memory)
        else:
            extra_args.append('-Xmx8G')
    if options.golem:
        golem.link_third_party()
        options.out = os.getcwd()
    if not options.ignore_java_version:
        utils.check_java_version()

    if options.print_times:
        extra_args.append('-Dcom.android.tools.r8.printtimes=1')

    outdir = options.out
    (version_id, data) = get_version_and_data(options)

    if options.compiler not in COMPILERS:
        raise Exception("You need to specify '--compiler={}'".format(
            '|'.join(COMPILERS)))

    if options.compiler_build not in COMPILER_BUILDS:
        raise Exception("You need to specify '--compiler-build={}'".format(
            '|'.join(COMPILER_BUILDS)))

    if not version_id in data.VERSIONS.keys():
        print('No version {} for application {}'.format(
            version_id, options.app))
        print('Valid versions are {}'.format(data.VERSIONS.keys()))
        return 1

    version = data.VERSIONS[version_id]

    type = get_type(options)

    if type not in version:
        print('No type {} for version {}'.format(type, version))
        print('Valid types are {}'.format(version.keys()))
        return 1
    values = version[type]
    inputs = []
    # For R8 'deploy' the JAR is located using the Proguard configuration
    # -injars option. For chrome and nest we don't have the injars in the
    # proguard files.
    if 'inputs' in values and (options.compiler != 'r8' or type != 'deploy'
                               or options.app == 'chrome'
                               or options.app == 'nest' or options.app == 'r8'
                               or options.app == 'iosched'
                               or options.app == 'tachiyomi'):
        inputs = values['inputs']

    args.extend(['--output', outdir])
    if 'min-api' in values:
        args.extend(['--min-api', values['min-api']])

    if 'main-dex-list' in values:
        args.extend(['--main-dex-list', values['main-dex-list']])

    libraries = values['libraries'] if 'libraries' in values else []
    if options.compiler == 'r8':
        if 'pgconf' in values and not options.k:
            if has_injars_and_libraryjars(values['pgconf']):
                sanitized_lib_path = os.path.join(os.path.abspath(outdir),
                                                  'sanitized_lib.jar')
                sanitized_pgconf_path = os.path.join(os.path.abspath(outdir),
                                                     'sanitized.config')
                SanitizeLibrariesInPgconf(sanitized_lib_path,
                                          sanitized_pgconf_path,
                                          values['pgconf'])
                libraries = [sanitized_lib_path]
                args.extend(['--pg-conf', sanitized_pgconf_path])
            else:
                # -injars without -libraryjars or vice versa is not supported.
                check_no_injars_and_no_libraryjars(values['pgconf'])
                for pgconf in values['pgconf']:
                    args.extend(['--pg-conf', pgconf])
                if 'sanitize_libraries' in values and values[
                        'sanitize_libraries']:
                    sanitized_lib_path = os.path.join(os.path.abspath(outdir),
                                                      'sanitized_lib.jar')
                    SanitizeLibraries(sanitized_lib_path, values['libraries'],
                                      values['inputs'])
                    libraries = [sanitized_lib_path]
                    inputs = values['inputs']
            app_provided_pg_conf = True
        if options.k:
            args.extend(['--pg-conf', options.k])
        if 'maindexrules' in values:
            for rules in values['maindexrules']:
                args.extend(['--main-dex-rules', rules])
        if 'allow-type-errors' in values:
            extra_args.append('-Dcom.android.tools.r8.allowTypeErrors=1')
        extra_args.append(
            '-Dcom.android.tools.r8.disallowClassInlinerGracefulExit=1')

    if options.debug_agent:
        if not options.compiler_build == 'full':
            print(
                'WARNING: Running debugging agent on r8lib is questionable...')
        extra_args.append(
            '-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=*:5005'
        )

    if not options.no_libraries:
        for lib in libraries:
            args.extend(['--lib', lib])

    if not outdir.endswith('.zip') and not outdir.endswith('.jar') \
        and not os.path.exists(outdir):
        os.makedirs(outdir)

    if options.hash:
        # Download r8-<hash>.jar from
        # https://storage.googleapis.com/r8-releases/raw/<hash>/.
        download_path = archive.GetUploadDestination(options.hash, 'r8.jar',
                                                     True)
        assert utils.file_exists_on_cloud_storage(download_path), (
            'Could not find r8.jar file from provided hash: %s' % options.hash)
        destination = os.path.join(utils.LIBS, 'r8-' + options.hash + '.jar')
        utils.download_file_from_cloud_storage(download_path,
                                               destination,
                                               quiet=quiet)

    # Additional flags for the compiler from the configuration file.
    if 'flags' in values:
        args.extend(values['flags'].split(' '))
    if options.compiler == 'r8':
        if 'r8-flags' in values:
            args.extend(values['r8-flags'].split(' '))

    # Additional flags for the compiler from the command line.
    if options.compiler_flags:
        args.extend(options.compiler_flags.split(' '))
    if options.r8_flags:
        args.extend(options.r8_flags.split(' '))

    # Feature jars.
    features = values['features'] if 'features' in values else []
    for i, feature in enumerate(features, start=1):
        feature_out = os.path.join(outdir, 'feature-%d.zip' % i)
        for feature_jar in feature['inputs']:
            args.extend(['--feature', feature_jar, feature_out])

    args.extend(inputs)

    t0 = time.time()
    if options.dump_args_file:
        with open(options.dump_args_file, 'w') as args_file:
            args_file.writelines([arg + os.linesep for arg in args])
    else:
        with utils.TempDir() as temp:
            if options.print_memoryuse and not options.track_memory_to_file:
                options.track_memory_to_file = os.path.join(
                    temp, utils.MEMORY_USE_TMP_FILE)
            if options.compiler == 'r8' and app_provided_pg_conf:
                # Ensure that output of -printmapping and -printseeds go to the output
                # location and not where the app Proguard configuration places them.
                if outdir.endswith('.zip') or outdir.endswith('.jar'):
                    pg_outdir = os.path.dirname(outdir)
                else:
                    pg_outdir = outdir
                if not options.no_extra_pgconf:
                    additional_pg_conf = GenerateAdditionalProguardConfiguration(
                        temp, os.path.abspath(pg_outdir))
                    args.extend(['--pg-conf', additional_pg_conf])
            build = not options.no_build and not options.golem
            stderr_path = os.path.join(temp, 'stderr')
            with open(stderr_path, 'w') as stderr:
                jar = None
                main = None
                if options.compiler_build == 'full':
                    tool = options.compiler
                else:
                    assert (options.compiler_build == 'lib')
                    tool = 'r8lib-' + options.compiler
                if options.hash:
                    jar = os.path.join(utils.LIBS,
                                       'r8-' + options.hash + '.jar')
                    main = 'com.android.tools.r8.' + options.compiler.upper()
                exit_code = toolhelper.run(
                    tool,
                    args,
                    build=build,
                    debug=not options.no_debug,
                    profile=options.profile,
                    track_memory_file=options.track_memory_to_file,
                    extra_args=extra_args,
                    stdout=stdout,
                    stderr=stderr,
                    timeout=options.timeout,
                    quiet=quiet,
                    cmd_prefix=['taskset', '-c', options.cpu_list]
                    if options.cpu_list else [],
                    jar=jar,
                    main=main)
            if exit_code != 0:
                with open(stderr_path) as stderr:
                    stderr_text = stderr.read()
                    if not quiet:
                        print(stderr_text)
                    if 'java.lang.OutOfMemoryError' in stderr_text:
                        if not quiet:
                            print('Failure was OOM')
                        return OOM_EXIT_CODE
                    return exit_code

            if options.print_memoryuse:
                print('{}(MemoryUse): {}'.format(
                    options.print_memoryuse,
                    utils.grep_memoryuse(options.track_memory_to_file)))

    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)
    return 0
Example #11
0
def run_with_options(options, args):
  app_provided_pg_conf = False;
  if options.golem:
    golem.link_third_party()
    options.out = os.getcwd()
  outdir = options.out
  data = None
  if options.app == 'gmscore':
    options.version = options.version or 'v9'
    data = gmscore_data
  elif options.app == 'nest':
    options.version = options.version or '20180926'
    data = nest_data
  elif options.app == 'youtube':
    options.version = options.version or '12.22'
    data = youtube_data
  elif options.app == 'chrome':
    options.version = options.version or 'default'
    data = chrome_data
  elif options.app == 'gmail':
    options.version = options.version or '170604.16'
    data = gmail_data
  else:
    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 {}'
        .format(options.version, options.app))
    print('Valid versions are {}'.format(data.VERSIONS.keys()))
    return 1

  version = data.VERSIONS[options.version]

  if not options.type:
    options.type = 'deploy' if options.compiler == 'r8' \
        else 'proguarded'

  if options.type not in version:
    print('No type {} for version {}'.format(options.type, options.version))
    print('Valid types are {}'.format(version.keys()))
    return 1
  values = version[options.type]
  inputs = None
  # For R8 'deploy' the JAR is located using the Proguard configuration
  # -injars option. For chrome and nest we don't have the injars in the
  # proguard files.
  if 'inputs' in values and (options.compiler != 'r8'
                             or options.type != 'deploy'
                             or options.app == 'chrome'
                             or options.app == 'nest'):
    inputs = values['inputs']

  args.extend(['--output', outdir])
  if 'min-api' in values:
    args.extend(['--min-api', values['min-api']])

  if 'main-dex-list' in values:
    args.extend(['--main-dex-list', values['main-dex-list']])

  if options.compiler == 'r8':
    if 'pgconf' in values and not options.k:
      for pgconf in values['pgconf']:
        args.extend(['--pg-conf', pgconf])
        app_provided_pg_conf = True
    if options.k:
      args.extend(['--pg-conf', options.k])
    if 'maindexrules' in values:
      for rules in values['maindexrules']:
        args.extend(['--main-dex-rules', rules])

  if not options.no_libraries and 'libraries' in values:
    for lib in values['libraries']:
      args.extend(['--lib', lib])

  if not outdir.endswith('.zip') and not outdir.endswith('.jar') \
      and not os.path.exists(outdir):
    os.makedirs(outdir)

  # Additional flags for the compiler from the configuration file.
  if 'flags' in values:
    args.extend(values['flags'].split(' '))
  if options.compiler == 'r8':
    if 'r8-flags' in values:
      args.extend(values['r8-flags'].split(' '))

  # Additional flags for the compiler from the command line.
  if options.compiler_flags:
    args.extend(options.compiler_flags.split(' '))
  if options.r8_flags:
    args.extend(options.r8_flags.split(' '))

  if inputs:
    args.extend(inputs)

  t0 = time.time()
  if options.dump_args_file:
    with open(options.dump_args_file, 'w') as args_file:
      args_file.writelines([arg + os.linesep for arg in args])
  else:
    with utils.TempDir() as temp:
      if options.print_memoryuse and not options.track_memory_to_file:
        options.track_memory_to_file = os.path.join(temp,
            utils.MEMORY_USE_TMP_FILE)
      if options.compiler == 'r8' and app_provided_pg_conf:
        # Ensure that output of -printmapping and -printseeds go to the output
        # location and not where the app Proguard configuration places them.
        if outdir.endswith('.zip') or outdir.endswith('.jar'):
          pg_outdir = os.path.dirname(outdir)
        else:
          pg_outdir = outdir
        additional_pg_conf = GenerateAdditionalProguardConfiguration(
            temp, os.path.abspath(pg_outdir))
        args.extend(['--pg-conf', additional_pg_conf])
      build = not options.no_build and not options.golem
      exit_code = toolhelper.run(options.compiler, args,
                     build=build,
                     debug=not options.no_debug,
                     profile=options.profile,
                     track_memory_file=options.track_memory_to_file)
      if exit_code != 0:
        return exit_code

      if options.print_memoryuse:
        print('{}(MemoryUse): {}'
            .format(options.print_memoryuse,
                utils.grep_memoryuse(options.track_memory_to_file)))

  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)
  return 0