#!/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',
    'arc_hw_oemcrypto',
    'arcpp',
    'arcvm',
    'arm',
    'asan',
    'attestation',
    'bluetooth_suspend_management',
    'camera_feature_auto_framing',
    'camera_feature_face_detection',
    'camera_feature_hdrnet',
    'camera_feature_portrait_mode',
    'cdm_factory_daemon',
    'cellular',
    'cert_provision',
    'cfm',
    'cfm_enabled_device',
    'cheets',
    'chromeless_tty',
    'containers',
    'coverage',
    'cr50_onboard',
    '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_reboot_vault',
    'encrypted_stateful',
    'factory_runtime_probe',
    'fake_drivefs_launcher',
    'feedback',
    'fp_on_power_button',
    'fsverity',
    'ftdi_tpm',
    'fuzzer',
    'generic_tpm2',
    'hammerd_api',
    'houdini',
    'houdini64',
    'hw_details',
    'hwid_override',
    'iioservice',
    'inference_accuracy_eval',
    'intel_oemcrypto',
    'internal',
    'ipu6',
    'ipu6ep',
    'ipu6se',
    'iwlwifi_dump',
    'jetstream_routing',
    'kvm_guest',
    'kvm_host',
    'libglvnd',
    'local_federated_server',
    'lvm_stateful_partition',
    'crosvm_siblings',
    'manage_efi_boot_entries',
    'metrics_uploader',
    'ml_benchmark_drivers',
    'mojo',
    'mount_oop',
    'msan',
    'mtd',
    'ndk_translation',
    'oemcrypto_v16',
    'ondevice_document_scanner',
    'ondevice_grammar',
    'ondevice_handwriting',
    'ondevice_handwriting_dlc',
    'ondevice_speech',
    'ondevice_text_suggestions',
    'opengles',
    'os_install_service',
    'passive_metrics',
    'pinweaver',
    'pinweaver_csme',
    'postinstall_config_efi_and_legacy',
    'power_management',
    'prjquota',
    'profiling',
    'qrtr',
    'report_requisition',
    'selinux',
    'slow_mount',
    'systemd',
    'tcmalloc',
    'test',
    'ti50_onboard',
    'timers',
    'tpm',
    'tpm_dynamic',
    'tpm_insecure_fallback',
    'tpm2',
    'tpm2_simulator',
    'ubsan',
    'udev',
    'user_session_isolation',
    'v4l2_codec',
    'vaapi',
    'video_cards_msm',
    'vm_borealis',
    'vpn',
    'vtpm_proxy',
    'vulkan',
    'wake_on_wifi',
    'wifi',
    'wilco',
    '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)
