#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Wrapper for building the Chromium OS platform.

Takes care of running GN/ninja/etc... with all the right values.
"""

from __future__ import print_function

import collections
import glob
import json
import os

import six

from chromite.lib import commandline
from chromite.lib import cros_build_lib
from chromite.lib import osutils
from chromite.lib import portage_util

import common_utils
import ebuild_function

# USE flags used in BUILD.gn should be listed in _IUSE or _IUSE_TRUE.

# USE flags whose default values are false.
_IUSE = [
    'amd64',
    'arc_adb_sideloading',
    'arcvm',
    'arm',
    'asan',
    'attestation',
    'beanstalk',
    'bluetooth_suspend_management',
    'buffet',
    'cdm_factory_daemon',
    'cellular',
    'cert_provision',
    'cfm',
    'cfm_enabled_device',
    'cheets',
    'chromeless_tty',
    'containers',
    'coverage',
    'cros_arm64',
    'cros_host',
    'cros_i686',
    'crosvm_wl_dmabuf',
    'crypto',
    'cryptohome_userdataauth_interface',
    'dbus',
    'device_mapper',
    'dhcpv6',
    'direncryption',
    'dlc',
    'double_extend_pcr_issue',
    'enable_slow_boot_notify',
    'fake_drivefs_launcher',
    'fast_transition',
    'feedback',
    'fp_on_power_button',
    'ftdi_tpm',
    'fuzzer',
    'hammerd_api',
    'houdini',
    'houdini64',
    'hwid_override',
    'iioservice',
    'ipu6',
    'ipu6se',
    'iwlwifi_dump',
    'jetstream_routing',
    'kvm_guest',
    'kvm_host',
    'metrics_uploader',
    'mojo',
    'mount_oop',
    'msan',
    'mtd',
    'ndk_translation',
    'ondevice_handwriting',
    'ondevice_handwriting_dlc',
    'ondevice_speech',
    'opengles',
    'passive_metrics',
    'pinweaver',
    'power_management',
    'pppoe',
    'profiling',
    'selinux',
    'systemd',
    'tcmalloc',
    'test',
    'timers',
    'tpm',
    'tpm2',
    'tpm2_simulator',
    'trogdor_sar_hack',
    'ubsan',
    'udev',
    'usb_camera_monocle',
    'user_session_isolation',
    'vm_borealis',
    'vpn',
    'wake_on_wifi',
    'wifi',
    'wired_8021x',
]

# USE flags whose default values are true.
_IUSE_TRUE = [
    'chrome_kiosk_app',
    'chrome_network_proxy',
]


class Platform2(object):
  """Main builder logic for platform2"""

  def __init__(self, use_flags=None, board=None, host=False, libdir=None,
               incremental=True, verbose=False, enable_tests=False,
               cache_dir=None, jobs=None, platform_subdir=None):
    self.board = board
    self.host = host
    self.incremental = incremental
    self.jobs = jobs
    self.verbose = verbose
    self.platform_subdir = platform_subdir

    if use_flags is not None:
      self.use_flags = use_flags
    else:
      self.use_flags = portage_util.GetBoardUseFlags(self.board)

    if enable_tests:
      self.use_flags.add('test')

    if self.host:
      self.sysroot = '/'
    else:
      board_vars = self.get_portageq_envvars(['SYSROOT'], board=board)
      self.sysroot = board_vars['SYSROOT']

    if libdir:
      self.libdir = libdir
    else:
      self.libdir = '/usr/lib'

    if cache_dir:
      self.cache_dir = cache_dir
    else:
      self.cache_dir = os.path.join(self.sysroot,
                                    'var/cache/portage/chromeos-base/platform2')

    self.libbase_ver = os.environ.get('BASE_VER', '')
    if not self.libbase_ver:
      # If BASE_VER variable not set, read the content of
      # $SYSROOT/usr/share/libchrome/BASE_VER
      # file which contains the default libchrome revision number.
      base_ver_file = os.path.join(self.sysroot,
                                   'usr/share/libchrome/BASE_VER')
      try:
        self.libbase_ver = osutils.ReadFile(base_ver_file).strip()
      except FileNotFoundError:
        # Software not depending on libchrome still uses platform2.py, Instead
        # of asserting here. Provide a human readable bad value that is not
        # supposed to be used.
        self.libbase_ver = 'NOT-INSTALLED'

  def get_src_dir(self):
    """Return the path to build tools and common GN files"""
    return os.path.realpath(os.path.dirname(__file__))

  def get_platform2_root(self):
    """Return the path to src/platform2"""
    return os.path.dirname(self.get_src_dir())

  def get_buildroot(self):
    """Return the path to the folder where build artifacts are located."""
    if not self.incremental:
      workdir = os.environ.get('WORKDIR')
      if workdir:
        # Matches $(cros-workon_get_build_dir) behavior.
        return os.path.join(workdir, 'build')
      else:
        return os.getcwd()
    else:
      return self.cache_dir

  def get_products_path(self):
    """Return the path to the folder where build product are located."""
    return os.path.join(self.get_buildroot(), 'out/Default')

  def get_portageq_envvars(self, varnames, board=None):
    """Returns the values of a given set of variables using portageq."""

    # See if the env already has these settings.  If so, grab them directly.
    # This avoids the need to specify --board at all most of the time.
    try:
      board_vars = {}
      for varname in varnames:
        board_vars[varname] = os.environ[varname]
      return board_vars
    except KeyError:
      pass

    if board is None and not self.host:
      board = self.board

    # Portage will set this to an incomplete list which breaks portageq
    # walking all of the repos.  Clear it and let the value be repopulated.
    os.environ.pop('PORTDIR_OVERLAY', None)

    return portage_util.PortageqEnvvars(varnames, board=board,
                                        allow_undefined=True)

  def get_build_environment(self):
    """Returns a dict containing environment variables we will use to run GN.

    We do this to set the various toolchain names for the target board.
    """
    varnames = ['CHOST', 'AR', 'CC', 'CXX', 'PKG_CONFIG']
    if not self.host and not self.board:
      for v in varnames:
        os.environ.setdefault(v, '')
    board_env = self.get_portageq_envvars(varnames)

    tool_names = {
        'AR': 'ar',
        'CC': 'gcc',
        'CXX': 'g++',
        'PKG_CONFIG': 'pkg-config',
    }

    env = os.environ.copy()
    for var, tool in tool_names.items():
      env['%s_target' % var] = (board_env[var] if board_env[var] else \
                                '%s-%s' % (board_env['CHOST'], tool))

    return env

  def get_components_glob(self):
    """Return a glob of marker files for components/projects that were built.

    Each project spits out a file whilst building: we return a glob of them
    so we can install/test those projects or reset between compiles to ensure
    components that are no longer part of the build don't get installed.
    """
    return glob.glob(os.path.join(self.get_products_path(),
                                  'gen/components_*'))

  def can_use_gn(self):
    """Returns true if GN can be used on configure.

    All packages in platform2/ should be configured by GN.
    """
    build_gn = os.path.join(self.get_platform2_root(), self.platform_subdir,
                            'BUILD.gn')
    return os.path.isfile(build_gn)

  def configure(self, args):
    """Runs the configure step of the Platform2 build.

    Creates the build root if it doesn't already exists.  Then runs the
    appropriate configure tool. Currenty only GN is supported.
    """
    assert self.can_use_gn()
    # The args was used only for gyp.
    # TODO(crbug.com/767517): remove code for handling args.
    # There is a logic to in the platform eclass file, which detects a .gyp
    # file under project root and passes it to here an arg.
    if args:
      print('Warning: Args for GYP was given. We will no longer use GYP. '
            'Ignoring it and continuing configuration with GN.')

    if not os.path.isdir(self.get_buildroot()):
      os.makedirs(self.get_buildroot())

    if not self.incremental:
      osutils.RmDir(self.get_products_path(), ignore_missing=True)

    self.configure_gn()

  def gen_common_args(self, should_parse_shell_string):
    """Generates common arguments for the tools to configure as a dict.

    Returned value types are str, bool or list of strs.
    Lists are returned only when should_parse_shell_string is set to True.
    """
    def flags(s):
      if should_parse_shell_string:
        return common_utils.parse_shell_args(s)
      return s

    args = {
        'OS': 'linux',
        'sysroot': self.sysroot,
        'libdir': self.libdir,
        'build_root': self.get_buildroot(),
        'platform2_root': self.get_platform2_root(),
        'libbase_ver': self.libbase_ver,
        'enable_exceptions': os.environ.get('CXXEXCEPTIONS', 0) == '1',
        'external_cflags': flags(os.environ.get('CFLAGS', '')),
        'external_cxxflags': flags(os.environ.get('CXXFLAGS', '')),
        'external_cppflags': flags(os.environ.get('CPPFLAGS', '')),
        'external_ldflags': flags(os.environ.get('LDFLAGS', '')),
    }
    return args

  def configure_gn_args(self):
    """Configure with GN.

    Generates flags to run GN with, and then runs GN.
    """
    def to_gn_string(s):
      return '"%s"' % s.replace('"', '\\"')

    def to_gn_list(strs):
      return '[%s]' % ','.join([to_gn_string(s) for s in strs])

    def to_gn_args_args(gn_args):
      for k, v in gn_args.items():
        if isinstance(v, bool):
          v = str(v).lower()
        elif isinstance(v, list):
          v = to_gn_list(v)
        elif isinstance(v, six.string_types):
          v = to_gn_string(v)
        else:
          raise AssertionError('Unexpected %s, %r=%r' % (type(v), k, v))
        yield '%s=%s' % (k.replace('-', '_'), v)

    buildenv = self.get_build_environment()
    gn_args = {
        'platform_subdir': self.platform_subdir,
        'cc': buildenv.get('CC_target', buildenv.get('CC', '')),
        'cxx': buildenv.get('CXX_target', buildenv.get('CXX', '')),
        'ar': buildenv.get('AR_target', buildenv.get('AR', '')),
        'pkg-config': buildenv.get('PKG_CONFIG_target',
                                   buildenv.get('PKG_CONFIG', '')),
    }
    gn_args['clang_cc'] = 'clang' in gn_args['cc']
    gn_args['clang_cxx'] = 'clang' in gn_args['cxx']
    gn_args.update(self.gen_common_args(True))
    gn_args_args = list(to_gn_args_args(gn_args))

    # Set use flags as a scope.
    uses = {}
    for flag in _IUSE:
      uses[flag] = False
    for flag in _IUSE_TRUE:
      uses[flag] = True
    for x in self.use_flags:
      uses[x.replace('-', '_')] = True
    use_args = ['%s=%s' % (x, str(uses[x]).lower()) for x in uses]
    gn_args_args += ['use={%s}' % (' '.join(use_args))]

    return gn_args_args

  def configure_gn(self):
    """Configure with GN.

    Runs gn gen with generated flags.
    """
    gn_args_args = self.configure_gn_args()

    gn_args = ['gn', 'gen']
    if self.verbose:
      gn_args += ['-v']
    gn_args += [
        '--root=%s' % self.get_platform2_root(),
        '--args=%s' % ' '.join(gn_args_args),
        self.get_products_path(),
    ]
    cros_build_lib.run(gn_args, env=self.get_build_environment(),
                       cwd=self.get_platform2_root())

  def gn_desc(self, *args):
    """Describe BUILD.gn.

    Runs gn desc with generated flags.
    """
    gn_args_args = self.configure_gn_args()

    cmd = [
        'gn', 'desc',
        self.get_products_path(),
        '//%s/*' % self.platform_subdir,
        '--root=%s' % self.get_platform2_root(),
        '--args=%s' % ' '.join(gn_args_args),
        '--format=json',
    ]
    cmd += args
    result = cros_build_lib.run(cmd, env=self.get_build_environment(),
                                cwd=self.get_platform2_root(),
                                stdout=True, encoding='utf-8')
    return json.loads(result.output)

  def compile(self, args):
    """Runs the compile step of the Platform2 build.

    Removes any existing component markers that may exist (so we don't run
    tests/install for projects that have been disabled since the last
    build). Builds arguments for running Ninja and then runs Ninja.
    """
    for component in self.get_components_glob():
      os.remove(component)

    args = ['%s:%s' % (self.platform_subdir, x) for x in args]
    ninja_args = ['ninja', '-C', self.get_products_path()]
    if self.jobs:
      ninja_args += ['-j', str(self.jobs)]
    ninja_args += args

    if self.verbose:
      ninja_args.append('-v')

    if os.environ.get('NINJA_ARGS'):
      ninja_args.extend(os.environ['NINJA_ARGS'].split())

    cros_build_lib.run(ninja_args)

  def deviterate(self, args):
    """Runs the configure and compile steps of the Platform2 build.

    This is the default action, to allow easy iterative testing of changes
    as a developer.
    """
    self.configure([])
    self.compile(args)

  def configure_test(self):
    """Generates test options from GN."""

    def to_options(options):
      """Convert dict to shell string."""
      result = []
      for key, value in options.items():
        if isinstance(value, bool):
          if value:
            result.append('--%s' % key)
          continue
        if key == 'raw':
          result.append(value)
          continue
        result.append('--%s=%s' % (key, value))
      return result

    conf = self.gn_desc('--all', '--type=executable')
    group_all = conf.get('//%s:all' % self.platform_subdir, {})
    group_all_deps = group_all.get('deps', [])
    options_list = []
    for target_name in group_all_deps:
      test_target = conf.get(target_name)
      outputs = test_target.get('outputs', [])
      if len(outputs) != 1:
        continue
      output = outputs[0]
      metadata = test_target.get('metadata', {})
      run_test = unwrap_value(metadata, '_run_test', False)
      if not run_test:
        continue
      test_config = unwrap_value(metadata, '_test_config', {})

      p2_test_py = os.path.join(self.get_src_dir(), 'platform2_test.py')
      options = [
          p2_test_py,
          '--action=run',
          '--sysroot=%s' % self.sysroot,
      ]
      if self.host:
        options += ['--host']
      p2_test_filter = os.environ.get('P2_TEST_FILTER')
      if p2_test_filter:
        options += ['--user_gtest_filter=%s' % p2_test_filter]
      options += to_options(test_config)
      options += ['--', output]

      options_list.append(options)
    return options_list

  def test_all(self, _args):
    """Runs all tests described from GN."""
    test_options_list = self.configure_test()
    for test_options in test_options_list:
      cros_build_lib.run(test_options, encoding='utf-8')

  def configure_install(self):
    """Generates installation commands of ebuild."""
    conf = self.gn_desc('--all')
    group_all = conf.get('//%s:all' % self.platform_subdir, {})
    group_all_deps = group_all.get('deps', [])
    config_group = collections.defaultdict(list)
    for target_name in group_all_deps:
      target_conf = conf.get(target_name, {})
      metadata = target_conf.get('metadata', {})
      install_config = unwrap_value(metadata, '_install_config')
      if not install_config:
        continue
      sources = install_config.get('sources')
      if not sources:
        continue
      install_path = install_config.get('install_path')
      outputs = install_config.get('outputs')
      symlinks = install_config.get('symlinks')
      recursive = install_config.get('recursive')
      options = install_config.get('options')
      command_type = install_config.get('type')
      config_key = (install_path, recursive, options, command_type)
      config_group[config_key].append((sources, outputs, symlinks))
    cmd_list = []
    for install_config, install_args in config_group.items():
      args = []
      # Commands to install sources without explicit outputs nor symlinks can be
      # merged into one. Concat all such sources.
      sources = sum([sources for sources, outputs, symlinks in install_args
                     if not outputs and not symlinks], [])
      if sources:
        args.append((sources, None, None))
      # Append all remaining sources/outputs/symlinks.
      args += [(sources, outputs, symlinks) for
               sources, outputs, symlinks in install_args
               if outputs or symlinks]
      # Generate the command line.
      install_path, recursive, options, command_type = install_config
      for sources, outputs, symlinks in args:
        cmd_list += ebuild_function.generate(sources=sources,
                                             install_path=install_path,
                                             outputs=outputs,
                                             symlinks=symlinks,
                                             recursive=recursive,
                                             options=options,
                                             command_type=command_type)
    return cmd_list

  def install(self, _args):
    """Outputs the installation commands of ebuild as a standard output."""
    install_cmd_list = self.configure_install()
    for install_cmd in install_cmd_list:
      # An error occurs at six.moves.shlex_quote when running pylint.
      # https://github.com/PyCQA/pylint/issues/1965
      # pylint: disable=too-many-function-args
      print(' '.join(six.moves.shlex_quote(arg) for arg in install_cmd))


def unwrap_value(metadata, attr, default=None):
  """Gets a value like dict.get() with unwrapping it."""
  data = metadata.get(attr)
  if data is None:
    return default
  return data[0]


def GetParser():
  """Return a command line parser."""
  actions = ['configure', 'compile', 'deviterate', 'test_all', 'install']

  parser = commandline.ArgumentParser(description=__doc__)
  parser.add_argument('--action', default='deviterate',
                      choices=actions, help='action to run')
  parser.add_argument('--board',
                      help='board to build for')
  parser.add_argument('--cache_dir',
                      help='directory to use as cache for incremental build')
  parser.add_argument('--disable_incremental', action='store_false',
                      dest='incremental', help='disable incremental build')
  parser.add_argument('--enable_tests', action='store_true',
                      help='build and run tests')
  parser.add_argument('--host', action='store_true',
                      help="specify that we're building for the host")
  parser.add_argument('--libdir',
                      help='the libdir for the specific board, eg /usr/lib64')
  parser.add_argument('--use_flags',
                      action='split_extend', help='USE flags to enable')
  parser.add_argument('-j', '--jobs', type=int, default=None,
                      help='number of jobs to run in parallel')
  parser.add_argument('--platform_subdir', required=True,
                      help='subdir in platform2 where the package is located')
  parser.add_argument('args', nargs='*')

  return parser


def main(argv):
  parser = GetParser()

  # Temporary measure. Moving verbose argument, but can't do it all in one
  # sweep due to CROS_WORKON_BLACKLISTed packages. Use parse_known_args and
  # manually handle verbose parsing to maintain compatibility.
  options, unknown = parser.parse_known_args(argv)

  if not hasattr(options, 'verbose'):
    options.verbose = '--verbose' in unknown

  if '--verbose' in unknown:
    unknown.remove('--verbose')
  if unknown:
    parser.error('Unrecognized arguments: %s' % unknown)

  if options.host and options.board:
    raise AssertionError('You must provide only one of --board or --host')

  if not options.verbose:
    # Should convert to cros_build_lib.BooleanShellValue.
    options.verbose = (os.environ.get('VERBOSE', '0') == '1')
  p2 = Platform2(options.use_flags, options.board, options.host,
                 options.libdir, options.incremental, options.verbose,
                 options.enable_tests, options.cache_dir, jobs=options.jobs,
                 platform_subdir=options.platform_subdir)
  getattr(p2, options.action)(options.args)


if __name__ == '__main__':
  commandline.ScriptWrapperMain(lambda _: main)
