#!/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',
    'esdfs',
    '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 = ['ARCH', 'CHOST', 'AR', 'CC', 'CXX', 'PKG_CONFIG']
        board_env = self.get_portageq_envvars(varnames)

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

        env = {
            'ARCH': board_env.get('ARCH'),
        }
        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()

        # Map Gentoo ARCH to GN target_cpu. Sometimes they're the same.
        arch_to_target_cpu = {
            'amd64': 'x64',
            'mips': 'mipsel',
        }
        target_cpu = buildenv.get('ARCH')
        target_cpu = arch_to_target_cpu.get(target_cpu, target_cpu)
        assert target_cpu, '$ARCH is missing from the env'

        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', '')),
            'target_cpu':
            target_cpu,
            'target_os':
            'linux',
        }

        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,
                           extra_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,
                                    extra_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)
