#!/usr/bin/env python3
# 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.
"""

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 = [
    'amd_oemcrypto',
    'amd64',
    'android_vm_rvc',
    'arc_adb_sideloading',
    'arcpp',
    'arcvm',
    'arm',
    'asan',
    'attestation',
    'bluetooth_suspend_management',
    'buffet',
    'camera_feature_hdrnet',
    'camera_feature_portrait_mode',
    'cdm_factory_daemon',
    'cellular',
    'cert_provision',
    'cfm',
    'cfm_enabled_device',
    'cheets',
    'chromeless_tty',
    'containers',
    'coverage',
    'cros_arm64',
    'cros_host',
    'cros_i686',
    'crosvm_virtio_video',
    'crosvm_wl_dmabuf',
    'crypto',
    'csme_emulator',
    'dbus',
    'device_mapper',
    'dhcpv6',
    'direncryption',
    'dlc',
    'double_extend_pcr_issue',
    'enable_slow_boot_notify',
    'encrypted_stateful',
    'factory_runtime_probe',
    'fake_drivefs_launcher',
    'feedback',
    'fp_on_power_button',
    'ftdi_tpm',
    'fuzzer',
    'generic_tpm2',
    'hammerd_api',
    'houdini',
    'houdini64',
    'hw_details',
    'hwid_override',
    'iioservice',
    'intel_oemcrypto',
    'ipu6',
    'ipu6ep',
    'ipu6se',
    'iwlwifi_dump',
    'jetstream_routing',
    'kvm_guest',
    'kvm_host',
    'lvm_stateful_partition',
    'metrics_uploader',
    'ml_benchmark_drivers',
    'mojo',
    'mount_oop',
    'msan',
    'mtd',
    'ndk_translation',
    'ondevice_document_scanner',
    'ondevice_grammar',
    'ondevice_handwriting',
    'ondevice_handwriting_dlc',
    'ondevice_speech',
    'ondevice_text_suggestions',
    'opengles',
    'passive_metrics',
    'pinweaver',
    'power_management',
    'pppoe',
    'profiling',
    'qrtr',
    'selinux',
    'slow_mount',
    'systemd',
    'tcmalloc',
    'test',
    'timers',
    'tpm',
    'tpm_dynamic',
    'tpm2',
    'tpm2_simulator',
    'ubsan',
    'udev',
    'user_session_isolation',
    'v4l2_codec',
    'vaapi',
    'vm_borealis',
    'vpn',
    'vtpm_proxy',
    'vulkan',
    'wake_on_wifi',
    'wifi',
    'wired_8021x',
    'wpa3_sae',
]

# 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 of 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 built components/projects.

        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. Currently 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_MANUAL_UPREVed 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)
