#!/usr/bin/env python3
# Copyright (c) 2022, 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 subprocess
import sys

import compiledump
import gradle
import jdk
import utils

NONLIB_BUILD_TARGET = 'R8WithRelocatedDeps'
NONLIB_TEST_BUILD_TARGETS = [utils.R8_TESTS_TARGET, utils.R8_TESTS_DEPS_TARGET]

R8LIB_BUILD_TARGET = utils.R8LIB
R8LIB_TEST_BUILD_TARGETS = [utils.R8LIB_TESTS_TARGET, utils.R8LIB_TESTS_DEPS_TARGET]

# The r8lib target is always the golem target.
GOLEM_BUILD_TARGETS = [R8LIB_BUILD_TARGET] + R8LIB_TEST_BUILD_TARGETS

def get_golem_resource_path(benchmark):
  return os.path.join('benchmarks', benchmark)

def get_jdk_home(options, benchmark):
  if options.golem:
    return os.path.join(get_golem_resource_path(benchmark), 'linux')
  return None

def parse_options(argv):
  result = argparse.ArgumentParser(description = 'Run test-based benchmarks.')
  result.add_argument('--golem',
                      help='Indicate this as a run on golem',
                      default=False,
                      action='store_true')
  result.add_argument('--benchmark',
                      help='The test benchmark to run',
                      required=True)
  result.add_argument('--target',
                      help='The test target to run',
                      required=True,
                      # These should 1:1 with benchmarks/BenchmarkTarget.java
                      choices=['d8', 'r8-full', 'r8-force', 'r8-compat'])
  result.add_argument('--nolib', '--no-lib', '--no-r8lib',
                      help='Run the non-lib R8 build (default false)',
                      default=False,
                      action='store_true')
  result.add_argument('--no-build', '--no_build',
                      help='Run without building first (default false)',
                      default=False,
                      action='store_true')
  result.add_argument('--enable-assertions', '--enable_assertions', '-ea',
                      help='Enable assertions when running',
                      default=False,
                      action='store_true')
  result.add_argument('--print-times',
                      help='Print timing information from r8',
                      default=False,
                      action='store_true')
  result.add_argument('--version', '-v',
                      help='Use R8 version/hash for the run (default local build)',
                      default=None)
  result.add_argument('--temp',
                      help='A directory to use for temporaries and outputs.',
                      default=None)
  return result.parse_known_args(argv)

def main(argv, temp):
  (options, args) = parse_options(argv)

  if options.temp:
    temp = options.temp

  if options.golem:
    options.no_build = True
    if options.nolib:
      print("Error: golem should always run r8lib")
      return 1

  if options.nolib:
    testBuildTargets = NONLIB_TEST_BUILD_TARGETS
    buildTargets = [NONLIB_BUILD_TARGET] + NONLIB_TEST_BUILD_TARGETS
    r8jar = utils.R8_WITH_RELOCATED_DEPS_JAR
    testjars = [utils.R8_TESTS_DEPS_JAR, utils.R8_TESTS_JAR]
  else:
    testBuildTargets = R8LIB_TEST_BUILD_TARGETS
    buildTargets = GOLEM_BUILD_TARGETS
    r8jar = utils.R8LIB_JAR
    testjars = [utils.R8LIB_TESTS_DEPS_JAR, utils.R8LIB_TESTS_JAR]

  if options.version:
    # r8 is downloaded so only test jar needs to be built.
    buildTargets = testBuildTargets
    r8jar = compiledump.download_distribution(options.version, options.nolib, temp)

  if not options.no_build:
    gradle.RunGradle(buildTargets + ['-Pno_internal'])

  if not options.golem:
    # When running locally, change the working directory to be in 'temp'.
    # This is hard to do properly within the JVM so we do it here.
    with utils.ChangedWorkingDirectory(temp):
      return run(options, r8jar, testjars)
  else:
    return run(options, r8jar, testjars)

def run(options, r8jar, testjars):
  jdkhome = get_jdk_home(options, options.benchmark)
  cmd = [jdk.GetJavaExecutable(jdkhome)]
  if options.enable_assertions:
    cmd.append('-ea')
  if options.print_times:
    cmd.append('-Dcom.android.tools.r8.printtimes=1')
  cmd.extend(['-cp', ':'.join([r8jar] + testjars)])
  cmd.extend([
    'com.android.tools.r8.benchmarks.BenchmarkMainEntryRunner',
    options.benchmark,
    options.target,
    # When running locally the working directory is moved and we pass the
    # repository root as an argument. The runner can then setup dependencies.
    'golem' if options.golem else utils.REPO_ROOT,
    ])
  return subprocess.check_call(cmd)

if __name__ == '__main__':
  with utils.TempDir() as temp:
    sys.exit(main(sys.argv[1:], temp))
